ogelf.pas 121 KB

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