ogelf.pas 119 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428
  1. {
  2. Copyright (c) 1998-2006 by Peter Vreman
  3. Contains the binary elf writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogelf;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,
  25. { assembler }
  26. cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,assemble,
  27. { ELF definitions }
  28. elfbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. {$ifdef cpu64bitaddr}
  34. TElfsechdr = TElf64sechdr;
  35. {$else cpu64bitaddr}
  36. TElfsechdr = TElf32sechdr;
  37. {$endif cpu64bitaddr}
  38. TElfObjSection = class(TObjSection)
  39. public
  40. shstridx,
  41. shtype,
  42. shflags,
  43. shlink,
  44. shinfo,
  45. shentsize : longint;
  46. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  47. constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags:longint;Aalign:shortint;Aentsize:longint);
  48. constructor create_reloc(aobjdata:TObjData;const Aname:string;allocflag:boolean);
  49. procedure writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);override;
  50. end;
  51. TElfSymtabKind = (esk_obj,esk_exe,esk_dyn);
  52. TElfSymtab = class(TElfObjSection)
  53. public
  54. kind: TElfSymtabKind;
  55. fstrsec: TObjSection;
  56. symidx: longint;
  57. tlsbase: aword;
  58. constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce;
  59. procedure writeSymbol(objsym:TObjSymbol;nameidx:longword=0);
  60. procedure writeInternalSymbol(avalue:aword;astridx:longword;ainfo:byte;ashndx:word);
  61. end;
  62. TElfObjData = class(TObjData)
  63. public
  64. ident: TElfIdent;
  65. flags: longword;
  66. {$ifdef mips}
  67. gp_value: longword;
  68. {$endif mips}
  69. constructor create(const n:string);override;
  70. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  71. procedure CreateDebugSections;override;
  72. procedure writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);override;
  73. end;
  74. TElfObjectOutput = class(tObjOutput)
  75. private
  76. symtabsect: TElfSymtab;
  77. shstrtabsect: TElfObjSection;
  78. procedure createrelocsection(s:TElfObjSection;data:TObjData);
  79. procedure createshstrtab(data:TObjData);
  80. procedure createsymtab(data: TObjData);
  81. procedure writesectionheader(s:TElfObjSection);
  82. procedure section_write_symbol(p:TObject;arg:pointer);
  83. procedure section_count_sections(p:TObject;arg:pointer);
  84. procedure section_create_relocsec(p:TObject;arg:pointer);
  85. procedure section_write_sechdr(p:TObject;arg:pointer);
  86. protected
  87. function writedata(data:TObjData):boolean;override;
  88. public
  89. constructor Create(AWriter:TObjectWriter);override;
  90. end;
  91. TElfAssembler = class(tinternalassembler)
  92. constructor create(smart:boolean);override;
  93. end;
  94. PSectionRec=^TSectionRec;
  95. TSectionRec=record
  96. sec: TObjSection;
  97. relocpos: aword;
  98. relocs: longint;
  99. relentsize: longint;
  100. end;
  101. TElfsecheaderarray=array of TElfsechdr;
  102. TObjSymbolClass=class of TObjSymbol;
  103. TElfObjInput=class(TObjInput)
  104. private
  105. FSecTbl: PSectionRec;
  106. FSymTbl: PPointer;
  107. FLoaded: PBoolean;
  108. shdrs: TElfsecheaderarray;
  109. nsects: longword;
  110. shoffset: aword;
  111. shstrndx: longword;
  112. symtabndx: longword;
  113. shstrtab: PChar;
  114. strtab: PChar;
  115. shstrtablen: longword;
  116. strtablen: longword;
  117. symtaboffset: aword;
  118. syms: longword;
  119. localsyms: longword;
  120. symversions: PWord;
  121. dynobj: boolean;
  122. CObjSymbol: TObjSymbolClass;
  123. verdefs: TFPHashObjectList;
  124. function LoadHeader(out objdata:TObjData):boolean;
  125. procedure LoadSection(const shdr:TElfsechdr;index:longint;objdata:TObjData);
  126. procedure LoadRelocations(const secrec:TSectionRec);
  127. procedure LoadSymbols(objdata:TObjData;count,locals:longword);
  128. procedure LoadDynamic(const shdr:TElfsechdr;objdata:TObjData);
  129. public
  130. constructor Create;override;
  131. destructor Destroy;override;
  132. function ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;override;
  133. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  134. function CreateSection(const shdr:TElfsechdr;index:longint;objdata:TObjData;
  135. out secname:string):TElfObjSection;
  136. function ReadBytes(offs:longint;out buf;len:longint):boolean;
  137. end;
  138. TElfVersionDef = class(TFPHashObject)
  139. public
  140. index: longword;
  141. end;
  142. TElfDynamicObjData = class(TElfObjData)
  143. private
  144. FVersionDefs: TFPHashObjectList;
  145. public
  146. soname_strofs: longword;
  147. vernaux_count: longword;
  148. constructor create(const n:string);override;
  149. destructor destroy;override;
  150. property versiondefs:TFPHashObjectList read FVersionDefs;
  151. end;
  152. TVersionedObjSymbol = class(TObjSymbol)
  153. private
  154. FVersion: TElfVersionDef;
  155. public
  156. property version: TElfVersionDef read FVersion write FVersion;
  157. end;
  158. TRelocNameProc=function(reltyp:byte):string;
  159. TEncodeRelocProc=function(objrel:TObjRelocation):byte;
  160. TLoadRelocProc=procedure(objrel:TObjRelocation);
  161. TLoadSectionProc=function(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
  162. TEncodeFlagsProc=function:longword;
  163. TDynamicReloc=(
  164. dr_relative,
  165. dr_glob_dat,
  166. dr_jump_slot,
  167. dr_copy,
  168. dr_irelative
  169. );
  170. TElfTarget=record
  171. max_page_size: longword;
  172. exe_image_base: longword;
  173. machine_code: word;
  174. relocs_use_addend: boolean;
  175. dyn_reloc_codes: array[TDynamicReloc] of byte;
  176. relocname: TRelocNameProc;
  177. encodereloc: TEncodeRelocProc;
  178. loadreloc: TLoadRelocProc;
  179. loadsection: TLoadSectionProc;
  180. encodeflags: TEncodeFlagsProc;
  181. end;
  182. TElfExeSection=class(TExeSection)
  183. public
  184. secshidx : longword; { index of the section header }
  185. shstridx,
  186. shtype,
  187. shflags,
  188. shlink,
  189. shinfo,
  190. shentsize : longword;
  191. procedure AddObjSection(objsec:TObjSection;ignoreprops:boolean=false);override;
  192. end;
  193. TElfSegment=class
  194. public
  195. ptype: longword;
  196. pflags: longword;
  197. DataPos: aword;
  198. DataSize: aword;
  199. MemPos: aword;
  200. MemSize: aword;
  201. align: longword;
  202. //physaddr: aword;
  203. FSectionList: TFPObjectList;
  204. constructor Create(atype,aflags,aalign:longword);
  205. destructor Destroy; override;
  206. procedure Add(exesec:TExeSection);
  207. end;
  208. TElfExeOutput=class(TExeOutput)
  209. private
  210. segmentlist: TFPObjectList;
  211. textseg,
  212. dataseg,
  213. noteseg,
  214. phdrseg: TElfSegment;
  215. shstrtabsect: TElfObjSection;
  216. symtab: TElfSymtab;
  217. shoffset: aword;
  218. gotwritten: boolean;
  219. { dynamic linking }
  220. dynsymnames: Plongword;
  221. dynsymtable: TElfSymtab;
  222. interpobjsec: TObjSection;
  223. FInterpreter: pshortstring;
  224. verneedcount,
  225. verdefcount: longword;
  226. symversec,
  227. verdefsec,
  228. verneedsec,
  229. hashobjsec: TElfObjSection;
  230. neededlist: TFPHashList;
  231. dyncopysyms: TFPObjectList;
  232. function AttachSection(objsec:TObjSection):TElfExeSection;
  233. function CreateSegment(atype,aflags,aalign:longword):TElfSegment;
  234. procedure WriteHeader;
  235. procedure WriteDynamicSymbolsHash;
  236. procedure WriteVersionSections;
  237. procedure WriteDynamicTags;
  238. procedure FinishDynamicTags;
  239. procedure exesection_write_header(p:TObject;arg:Pointer);
  240. procedure segment_write_header(p:TObject;arg:Pointer);
  241. procedure mempos_segment(seg:TElfSegment);
  242. procedure datapos_segment(seg:TElfSegment);
  243. procedure MapSectionsToSegments;
  244. procedure WriteStaticSymtable;
  245. procedure WriteShstrtab;
  246. procedure FixupSectionLinks;
  247. procedure InitDynlink;
  248. procedure OrderOrphanSections;
  249. protected
  250. dynamiclink: boolean;
  251. hastextrelocs: boolean;
  252. gotsymbol: TObjSymbol;
  253. dynsymlist: TFPObjectList;
  254. dynamicsec,
  255. gotobjsec: TObjSection;
  256. dynbssobjsec,
  257. pltobjsec,
  258. gotpltobjsec,
  259. pltrelocsec,
  260. ipltrelocsec,
  261. dynrelocsec: TElfObjSection;
  262. dynreloclist: TFPObjectList;
  263. tlsseg: TElfSegment;
  264. relative_reloc_count: longint;
  265. gotsize: aword;
  266. dynrelsize: aword;
  267. procedure PrepareGOT;virtual;
  268. function AllocGOTSlot(objsym: TObjSymbol):boolean;virtual;
  269. procedure CreateGOTSection;virtual;
  270. procedure make_dynamic_if_undefweak(exesym:TExeSymbol);
  271. procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
  272. procedure CreatePLT;virtual;
  273. procedure WriteFirstPLTEntry;virtual;abstract;
  274. procedure WritePLTEntry(exesym:TExeSymbol);virtual;
  275. procedure WriteIndirectPLTEntry(exesym:TExeSymbol);virtual;
  276. procedure WriteTargetDynamicTags;virtual;
  277. procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);virtual;abstract;
  278. procedure ReportNonDSOReloc(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
  279. procedure ReportRelocOverflow(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
  280. procedure WriteDynTag(aTag:longword;aValue:longword);
  281. procedure WriteDynTag(aTag:longword;aSection:TObjSection;aOffs:aword=0);
  282. procedure Do_Mempos;virtual;
  283. public
  284. constructor Create;override;
  285. destructor Destroy;override;
  286. procedure Load_Start;override;
  287. procedure Load_DynamicObject(ObjData:TObjData;asneeded:boolean);override;
  288. procedure Order_Start;override;
  289. procedure Order_end;override;
  290. procedure AfterUnusedSectionRemoval;override;
  291. procedure MemPos_Start;override;
  292. procedure MemPos_ExeSection(const aname:string);override;
  293. procedure DataPos_Start;override;
  294. procedure DataPos_ExeSection(const aname:string);override;
  295. function writeData:boolean;override;
  296. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  297. property interpreter:pshortstring read FInterpreter write FInterpreter;
  298. end;
  299. var
  300. ElfExeOutputClass: TExeOutputClass;
  301. ElfTarget: TElfTarget;
  302. const
  303. { Bits of TObjSymbol.refs field }
  304. symref_plt = 1;
  305. symref_from_text = 2;
  306. implementation
  307. uses
  308. SysUtils,
  309. verbose,
  310. export,expunix,
  311. cutils,globals,fmodule;
  312. const
  313. symbolresize = 200*18;
  314. {$ifdef cpu64bitaddr}
  315. const
  316. ELFCLASS = ELFCLASS64;
  317. type
  318. telfheader = telf64header;
  319. telfreloc = telf64reloc;
  320. telfsymbol = telf64symbol;
  321. telfproghdr = telf64proghdr;
  322. telfdyn = telf64dyn;
  323. function ELF_R_INFO(sym:longword;typ:byte):qword;inline;
  324. begin
  325. result:=(qword(sym) shl 32) or typ;
  326. end;
  327. {$else cpu64bitaddr}
  328. const
  329. ELFCLASS = ELFCLASS32;
  330. type
  331. telfheader = telf32header;
  332. telfreloc = telf32reloc;
  333. telfsymbol = telf32symbol;
  334. telfproghdr = telf32proghdr;
  335. telfdyn = telf32dyn;
  336. function ELF_R_INFO(sym:longword;typ:byte):longword;inline;
  337. begin
  338. result:=(sym shl 8) or typ;
  339. end;
  340. {$endif cpu64bitaddr}
  341. procedure MayBeSwapHeader(var h : telf32header);
  342. begin
  343. if source_info.endian<>target_info.endian then
  344. with h do
  345. begin
  346. e_type:=swapendian(e_type);
  347. e_machine:=swapendian(e_machine);
  348. e_version:=swapendian(e_version);
  349. e_entry:=swapendian(e_entry);
  350. e_phoff:=swapendian(e_phoff);
  351. e_shoff:=swapendian(e_shoff);
  352. e_flags:=swapendian(e_flags);
  353. e_ehsize:=swapendian(e_ehsize);
  354. e_phentsize:=swapendian(e_phentsize);
  355. e_phnum:=swapendian(e_phnum);
  356. e_shentsize:=swapendian(e_shentsize);
  357. e_shnum:=swapendian(e_shnum);
  358. e_shstrndx:=swapendian(e_shstrndx);
  359. end;
  360. end;
  361. procedure MayBeSwapHeader(var h : telf64header);
  362. begin
  363. if source_info.endian<>target_info.endian then
  364. with h do
  365. begin
  366. e_type:=swapendian(e_type);
  367. e_machine:=swapendian(e_machine);
  368. e_version:=swapendian(e_version);
  369. e_entry:=swapendian(e_entry);
  370. e_phoff:=swapendian(e_phoff);
  371. e_shoff:=swapendian(e_shoff);
  372. e_flags:=swapendian(e_flags);
  373. e_ehsize:=swapendian(e_ehsize);
  374. e_phentsize:=swapendian(e_phentsize);
  375. e_phnum:=swapendian(e_phnum);
  376. e_shentsize:=swapendian(e_shentsize);
  377. e_shnum:=swapendian(e_shnum);
  378. e_shstrndx:=swapendian(e_shstrndx);
  379. end;
  380. end;
  381. procedure MayBeSwapHeader(var h : telf32proghdr);
  382. begin
  383. if source_info.endian<>target_info.endian then
  384. with h do
  385. begin
  386. p_align:=swapendian(p_align);
  387. p_filesz:=swapendian(p_filesz);
  388. p_flags:=swapendian(p_flags);
  389. p_memsz:=swapendian(p_memsz);
  390. p_offset:=swapendian(p_offset);
  391. p_paddr:=swapendian(p_paddr);
  392. p_type:=swapendian(p_type);
  393. p_vaddr:=swapendian(p_vaddr);
  394. end;
  395. end;
  396. procedure MayBeSwapHeader(var h : telf64proghdr);
  397. begin
  398. if source_info.endian<>target_info.endian then
  399. with h do
  400. begin
  401. p_align:=swapendian(p_align);
  402. p_filesz:=swapendian(p_filesz);
  403. p_flags:=swapendian(p_flags);
  404. p_memsz:=swapendian(p_memsz);
  405. p_offset:=swapendian(p_offset);
  406. p_paddr:=swapendian(p_paddr);
  407. p_type:=swapendian(p_type);
  408. p_vaddr:=swapendian(p_vaddr);
  409. end;
  410. end;
  411. procedure MaybeSwapSecHeader(var h : telf32sechdr);
  412. begin
  413. if source_info.endian<>target_info.endian then
  414. with h do
  415. begin
  416. sh_name:=swapendian(sh_name);
  417. sh_type:=swapendian(sh_type);
  418. sh_flags:=swapendian(sh_flags);
  419. sh_addr:=swapendian(sh_addr);
  420. sh_offset:=swapendian(sh_offset);
  421. sh_size:=swapendian(sh_size);
  422. sh_link:=swapendian(sh_link);
  423. sh_info:=swapendian(sh_info);
  424. sh_addralign:=swapendian(sh_addralign);
  425. sh_entsize:=swapendian(sh_entsize);
  426. end;
  427. end;
  428. procedure MaybeSwapSecHeader(var h : telf64sechdr);
  429. begin
  430. if source_info.endian<>target_info.endian then
  431. with h do
  432. begin
  433. sh_name:=swapendian(sh_name);
  434. sh_type:=swapendian(sh_type);
  435. sh_flags:=swapendian(sh_flags);
  436. sh_addr:=swapendian(sh_addr);
  437. sh_offset:=swapendian(sh_offset);
  438. sh_size:=swapendian(sh_size);
  439. sh_link:=swapendian(sh_link);
  440. sh_info:=swapendian(sh_info);
  441. sh_addralign:=swapendian(sh_addralign);
  442. sh_entsize:=swapendian(sh_entsize);
  443. end;
  444. end;
  445. procedure MaybeSwapElfSymbol(var h : telf32symbol);
  446. begin
  447. if source_info.endian<>target_info.endian then
  448. with h do
  449. begin
  450. st_name:=swapendian(st_name);
  451. st_value:=swapendian(st_value);
  452. st_size:=swapendian(st_size);
  453. st_shndx:=swapendian(st_shndx);
  454. end;
  455. end;
  456. procedure MaybeSwapElfSymbol(var h : telf64symbol);
  457. begin
  458. if source_info.endian<>target_info.endian then
  459. with h do
  460. begin
  461. st_name:=swapendian(st_name);
  462. st_value:=swapendian(st_value);
  463. st_size:=swapendian(st_size);
  464. st_shndx:=swapendian(st_shndx);
  465. end;
  466. end;
  467. procedure MaybeSwapElfReloc(var h : telf32reloc);
  468. begin
  469. if source_info.endian<>target_info.endian then
  470. with h do
  471. begin
  472. address:=swapendian(address);
  473. info:=swapendian(info);
  474. addend:=swapendian(addend);
  475. end;
  476. end;
  477. procedure MaybeSwapElfReloc(var h : telf64reloc);
  478. begin
  479. if source_info.endian<>target_info.endian then
  480. with h do
  481. begin
  482. address:=swapendian(address);
  483. info:=swapendian(info);
  484. addend:=swapendian(addend);
  485. end;
  486. end;
  487. procedure MaybeSwapElfDyn(var h : telf32dyn);
  488. begin
  489. if source_info.endian<>target_info.endian then
  490. with h do
  491. begin
  492. d_tag:=swapendian(d_tag);
  493. d_val:=swapendian(d_val);
  494. end;
  495. end;
  496. procedure MaybeSwapElfDyn(var h : telf64dyn);
  497. begin
  498. if source_info.endian<>target_info.endian then
  499. with h do
  500. begin
  501. d_tag:=swapendian(d_tag);
  502. d_val:=swapendian(d_val);
  503. end;
  504. end;
  505. procedure MaybeSwapElfverdef(var h: TElfverdef);
  506. begin
  507. if source_info.endian<>target_info.endian then
  508. with h do
  509. begin
  510. vd_version:=swapendian(vd_version);
  511. vd_flags:=swapendian(vd_flags);
  512. vd_ndx:=swapendian(vd_ndx);
  513. vd_cnt:=swapendian(vd_cnt);
  514. vd_hash:=swapendian(vd_hash);
  515. vd_aux:=swapendian(vd_aux);
  516. vd_next:=swapendian(vd_next);
  517. end;
  518. end;
  519. procedure MaybeSwapElfverdaux(var h: TElfverdaux);
  520. begin
  521. if source_info.endian<>target_info.endian then
  522. with h do
  523. begin
  524. vda_name:=swapendian(vda_name);
  525. vda_next:=swapendian(vda_next);
  526. end;
  527. end;
  528. procedure MaybeSwapElfverneed(var h: TElfverneed);
  529. begin
  530. if source_info.endian<>target_info.endian then
  531. with h do
  532. begin
  533. vn_version:=swapendian(vn_version);
  534. vn_cnt:=swapendian(vn_cnt);
  535. vn_file:=swapendian(vn_file);
  536. vn_aux:=swapendian(vn_aux);
  537. vn_next:=swapendian(vn_next);
  538. end;
  539. end;
  540. procedure MaybeSwapElfvernaux(var h: TElfvernaux);
  541. begin
  542. if source_info.endian<>target_info.endian then
  543. with h do
  544. begin
  545. vna_hash:=swapendian(vna_hash);
  546. vna_flags:=swapendian(vna_flags);
  547. vna_other:=swapendian(vna_other);
  548. vna_name:=swapendian(vna_name);
  549. vna_next:=swapendian(vna_next);
  550. end;
  551. end;
  552. {****************************************************************************
  553. Helpers
  554. ****************************************************************************}
  555. procedure encodesechdrflags(aoptions:TObjSectionOptions;out AshType:longint;out Ashflags:longint);
  556. begin
  557. { Section Type }
  558. AshType:=SHT_PROGBITS;
  559. if oso_strings in aoptions then
  560. AshType:=SHT_STRTAB
  561. else if not(oso_data in aoptions) then
  562. AshType:=SHT_NOBITS;
  563. { Section Flags }
  564. Ashflags:=0;
  565. if oso_load in aoptions then
  566. Ashflags:=Ashflags or SHF_ALLOC;
  567. if oso_executable in aoptions then
  568. Ashflags:=Ashflags or SHF_EXECINSTR;
  569. if oso_write in aoptions then
  570. Ashflags:=Ashflags or SHF_WRITE;
  571. end;
  572. procedure decodesechdrflags(AshType:longint;Ashflags:longint;out aoptions:TObjSectionOptions);
  573. begin
  574. aoptions:=[];
  575. { Section Type }
  576. if AshType<>SHT_NOBITS then
  577. include(aoptions,oso_data);
  578. if AshType=SHT_STRTAB then
  579. include(aoptions,oso_strings);
  580. { Section Flags }
  581. if Ashflags and SHF_ALLOC<>0 then
  582. include(aoptions,oso_load);
  583. if Ashflags and SHF_WRITE<>0 then
  584. include(aoptions,oso_write);
  585. if Ashflags and SHF_EXECINSTR<>0 then
  586. include(aoptions,oso_executable);
  587. end;
  588. {****************************************************************************
  589. TElfObjSection
  590. ****************************************************************************}
  591. constructor TElfObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
  592. begin
  593. inherited create(AList,Aname,Aalign,aoptions);
  594. index:=0;
  595. shstridx:=0;
  596. encodesechdrflags(aoptions,shtype,shflags);
  597. shlink:=0;
  598. shinfo:=0;
  599. if name='.stab' then
  600. shentsize:=sizeof(TObjStabEntry);
  601. end;
  602. constructor TElfObjSection.create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags:longint;Aalign:shortint;Aentsize:longint);
  603. var
  604. aoptions : TObjSectionOptions;
  605. begin
  606. decodesechdrflags(Ashtype,Ashflags,aoptions);
  607. inherited create(aobjdata.ObjSectionList,Aname,Aalign,aoptions);
  608. objdata:=aobjdata;
  609. index:=0;
  610. shstridx:=0;
  611. shtype:=AshType;
  612. shflags:=AshFlags;
  613. shentsize:=Aentsize;
  614. end;
  615. const
  616. relsec_prefix:array[boolean] of string[5] = ('.rel','.rela');
  617. relsec_shtype:array[boolean] of longword = (SHT_REL,SHT_RELA);
  618. constructor TElfObjSection.create_reloc(aobjdata:TObjData;const Aname:string;allocflag:boolean);
  619. begin
  620. create_ext(aobjdata,
  621. relsec_prefix[ElfTarget.relocs_use_addend]+aname,
  622. relsec_shtype[ElfTarget.relocs_use_addend],
  623. SHF_ALLOC*ord(allocflag),
  624. sizeof(pint),
  625. (2+ord(ElfTarget.relocs_use_addend))*sizeof(pint));
  626. end;
  627. procedure TElfObjSection.writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
  628. var
  629. reloc: TObjRelocation;
  630. begin
  631. reloc:=TObjRelocation.CreateSection(Size,aTarget,reltype);
  632. reloc.size:=len;
  633. ObjRelocations.Add(reloc);
  634. if reltype=RELOC_RELATIVE then
  635. { ARM does not require this adjustment, other CPUs must be checked }
  636. {$if defined(i386) or defined(x86_64)}
  637. dec(offset,len)
  638. {$endif i386 or x86_64}
  639. else if reltype<>RELOC_ABSOLUTE then
  640. InternalError(2012062401);
  641. if ElfTarget.relocs_use_addend then
  642. begin
  643. reloc.orgsize:=offset;
  644. offset:=0;
  645. end;
  646. write(offset,len);
  647. end;
  648. {****************************************************************************
  649. TElfObjData
  650. ****************************************************************************}
  651. constructor TElfObjData.create(const n:string);
  652. begin
  653. inherited create(n);
  654. CObjSection:=TElfObjSection;
  655. end;
  656. function TElfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  657. const
  658. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  659. { TODO: sec_rodata is still writable }
  660. '.text','.data','.data','.rodata','.bss','.threadvar',
  661. '.pdata',
  662. '.text', { darwin stubs }
  663. '__DATA,__nl_symbol_ptr',
  664. '__DATA,__la_symbol_ptr',
  665. '__DATA,__mod_init_func',
  666. '__DATA,__mod_term_func',
  667. '.stab','.stabstr',
  668. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  669. '.eh_frame',
  670. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  671. '.fpc',
  672. '.toc',
  673. '.init',
  674. '.fini',
  675. '.objc_class',
  676. '.objc_meta_class',
  677. '.objc_cat_cls_meth',
  678. '.objc_cat_inst_meth',
  679. '.objc_protocol',
  680. '.objc_string_object',
  681. '.objc_cls_meth',
  682. '.objc_inst_meth',
  683. '.objc_cls_refs',
  684. '.objc_message_refs',
  685. '.objc_symbols',
  686. '.objc_category',
  687. '.objc_class_vars',
  688. '.objc_instance_vars',
  689. '.objc_module_info',
  690. '.objc_class_names',
  691. '.objc_meth_var_types',
  692. '.objc_meth_var_names',
  693. '.objc_selector_strs',
  694. '.objc_protocol_ext',
  695. '.objc_class_ext',
  696. '.objc_property',
  697. '.objc_image_info',
  698. '.objc_cstring_object',
  699. '.objc_sel_fixup',
  700. '__DATA,__objc_data',
  701. '__DATA,__objc_const',
  702. '.objc_superrefs',
  703. '__DATA, __datacoal_nt,coalesced',
  704. '.objc_classlist',
  705. '.objc_nlclasslist',
  706. '.objc_catlist',
  707. '.obcj_nlcatlist',
  708. '.objc_protolist',
  709. '.stack',
  710. '.heap'
  711. );
  712. var
  713. sep : string[3];
  714. secname : string;
  715. begin
  716. { section type user gives the user full controll on the section name }
  717. if atype=sec_user then
  718. result:=aname
  719. else
  720. begin
  721. secname:=secnames[atype];
  722. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  723. begin
  724. result:=secname+'.'+aname;
  725. exit;
  726. end;
  727. if create_smartlink_sections and (aname<>'') then
  728. begin
  729. case aorder of
  730. secorder_begin :
  731. sep:='.b_';
  732. secorder_end :
  733. sep:='.z_';
  734. else
  735. sep:='.n_';
  736. end;
  737. result:=secname+sep+aname
  738. end
  739. else
  740. result:=secname;
  741. end;
  742. end;
  743. procedure TElfObjData.CreateDebugSections;
  744. begin
  745. if target_dbg.id=dbg_stabs then
  746. begin
  747. stabssec:=createsection(sec_stab);
  748. stabstrsec:=createsection(sec_stabstr);
  749. end;
  750. end;
  751. procedure TElfObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);
  752. var
  753. symaddr : aint;
  754. objreloc: TObjRelocation;
  755. begin
  756. if CurrObjSec=nil then
  757. internalerror(200403292);
  758. objreloc:=nil;
  759. if assigned(p) then
  760. begin
  761. { real address of the symbol }
  762. symaddr:=p.address;
  763. { Local ObjSymbols can be resolved already or need a section reloc }
  764. if (p.bind=AB_LOCAL) and
  765. (reltype in [RELOC_RELATIVE,RELOC_ABSOLUTE{$ifdef x86_64},RELOC_ABSOLUTE32{$endif x86_64}]) then
  766. begin
  767. { For a reltype relocation in the same section the
  768. value can be calculated }
  769. if (p.objsection=CurrObjSec) and
  770. (reltype=RELOC_RELATIVE) then
  771. inc(data,symaddr-len-CurrObjSec.Size)
  772. else
  773. begin
  774. objreloc:=TObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,reltype);
  775. CurrObjSec.ObjRelocations.Add(objreloc);
  776. inc(data,symaddr);
  777. end;
  778. end
  779. else
  780. begin
  781. objreloc:=TObjRelocation.CreateSymbol(CurrObjSec.Size,p,reltype);
  782. CurrObjSec.ObjRelocations.Add(objreloc);
  783. { If target is a local label and it isn't handled above,
  784. patch its type in order to get it written to symtable.
  785. This may happen e.g. when taking address of Pascal label in PIC mode. }
  786. if (p.bind=AB_LOCAL) and (p.typ=AT_LABEL) then
  787. p.typ:=AT_ADDR;
  788. end;
  789. end;
  790. if assigned(objreloc) then
  791. begin
  792. objreloc.size:=len;
  793. if reltype in [RELOC_RELATIVE{$ifdef x86},RELOC_PLT32{$endif}{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then
  794. dec(data,len);
  795. if ElfTarget.relocs_use_addend then
  796. begin
  797. objreloc.orgsize:=aword(data);
  798. data:=0;
  799. end;
  800. end;
  801. CurrObjSec.write(data,len);
  802. end;
  803. {****************************************************************************
  804. TElfDynamicObjData
  805. ****************************************************************************}
  806. constructor TElfDynamicObjData.create(const n:string);
  807. begin
  808. inherited Create(n);
  809. FVersionDefs:=TFPHashObjectList.create(true);
  810. { Default symversions with indices 0 and 1 }
  811. TElfVersionDef.create(FVersionDefs,'*local*');
  812. TElfVersionDef.create(FVersionDefs,'*global*');
  813. end;
  814. destructor TElfDynamicObjData.destroy;
  815. begin
  816. FVersionDefs.free;
  817. inherited Destroy;
  818. end;
  819. {****************************************************************************
  820. TElfSymtab
  821. ****************************************************************************}
  822. const
  823. symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym');
  824. strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr');
  825. symsectypes: array[boolean] of longword = (SHT_SYMTAB,SHT_DYNSYM);
  826. symsecattrs: array[boolean] of longword = (0,SHF_ALLOC);
  827. constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind);
  828. var
  829. dyn:boolean;
  830. begin
  831. dyn:=(aKind=esk_dyn);
  832. create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],sizeof(pint),sizeof(TElfSymbol));
  833. fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],1,0);
  834. fstrsec.writezeros(1);
  835. writezeros(sizeof(TElfSymbol));
  836. symidx:=1;
  837. shinfo:=1;
  838. kind:=aKind;
  839. end;
  840. procedure TElfSymtab.writeInternalSymbol(avalue:aword;astridx:longword;ainfo:byte;ashndx:word);
  841. var
  842. elfsym:TElfSymbol;
  843. begin
  844. fillchar(elfsym,sizeof(elfsym),0);
  845. elfsym.st_value:=avalue;
  846. elfsym.st_name:=astridx;
  847. elfsym.st_info:=ainfo;
  848. elfsym.st_shndx:=ashndx;
  849. inc(symidx);
  850. inc(shinfo);
  851. MaybeSwapElfSymbol(elfsym);
  852. write(elfsym,sizeof(elfsym));
  853. end;
  854. procedure TElfSymtab.writeSymbol(objsym:TObjSymbol;nameidx:longword);
  855. var
  856. elfsym:TElfSymbol;
  857. begin
  858. fillchar(elfsym,sizeof(elfsym),0);
  859. if nameidx=0 then
  860. elfsym.st_name:=fstrsec.writestr(objsym.name)
  861. else
  862. elfsym.st_name:=nameidx;
  863. elfsym.st_size:=objsym.size;
  864. elfsym.st_value:=objsym.address;
  865. {$ifdef ARM}
  866. if (objsym.typ=AT_FUNCTION) and
  867. objsym.objsection.ThumbFunc then
  868. inc(elfsym.st_value);
  869. {$endif ARM}
  870. case objsym.bind of
  871. AB_LOCAL :
  872. begin
  873. elfsym.st_info:=STB_LOCAL shl 4;
  874. inc(shinfo);
  875. end;
  876. AB_COMMON :
  877. begin
  878. elfsym.st_value:=size_2_align(objsym.size);
  879. elfsym.st_info:=STB_GLOBAL shl 4;
  880. elfsym.st_shndx:=SHN_COMMON;
  881. end;
  882. AB_EXTERNAL :
  883. elfsym.st_info:=STB_GLOBAL shl 4;
  884. AB_WEAK_EXTERNAL :
  885. elfsym.st_info:=STB_WEAK shl 4;
  886. AB_GLOBAL :
  887. elfsym.st_info:=STB_GLOBAL shl 4;
  888. else
  889. InternalError(2012111801);
  890. end;
  891. { External symbols must be NOTYPE in relocatable files }
  892. if (objsym.bind<>AB_EXTERNAL) or (kind<>esk_obj) then
  893. begin
  894. case objsym.typ of
  895. AT_FUNCTION :
  896. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  897. AT_DATA :
  898. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  899. AT_TLS:
  900. elfsym.st_info:=elfsym.st_info or STT_TLS;
  901. AT_GNU_IFUNC:
  902. elfsym.st_info:=elfsym.st_info or STT_GNU_IFUNC;
  903. { other types are implicitly mapped to STT_NOTYPE }
  904. end;
  905. end;
  906. if objsym.bind<>AB_COMMON then
  907. begin
  908. if kind<>esk_obj then
  909. begin
  910. if assigned(objsym.objsection) and assigned(objsym.objsection.ExeSection) then
  911. begin
  912. if (objsym.typ=AT_TLS) then
  913. elfsym.st_value:=elfsym.st_value-tlsbase
  914. else if (oso_plt in objsym.objsection.SecOptions) then
  915. elfsym.st_value:=0
  916. else
  917. elfsym.st_shndx:=TElfExeSection(objsym.objsection.ExeSection).secshidx;
  918. end;
  919. end
  920. else
  921. begin
  922. if assigned(objsym.objsection) then
  923. elfsym.st_shndx:=objsym.objsection.index
  924. else
  925. elfsym.st_shndx:=SHN_UNDEF;
  926. objsym.symidx:=symidx;
  927. end;
  928. end;
  929. inc(symidx);
  930. MaybeSwapElfSymbol(elfsym);
  931. write(elfsym,sizeof(TElfSymbol));
  932. end;
  933. {****************************************************************************
  934. TElfObjectOutput
  935. ****************************************************************************}
  936. constructor TElfObjectOutput.create(AWriter:TObjectWriter);
  937. begin
  938. inherited Create(AWriter);
  939. CObjData:=TElfObjData;
  940. end;
  941. procedure TElfObjectOutput.createrelocsection(s:TElfObjSection;data:TObjData);
  942. var
  943. i : longint;
  944. rel : telfreloc;
  945. objreloc : TObjRelocation;
  946. relsym : longint;
  947. relocsect : TElfObjSection;
  948. begin
  949. { create the reloc section }
  950. relocsect:=TElfObjSection.create_reloc(data,s.name,false);
  951. relocsect.shlink:=symtabsect.index;
  952. relocsect.shinfo:=s.index;
  953. { add the relocations }
  954. for i:=0 to s.Objrelocations.count-1 do
  955. begin
  956. objreloc:=TObjRelocation(s.Objrelocations[i]);
  957. { Symbol }
  958. if assigned(objreloc.symbol) then
  959. begin
  960. if objreloc.symbol.symidx=-1 then
  961. begin
  962. writeln(objreloc.symbol.Name);
  963. internalerror(200603012);
  964. end;
  965. relsym:=objreloc.symbol.symidx;
  966. end
  967. else
  968. begin
  969. if objreloc.objsection<>nil then
  970. relsym:=objreloc.objsection.secsymidx
  971. else
  972. relsym:=SHN_UNDEF;
  973. end;
  974. rel.address:=objreloc.dataoffset;
  975. rel.info:=ELF_R_INFO(relsym,ElfTarget.encodereloc(objreloc));
  976. {$push}{$r-}
  977. rel.addend:=objreloc.orgsize;
  978. {$pop}
  979. { write reloc }
  980. { ElfXX_Rel is essentially ElfXX_Rela without the addend field. }
  981. MaybeSwapElfReloc(rel);
  982. relocsect.write(rel,relocsect.shentsize);
  983. end;
  984. end;
  985. procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
  986. begin
  987. { Must not write symbols for internal sections like .symtab }
  988. { TODO: maybe use inclusive list of section types instead }
  989. if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
  990. exit;
  991. TObjSection(p).secsymidx:=symtabsect.symidx;
  992. symtabsect.writeInternalSymbol(0,0,STT_SECTION,TObjSection(p).index);
  993. end;
  994. procedure TElfObjectOutput.createsymtab(data: TObjData);
  995. var
  996. i : longint;
  997. objsym : TObjSymbol;
  998. begin
  999. with data do
  1000. begin
  1001. { section symbols }
  1002. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1003. { First the Local Symbols, this is required by ELF. The localsyms
  1004. count stored in shinfo is used to skip the local symbols
  1005. when traversing the symtab }
  1006. for i:=0 to ObjSymbolList.Count-1 do
  1007. begin
  1008. objsym:=TObjSymbol(ObjSymbolList[i]);
  1009. if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
  1010. symtabsect.WriteSymbol(objsym);
  1011. end;
  1012. { Global Symbols }
  1013. for i:=0 to ObjSymbolList.Count-1 do
  1014. begin
  1015. objsym:=TObjSymbol(ObjSymbolList[i]);
  1016. if (objsym.bind<>AB_LOCAL) then
  1017. symtabsect.WriteSymbol(objsym);
  1018. end;
  1019. { update the .symtab section header }
  1020. symtabsect.shlink:=symtabsect.fstrsec.index;
  1021. end;
  1022. end;
  1023. procedure TElfObjectOutput.createshstrtab(data: TObjData);
  1024. var
  1025. i,prefixlen:longint;
  1026. objsec,target:TElfObjSection;
  1027. begin
  1028. shstrtabsect.writezeros(1);
  1029. prefixlen:=length('.rel')+ord(ElfTarget.relocs_use_addend);
  1030. for i:=0 to data.ObjSectionList.Count-1 do
  1031. begin
  1032. objsec:=TElfObjSection(data.ObjSectionList[i]);
  1033. { Alias section names into names of corresponding reloc sections,
  1034. this is allowed by ELF specs and saves good half of .shstrtab space. }
  1035. if objsec.shtype=relsec_shtype[ElfTarget.relocs_use_addend] then
  1036. begin
  1037. target:=TElfObjSection(data.ObjSectionList[objsec.shinfo-1]);
  1038. if (target.ObjRelocations.Count=0) or
  1039. (target.shstridx<prefixlen) then
  1040. InternalError(2012101204);
  1041. objsec.shstridx:=target.shstridx-prefixlen;
  1042. end
  1043. else
  1044. begin
  1045. if objsec.ObjRelocations.Count<>0 then
  1046. shstrtabsect.write(relsec_prefix[true][1],prefixlen);
  1047. objsec.shstridx:=shstrtabsect.writestr(objsec.name);
  1048. end;
  1049. end;
  1050. end;
  1051. procedure TElfObjectOutput.writesectionheader(s:TElfObjSection);
  1052. var
  1053. sechdr : telfsechdr;
  1054. begin
  1055. fillchar(sechdr,sizeof(sechdr),0);
  1056. sechdr.sh_name:=s.shstridx;
  1057. sechdr.sh_type:=s.shtype;
  1058. sechdr.sh_flags:=s.shflags;
  1059. sechdr.sh_offset:=s.datapos;
  1060. sechdr.sh_size:=s.Size;
  1061. sechdr.sh_link:=s.shlink;
  1062. sechdr.sh_info:=s.shinfo;
  1063. sechdr.sh_addralign:=s.secalign;
  1064. sechdr.sh_entsize:=s.shentsize;
  1065. MaybeSwapSecHeader(sechdr);
  1066. writer.write(sechdr,sizeof(sechdr));
  1067. end;
  1068. procedure TElfObjectOutput.section_count_sections(p:TObject;arg:pointer);
  1069. begin
  1070. TElfObjSection(p).index:=pword(arg)^;
  1071. inc(pword(arg)^);
  1072. end;
  1073. procedure TElfObjectOutput.section_create_relocsec(p:TObject;arg:pointer);
  1074. begin
  1075. if (TElfObjSection(p).ObjRelocations.count>0) then
  1076. createrelocsection(TElfObjSection(p),TObjData(arg));
  1077. end;
  1078. procedure TElfObjectOutput.section_write_sechdr(p:TObject;arg:pointer);
  1079. begin
  1080. writesectionheader(TElfObjSection(p));
  1081. end;
  1082. function TElfObjectOutput.writedata(data:TObjData):boolean;
  1083. var
  1084. header : telfheader;
  1085. shoffset,
  1086. datapos : aword;
  1087. nsections : word;
  1088. begin
  1089. result:=false;
  1090. with data do
  1091. begin
  1092. { default sections }
  1093. symtabsect:=TElfSymtab.create(data,esk_obj);
  1094. shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,1,0);
  1095. { "no executable stack" marker }
  1096. { TODO: used by OpenBSD/NetBSD as well? }
  1097. if (target_info.system in (systems_linux + systems_android + systems_freebsd + systems_dragonfly)) and
  1098. not(cs_executable_stack in current_settings.moduleswitches) then
  1099. TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,1,0);
  1100. { symbol for filename }
  1101. symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
  1102. symtabsect.writeInternalSymbol(0,1,STT_FILE,SHN_ABS);
  1103. { calc amount of sections we have }
  1104. nsections:=1;
  1105. { also create the index in the section header table }
  1106. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1107. { create .symtab and .strtab }
  1108. createsymtab(data);
  1109. { Create the relocation sections, this needs valid secidx and symidx }
  1110. ObjSectionList.ForEachCall(@section_create_relocsec,data);
  1111. { recalc nsections to incude the reloc sections }
  1112. nsections:=1;
  1113. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1114. { create .shstrtab }
  1115. createshstrtab(data);
  1116. { Calculate the filepositions }
  1117. datapos:=$40; { elfheader + alignment }
  1118. { section data }
  1119. layoutsections(datapos);
  1120. { section headers }
  1121. shoffset:=datapos;
  1122. inc(datapos,(nsections+1)*sizeof(telfsechdr));
  1123. { Write ELF Header }
  1124. fillchar(header,sizeof(header),0);
  1125. header.e_ident[EI_MAG0]:=ELFMAG0; { = #127'ELF' }
  1126. header.e_ident[EI_MAG1]:=ELFMAG1;
  1127. header.e_ident[EI_MAG2]:=ELFMAG2;
  1128. header.e_ident[EI_MAG3]:=ELFMAG3;
  1129. header.e_ident[EI_CLASS]:=ELFCLASS;
  1130. if target_info.endian=endian_big then
  1131. header.e_ident[EI_DATA]:=ELFDATA2MSB
  1132. else
  1133. header.e_ident[EI_DATA]:=ELFDATA2LSB;
  1134. header.e_ident[EI_VERSION]:=1;
  1135. if target_info.system in systems_openbsd then
  1136. header.e_ident[EI_OSABI]:=ELFOSABI_OPENBSD
  1137. else if target_info.system in systems_freebsd then
  1138. header.e_ident[EI_OSABI]:=ELFOSABI_FREEBSD
  1139. else if target_info.system in systems_dragonfly then
  1140. header.e_ident[EI_OSABI]:=ELFOSABI_NONE;
  1141. header.e_type:=ET_REL;
  1142. header.e_machine:=ElfTarget.machine_code;
  1143. header.e_version:=1;
  1144. header.e_shoff:=shoffset;
  1145. header.e_shstrndx:=shstrtabsect.index;
  1146. header.e_shnum:=nsections;
  1147. header.e_ehsize:=sizeof(telfheader);
  1148. header.e_shentsize:=sizeof(telfsechdr);
  1149. if assigned(ElfTarget.encodeflags) then
  1150. header.e_flags:=ElfTarget.encodeflags();
  1151. MaybeSwapHeader(header);
  1152. writer.write(header,sizeof(header));
  1153. writer.writezeros($40-sizeof(header)); { align }
  1154. { Sections }
  1155. WriteSectionContent(data);
  1156. { section headers, start with an empty header for sh_undef }
  1157. writer.writezeros(sizeof(telfsechdr));
  1158. ObjSectionList.ForEachCall(@section_write_sechdr,nil);
  1159. end;
  1160. result:=true;
  1161. end;
  1162. {****************************************************************************
  1163. TELFAssembler
  1164. ****************************************************************************}
  1165. constructor TElfAssembler.Create(smart:boolean);
  1166. begin
  1167. inherited Create(smart);
  1168. CObjOutput:=TElfObjectOutput;
  1169. end;
  1170. {****************************************************************************
  1171. TELFObjectInput
  1172. ****************************************************************************}
  1173. constructor TElfObjInput.Create;
  1174. begin
  1175. inherited Create;
  1176. CObjData:=TElfObjData;
  1177. CObjSymbol:=TObjSymbol;
  1178. end;
  1179. destructor TElfObjInput.Destroy;
  1180. begin
  1181. if Assigned(FSymTbl) then
  1182. FreeMem(FSymTbl);
  1183. if Assigned(FSecTbl) then
  1184. FreeMem(FSecTbl);
  1185. if Assigned(strtab) then
  1186. FreeMem(strtab);
  1187. if Assigned(shstrtab) then
  1188. FreeMem(shstrtab);
  1189. if Assigned(symversions) then
  1190. FreeMem(symversions);
  1191. inherited Destroy;
  1192. end;
  1193. procedure TElfObjInput.LoadRelocations(const secrec:TSectionRec);
  1194. var
  1195. i: longint;
  1196. rel: TElfReloc;
  1197. reltyp: byte;
  1198. relsym: longint;
  1199. objrel: TObjRelocation;
  1200. p: TObjSymbol;
  1201. begin
  1202. FReader.Seek(secrec.relocpos);
  1203. if secrec.sec=nil then
  1204. InternalError(2012060203);
  1205. if (secrec.relentsize=3*sizeof(pint)) then
  1206. with secrec.sec do SecOptions:=SecOptions+[oso_rela_relocs];
  1207. for i:=0 to secrec.relocs-1 do
  1208. begin
  1209. FReader.Read(rel,secrec.relentsize);
  1210. MaybeSwapElfReloc(rel);
  1211. reltyp:=rel.info and $FF;
  1212. {$ifdef cpu64bitaddr}
  1213. relsym:=rel.info shr 32;
  1214. {$else cpu64bitaddr}
  1215. relsym:=(rel.info shr 8) and $FFFFFF;
  1216. {$endif cpu64bitaddr}
  1217. if relsym>=syms then
  1218. InternalError(2012060204);
  1219. p:=TObjSymbol(FSymTbl[relsym]);
  1220. { Some relocations (e.g. R_ARM_V4BX) don't use a symbol at all }
  1221. if assigned(p) or (relsym=0) then
  1222. begin
  1223. objrel:=TObjRelocation.CreateRaw(rel.address-secrec.sec.mempos,p,reltyp);
  1224. if (secrec.relentsize=3*sizeof(pint)) then
  1225. objrel.orgsize:=rel.addend;
  1226. { perform target-specific actions }
  1227. if Assigned(ElfTarget.loadreloc) then
  1228. ElfTarget.loadreloc(objrel);
  1229. secrec.sec.ObjRelocations.add(objrel);
  1230. end
  1231. else
  1232. begin
  1233. InputError('Unable to resolve symbol of relocation');
  1234. exit;
  1235. end;
  1236. end;
  1237. end;
  1238. procedure TElfObjInput.LoadSymbols(objdata:TObjData;count,locals:longword);
  1239. var
  1240. i: longint;
  1241. sym: TElfSymbol;
  1242. bind: TAsmSymBind;
  1243. typ: TAsmSymType;
  1244. objsym: TObjSymbol;
  1245. ver: word;
  1246. begin
  1247. FSymTbl:=AllocMem(count*sizeof(Pointer));
  1248. for i:=1 to count-1 do
  1249. begin
  1250. FReader.Read(sym,sizeof(TElfSymbol));
  1251. MaybeSwapElfSymbol(sym);
  1252. if sym.st_name>=strtablen then
  1253. InternalError(2012060205);
  1254. if sym.st_shndx=SHN_ABS then { ignore absolute symbols (should we really do it???) }
  1255. Continue
  1256. else if sym.st_shndx=SHN_COMMON then
  1257. bind:=AB_COMMON
  1258. else if (sym.st_shndx>=nsects) then
  1259. InternalError(2012060206)
  1260. else
  1261. case (sym.st_info shr 4) of
  1262. STB_LOCAL:
  1263. bind:=AB_LOCAL;
  1264. STB_GLOBAL:
  1265. if sym.st_shndx=SHN_UNDEF then
  1266. bind:=AB_EXTERNAL
  1267. else
  1268. bind:=AB_GLOBAL;
  1269. STB_WEAK:
  1270. bind:=AB_WEAK_EXTERNAL;
  1271. else
  1272. InternalError(2012060207);
  1273. end;
  1274. { Ignore section symbol if we didn't create the corresponding objsection
  1275. (examples are SHT_GROUP or .note.GNU-stack sections). }
  1276. if (sym.st_shndx>0) and (sym.st_shndx<SHN_LORESERVE) and
  1277. (FSecTbl[sym.st_shndx].sec=nil) and
  1278. (not dynobj) then
  1279. if ((sym.st_info and $0F)=STT_SECTION) then
  1280. Continue
  1281. else
  1282. begin
  1283. writeln(objdata.name,' ',i);
  1284. InternalError(2012110701)
  1285. end;
  1286. case (sym.st_info and $0F) of
  1287. STT_NOTYPE:
  1288. typ:=AT_NONE;
  1289. STT_OBJECT:
  1290. typ:=AT_DATA;
  1291. STT_FUNC:
  1292. typ:=AT_FUNCTION;
  1293. STT_SECTION:
  1294. typ:=AT_SECTION;
  1295. STT_FILE:
  1296. continue;
  1297. STT_TLS:
  1298. typ:=AT_TLS;
  1299. STT_GNU_IFUNC:
  1300. typ:=AT_GNU_IFUNC;
  1301. else
  1302. writeln(objdata.name,' ',sym.st_info and $0F);
  1303. InternalError(2012060208);
  1304. end;
  1305. { If reading DSO, we're interested only in global symbols defined there.
  1306. Symbols with non-current version should also be ignored. }
  1307. ver:=0;
  1308. if dynobj then
  1309. begin
  1310. if assigned(symversions) then
  1311. begin
  1312. ver:=symversions[i];
  1313. if (ver=VER_NDX_LOCAL) or (ver>VERSYM_VERSION) then
  1314. continue;
  1315. end;
  1316. if (bind=AB_LOCAL) or (sym.st_shndx=SHN_UNDEF) then
  1317. continue;
  1318. if ver>=verdefs.count then
  1319. InternalError(2012120505);
  1320. end;
  1321. { validity of name and objsection has been checked above }
  1322. { !! all AT_SECTION symbols have duplicate (null) name,
  1323. therefore TObjSection.CreateSymbol cannot be used here }
  1324. objsym:=CObjSymbol.Create(objdata.ObjSymbolList,string(PChar(@strtab[sym.st_name])));
  1325. objsym.bind:=bind;
  1326. objsym.typ:=typ;
  1327. if bind<>AB_COMMON then
  1328. objsym.objsection:=FSecTbl[sym.st_shndx].sec;
  1329. objsym.offset:=sym.st_value;
  1330. objsym.size:=sym.st_size;
  1331. FSymTbl[i]:=objsym;
  1332. if (ver>VER_NDX_GLOBAL) then
  1333. TVersionedObjSymbol(objsym).version:=TElfVersionDef(verdefs[ver]);
  1334. end;
  1335. end;
  1336. function TElfObjInput.CreateSection(const shdr:TElfsechdr;index:longint;objdata:tobjdata;
  1337. out secname:string):TElfObjSection;
  1338. begin
  1339. secname:=string(PChar(@shstrtab[shdr.sh_name]));
  1340. result:=TElfObjSection.create_ext(objdata,secname,
  1341. shdr.sh_type,shdr.sh_flags,shdr.sh_addralign,shdr.sh_entsize);
  1342. result.index:=index;
  1343. result.DataPos:=shdr.sh_offset;
  1344. result.MemPos:=shdr.sh_addr;
  1345. result.Size:=shdr.sh_size;
  1346. FSecTbl[index].sec:=result;
  1347. end;
  1348. function TElfObjInput.ReadBytes(offs:longint;out buf;len:longint):boolean;
  1349. begin
  1350. FReader.Seek(offs);
  1351. result:=FReader.Read(buf,len);
  1352. end;
  1353. procedure TElfObjInput.LoadSection(const shdr:TElfsechdr;index:longint;objdata:tobjdata);
  1354. var
  1355. sec: TElfObjSection;
  1356. sym: TElfSymbol;
  1357. secname: string;
  1358. begin
  1359. if shdr.sh_name>=shstrtablen then
  1360. InternalError(2012060210);
  1361. case shdr.sh_type of
  1362. SHT_NULL:
  1363. {ignore};
  1364. { SHT_STRTAB may appear for .stabstr and other debug sections.
  1365. .shstrtab and .strtab are processed separately and don't appear here. }
  1366. SHT_PROGBITS,SHT_NOBITS,SHT_NOTE,SHT_STRTAB,
  1367. SHT_INIT_ARRAY,SHT_FINI_ARRAY,SHT_PREINIT_ARRAY:
  1368. begin
  1369. sec:=CreateSection(shdr,index,objdata,secname);
  1370. if (Length(secname)>3) and (secname[2] in ['d','f','n','s']) then
  1371. begin
  1372. if (Pos('.stub',secname)=1) or
  1373. (Pos('.fpc',secname)=1) then
  1374. sec.SecOptions:=[oso_keep]
  1375. { ELF does not have any flags specific to debug sections,
  1376. but reserves names starting with '.debug' for this purpose }
  1377. else if (Pos('.debug',secname)=1) or
  1378. (secname='.stab') or
  1379. (secname='.stabstr') then
  1380. sec.SecOptions:=[oso_debug]
  1381. else if (secname='.note.GNU-stack') and (shdr.sh_type=SHT_PROGBITS) then
  1382. begin
  1383. if (shdr.sh_flags and SHF_EXECINSTR)=0 then
  1384. objdata.ExecStack:=False;
  1385. end;
  1386. end;
  1387. if (shdr.sh_type=SHT_NOTE) and (shdr.sh_size<>0) then
  1388. sec.SecOptions:=[oso_keep];
  1389. end;
  1390. SHT_REL,SHT_RELA:
  1391. begin
  1392. if shdr.sh_info>=nsects then
  1393. InternalError(2012060211);
  1394. if shdr.sh_entsize<>longword((2+ord(shdr.sh_type=SHT_RELA))*sizeof(pint)) then
  1395. InternalError(2012060212);
  1396. with FSecTbl[shdr.sh_info] do
  1397. begin
  1398. relocpos:=shdr.sh_offset;
  1399. relocs:=shdr.sh_size div shdr.sh_entsize;
  1400. relentsize:=shdr.sh_entsize;
  1401. end;
  1402. end;
  1403. SHT_GROUP:
  1404. if (shdr.sh_size>=2*sizeof(longword)) and
  1405. (shdr.sh_entsize=sizeof(longword)) and
  1406. ((shdr.sh_size mod shdr.sh_entsize)=0) then
  1407. begin
  1408. { Groups are identified by name of symbol pointed to by
  1409. sh_link and sh_info, not by sh_name. This symbol
  1410. may as well be STT_SECTION symbol of this section,
  1411. in which case we end up using sh_name. }
  1412. if dynobj then
  1413. InternalError(2012110801);
  1414. if (shdr.sh_link<>symtabndx) then
  1415. InternalError(2012110703);
  1416. if (shdr.sh_info>=syms) then
  1417. InternalError(2012110704);
  1418. FReader.Seek(symtaboffset+shdr.sh_info*sizeof(TElfSymbol));
  1419. FReader.Read(sym,sizeof(TElfSymbol));
  1420. MaybeSwapElfSymbol(sym);
  1421. if sym.st_name>=strtablen then
  1422. InternalError(2012110705);
  1423. if (sym.st_shndx=index) and (sym.st_info=((STB_LOCAL shl 4) or STT_SECTION)) then
  1424. secname:=string(PChar(@shstrtab[shdr.sh_name]))
  1425. else
  1426. secname:=string(PChar(@strtab[sym.st_name]));
  1427. { Postpone further processing until all sections are loaded,
  1428. we'll need to access correct section header.
  1429. Since ABI requires SHT_GROUP sections to come first in the file,
  1430. we assume that group number x has header index x+1.
  1431. If we ever encounter files where this is not true, we'll have
  1432. to maintain a separate index. }
  1433. objdata.CreateSectionGroup(secname);
  1434. if (index<>objdata.GroupsList.Count) then
  1435. InternalError(2012110802);
  1436. end
  1437. else
  1438. InternalError(2012110706);
  1439. SHT_GNU_ATTRIBUTES:
  1440. { TODO: must not be ignored };
  1441. else
  1442. if not (assigned(ElfTarget.loadsection) and
  1443. ElfTarget.loadsection(self,objdata,shdr,index)) then
  1444. InternalError(2012072603);
  1445. end;
  1446. FLoaded[index]:=True;
  1447. end;
  1448. function TElfObjInput.LoadHeader(out objdata:TObjData):boolean;
  1449. var
  1450. header:TElfHeader;
  1451. begin
  1452. result:=false;
  1453. if not FReader.read(header,sizeof(header)) then
  1454. begin
  1455. InputError('Can''t read ELF header');
  1456. exit;
  1457. end;
  1458. if (header.e_ident[EI_MAG0]<>ELFMAG0) or (header.e_ident[EI_MAG1]<>ELFMAG1) or
  1459. (header.e_ident[EI_MAG2]<>ELFMAG2) or (header.e_ident[EI_MAG3]<>ELFMAG3) then
  1460. begin
  1461. InputError('Illegal ELF magic');
  1462. exit;
  1463. end;
  1464. if (header.e_ident[EI_VERSION]<>1) then
  1465. begin
  1466. InputError('Unknown ELF file version');
  1467. exit;
  1468. end;
  1469. if (header.e_ident[EI_CLASS]<>ELFCLASS) then
  1470. begin
  1471. InputError('Wrong ELF file class (32/64 bit mismatch)');
  1472. exit;
  1473. end;
  1474. if (header.e_ident[EI_DATA]<>1+ord(target_info.endian=endian_big)) then
  1475. begin
  1476. InputError('ELF endianness does not match target');
  1477. exit;
  1478. end;
  1479. MaybeSwapHeader(header);
  1480. if (header.e_version<>1) then
  1481. begin
  1482. InputError('Unknown ELF data version');
  1483. exit;
  1484. end;
  1485. if (header.e_machine<>ElfTarget.machine_code) then
  1486. begin
  1487. InputError('ELF file is for different CPU');
  1488. exit;
  1489. end;
  1490. if (header.e_type<>ET_REL) and (header.e_type<>ET_DYN) then
  1491. begin
  1492. InputError('Not a relocatable or dynamic ELF file');
  1493. exit;
  1494. end;
  1495. if header.e_shentsize<>sizeof(TElfsechdr) then
  1496. InternalError(2012062701);
  1497. nsects:=header.e_shnum;
  1498. dynobj:=(header.e_type=ET_DYN);
  1499. shoffset:=header.e_shoff;
  1500. shstrndx:=header.e_shstrndx;
  1501. if dynobj then
  1502. begin
  1503. objdata:=TElfDynamicObjData.Create(InputFilename);
  1504. verdefs:=TElfDynamicObjData(objdata).versiondefs;
  1505. CObjSymbol:=TVersionedObjSymbol;
  1506. end
  1507. else
  1508. objdata:=CObjData.Create(InputFilename);
  1509. TElfObjData(objdata).ident:=header.e_ident;
  1510. TElfObjData(objdata).flags:=header.e_flags;
  1511. result:=true;
  1512. end;
  1513. procedure TElfObjInput.LoadDynamic(const shdr:TElfsechdr;objdata:TObjData);
  1514. var
  1515. dt: TElfDyn;
  1516. i: longint;
  1517. begin
  1518. if (shdr.sh_entsize<>sizeof(TElfDyn)) then
  1519. InternalError(2012071403);
  1520. FReader.Seek(shdr.sh_offset);
  1521. for i:=0 to (shdr.sh_size div shdr.sh_entsize)-1 do
  1522. begin
  1523. FReader.Read(dt,sizeof(TElfDyn));
  1524. MaybeSwapElfDyn(dt);
  1525. case dt.d_tag of
  1526. DT_NULL:
  1527. break;
  1528. DT_SONAME:
  1529. TElfObjData(objdata).FName:=string(PChar(@strtab[dt.d_ptr]));
  1530. DT_NEEDED:
  1531. ;
  1532. end;
  1533. end;
  1534. end;
  1535. function TElfObjInput.ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;
  1536. var
  1537. i,j,strndx,dynndx,
  1538. versymndx,verdefndx,verneedndx: longint;
  1539. objsec: TObjSection;
  1540. grp: TObjSectionGroup;
  1541. tmp: longword;
  1542. count: longint;
  1543. vd: TElfverdef;
  1544. vda: TElfverdaux;
  1545. vdoffset: aword;
  1546. begin
  1547. FReader:=AReader;
  1548. InputFileName:=AReader.FileName;
  1549. result:=false;
  1550. strndx:=0;
  1551. if not LoadHeader(objData) then
  1552. exit;
  1553. FSecTbl:=AllocMem(nsects*sizeof(TSectionRec));
  1554. FLoaded:=AllocMem(nsects*sizeof(boolean));
  1555. SetLength(shdrs,nsects);
  1556. FReader.Seek(shoffset);
  1557. if not FReader.Read(shdrs[0],nsects*sizeof(TElfsechdr)) then
  1558. begin
  1559. InputError('Can''t read ELF section headers');
  1560. exit;
  1561. end;
  1562. if source_info.endian<>target_info.endian then
  1563. for i:=0 to nsects-1 do
  1564. MaybeSwapSecHeader(shdrs[i]);
  1565. { First, load the .shstrtab section }
  1566. if shstrndx>=nsects then
  1567. InternalError(2012060201);
  1568. if shdrs[shstrndx].sh_type<>SHT_STRTAB then
  1569. InternalError(2012060202);
  1570. shstrtablen:=shdrs[shstrndx].sh_size;
  1571. GetMem(shstrtab,shstrtablen);
  1572. FReader.seek(shdrs[shstrndx].sh_offset);
  1573. FReader.read(shstrtab^,shstrtablen);
  1574. FLoaded[shstrndx]:=True;
  1575. { Locate the symtable, it is typically at the end so loop backwards.
  1576. Load the strings, postpone symtable itself until done with sections.
  1577. Note that is is legal to have no symtable.
  1578. For DSO, locate .dynsym instead, this one is near the beginning, but
  1579. overall number of sections won't be big. }
  1580. symtabndx:=0;
  1581. for i:=nsects-1 downto 1 do
  1582. begin
  1583. if (shdrs[i].sh_type<>symsectypes[dynobj]) then
  1584. continue;
  1585. if (shdrs[i].sh_entsize<>sizeof(TElfSymbol)) then
  1586. InternalError(2012060213);
  1587. if shdrs[i].sh_link>=nsects then
  1588. InternalError(2012062702);
  1589. strndx:=shdrs[i].sh_link;
  1590. if shdrs[strndx].sh_type<>SHT_STRTAB then
  1591. InternalError(2012062703);
  1592. strtablen:=shdrs[strndx].sh_size;
  1593. GetMem(strtab,strtablen);
  1594. FReader.seek(shdrs[strndx].sh_offset);
  1595. FReader.read(strtab^,strtablen);
  1596. symtaboffset:=shdrs[i].sh_offset;
  1597. syms:=shdrs[i].sh_size div sizeof(TElfSymbol);
  1598. localsyms:=shdrs[i].sh_info;
  1599. FLoaded[i]:=True;
  1600. FLoaded[strndx]:=True;
  1601. symtabndx:=i;
  1602. break;
  1603. end;
  1604. if dynobj then
  1605. begin
  1606. if symtabndx=0 then
  1607. InternalError(2012110707);
  1608. { Locate .dynamic and version sections. Expect a single one of a kind. }
  1609. dynndx:=0;
  1610. versymndx:=0;
  1611. verdefndx:=0;
  1612. verneedndx:=0;
  1613. for i:=nsects-1 downto 0 do
  1614. begin
  1615. case shdrs[i].sh_type of
  1616. SHT_DYNAMIC:
  1617. begin
  1618. if dynndx<>0 then
  1619. InternalError(2012102001);
  1620. dynndx:=i;
  1621. if (shdrs[dynndx].sh_link<>strndx) then
  1622. InternalError(2012071402);
  1623. LoadDynamic(shdrs[dynndx],objdata);
  1624. end;
  1625. SHT_GNU_versym:
  1626. begin
  1627. if versymndx<>0 then
  1628. InternalError(2012102002);
  1629. versymndx:=i;
  1630. if shdrs[i].sh_entsize<>sizeof(word) then
  1631. InternalError(2012102003);
  1632. if shdrs[i].sh_link<>symtabndx then
  1633. InternalError(2012102004);
  1634. if shdrs[i].sh_size<>syms*sizeof(word) then
  1635. InternalError(2012102005);
  1636. GetMem(symversions,shdrs[i].sh_size);
  1637. FReader.seek(shdrs[i].sh_offset);
  1638. FReader.read(symversions^,shdrs[i].sh_size);
  1639. if source_info.endian<>target_info.endian then
  1640. for j:=0 to syms-1 do
  1641. symversions[j]:=SwapEndian(symversions[j]);
  1642. end;
  1643. SHT_GNU_verdef:
  1644. begin
  1645. if verdefndx<>0 then
  1646. InternalError(2012102006);
  1647. verdefndx:=i;
  1648. if shdrs[i].sh_link<>strndx then
  1649. InternalError(2012120501);
  1650. vdoffset:=shdrs[i].sh_offset;
  1651. { TODO: can we rely on sh_info, or must read until vd_next=0? }
  1652. for j:=1 to shdrs[i].sh_info do
  1653. begin
  1654. FReader.seek(vdoffset);
  1655. FReader.Read(vd,sizeof(TElfverdef));
  1656. MaybeSwapElfverdef(vd);
  1657. if vd.vd_version<>VER_DEF_CURRENT then
  1658. InternalError(2012120502);
  1659. FReader.seek(vdoffset+vd.vd_aux);
  1660. vdoffset:=vdoffset+vd.vd_next;
  1661. { First verdaux entry holds name of version (unless VER_FLG_BASE flag is set),
  1662. subsequent one(s) point to parent(s). For our purposes, version hierarchy
  1663. looks irrelevant. }
  1664. FReader.Read(vda,sizeof(TElfverdaux));
  1665. MaybeSwapElfverdaux(vda);
  1666. if vda.vda_name>=strtablen then
  1667. InternalError(2012120503);
  1668. if (vd.vd_flags and VER_FLG_BASE)<>0 then
  1669. continue;
  1670. { Assuming verdef indices assigned continuously starting from 2,
  1671. at least BFD produces files that way. }
  1672. if verdefs.count<>vd.vd_ndx then
  1673. InternalError(2012120504);
  1674. TElfVersionDef.Create(verdefs,string(PChar(@strtab[vda.vda_name])));
  1675. end;
  1676. end;
  1677. SHT_GNU_verneed:
  1678. begin
  1679. if verneedndx<>0 then
  1680. InternalError(2012102007);
  1681. verneedndx:=i;
  1682. //sh_link->.dynstr
  1683. //sh_info->number of entries
  1684. end;
  1685. end;
  1686. end;
  1687. if dynndx=0 then
  1688. InternalError(2012071401);
  1689. { load the symtable }
  1690. FReader.Seek(symtaboffset+sizeof(TElfSymbol));
  1691. LoadSymbols(objdata,syms,localsyms);
  1692. result:=True;
  1693. exit;
  1694. end;
  1695. { assume stack is executable until proven otherwise }
  1696. objdata.ExecStack:=True;
  1697. { Process section headers }
  1698. for i:=1 to nsects-1 do
  1699. if not FLoaded[i] then
  1700. LoadSection(shdrs[i],i,objdata);
  1701. { load the content }
  1702. ReadSectionContent(objdata);
  1703. { load the symtable }
  1704. FReader.Seek(symtaboffset+sizeof(TElfSymbol));
  1705. LoadSymbols(objdata,syms,localsyms);
  1706. { finish relocations }
  1707. for i:=0 to objdata.ObjSectionList.Count-1 do
  1708. begin
  1709. objsec:=TObjSection(objdata.ObjsectionList[i]);
  1710. { skip debug sections }
  1711. if (oso_debug in objsec.SecOptions) and
  1712. (cs_link_strip in current_settings.globalswitches) and
  1713. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1714. continue;
  1715. if FSecTbl[objsec.index].relocpos>0 then
  1716. LoadRelocations(FSecTbl[objsec.index]);
  1717. end;
  1718. { finish processing section groups, if any }
  1719. if Assigned(objdata.GroupsList) then
  1720. begin
  1721. for i:=0 to objdata.GroupsList.Count-1 do
  1722. begin
  1723. grp:=TObjSectionGroup(objData.GroupsList[i]);
  1724. FReader.Seek(shdrs[i+1].sh_offset);
  1725. { first dword is flags }
  1726. FReader.Read(tmp,sizeof(longword));
  1727. if source_info.endian<>target_info.endian then
  1728. tmp:=SwapEndian(tmp);
  1729. if (tmp and GRP_COMDAT)<>0 then
  1730. grp.IsComdat:=true;
  1731. count:=(shdrs[i+1].sh_size div sizeof(longword))-1;
  1732. SetLength(grp.members,count);
  1733. for j:=0 to count-1 do
  1734. begin
  1735. FReader.Read(tmp,sizeof(longword));
  1736. if source_info.endian<>target_info.endian then
  1737. tmp:=SwapEndian(tmp);
  1738. if (tmp>=nsects) then
  1739. InternalError(2012110805);
  1740. objsec:=FSecTbl[tmp].sec;
  1741. if (objsec=nil) then
  1742. InternalError(2012110806);
  1743. if (TElfObjSection(objsec).shflags and SHF_GROUP)=0 then
  1744. InternalError(2012110807);
  1745. grp.members[j]:=objsec;
  1746. objsec.Group:=grp;
  1747. end;
  1748. end;
  1749. end;
  1750. result:=True;
  1751. end;
  1752. class function TElfObjInput.CanReadObjData(AReader:TObjectreader):boolean;
  1753. var
  1754. header: TElfHeader;
  1755. begin
  1756. result:=false;
  1757. if AReader.Read(header,sizeof(header)) then
  1758. begin;
  1759. if (header.e_ident[EI_MAG0]=ELFMAG0) and (header.e_ident[EI_MAG1]=ELFMAG1) and
  1760. (header.e_ident[EI_MAG2]=ELFMAG2) and (header.e_ident[EI_MAG3]=ELFMAG3) then
  1761. { TODO: check additional fields }
  1762. result:=true;
  1763. end;
  1764. AReader.Seek(0);
  1765. end;
  1766. {*****************************************************************************
  1767. TElfExeOutput
  1768. *****************************************************************************}
  1769. constructor TElfExeOutput.Create;
  1770. begin
  1771. inherited Create;
  1772. CObjData:=TElfObjData;
  1773. CExeSection:=TElfExeSection;
  1774. {$ifdef cpu64}
  1775. MaxMemPos:=Qword($FFFFFFFFFFFFFFFF);
  1776. //MaxMemPos:=$7EFFFFFF; { As specified by SysV AMD64 ABI for small memory model }
  1777. {$else cpu64}
  1778. MaxMemPos:=$7FFFFFFF;
  1779. {$endif cpu64}
  1780. SectionMemAlign:=$20;
  1781. SectionDataAlign:=$20;
  1782. segmentlist:=TFPObjectList.Create(True);
  1783. neededlist:=TFPHashList.Create;
  1784. end;
  1785. destructor TElfExeOutput.Destroy;
  1786. begin
  1787. dyncopysyms.Free;
  1788. neededlist.Free;
  1789. segmentlist.Free;
  1790. dynsymlist.Free;
  1791. dynreloclist.Free;
  1792. if assigned(dynsymnames) then
  1793. FreeMem(dynsymnames);
  1794. stringdispose(FInterpreter);
  1795. inherited Destroy;
  1796. end;
  1797. function TElfExeOutput.AttachSection(objsec:TObjSection):TElfExeSection;
  1798. begin
  1799. objsec.SecOptions:=[oso_keep];
  1800. result:=TElfExeSection(FindExeSection(objsec.name));
  1801. if result=nil then
  1802. result:=TElfExeSection.Create(ExeSectionList,objsec.name);
  1803. result.AddObjSection(objsec);
  1804. end;
  1805. function TElfExeOutput.CreateSegment(atype,aflags,aalign:longword):TElfSegment;
  1806. begin
  1807. result:=TElfSegment.Create(atype,aflags,aalign);
  1808. segmentlist.add(result);
  1809. end;
  1810. procedure TElfExeOutput.WriteHeader;
  1811. var
  1812. header: TElfHeader;
  1813. begin
  1814. FillChar(header,sizeof(header),0);
  1815. header.e_ident[EI_MAG0]:=ELFMAG0; { = #127'ELF' }
  1816. header.e_ident[EI_MAG1]:=ELFMAG1;
  1817. header.e_ident[EI_MAG2]:=ELFMAG2;
  1818. header.e_ident[EI_MAG3]:=ELFMAG3;
  1819. header.e_ident[EI_CLASS]:=ELFCLASS;
  1820. if target_info.endian=endian_big then
  1821. header.e_ident[EI_DATA]:=ELFDATA2MSB
  1822. else
  1823. header.e_ident[EI_DATA]:=ELFDATA2LSB;
  1824. header.e_ident[EI_VERSION]:=1;
  1825. if target_info.system in systems_openbsd then
  1826. header.e_ident[EI_OSABI]:=ELFOSABI_OPENBSD
  1827. else if target_info.system in systems_freebsd then
  1828. header.e_ident[EI_OSABI]:=ELFOSABI_FREEBSD
  1829. else if target_info.system in systems_dragonfly then
  1830. header.e_ident[EI_OSABI]:=ELFOSABI_NONE;
  1831. if IsSharedLibrary then
  1832. header.e_type:=ET_DYN
  1833. else
  1834. header.e_type:=ET_EXEC;
  1835. header.e_machine:=ElfTarget.machine_code;
  1836. header.e_version:=1;
  1837. header.e_phoff:=sizeof(TElfHeader);
  1838. header.e_shoff:=shoffset;
  1839. header.e_shstrndx:=ExeSectionList.IndexOf(shstrtabsect.ExeSection)+1;
  1840. header.e_shnum:=ExeSectionList.Count+1;
  1841. header.e_phnum:=segmentlist.count;
  1842. header.e_ehsize:=sizeof(telfheader);
  1843. if assigned(ElfTarget.encodeflags) then
  1844. header.e_flags:=ElfTarget.encodeflags();
  1845. if assigned(EntrySym) then
  1846. header.e_entry:=EntrySym.Address;
  1847. header.e_shentsize:=sizeof(telfsechdr);
  1848. header.e_phentsize:=sizeof(telfproghdr);
  1849. MaybeSwapHeader(header);
  1850. FWriter.Write(header,sizeof(header));
  1851. end;
  1852. procedure TElfExeOutput.exesection_write_header(p:TObject;arg:Pointer);
  1853. var
  1854. shdr: TElfsechdr;
  1855. exesec: TElfExeSection absolute p;
  1856. begin
  1857. FillChar(shdr,sizeof(shdr),0);
  1858. shdr.sh_name:=exesec.shstridx;
  1859. if (ExeWriteMode=ewm_dbgonly) and
  1860. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  1861. shdr.sh_type:=SHT_NOBITS
  1862. else
  1863. shdr.sh_type:=exesec.shtype;
  1864. shdr.sh_flags:=exesec.shflags;
  1865. if (oso_load in exesec.SecOptions) then
  1866. shdr.sh_addr:=exesec.MemPos;
  1867. shdr.sh_offset:=exesec.DataPos;
  1868. shdr.sh_size:=exesec.Size;
  1869. shdr.sh_link:=exesec.shlink;
  1870. shdr.sh_info:=exesec.shinfo;
  1871. shdr.sh_addralign:=exesec.SecAlign;
  1872. shdr.sh_entsize:=exesec.shentsize;
  1873. MaybeSwapSecHeader(shdr);
  1874. FWriter.Write(shdr,sizeof(shdr));
  1875. end;
  1876. procedure TElfExeOutput.segment_write_header(p:TObject;arg:Pointer);
  1877. var
  1878. phdr: TElfproghdr;
  1879. seg: TElfSegment absolute p;
  1880. begin
  1881. FillChar(phdr,sizeof(phdr),0);
  1882. phdr.p_type:=seg.ptype;
  1883. phdr.p_flags:=seg.pflags;
  1884. phdr.p_align:=seg.align;
  1885. phdr.p_offset:=seg.DataPos;
  1886. phdr.p_filesz:=seg.DataSize;
  1887. phdr.p_memsz:=seg.MemSize;
  1888. phdr.p_vaddr:=seg.MemPos;
  1889. phdr.p_paddr:=seg.MemPos;
  1890. MaybeSwapHeader(phdr);
  1891. FWriter.Write(phdr,sizeof(phdr));
  1892. end;
  1893. procedure TElfExeOutput.WriteStaticSymtable;
  1894. var
  1895. i: longint;
  1896. sec: TElfExeSection;
  1897. exesym: TExeSymbol;
  1898. begin
  1899. if assigned(tlsseg) then
  1900. symtab.tlsbase:=tlsseg.MemPos;
  1901. for i:=0 to ExeSectionList.Count-1 do
  1902. begin
  1903. sec:=TElfExeSection(ExeSectionList[i]);
  1904. { Must not write symbols for internal sections like .symtab }
  1905. if (sec.shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
  1906. continue;
  1907. sec.secsymidx:=symtab.symidx;
  1908. symtab.writeInternalSymbol(sec.mempos,0,STT_SECTION,sec.secshidx);
  1909. end;
  1910. { local symbols first }
  1911. for i:=0 to ExeSymbolList.Count-1 do
  1912. begin
  1913. exesym:=TExeSymbol(ExeSymbolList[i]);
  1914. if (exesym.objsymbol.bind=AB_LOCAL) and (exesym.objsymbol.typ<>AT_LABEL) then
  1915. symtab.WriteSymbol(exesym.objsymbol);
  1916. end;
  1917. { Global Symbols }
  1918. for i:=0 to ExeSymbolList.Count-1 do
  1919. begin
  1920. exesym:=TExeSymbol(ExeSymbolList[i]);
  1921. if (exesym.objsymbol.bind<>AB_LOCAL) then
  1922. symtab.WriteSymbol(exesym.objsymbol);
  1923. end;
  1924. { update exe section properties }
  1925. symtab.ExeSection.size:=symtab.size;
  1926. TElfExeSection(symtab.ExeSection).shinfo:=symtab.shinfo;
  1927. TElfExeSection(symtab.ExeSection).shlink:=ExeSectionList.IndexOf(symtab.fstrsec.ExeSection)+1;
  1928. symtab.fstrsec.ExeSection.Size:=symtab.fstrsec.size;
  1929. end;
  1930. procedure TElfExeOutput.MapSectionsToSegments;
  1931. var
  1932. seg: TElfSegment;
  1933. exesec: TExeSection;
  1934. i: longint;
  1935. begin
  1936. if (not IsSharedLibrary) and assigned(interpobjsec) then
  1937. begin
  1938. phdrseg:=CreateSegment(PT_PHDR,PF_R or PF_X,sizeof(pint));
  1939. seg:=CreateSegment(PT_INTERP,PF_R,1);
  1940. seg.Add(interpobjsec.ExeSection);
  1941. end;
  1942. textseg:=CreateSegment(PT_LOAD,PF_X or PF_R,ElfTarget.max_page_size);
  1943. dataseg:=CreateSegment(PT_LOAD,PF_R or PF_W,ElfTarget.max_page_size);
  1944. for i:=0 to ExeSectionList.Count-1 do
  1945. begin
  1946. exesec:=TExeSection(ExeSectionList[i]);
  1947. if (oso_load in exesec.SecOptions) then
  1948. begin
  1949. if (TElfExeSection(exesec).shflags and SHF_TLS)<>0 then
  1950. begin
  1951. if tlsseg=nil then
  1952. tlsseg:=CreateSegment(PT_TLS,PF_R,sizeof(pint));
  1953. tlsseg.add(exesec);
  1954. end;
  1955. { TODO: at least on Linux, ld seems to drop .note.ABI-tag for static executables.
  1956. (Logic is as follows: there is no .note.ABI-tag section in ld script, so it
  1957. is processed as orphan section. As such, it is placed after .interp.
  1958. For static executables .interp is dropped, and it looks like there's nowhere to
  1959. place .note.ABI-tag in this case)
  1960. Always including it doesn't harm though (except increasing file size). }
  1961. if TElfExeSection(exesec).shtype=SHT_NOTE then
  1962. begin
  1963. if noteseg=nil then
  1964. noteseg:=CreateSegment(PT_NOTE,PF_R,4);
  1965. noteseg.Add(exesec);
  1966. Include(exesec.SecOptions,oso_debug_copy);
  1967. end;
  1968. if (oso_executable in exesec.SecOptions) or
  1969. not (oso_write in exesec.SecOptions) then
  1970. textseg.add(exesec)
  1971. else
  1972. dataseg.add(exesec);
  1973. end;
  1974. end;
  1975. if dynamiclink then
  1976. begin
  1977. seg:=CreateSegment(PT_DYNAMIC,PF_R or PF_W,sizeof(pint));
  1978. seg.add(dynamicsec.ExeSection);
  1979. end;
  1980. { stack flags }
  1981. CreateSegment(PT_GNU_STACK,PF_R or PF_W or (PF_X*ord(ExecStack)),sizeof(pint));
  1982. end;
  1983. procedure TElfExeOutput.make_dynamic_if_undefweak(exesym:TExeSymbol);
  1984. begin
  1985. if (exesym.dynindex=0) and (exesym.state=symstate_undefweak) and
  1986. not (cs_link_staticflag in current_settings.globalswitches) then
  1987. exesym.dynindex:=dynsymlist.add(exesym)+1;
  1988. end;
  1989. function TElfExeOutput.AllocGOTSlot(objsym:TObjSymbol):boolean;
  1990. var
  1991. exesym: TExeSymbol;
  1992. begin
  1993. result:=false;
  1994. exesym:=objsym.exesymbol;
  1995. { Although local symbols should not be accessed through GOT,
  1996. this isn't strictly forbidden. In this case we need to fake up
  1997. the exesym to store the GOT offset in it.
  1998. TODO: name collision; maybe use a different symbol list object? }
  1999. if exesym=nil then
  2000. begin
  2001. exesym:=TExeSymbol.Create(ExeSymbolList,objsym.name+'*local*');
  2002. exesym.objsymbol:=objsym;
  2003. objsym.exesymbol:=exesym;
  2004. end;
  2005. if exesym.GotOffset>0 then
  2006. exit;
  2007. gotobjsec.alloc(sizeof(pint));
  2008. exesym.GotOffset:=gotobjsec.size;
  2009. make_dynamic_if_undefweak(exesym);
  2010. { In shared library, every GOT entry needs a RELATIVE dynamic reloc,
  2011. imported/exported symbols need GLOB_DAT instead. For executables,
  2012. only the latter applies. }
  2013. if IsSharedLibrary or (exesym.dynindex>0) then
  2014. dynrelocsec.alloc(dynrelocsec.shentsize);
  2015. result:=true;
  2016. end;
  2017. procedure TElfExeOutput.PrepareGOT;
  2018. var
  2019. i,j,k: longint;
  2020. objsec: TElfObjSection;
  2021. exesec: TExeSection;
  2022. begin
  2023. for i:=0 to ExeSectionList.Count-1 do
  2024. begin
  2025. exesec:=TExeSection(ExeSectionList[i]);
  2026. for j:=0 to exesec.ObjSectionlist.count-1 do
  2027. begin
  2028. objsec:=TElfObjSection(exesec.ObjSectionlist[j]);
  2029. { ignore linker-generated and debug sections }
  2030. if (objsec.objdata=internalobjdata) or (oso_debug in objsec.SecOptions) then
  2031. continue;
  2032. if not objsec.Used then
  2033. internalerror(2012060901);
  2034. k:=0;
  2035. while k<objsec.ObjRelocations.Count do
  2036. begin
  2037. GOTRelocPass1(objsec,k);
  2038. inc(k);
  2039. end;
  2040. end;
  2041. end;
  2042. { remember sizes for sanity checking }
  2043. gotsize:=gotobjsec.size;
  2044. if assigned(dynrelocsec) then
  2045. dynrelsize:=dynrelocsec.size
  2046. else
  2047. dynrelsize:=0;
  2048. end;
  2049. procedure TElfExeOutput.CreateGOTSection;
  2050. begin
  2051. gotpltobjsec:=TElfObjSection.create_ext(internalObjData,'.got.plt',
  2052. SHT_PROGBITS,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(pint));
  2053. gotobjsec:=TElfObjSection.create_ext(internalObjData,'.got',
  2054. SHT_PROGBITS,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(pint));
  2055. gotobjsec.SecOptions:=[oso_keep];
  2056. { GOT symbol and reserved .got.plt entries }
  2057. internalObjData.SetSection(gotpltobjsec);
  2058. gotsymbol:=internalObjData.SymbolDefine('_GLOBAL_OFFSET_TABLE_',AB_GLOBAL,AT_DATA);
  2059. gotpltobjsec.writeZeros(3*sizeof(pint));
  2060. end;
  2061. procedure TElfExeOutput.Load_Start;
  2062. begin
  2063. inherited Load_Start;
  2064. dynsymlist:=TFPObjectList.Create(False);
  2065. CreateGOTSection;
  2066. end;
  2067. procedure TElfExeOutput.Load_DynamicObject(objdata:TObjData;asneeded:boolean);
  2068. var
  2069. i: longint;
  2070. exesym: TExeSymbol;
  2071. objsym: TObjSymbol;
  2072. needed: boolean;
  2073. begin
  2074. Comment(v_debug,'Dynamic object: '+objdata.name);
  2075. needed:=false;
  2076. for i:=0 to UnresolvedExeSymbols.Count-1 do
  2077. begin
  2078. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2079. if not (exesym.State in [symstate_undefined,symstate_undefweak]) then
  2080. continue;
  2081. objsym:=TObjSymbol(objdata.ObjSymbolList.Find(exesym.name));
  2082. if assigned(objsym) then
  2083. begin
  2084. exesym.State:=symstate_defined;
  2085. exesym.dynindex:=dynsymlist.Add(exesym)+1;
  2086. { The original binding, value and section of external symbol
  2087. must be preserved, therefore resolving directly to .so symbol
  2088. hurts more than it helps. Copy type and size, and store .so
  2089. symbol in objsym.indsymbol for later use. }
  2090. exesym.ObjSymbol.typ:=objsym.typ;
  2091. if objsym.typ<>AT_FUNCTION then
  2092. exesym.ObjSymbol.size:=objsym.size;
  2093. exesym.ObjSymbol.indsymbol:=objsym;
  2094. objsym.ExeSymbol:=exesym;
  2095. needed:=true;
  2096. end;
  2097. end;
  2098. if (needed or (not asneeded)) and
  2099. (neededlist.Find(objdata.name)=nil) then
  2100. neededlist.Add(objdata.name,objdata);
  2101. end;
  2102. procedure TElfExeOutput.Order_Start;
  2103. begin
  2104. inherited Order_Start;
  2105. dynamiclink:=IsSharedLibrary or (dynsymlist.count>0) or
  2106. (
  2107. (UnresolvedExeSymbols.Count>0) and
  2108. not (cs_link_staticflag in current_settings.globalswitches)
  2109. );
  2110. if dynamiclink then
  2111. InitDynlink;
  2112. if dynamiclink or (IndirectObjSymbols.Count>0) then
  2113. CreatePLT;
  2114. end;
  2115. procedure TElfExeOutput.Order_end;
  2116. procedure set_oso_keep(const s:string);
  2117. var
  2118. exesec:TExeSection;
  2119. objsec:TObjSection;
  2120. i:longint;
  2121. begin
  2122. exesec:=TExeSection(ExeSectionList.Find(s));
  2123. if assigned(exesec) then
  2124. begin
  2125. for i:=0 to exesec.ObjSectionList.Count-1 do
  2126. begin
  2127. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2128. { ignore sections used for symbol definition }
  2129. if oso_data in objsec.SecOptions then
  2130. objsec.SecOptions:=[oso_keep];
  2131. end;
  2132. end;
  2133. end;
  2134. begin
  2135. OrderOrphanSections;
  2136. inherited Order_end;
  2137. set_oso_keep('.init');
  2138. set_oso_keep('.fini');
  2139. set_oso_keep('.jcr');
  2140. set_oso_keep('.ctors');
  2141. set_oso_keep('.dtors');
  2142. set_oso_keep('.preinit_array');
  2143. set_oso_keep('.init_array');
  2144. set_oso_keep('.fini_array');
  2145. set_oso_keep('.eh_frame');
  2146. { let .dynamic reference other dynamic sections so they aren't marked
  2147. for removal as unused }
  2148. if dynamiclink then
  2149. WriteDynamicTags;
  2150. end;
  2151. procedure TElfExeOutput.OrderOrphanSections;
  2152. var
  2153. i,j:longint;
  2154. objdata:TObjData;
  2155. objsec:TObjSection;
  2156. exesec:TExeSection;
  2157. opts:TObjSectionOptions;
  2158. s:string;
  2159. newsections,tmp:TFPHashObjectList;
  2160. allsections:TFPList;
  2161. inserts:array[0..6] of TExeSection;
  2162. idx,inspos:longint;
  2163. begin
  2164. newsections:=TFPHashObjectList.Create(false);
  2165. allsections:=TFPList.Create;
  2166. { copy existing sections }
  2167. for i:=0 to ExeSectionList.Count-1 do
  2168. allsections.add(ExeSectionList[i]);
  2169. inserts[0]:=FindExeSection('.comment');
  2170. inserts[1]:=nil;
  2171. inserts[2]:=FindExeSection('.interp');
  2172. inserts[3]:=FindExeSection('.bss');
  2173. inserts[4]:=FindExeSection('.data');
  2174. inserts[5]:=FindExeSection('.rodata');
  2175. inserts[6]:=FindExeSection('.text');
  2176. for i:=0 to ObjDataList.Count-1 do
  2177. begin
  2178. ObjData:=TObjData(ObjDataList[i]);
  2179. for j:=0 to ObjData.ObjSectionList.Count-1 do
  2180. begin
  2181. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  2182. if objsec.Used then
  2183. continue;
  2184. s:=objsec.name;
  2185. exesec:=TExeSection(newsections.Find(s));
  2186. if assigned(exesec) then
  2187. begin
  2188. exesec.AddObjSection(objsec);
  2189. continue;
  2190. end;
  2191. opts:=objsec.SecOptions*[oso_data,oso_load,oso_write,oso_executable];
  2192. if (objsec.SecOptions*[oso_load,oso_debug]=[]) then
  2193. { non-alloc, after .comment
  2194. GNU ld places .comment between stabs and dwarf debug info }
  2195. inspos:=0
  2196. else if not (oso_load in objsec.SecOptions) then
  2197. inspos:=1 { debugging, skip }
  2198. else if (oso_load in objsec.SecOptions) and
  2199. (TElfObjSection(objsec).shtype=SHT_NOTE) then
  2200. inspos:=2 { after .interp }
  2201. else if (opts=[oso_load,oso_write]) then
  2202. inspos:=3 { after .bss }
  2203. else if (opts=[oso_data,oso_load,oso_write]) then
  2204. inspos:=4 { after .data }
  2205. else if (opts=[oso_data,oso_load]) then
  2206. inspos:=5 { rodata, relocs=??? }
  2207. else if (opts=[oso_data,oso_load,oso_executable]) then
  2208. inspos:=6 { text }
  2209. else
  2210. begin
  2211. Comment(v_debug,'Orphan section '+objsec.fullname+' has attributes that are not handled!');
  2212. continue;
  2213. end;
  2214. if (inserts[inspos]=nil) then
  2215. begin
  2216. Comment(v_debug,'Orphan section '+objsec.fullname+': nowhere to insert, ignored');
  2217. continue;
  2218. end;
  2219. idx:=allsections.IndexOf(inserts[inspos]);
  2220. exesec:=CExeSection.Create(newsections,s);
  2221. allsections.Insert(idx+1,exesec);
  2222. inserts[inspos]:=exesec;
  2223. exesec.AddObjSection(objsec);
  2224. end;
  2225. end;
  2226. { Now replace the ExeSectionList with content of allsections }
  2227. if (newsections.count<>0) then
  2228. ReplaceExeSectionList(allsections);
  2229. newsections.Free;
  2230. allsections.Free;
  2231. end;
  2232. procedure TElfExeOutput.AfterUnusedSectionRemoval;
  2233. var
  2234. i:longint;
  2235. exesym:TExeSymbol;
  2236. objsym:TObjSymbol;
  2237. objsec: TObjSection;
  2238. begin
  2239. { Unused section removal sets Used property of referenced exesymbols.
  2240. Remaining ones can be removed. }
  2241. for i:=0 to dynsymlist.count-1 do
  2242. begin
  2243. exesym:=TExeSymbol(dynsymlist[i]);
  2244. if assigned(exesym.ObjSymbol.ObjSection) then // an exported symbol
  2245. continue;
  2246. if not exesym.used then
  2247. begin
  2248. dynsymlist[i]:=nil;
  2249. exesym.dynindex:=0;
  2250. end;
  2251. end;
  2252. dynsymlist.Pack;
  2253. { reindex }
  2254. for i:=0 to dynsymlist.count-1 do
  2255. TExeSymbol(dynsymlist[i]).dynindex:=i+1;
  2256. { Drop unresolved symbols that aren't referenced, assign dynamic
  2257. indices to remaining ones, but not if linking with -Xt.
  2258. TODO: behavior of .so with -Xt ? }
  2259. if (cs_link_staticflag in current_settings.globalswitches) then
  2260. UnresolvedExeSymbols.Clear
  2261. else
  2262. for i:=0 to UnresolvedExeSymbols.Count-1 do
  2263. begin
  2264. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2265. if exesym.used then
  2266. begin
  2267. if exesym.dynindex<>0 then
  2268. InternalError(2012062301);
  2269. { Weak-referenced symbols are changed into dynamic ones
  2270. only if referenced through GOT or PLT (this is BFD-compatible) }
  2271. if exesym.state<>symstate_undefweak then
  2272. exesym.dynindex:=dynsymlist.add(exesym)+1;
  2273. end
  2274. else
  2275. UnresolvedExeSymbols[i]:=nil;
  2276. end;
  2277. UnresolvedExeSymbols.Pack;
  2278. { Scan relocations to determine size of GOT, dynamic reloc section, etc. }
  2279. PrepareGOT;
  2280. { Write required PLT entries }
  2281. for i:=0 to dynsymlist.Count-1 do
  2282. begin
  2283. exesym:=TExeSymbol(dynsymlist[i]);
  2284. if assigned(exesym.ObjSymbol.objsection) then // an exported symbol
  2285. continue;
  2286. if ((exesym.ObjSymbol.refs and symref_plt)<>0) or
  2287. ((exesym.ObjSymbol.typ in [AT_FUNCTION,AT_GNU_IFUNC]) and (not IsSharedLibrary)) then
  2288. begin
  2289. make_dynamic_if_undefweak(exesym);
  2290. { This symbol has a valid address to which relocations are resolved,
  2291. but it remains (weak)external when written to dynamic symtable. }
  2292. objsym:=internalobjdata.CreateSymbol(exesym.name);
  2293. objsym.typ:=AT_FUNCTION;
  2294. objsym.bind:=exesym.ObjSymbol.bind; { AB_EXTERNAL or AB_WEAK_EXTERNAL }
  2295. objsym.indsymbol:=exesym.ObjSymbol.indsymbol;
  2296. objsym.offset:=pltobjsec.size;
  2297. objsym.objsection:=pltobjsec;
  2298. objsym.exesymbol:=exesym;
  2299. exesym.ObjSymbol:=objsym;
  2300. WritePLTEntry(exesym);
  2301. end
  2302. else if ((exesym.ObjSymbol.refs and symref_from_text)<>0) and
  2303. (exesym.ObjSymbol.typ<>AT_FUNCTION) and (not IsSharedLibrary) and
  2304. (exesym.state<>symstate_undefweak) then
  2305. begin
  2306. if exesym.ObjSymbol.size=0 then
  2307. Comment(v_error,'Dynamic variable '+exesym.name+' has zero size');
  2308. internalobjdata.setSection(dynbssobjsec);
  2309. internalobjdata.allocalign(size_2_align(exesym.ObjSymbol.size));
  2310. objsym:=internalobjdata.SymbolDefine(exesym.name,AB_GLOBAL,AT_DATA);
  2311. objsym.size:=exesym.ObjSymbol.size;
  2312. objsym.indsymbol:=exesym.ObjSymbol.indsymbol;
  2313. exesym.ObjSymbol:=objsym;
  2314. objsym.exesymbol:=exesym;
  2315. dynbssobjsec.alloc(objsym.size);
  2316. { allocate space for R_xx_COPY relocation for this symbol;
  2317. we'll create it later, to be consistent with "-z combreloc" semantics }
  2318. dyncopysyms.add(objsym);
  2319. dynrelocsec.alloc(dynrelocsec.shentsize);
  2320. inc(dynrelsize,dynrelocsec.shentsize);
  2321. end;
  2322. end;
  2323. { Handle indirect symbols }
  2324. for i:=0 to IndirectObjSymbols.Count-1 do
  2325. begin
  2326. objsym:=TObjSymbol(IndirectObjSymbols[i]);
  2327. objsec:=objsym.ExeSymbol.ObjSymbol.objsection;
  2328. objsym.bind:=AB_EXTERNAL; { cheat FixupSymbols }
  2329. if (oso_plt in objsec.SecOptions) then
  2330. continue;
  2331. WriteIndirectPLTEntry(objsym.ExeSymbol);
  2332. end;
  2333. FixupSymbols;
  2334. if dynamiclink then
  2335. begin
  2336. WriteVersionSections;
  2337. WriteDynamicSymbolsHash;
  2338. end;
  2339. { Create .shstrtab section, which is needed in both exe and .dbg files }
  2340. shstrtabsect:=TElfObjSection.Create_ext(internalObjData,'.shstrtab',SHT_STRTAB,0,1,0);
  2341. shstrtabsect.SecOptions:=[oso_debug_copy];
  2342. AttachSection(shstrtabsect);
  2343. { Create the static symtable (.symtab and .strtab) }
  2344. if (cs_link_separate_dbg_file in current_settings.globalswitches) or
  2345. not(cs_link_strip in current_settings.globalswitches) then
  2346. begin
  2347. symtab:=TElfSymtab.Create(internalObjData,esk_exe);
  2348. symtab.SecOptions:=[oso_debug];
  2349. symtab.fstrsec.SecOptions:=[oso_debug];
  2350. AttachSection(symtab);
  2351. AttachSection(symtab.fstrsec);
  2352. end;
  2353. { Re-enable sections which end up to contain some data
  2354. (.got, .rel[a].dyn, .rel[a].plt (includes .rel[a].iplt) and .hash }
  2355. if gotobjsec.size<>0 then
  2356. gotobjsec.ExeSection.Disabled:=false;
  2357. if assigned(dynrelocsec) and
  2358. ((dynrelocsec.size<>0) or (dyncopysyms.count<>0)) then
  2359. dynrelocsec.ExeSection.Disabled:=false;
  2360. if assigned(pltrelocsec) and (pltrelocsec.size>0) then
  2361. pltrelocsec.ExeSection.Disabled:=false;
  2362. if assigned(ipltrelocsec) and (ipltrelocsec.size>0) then
  2363. ipltrelocsec.ExeSection.Disabled:=false;
  2364. if assigned(hashobjsec) then
  2365. hashobjsec.ExeSection.Disabled:=false;
  2366. if assigned(symversec) and (symversec.size<>0) then
  2367. symversec.ExeSection.Disabled:=false;
  2368. if assigned(verneedsec) and (verneedsec.size<>0) then
  2369. verneedsec.ExeSection.Disabled:=false;
  2370. if assigned(verdefsec) and (verdefsec.size<>0) then
  2371. verdefsec.ExeSection.Disabled:=false;
  2372. RemoveDisabledSections;
  2373. MapSectionsToSegments;
  2374. if dynamiclink then
  2375. FinishDynamicTags;
  2376. end;
  2377. procedure TElfExeOutput.WriteShStrtab;
  2378. var
  2379. i: longint;
  2380. exesec: TElfExeSection;
  2381. begin
  2382. { Remove any existing .shstrtab contents }
  2383. if (shstrtabsect.size>0) then
  2384. begin
  2385. shstrtabsect.ReleaseData;
  2386. shstrtabsect.Size:=0;
  2387. shstrtabsect.SecOptions:=[oso_data];
  2388. end;
  2389. shstrtabsect.writezeros(1);
  2390. for i:=0 to ExeSectionList.Count-1 do
  2391. begin
  2392. exesec:=TElfExeSection(ExeSectionList[i]);
  2393. exesec.shstridx:=shstrtabsect.writestr(exesec.Name);
  2394. exesec.secshidx:=i+1;
  2395. end;
  2396. end;
  2397. procedure TElfExeOutput.FixupSectionLinks;
  2398. var
  2399. dynstrndx,dynsymndx: longword;
  2400. begin
  2401. if dynamiclink then
  2402. begin
  2403. dynstrndx:=TElfExeSection(dynsymtable.fstrsec.ExeSection).secshidx;
  2404. dynsymndx:=TElfExeSection(dynsymtable.ExeSection).secshidx;
  2405. TElfExeSection(hashobjsec.ExeSection).shlink:=dynsymndx;
  2406. TElfExeSection(dynamicsec.ExeSection).shlink:=dynstrndx;
  2407. TElfExeSection(dynsymtable.ExeSection).shlink:=dynstrndx;
  2408. if assigned(pltrelocsec) then
  2409. begin
  2410. TElfExeSection(pltrelocsec.ExeSection).shlink:=dynsymndx;
  2411. TElfExeSection(pltrelocsec.ExeSection).shinfo:=TElfExeSection(pltobjsec.ExeSection).secshidx;
  2412. end;
  2413. if assigned(dynrelocsec) and assigned(dynrelocsec.ExeSection) then
  2414. TElfExeSection(dynrelocsec.ExeSection).shlink:=dynsymndx;
  2415. if symversec.size>0 then
  2416. TElfExeSection(symversec.ExeSection).shlink:=dynsymndx;
  2417. if verdefsec.size>0 then
  2418. TElfExeSection(verdefsec.ExeSection).shlink:=dynstrndx;
  2419. if verneedsec.size>0 then
  2420. TElfExeSection(verneedsec.ExeSection).shlink:=dynstrndx;
  2421. end
  2422. else if assigned(ipltrelocsec) then
  2423. TElfExeSection(ipltrelocsec.ExeSection).shinfo:=TElfExeSection(pltobjsec.ExeSection).secshidx;
  2424. end;
  2425. procedure TElfExeOutput.Do_Mempos;
  2426. var
  2427. i,j: longint;
  2428. seg: TElfSegment;
  2429. exesec: TElfExeSection;
  2430. objsec: TObjSection;
  2431. tempmempos: qword;
  2432. begin
  2433. if IsSharedLibrary then
  2434. CurrMemPos:=0
  2435. else
  2436. CurrMemPos:=ElfTarget.exe_image_base;
  2437. textseg.MemPos:=CurrMemPos;
  2438. if assigned(phdrseg) then
  2439. begin
  2440. phdrseg.Mempos:=CurrMemPos+sizeof(TElfHeader);
  2441. phdrseg.Memsize:=sizeof(TElfproghdr)*segmentlist.count;
  2442. end;
  2443. CurrMemPos:=CurrMemPos+sizeof(TElfHeader)+segmentlist.count*sizeof(TElfproghdr);
  2444. MemPos_Segment(textseg);
  2445. CurrMemPos:=Align(CurrMemPos,SectionDataAlign); {! Data,not MemAlign}
  2446. CurrMemPos:=CurrMemPos+ElfTarget.max_page_size;
  2447. dataseg.MemPos:=CurrMemPos;
  2448. MemPos_Segment(dataseg);
  2449. { Mempos of unmapped sections is forced to zero, but we have to set positions
  2450. of its objsections and update sizes }
  2451. for i:=0 to ExeSectionList.Count-1 do
  2452. begin
  2453. exesec:=TElfExeSection(ExeSectionList[i]);
  2454. if not (oso_load in exesec.SecOptions) then
  2455. begin
  2456. tempmempos:=0;
  2457. exesec.MemPos:=tempmempos;
  2458. for j:=0 to exesec.ObjSectionList.Count-1 do
  2459. begin
  2460. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2461. tempmempos:=objsec.setmempos(tempmempos);
  2462. end;
  2463. exesec.Size:=tempmempos;
  2464. end;
  2465. end;
  2466. { Update MemPos and MemSize of non-load segments,
  2467. in particular, TLS sizes are needed to resolve relocations }
  2468. for i:=0 to segmentlist.count-1 do
  2469. begin
  2470. seg:=TElfSegment(segmentlist[i]);
  2471. if (seg.ptype=PT_LOAD) or (seg.FSectionList.Count=0) then
  2472. continue;
  2473. seg.MemPos:=TExeSection(seg.FSectionList.First).MemPos;
  2474. for j:=0 to seg.FSectionList.Count-1 do
  2475. begin
  2476. exesec:=TElfExeSection(seg.FSectionList[j]);
  2477. seg.MemSize:=exesec.MemPos+exesec.Size-seg.MemPos;
  2478. end;
  2479. end;
  2480. end;
  2481. procedure TElfExeOutput.MemPos_Start;
  2482. var
  2483. i: longint;
  2484. begin
  2485. { Assign section indices and fill .shstrtab
  2486. List of sections cannot be modified after this point. }
  2487. WriteShStrtab;
  2488. { fixup sh_link/sh_info members of various dynamic sections }
  2489. FixupSectionLinks;
  2490. { The actual layout }
  2491. Do_Mempos;
  2492. if (not gotwritten) then
  2493. begin
  2494. { Reset size of .got and .rel[a].dyn, they will be refilled while fixing up relocations.
  2495. For .got, consider already written reserved entries. }
  2496. if assigned(gotobjsec) then
  2497. gotobjsec.size:=gotobjsec.data.size;
  2498. if assigned(dynrelocsec) then
  2499. begin
  2500. dynrelocsec.size:=0;
  2501. { write actual .dynsym content (needs valid symbol addresses) }
  2502. if assigned(tlsseg) then
  2503. dynsymtable.tlsbase:=tlsseg.MemPos;
  2504. dynsymtable.size:=sizeof(TElfsymbol);
  2505. for i:=0 to dynsymlist.count-1 do
  2506. dynsymtable.writeSymbol(TExeSymbol(dynsymlist[i]).objsymbol,dynsymnames[i]);
  2507. end;
  2508. end;
  2509. end;
  2510. procedure TElfExeOutput.MemPos_Segment(seg:TElfSegment);
  2511. var
  2512. i: longint;
  2513. exesec: TElfExeSection;
  2514. begin
  2515. for i:=0 to seg.FSectionList.Count-1 do
  2516. begin
  2517. exesec:=TElfExeSection(seg.FSectionList[i]);
  2518. inherited MemPos_ExeSection(exesec);
  2519. { .tbss should not contribute to address space }
  2520. if (exesec.shtype=SHT_NOBITS) and ((exesec.shflags and SHF_TLS)<>0) then
  2521. CurrMemPos:=exesec.MemPos;
  2522. end;
  2523. { calculate size of the segment }
  2524. seg.MemSize:=CurrMemPos-seg.MemPos;
  2525. end;
  2526. procedure TElfExeOutput.MemPos_ExeSection(const aname:string);
  2527. begin
  2528. // Ignore. All layout is done in mempos_start
  2529. end;
  2530. procedure TElfExeOutput.DataPos_Start;
  2531. var
  2532. i,j: longint;
  2533. exesec: TExeSection;
  2534. seg: TElfSegment;
  2535. objreloc: TObjRelocation;
  2536. objsym: TObjSymbol;
  2537. begin
  2538. gotwritten:=true;
  2539. { If target does not support sorted relocations, it is expected to write the
  2540. entire .rel[a].dyn section during FixupRelocations, and leave dynreloclist empty.
  2541. Otherwise, only RELATIVE ones should be written, space for non-relative relocations
  2542. should remain. }
  2543. if assigned(dynrelocsec) then
  2544. begin
  2545. { Append R_xx_COPY relocations }
  2546. for i:=0 to dyncopysyms.count-1 do
  2547. begin
  2548. objsym:=TObjSymbol(dyncopysyms[i]);
  2549. dynreloclist.Add(TObjRelocation.CreateRaw(objsym.address,objsym,ElfTarget.dyn_reloc_codes[dr_copy]));
  2550. end;
  2551. dyncopysyms.Clear;
  2552. if (dynrelocsec.size+(dynreloclist.count*dynrelocsec.shentsize)<>dynrelsize) then
  2553. InternalError(2012110601);
  2554. { Write out non-RELATIVE dynamic relocations
  2555. TODO: additional sorting? }
  2556. for i:=0 to dynreloclist.count-1 do
  2557. begin
  2558. objreloc:=TObjRelocation(dynreloclist[i]);
  2559. WriteDynRelocEntry(objreloc.dataoffset,objreloc.ftype,objreloc.symbol.exesymbol.dynindex,0);
  2560. end;
  2561. end;
  2562. { sanity checks }
  2563. if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
  2564. InternalError(2012092501);
  2565. if assigned(dynrelocsec) and (dynrelsize<>dynrelocsec.size) then
  2566. InternalError(2012092502);
  2567. if (ExeWriteMode=ewm_dbgonly) or
  2568. (
  2569. (ExeWriteMode=ewm_exefull) and
  2570. not(cs_link_strip in current_settings.globalswitches)
  2571. ) then
  2572. WriteStaticSymtable;
  2573. { first handle primary segments }
  2574. textseg.DataPos:=0;
  2575. CurrDataPos:=sizeof(TElfHeader)+sizeof(TElfproghdr)*segmentlist.count;
  2576. if assigned(phdrseg) then
  2577. begin
  2578. phdrseg.DataPos:=sizeof(TElfHeader);
  2579. phdrseg.DataSize:=sizeof(TElfproghdr)*segmentlist.count;
  2580. end;
  2581. DataPos_Segment(textseg);
  2582. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  2583. dataseg.DataPos:=CurrDataPos;
  2584. DataPos_Segment(dataseg);
  2585. { then unmapped sections }
  2586. for i:=0 to ExeSectionList.Count-1 do
  2587. begin
  2588. exesec:=TExeSection(ExeSectionList[i]);
  2589. if not (oso_load in exesec.SecOptions) then
  2590. inherited DataPos_ExeSection(exesec);
  2591. end;
  2592. { finally, update size/position of non-load segments }
  2593. for i:=0 to segmentlist.count-1 do
  2594. begin
  2595. seg:=TElfSegment(segmentlist[i]);
  2596. if (seg.ptype=PT_LOAD) or (seg.FSectionList.Count=0) then
  2597. continue;
  2598. seg.DataPos:=TExeSection(seg.FSectionList.First).DataPos;
  2599. for j:=0 to seg.FSectionList.Count-1 do
  2600. begin
  2601. exesec:=TExeSection(seg.FSectionList[j]);
  2602. if oso_data in exesec.SecOptions then
  2603. seg.DataSize:=exesec.DataPos+exesec.Size-seg.DataPos;
  2604. end;
  2605. end;
  2606. { place section headers after the data }
  2607. shoffset:=CurrDataPos;
  2608. CurrDataPos:=CurrDataPos+ExeSectionList.Count*sizeof(TElfsechdr);
  2609. end;
  2610. procedure TElfExeOutput.DataPos_Segment(seg:TElfSegment);
  2611. var
  2612. i: longint;
  2613. exesec: TElfExeSection;
  2614. begin
  2615. for i:=0 to seg.FSectionList.Count-1 do
  2616. begin
  2617. exesec:=TElfExeSection(seg.FSectionList[i]);
  2618. { ELF needs DataPos set to 'would-be' value for sections that
  2619. don't have data, and for non-debug sections in .dbg file, too.
  2620. This slightly differs from generic approach. }
  2621. if not (oso_data in exesec.SecOptions) or
  2622. (
  2623. (ExeWriteMode=ewm_dbgonly) and
  2624. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[])
  2625. ) then
  2626. begin
  2627. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  2628. exesec.DataPos:=CurrDataPos;
  2629. end
  2630. else
  2631. inherited DataPos_ExeSection(exesec);
  2632. end;
  2633. { calculate size of the segment }
  2634. seg.DataSize:=CurrDataPos-seg.DataPos;
  2635. end;
  2636. procedure TElfExeOutput.DataPos_ExeSection(const aname:string);
  2637. begin
  2638. // Ignore. Work is done entirely in datapos_start.
  2639. end;
  2640. procedure TElfExeOutput.InitDynlink;
  2641. begin
  2642. if not IsSharedLibrary then
  2643. begin
  2644. interpobjsec:=internalObjData.createsection('.interp',1,[oso_data,oso_load,oso_keep]);
  2645. interpobjsec.writestr(interpreter^);
  2646. end;
  2647. hashobjsec:=TElfObjSection.create_ext(internalObjData,'.hash',
  2648. SHT_HASH,SHF_ALLOC,sizeof(pint),4);
  2649. hashobjsec.secoptions:=[oso_keep];
  2650. dynsymtable:=TElfSymtab.create(internalObjData,esk_dyn);
  2651. dynamicsec:=TElfObjSection.create_ext(internalObjData,'.dynamic',
  2652. SHT_DYNAMIC,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(TElfDyn));
  2653. dynamicsec.SecOptions:=[oso_keep];
  2654. dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
  2655. dynrelocsec.SecOptions:=[oso_keep];
  2656. dynbssobjsec:=TElfObjSection.create_ext(internalObjData,'.dynbss',
  2657. SHT_NOBITS,SHF_ALLOC or SHF_WRITE,sizeof(pint){16??},0);
  2658. dynbssobjsec.SecOptions:=[oso_keep];
  2659. dynreloclist:=TFPObjectList.Create(true);
  2660. symversec:=TElfObjSection.create_ext(internalObjData,'.gnu.version',
  2661. SHT_GNU_VERSYM,SHF_ALLOC,sizeof(word),sizeof(word));
  2662. symversec.SecOptions:=[oso_keep];
  2663. verdefsec:=TElfObjSection.create_ext(internalObjData,'.gnu.version_d',
  2664. SHT_GNU_VERDEF,SHF_ALLOC,sizeof(pint),0);
  2665. verdefsec.SecOptions:=[oso_keep];
  2666. verneedsec:=TElfObjSection.create_ext(internalObjData,'.gnu.version_r',
  2667. SHT_GNU_VERNEED,SHF_ALLOC,sizeof(pint),0);
  2668. verneedsec.SecOptions:=[oso_keep];
  2669. dyncopysyms:=TFPObjectList.Create(False);
  2670. end;
  2671. const
  2672. hashbuckets: array[0..15] of longint=(
  2673. 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
  2674. 16411, 32771);
  2675. {$push}{$r-,q-}
  2676. function elfhash(const name:string):longword;
  2677. var
  2678. g: longword;
  2679. i: longint;
  2680. begin
  2681. result:=0;
  2682. for i:=1 to length(name) do
  2683. begin
  2684. result:=(result shl 4)+ord(name[i]);
  2685. g:=result and $F0000000;
  2686. if g>0 then
  2687. result:=result xor (g shr 24);
  2688. result:=result and (not g);
  2689. end;
  2690. end;
  2691. {$pop}
  2692. procedure TElfExeOutput.WriteDynamicSymbolsHash;
  2693. var
  2694. nchains,nbuckets: longint;
  2695. i,j: longint;
  2696. hashdata: plongint;
  2697. sym: TExeSymbol;
  2698. begin
  2699. dynsymnames:=AllocMem(dynsymlist.count*sizeof(longword));
  2700. nchains:=dynsymlist.Count+1;
  2701. { determine suitable bucket count }
  2702. i:=high(hashbuckets);
  2703. while (i>=0) and (nchains<hashbuckets[i]) do
  2704. dec(i);
  2705. nbuckets:=hashbuckets[i];
  2706. hashdata:=AllocMem((2+nchains+nbuckets)*sizeof(longint));
  2707. hashdata[0]:=nbuckets;
  2708. hashdata[1]:=nchains;
  2709. { The contents of .dynsym can be written only after mempos pass
  2710. because it needs valid symbol virtual addresses and section indices.
  2711. Here we preset .dynsym size and write names, in order to get
  2712. correct size of .dynstr section. }
  2713. dynsymtable.size:=(dynsymlist.count+1)*sizeof(TElfsymbol);
  2714. for i:=0 to dynsymlist.Count-1 do
  2715. begin
  2716. sym:=TExeSymbol(dynsymlist[i]);
  2717. dynsymnames[i]:=dynsymtable.fstrsec.writestr(sym.objsymbol.name);
  2718. j:=(elfhash(sym.objsymbol.name) mod nbuckets)+2;
  2719. while hashdata[j]<>0 do
  2720. j:=2+nbuckets+hashdata[j];
  2721. hashdata[j]:=i+1;
  2722. end;
  2723. if source_info.endian<>target_info.endian then
  2724. for i:=0 to nchains+nbuckets+1 do
  2725. hashdata[i]:=swapendian(hashdata[i]);
  2726. hashobjsec.write(hashdata^,(2+nchains+nbuckets)*sizeof(longint));
  2727. freemem(hashdata);
  2728. end;
  2729. procedure TElfExeOutput.WriteVersionSections;
  2730. var
  2731. i,j: longint;
  2732. idx,auxidx: longword;
  2733. exesym: TExeSymbol;
  2734. dynobj: TElfDynamicObjData;
  2735. ver: TElfVersionDef;
  2736. vn: TElfverneed;
  2737. vna: TElfvernaux;
  2738. symversions: pword;
  2739. begin
  2740. symversions:=AllocMem((dynsymlist.count+1)*sizeof(word));
  2741. { Assign version indices }
  2742. idx:=VER_NDX_GLOBAL+1;
  2743. for i:=0 to dynsymlist.count-1 do
  2744. begin
  2745. exesym:=TExeSymbol(dynsymlist[i]);
  2746. if (exesym.objsymbol.indsymbol is TVersionedObjSymbol) then
  2747. ver:=TVersionedObjSymbol(exesym.objsymbol.indsymbol).version
  2748. else
  2749. ver:=nil;
  2750. if assigned(ver) then
  2751. begin
  2752. if ver.index=0 then
  2753. begin
  2754. ver.index:=idx;
  2755. inc(idx);
  2756. end;
  2757. symversions[i+1]:=ver.index;
  2758. end
  2759. else if exesym.state in [symstate_undefined,symstate_undefweak] then
  2760. symversions[i+1]:=VER_NDX_LOCAL
  2761. else
  2762. symversions[i+1]:=VER_NDX_GLOBAL;
  2763. end;
  2764. { Count entries to be written }
  2765. verneedcount:=0;
  2766. for i:=0 to neededlist.count-1 do
  2767. begin
  2768. dynobj:=TElfDynamicObjData(neededlist[i]);
  2769. dynobj.vernaux_count:=0;
  2770. for j:=2 to dynobj.versiondefs.count-1 do
  2771. begin
  2772. ver:=TElfVersionDef(dynobj.versiondefs[j]);
  2773. if ver.index>VER_NDX_GLOBAL then
  2774. inc(dynobj.vernaux_count);
  2775. end;
  2776. if (dynobj.vernaux_count>0) then
  2777. inc(verneedcount);
  2778. end;
  2779. { Now write }
  2780. idx:=0;
  2781. for i:=0 to neededlist.count-1 do
  2782. begin
  2783. dynobj:=TElfDynamicObjData(neededlist[i]);
  2784. if dynobj.vernaux_count=0 then
  2785. continue;
  2786. inc(idx);
  2787. vn.vn_version:=VER_NEED_CURRENT;
  2788. vn.vn_cnt:=dynobj.vernaux_count;
  2789. vn.vn_file:=dynobj.soname_strofs;
  2790. vn.vn_aux:=sizeof(TElfverneed);
  2791. vn.vn_next:=ord(idx<verneedcount)*(sizeof(TElfverneed)+vn.vn_cnt*sizeof(TElfvernaux));
  2792. MaybeSwapElfverneed(vn);
  2793. verneedsec.write(vn,sizeof(TElfverneed));
  2794. auxidx:=0;
  2795. for j:=2 to dynobj.versiondefs.count-1 do
  2796. begin
  2797. ver:=TElfVersionDef(dynobj.versiondefs[j]);
  2798. if ver.index<=VER_NDX_GLOBAL then
  2799. continue;
  2800. inc(auxidx);
  2801. vna.vna_hash:=elfhash(ver.name);
  2802. vna.vna_flags:=0; { BFD copies this from verdef.vd_flags?? }
  2803. vna.vna_other:=ver.index;
  2804. vna.vna_name:=dynsymtable.fstrsec.writestr(ver.name);
  2805. vna.vna_next:=ord(auxidx<dynobj.vernaux_count)*sizeof(TElfvernaux);
  2806. MaybeSwapElfvernaux(vna);
  2807. verneedsec.write(vna,sizeof(TElfvernaux));
  2808. end;
  2809. end;
  2810. TElfExeSection(verneedsec.ExeSection).shinfo:=verneedcount;
  2811. { If there are no needed versions, .gnu.version section is not needed }
  2812. if verneedcount>0 then
  2813. begin
  2814. if source_info.endian<>target_info.endian then
  2815. for i:=0 to dynsymlist.count+1 do
  2816. symversions[i]:=swapendian(symversions[i]);
  2817. symversec.write(symversions^,(dynsymlist.count+1)*sizeof(word));
  2818. end;
  2819. FreeMem(symversions);
  2820. end;
  2821. procedure TElfExeOutput.WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
  2822. var
  2823. rel:telfreloc;
  2824. begin
  2825. rel.address:=dataofs;
  2826. rel.info:=ELF_R_INFO(symidx,typ);
  2827. {$push}{$r-}
  2828. rel.addend:=addend;
  2829. {$pop}
  2830. MaybeSwapElfReloc(rel);
  2831. dynrelocsec.write(rel,dynrelocsec.shentsize);
  2832. end;
  2833. procedure TElfExeOutput.WriteDynTag(aTag:longword;aValue:longword);
  2834. var
  2835. d: TElfDyn;
  2836. begin
  2837. d.d_tag:=aTag;
  2838. d.d_val:=aValue;
  2839. MaybeSwapElfDyn(d);
  2840. dynamicsec.write(d,sizeof(TElfDyn));
  2841. end;
  2842. procedure TElfExeOutput.WriteDynTag(aTag:longword;aSection:TObjSection;aOffs:aword);
  2843. var
  2844. d: TElfDyn;
  2845. begin
  2846. d.d_tag:=aTag;
  2847. if source_info.endian<>target_info.endian then
  2848. d.d_tag:=swapendian(d.d_tag);
  2849. dynamicsec.write(d.d_tag,sizeof(d.d_tag));
  2850. { TODO: ignores endianness! }
  2851. dynamicsec.writeReloc_internal(aSection,aOffs,sizeof(d.d_ptr),RELOC_ABSOLUTE);
  2852. end;
  2853. procedure TElfExeOutput.WriteTargetDynamicTags;
  2854. begin
  2855. { to be overridden by CPU-specific descendants }
  2856. end;
  2857. procedure TElfExeOutput.WriteDynamicTags;
  2858. var
  2859. s: aword;
  2860. i: longint;
  2861. sym: TExeSymbol;
  2862. hs:string;
  2863. dynobj: TElfDynamicObjData;
  2864. begin
  2865. for i:=0 to neededlist.Count-1 do
  2866. begin
  2867. dynobj:=TElfDynamicObjData(neededlist[i]);
  2868. s:=dynsymtable.fstrsec.writestr(dynobj.name);
  2869. dynobj.soname_strofs:=s;
  2870. WriteDynTag(DT_NEEDED,s);
  2871. end;
  2872. if IsSharedLibrary then
  2873. begin
  2874. s:=dynsymtable.fstrsec.writestr(ExtractFileName(current_module.sharedlibfilename));
  2875. WriteDynTag(DT_SONAME,s);
  2876. { TODO: names hardcoded here }
  2877. sym:=TExeSymbol(ExeSymbolList.Find('FPC_SHARED_LIB_START'));
  2878. if assigned(sym) then
  2879. WriteDynTag(DT_INIT,sym.objsymbol.objsection,sym.objsymbol.offset);
  2880. sym:=TExeSymbol(ExeSymbolList.Find('FPC_LIB_EXIT'));
  2881. if assigned(sym) then
  2882. WriteDynTag(DT_FINI,sym.objsymbol.objsection,sym.objsymbol.offset);
  2883. end;
  2884. { TODO: we need a dedicated parameter to pass runpath, instead of this hack
  2885. (-Xr is a different thing, it passes "-rpath-link"). }
  2886. if (ParaLinkOptions<>'') then
  2887. begin
  2888. hs:=ParaLinkOptions;
  2889. while (hs<>'') do
  2890. begin
  2891. if (GetToken(hs,' ')='-rpath') then
  2892. begin
  2893. s:=dynsymtable.fstrsec.writestr(GetToken(hs,' '));
  2894. WriteDynTag(DT_RPATH,s);
  2895. end;
  2896. end;
  2897. end;
  2898. writeDynTag(DT_HASH,hashobjsec);
  2899. writeDynTag(DT_STRTAB,dynsymtable.fstrsec);
  2900. writeDynTag(DT_SYMTAB,dynsymtable);
  2901. writeDynTag(DT_SYMENT,sizeof(TElfSymbol));
  2902. if Assigned(gotpltobjsec) then
  2903. writeDynTag(DT_PLTGOT,gotpltobjsec);
  2904. end;
  2905. const
  2906. pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
  2907. relsztags: array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
  2908. relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
  2909. relcnttags: array[boolean] of longword=(DT_RELCOUNT,DT_RELACOUNT);
  2910. procedure TElfExeOutput.FinishDynamicTags;
  2911. var
  2912. rela: boolean;
  2913. begin
  2914. if assigned(dynsymtable) then
  2915. writeDynTag(DT_STRSZ,dynsymtable.fstrsec.size);
  2916. if hastextrelocs then
  2917. writeDynTag(DT_TEXTREL,0);
  2918. if Assigned(pltrelocsec) and (pltrelocsec.size>0) then
  2919. begin
  2920. writeDynTag(DT_PLTRELSZ,pltrelocsec.Size);
  2921. writeDynTag(DT_PLTREL,pltreltags[pltrelocsec.shtype=SHT_RELA]);
  2922. writeDynTag(DT_JMPREL,pltrelocsec);
  2923. end;
  2924. if Assigned(dynrelocsec) and (dynrelocsec.size>0) then
  2925. begin
  2926. rela:=(dynrelocsec.shtype=SHT_RELA);
  2927. writeDynTag(pltreltags[rela],dynrelocsec);
  2928. writeDynTag(relsztags[rela],dynrelocsec.Size);
  2929. writeDynTag(relenttags[rela],dynrelocsec.shentsize);
  2930. {$ifndef MIPS}
  2931. if (relative_reloc_count>0) then
  2932. writeDynTag(relcnttags[rela],relative_reloc_count);
  2933. {$endif MIPS}
  2934. end;
  2935. WriteTargetDynamicTags;
  2936. if (verdefcount>0) or (verneedcount>0) then
  2937. begin
  2938. if (verdefcount>0) then
  2939. begin
  2940. writeDynTag(DT_VERDEF,verdefsec);
  2941. writeDynTag(DT_VERDEFNUM,verdefcount);
  2942. end;
  2943. if (verneedcount>0) then
  2944. begin
  2945. writeDynTag(DT_VERNEED,verneedsec);
  2946. writeDynTag(DT_VERNEEDNUM,verneedcount);
  2947. end;
  2948. writeDynTag(DT_VERSYM,symversec);
  2949. end;
  2950. writeDynTag(DT_NULL,0);
  2951. end;
  2952. procedure TElfExeOutput.CreatePLT;
  2953. var
  2954. reloc: TObjRelocation;
  2955. begin
  2956. pltobjsec:=TElfObjSection.create_ext(internalObjData,'.plt',
  2957. SHT_PROGBITS,SHF_ALLOC or SHF_EXECINSTR,4,16);
  2958. pltobjsec.SecOptions:=[oso_keep,oso_plt];
  2959. pltrelocsec:=TElfObjSection.create_reloc(internalObjData,'.plt',true);
  2960. pltrelocsec.SecOptions:=[oso_keep];
  2961. ipltrelocsec:=TElfObjSection.create_reloc(internalObjData,'.iplt',true);
  2962. ipltrelocsec.SecOptions:=[oso_keep];
  2963. { reference .dynamic from .got.plt, this isn't necessary if linking statically }
  2964. { TODO: maybe move writing initial .got.plt entries here completely
  2965. (needs testing --- GOT symbol may get lost if .got.plt is empty)}
  2966. if dynamiclink then
  2967. begin
  2968. reloc:=TObjRelocation.CreateSection(0,dynamicsec,RELOC_ABSOLUTE);
  2969. reloc.size:=sizeof(pint);
  2970. gotpltobjsec.ObjRelocations.Add(reloc);
  2971. end;
  2972. { Initial PLT entry, CPU-specific }
  2973. WriteFirstPLTEntry;
  2974. end;
  2975. procedure TElfExeOutput.WritePLTEntry(exesym:TExeSymbol);
  2976. begin
  2977. // must be implemented by CPU-specific descendant
  2978. InternalError(2012092102);
  2979. end;
  2980. procedure TElfExeOutput.WriteIndirectPLTEntry(exesym:TExeSymbol);
  2981. begin
  2982. // must be implemented by CPU-specific descendant
  2983. InternalError(2012092101);
  2984. end;
  2985. function TElfExeOutput.WriteData:boolean;
  2986. begin
  2987. WriteHeader;
  2988. segmentlist.ForEachCall(@segment_write_header,nil);
  2989. WriteExeSectionContent;
  2990. FWriter.WriteZeros(sizeof(TElfsechdr));
  2991. ExeSectionList.ForEachCall(@exesection_write_header,nil);
  2992. result:=true;
  2993. end;
  2994. procedure TElfExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2995. var
  2996. exportlist: TCmdStrList;
  2997. sym: TExeSymbol;
  2998. begin
  2999. AllowUndefinedSymbols:=IsSharedLibrary;
  3000. { add exported symbols to dynamic list }
  3001. exportlist:=texportlibunix(exportlib).exportedsymnames;
  3002. if not exportlist.empty then
  3003. repeat
  3004. sym:=TExeSymbol(ExeSymbolList.Find(exportlist.getfirst));
  3005. if assigned(sym) then
  3006. begin
  3007. if assigned(sym.objsymbol.objsection) then
  3008. sym.objsymbol.objsection.SecOptions:=[oso_keep];
  3009. sym.dynindex:=dynsymlist.add(sym)+1
  3010. end
  3011. else
  3012. InternalError(2012071801);
  3013. until exportlist.empty;
  3014. end;
  3015. procedure TElfExeOutput.ReportNonDSOReloc(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
  3016. begin
  3017. { TODO: include objsec properties into message }
  3018. Comment(v_error,'Relocation '+ElfTarget.RelocName(reltyp)+' against '''+objreloc.TargetName+''' cannot be used when linking a shared object; recompile with -Cg');
  3019. end;
  3020. procedure TElfExeOutput.ReportRelocOverflow(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
  3021. begin
  3022. { TODO: include objsec properties into message }
  3023. Comment(v_error,'Relocation truncated to fit: '+ElfTarget.RelocName(reltyp)+' against '''+objreloc.TargetName+'''');
  3024. end;
  3025. {****************************************************************************
  3026. TElfExeSection
  3027. ****************************************************************************}
  3028. procedure TElfExeSection.AddObjSection(objsec:TObjSection;ignoreprops:boolean);
  3029. begin
  3030. inherited AddObjSection(objsec,ignoreprops);
  3031. if ignoreprops then
  3032. exit;
  3033. if (shtype=SHT_NULL) then
  3034. begin
  3035. shtype:=TElfObjSection(objsec).shtype;
  3036. shflags:=TElfObjSection(objsec).shflags;
  3037. shentsize:=TElfObjSection(objsec).shentsize;
  3038. end;
  3039. end;
  3040. {****************************************************************************
  3041. TElfSegment
  3042. ****************************************************************************}
  3043. constructor TElfSegment.Create(atype,aflags,aalign:longword);
  3044. begin
  3045. ptype:=atype;
  3046. pflags:=aflags;
  3047. align:=aalign;
  3048. FSectionList:=TFPObjectList.Create(false);
  3049. end;
  3050. destructor TElfSegment.Destroy;
  3051. begin
  3052. FSectionList.Free;
  3053. inherited Destroy;
  3054. end;
  3055. procedure TElfSegment.Add(exesec:TExeSection);
  3056. begin
  3057. FSectionList.Add(exesec);
  3058. end;
  3059. end.