ogelf.pas 104 KB

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