ogelf.pas 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059
  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: aword;
  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. var
  908. sep : string[3];
  909. secname : string;
  910. begin
  911. { section type user gives the user full controll on the section name }
  912. if atype=sec_user then
  913. result:=aname
  914. else
  915. begin
  916. secname:=secnames[atype];
  917. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  918. begin
  919. result:=secname+'.'+aname;
  920. exit;
  921. end;
  922. if create_smartlink_sections and (aname<>'') then
  923. begin
  924. case aorder of
  925. secorder_begin :
  926. sep:='.b_';
  927. secorder_end :
  928. sep:='.z_';
  929. else
  930. sep:='.n_';
  931. end;
  932. result:=secname+sep+aname
  933. end
  934. else
  935. result:=secname;
  936. end;
  937. end;
  938. procedure TElfObjData.CreateDebugSections;
  939. begin
  940. if target_dbg.id=dbg_stabs then
  941. begin
  942. stabssec:=createsection(sec_stab);
  943. stabstrsec:=createsection(sec_stabstr);
  944. end;
  945. end;
  946. procedure TElfObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);
  947. var
  948. symaddr : aint;
  949. objreloc: TObjRelocation;
  950. begin
  951. if CurrObjSec=nil then
  952. internalerror(200403292);
  953. objreloc:=nil;
  954. if assigned(p) then
  955. begin
  956. { real address of the symbol }
  957. symaddr:=p.address;
  958. { Local ObjSymbols can be resolved already or need a section reloc }
  959. if (p.bind=AB_LOCAL) and
  960. (reltype in [RELOC_RELATIVE,RELOC_ABSOLUTE{$ifdef x86_64},RELOC_ABSOLUTE32{$endif x86_64}]) then
  961. begin
  962. { For a reltype relocation in the same section the
  963. value can be calculated }
  964. if (p.objsection=CurrObjSec) and
  965. (reltype=RELOC_RELATIVE) then
  966. inc(data,symaddr-len-CurrObjSec.Size)
  967. else
  968. begin
  969. objreloc:=TObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,reltype);
  970. CurrObjSec.ObjRelocations.Add(objreloc);
  971. inc(data,symaddr);
  972. end;
  973. end
  974. else
  975. begin
  976. objreloc:=TObjRelocation.CreateSymbol(CurrObjSec.Size,p,reltype);
  977. CurrObjSec.ObjRelocations.Add(objreloc);
  978. { If target is a local label and it isn't handled above,
  979. patch its type in order to get it written to symtable.
  980. This may happen e.g. when taking address of Pascal label in PIC mode. }
  981. if (p.bind=AB_LOCAL) and (p.typ=AT_LABEL) then
  982. p.typ:=AT_ADDR;
  983. end;
  984. end;
  985. if assigned(objreloc) then
  986. begin
  987. objreloc.size:=len;
  988. if reltype in [RELOC_RELATIVE{$ifdef x86},RELOC_PLT32{$endif}{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then
  989. dec(data,len);
  990. if relocs_use_addend then
  991. begin
  992. objreloc.orgsize:=data;
  993. data:=0;
  994. end;
  995. end;
  996. CurrObjSec.write(data,len);
  997. end;
  998. {****************************************************************************
  999. TElfSymtab
  1000. ****************************************************************************}
  1001. const
  1002. symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym');
  1003. strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr');
  1004. symsectypes: array[boolean] of longword = (SHT_SYMTAB,SHT_DYNSYM);
  1005. symsecattrs: array[boolean] of longword = (0,SHF_ALLOC);
  1006. constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind);
  1007. var
  1008. dyn:boolean;
  1009. begin
  1010. dyn:=(aKind=esk_dyn);
  1011. create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],sizeof(pint),sizeof(TElfSymbol));
  1012. fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],1,0);
  1013. fstrsec.writezeros(1);
  1014. writezeros(sizeof(TElfSymbol));
  1015. symidx:=1;
  1016. shinfo:=1;
  1017. kind:=aKind;
  1018. end;
  1019. procedure TElfSymtab.writeInternalSymbol(avalue:aword;astridx:longword;ainfo:byte;ashndx:word);
  1020. var
  1021. elfsym:TElfSymbol;
  1022. begin
  1023. fillchar(elfsym,sizeof(elfsym),0);
  1024. elfsym.st_value:=avalue;
  1025. elfsym.st_name:=astridx;
  1026. elfsym.st_info:=ainfo;
  1027. elfsym.st_shndx:=ashndx;
  1028. inc(symidx);
  1029. inc(shinfo);
  1030. MaybeSwapElfSymbol(elfsym);
  1031. write(elfsym,sizeof(elfsym));
  1032. end;
  1033. procedure TElfSymtab.writeSymbol(objsym:TObjSymbol;nameidx:longword);
  1034. var
  1035. elfsym:TElfSymbol;
  1036. begin
  1037. fillchar(elfsym,sizeof(elfsym),0);
  1038. if nameidx=0 then
  1039. elfsym.st_name:=fstrsec.writestr(objsym.name)
  1040. else
  1041. elfsym.st_name:=nameidx;
  1042. elfsym.st_size:=objsym.size;
  1043. case objsym.bind of
  1044. AB_LOCAL :
  1045. begin
  1046. elfsym.st_value:=objsym.address;
  1047. elfsym.st_info:=STB_LOCAL shl 4;
  1048. inc(shinfo);
  1049. end;
  1050. AB_COMMON :
  1051. begin
  1052. elfsym.st_value:=var_align(objsym.size);
  1053. elfsym.st_info:=STB_GLOBAL shl 4;
  1054. elfsym.st_shndx:=SHN_COMMON;
  1055. end;
  1056. AB_EXTERNAL :
  1057. elfsym.st_info:=STB_GLOBAL shl 4;
  1058. AB_WEAK_EXTERNAL :
  1059. begin
  1060. elfsym.st_info:=STB_WEAK shl 4;
  1061. elfsym.st_value:=objsym.address;
  1062. end;
  1063. AB_GLOBAL :
  1064. begin
  1065. elfsym.st_value:=objsym.address;
  1066. elfsym.st_info:=STB_GLOBAL shl 4;
  1067. end;
  1068. end;
  1069. if (objsym.bind<>AB_EXTERNAL) {and
  1070. not(assigned(objsym.objsection) and
  1071. not(oso_data in objsym.objsection.secoptions))} then
  1072. begin
  1073. case objsym.typ of
  1074. AT_FUNCTION :
  1075. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  1076. AT_DATA :
  1077. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  1078. AT_TLS:
  1079. elfsym.st_info:=elfsym.st_info or STT_TLS;
  1080. AT_GNU_IFUNC:
  1081. elfsym.st_info:=elfsym.st_info or STT_GNU_IFUNC;
  1082. end;
  1083. end;
  1084. if objsym.bind<>AB_COMMON then
  1085. begin
  1086. if kind<>esk_obj then
  1087. begin
  1088. if assigned(objsym.objsection) and assigned(objsym.objsection.ExeSection) then
  1089. begin
  1090. if (oso_plt in objsym.objsection.SecOptions) then
  1091. elfsym.st_value:=0
  1092. else
  1093. elfsym.st_shndx:=TElfExeSection(objsym.objsection.ExeSection).secshidx;
  1094. end;
  1095. end
  1096. else
  1097. begin
  1098. if assigned(objsym.objsection) then
  1099. elfsym.st_shndx:=objsym.objsection.index
  1100. else
  1101. elfsym.st_shndx:=SHN_UNDEF;
  1102. objsym.symidx:=symidx;
  1103. end;
  1104. end;
  1105. inc(symidx);
  1106. MaybeSwapElfSymbol(elfsym);
  1107. write(elfsym,sizeof(TElfSymbol));
  1108. end;
  1109. {****************************************************************************
  1110. TElfObjectOutput
  1111. ****************************************************************************}
  1112. constructor TElfObjectOutput.create(AWriter:TObjectWriter);
  1113. begin
  1114. inherited Create(AWriter);
  1115. CObjData:=TElfObjData;
  1116. end;
  1117. procedure TElfObjectOutput.createrelocsection(s:TElfObjSection;data:TObjData);
  1118. var
  1119. i : longint;
  1120. rel : telfreloc;
  1121. objreloc : TObjRelocation;
  1122. relsym : longint;
  1123. relocsect : TElfObjSection;
  1124. begin
  1125. { create the reloc section }
  1126. relocsect:=TElfObjSection.create_reloc(data,s.name,false);
  1127. relocsect.shlink:=symtabsect.index;
  1128. relocsect.shinfo:=s.index;
  1129. { add the relocations }
  1130. for i:=0 to s.Objrelocations.count-1 do
  1131. begin
  1132. objreloc:=TObjRelocation(s.Objrelocations[i]);
  1133. { Symbol }
  1134. if assigned(objreloc.symbol) then
  1135. begin
  1136. if objreloc.symbol.symidx=-1 then
  1137. begin
  1138. writeln(objreloc.symbol.Name);
  1139. internalerror(200603012);
  1140. end;
  1141. relsym:=objreloc.symbol.symidx;
  1142. end
  1143. else
  1144. begin
  1145. if objreloc.objsection<>nil then
  1146. relsym:=objreloc.objsection.secsymidx
  1147. else
  1148. relsym:=SHN_UNDEF;
  1149. end;
  1150. rel.address:=objreloc.dataoffset;
  1151. rel.info:=ELF_R_INFO(relsym,ElfTarget.encodereloc(objreloc));
  1152. rel.addend:=objreloc.orgsize;
  1153. { write reloc }
  1154. { ElfXX_Rel is essentially ElfXX_Rela without the addend field. }
  1155. MaybeSwapElfReloc(rel);
  1156. relocsect.write(rel,relocsect.shentsize);
  1157. end;
  1158. end;
  1159. procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
  1160. begin
  1161. { Must not write symbols for internal sections like .symtab }
  1162. { TODO: maybe use inclusive list of section types instead }
  1163. if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
  1164. exit;
  1165. TObjSection(p).secsymidx:=symtabsect.symidx;
  1166. symtabsect.writeInternalSymbol(0,0,STT_SECTION,TObjSection(p).index);
  1167. end;
  1168. procedure TElfObjectOutput.createsymtab(data: TObjData);
  1169. var
  1170. i : longint;
  1171. objsym : TObjSymbol;
  1172. begin
  1173. with data do
  1174. begin
  1175. { filename entry }
  1176. symtabsect.writeInternalSymbol(0,1,STT_FILE,SHN_ABS);
  1177. { section }
  1178. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1179. { First the Local Symbols, this is required by ELF. The localsyms
  1180. count stored in shinfo is used to skip the local symbols
  1181. when traversing the symtab }
  1182. for i:=0 to ObjSymbolList.Count-1 do
  1183. begin
  1184. objsym:=TObjSymbol(ObjSymbolList[i]);
  1185. if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
  1186. symtabsect.WriteSymbol(objsym);
  1187. end;
  1188. { Global Symbols }
  1189. for i:=0 to ObjSymbolList.Count-1 do
  1190. begin
  1191. objsym:=TObjSymbol(ObjSymbolList[i]);
  1192. if (objsym.bind<>AB_LOCAL) then
  1193. symtabsect.WriteSymbol(objsym);
  1194. end;
  1195. { update the .symtab section header }
  1196. symtabsect.shlink:=symtabsect.fstrsec.index;
  1197. end;
  1198. end;
  1199. procedure TElfObjectOutput.createshstrtab(data: TObjData);
  1200. var
  1201. i,prefixlen:longint;
  1202. objsec,target:TElfObjSection;
  1203. begin
  1204. shstrtabsect.writezeros(1);
  1205. prefixlen:=length('.rel')+ord(relocs_use_addend);
  1206. for i:=0 to data.ObjSectionList.Count-1 do
  1207. begin
  1208. objsec:=TElfObjSection(data.ObjSectionList[i]);
  1209. { Alias section names into names of corresponding reloc sections,
  1210. this is allowed by ELF specs and saves good half of .shstrtab space. }
  1211. if objsec.shtype=relsec_shtype[relocs_use_addend] then
  1212. begin
  1213. target:=TElfObjSection(data.ObjSectionList[objsec.shinfo-1]);
  1214. if (target.ObjRelocations.Count=0) or
  1215. (target.shstridx<prefixlen) then
  1216. InternalError(2012101204);
  1217. objsec.shstridx:=target.shstridx-prefixlen;
  1218. end
  1219. else
  1220. begin
  1221. if objsec.ObjRelocations.Count<>0 then
  1222. shstrtabsect.write(relsec_prefix[true][1],prefixlen);
  1223. objsec.shstridx:=shstrtabsect.writestr(objsec.name);
  1224. end;
  1225. end;
  1226. end;
  1227. procedure TElfObjectOutput.writesectionheader(s:TElfObjSection);
  1228. var
  1229. sechdr : telfsechdr;
  1230. begin
  1231. fillchar(sechdr,sizeof(sechdr),0);
  1232. sechdr.sh_name:=s.shstridx;
  1233. sechdr.sh_type:=s.shtype;
  1234. sechdr.sh_flags:=s.shflags;
  1235. sechdr.sh_offset:=s.datapos;
  1236. sechdr.sh_size:=s.Size;
  1237. sechdr.sh_link:=s.shlink;
  1238. sechdr.sh_info:=s.shinfo;
  1239. sechdr.sh_addralign:=s.secalign;
  1240. sechdr.sh_entsize:=s.shentsize;
  1241. MaybeSwapSecHeader(sechdr);
  1242. writer.write(sechdr,sizeof(sechdr));
  1243. end;
  1244. procedure TElfObjectOutput.section_count_sections(p:TObject;arg:pointer);
  1245. begin
  1246. TElfObjSection(p).index:=pword(arg)^;
  1247. inc(pword(arg)^);
  1248. end;
  1249. procedure TElfObjectOutput.section_create_relocsec(p:TObject;arg:pointer);
  1250. begin
  1251. if (TElfObjSection(p).ObjRelocations.count>0) then
  1252. createrelocsection(TElfObjSection(p),TObjData(arg));
  1253. end;
  1254. procedure TElfObjectOutput.section_write_sechdr(p:TObject;arg:pointer);
  1255. begin
  1256. writesectionheader(TElfObjSection(p));
  1257. end;
  1258. function TElfObjectOutput.writedata(data:TObjData):boolean;
  1259. var
  1260. header : telfheader;
  1261. shoffset,
  1262. datapos : aword;
  1263. nsections : word;
  1264. begin
  1265. result:=false;
  1266. with data do
  1267. begin
  1268. { default sections }
  1269. symtabsect:=TElfSymtab.create(data,esk_obj);
  1270. shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,1,0);
  1271. { "no executable stack" marker for Linux }
  1272. if (target_info.system in systems_linux) and
  1273. not(cs_executable_stack in current_settings.moduleswitches) then
  1274. TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,1,0);
  1275. { insert filename as first in strtab }
  1276. symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
  1277. { calc amount of sections we have }
  1278. nsections:=1;
  1279. { also create the index in the section header table }
  1280. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1281. { create .symtab and .strtab }
  1282. createsymtab(data);
  1283. { Create the relocation sections, this needs valid secidx and symidx }
  1284. ObjSectionList.ForEachCall(@section_create_relocsec,data);
  1285. { recalc nsections to incude the reloc sections }
  1286. nsections:=1;
  1287. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1288. { create .shstrtab }
  1289. createshstrtab(data);
  1290. { Calculate the filepositions }
  1291. datapos:=$40; { elfheader + alignment }
  1292. { section data }
  1293. layoutsections(datapos);
  1294. { section headers }
  1295. shoffset:=datapos;
  1296. inc(datapos,(nsections+1)*sizeof(telfsechdr));
  1297. { Write ELF Header }
  1298. fillchar(header,sizeof(header),0);
  1299. header.magic[0]:=$7f; { = #127'ELF' }
  1300. header.magic[1]:=$45;
  1301. header.magic[2]:=$4c;
  1302. header.magic[3]:=$46;
  1303. header.file_class:=ELFCLASS;
  1304. if target_info.endian=endian_big then
  1305. header.data_encoding:=2
  1306. else
  1307. header.data_encoding:=1;
  1308. header.file_version:=1;
  1309. header.e_type:=ET_REL;
  1310. header.e_machine:=ELFMACHINE;
  1311. {$ifdef arm}
  1312. if (current_settings.fputype=fpu_soft) then
  1313. header.e_flags:=$600;
  1314. {$endif arm}
  1315. header.e_version:=1;
  1316. header.e_shoff:=shoffset;
  1317. header.e_shstrndx:=shstrtabsect.index;
  1318. header.e_shnum:=nsections;
  1319. header.e_ehsize:=sizeof(telfheader);
  1320. header.e_shentsize:=sizeof(telfsechdr);
  1321. MaybeSwapHeader(header);
  1322. writer.write(header,sizeof(header));
  1323. writer.writezeros($40-sizeof(header)); { align }
  1324. { Sections }
  1325. WriteSectionContent(data);
  1326. { section headers, start with an empty header for sh_undef }
  1327. writer.writezeros(sizeof(telfsechdr));
  1328. ObjSectionList.ForEachCall(@section_write_sechdr,nil);
  1329. end;
  1330. result:=true;
  1331. end;
  1332. {****************************************************************************
  1333. TELFAssembler
  1334. ****************************************************************************}
  1335. constructor TElfAssembler.Create(smart:boolean);
  1336. begin
  1337. inherited Create(smart);
  1338. CObjOutput:=TElfObjectOutput;
  1339. end;
  1340. {****************************************************************************
  1341. TELFObjectInput
  1342. ****************************************************************************}
  1343. constructor TElfObjInput.Create;
  1344. begin
  1345. inherited Create;
  1346. CObjData:=TElfObjData;
  1347. end;
  1348. destructor TElfObjInput.Destroy;
  1349. begin
  1350. if Assigned(FSymTbl) then
  1351. FreeMem(FSymTbl);
  1352. if Assigned(FSecTbl) then
  1353. FreeMem(FSecTbl);
  1354. if Assigned(strtab) then
  1355. FreeMem(strtab);
  1356. if Assigned(shstrtab) then
  1357. FreeMem(shstrtab);
  1358. if Assigned(symversions) then
  1359. FreeMem(symversions);
  1360. inherited Destroy;
  1361. end;
  1362. procedure TElfObjInput.LoadRelocations(const secrec:TSectionRec);
  1363. var
  1364. i: longint;
  1365. rel: TElfReloc;
  1366. reltyp: byte;
  1367. relsym: longint;
  1368. objrel: TObjRelocation;
  1369. p: TObjSymbol;
  1370. begin
  1371. FReader.Seek(secrec.relocpos);
  1372. if secrec.sec=nil then
  1373. InternalError(2012060203);
  1374. for i:=0 to secrec.relocs-1 do
  1375. begin
  1376. FReader.Read(rel,secrec.relentsize);
  1377. MaybeSwapElfReloc(rel);
  1378. reltyp:=rel.info and $FF;
  1379. {$ifdef cpu64bitaddr}
  1380. relsym:=rel.info shr 32;
  1381. {$else cpu64bitaddr}
  1382. relsym:=(rel.info shr 8) and $FFFFFF;
  1383. {$endif cpu64bitaddr}
  1384. if relsym>=syms then
  1385. InternalError(2012060204);
  1386. p:=TObjSymbol(FSymTbl[relsym]);
  1387. if assigned(p) then
  1388. begin
  1389. objrel:=TObjRelocation.CreateRaw(rel.address-secrec.sec.mempos,p,reltyp);
  1390. if relocs_use_addend then
  1391. objrel.orgsize:=rel.addend;
  1392. { perform target-specific actions }
  1393. ElfTarget.loadreloc(objrel);
  1394. secrec.sec.ObjRelocations.add(objrel);
  1395. end
  1396. else
  1397. begin
  1398. InputError('Unable to resolve symbol of relocation');
  1399. exit;
  1400. end;
  1401. end;
  1402. end;
  1403. procedure TElfObjInput.LoadSymbols(objdata:TObjData;count,locals:longword);
  1404. var
  1405. i: longint;
  1406. sym: TElfSymbol;
  1407. bind: TAsmSymBind;
  1408. typ: TAsmSymType;
  1409. objsym: TObjSymbol;
  1410. ver: word;
  1411. begin
  1412. FSymTbl:=AllocMem(count*sizeof(Pointer));
  1413. for i:=1 to count-1 do
  1414. begin
  1415. FReader.Read(sym,sizeof(TElfSymbol));
  1416. MaybeSwapElfSymbol(sym);
  1417. if sym.st_name>=strtablen then
  1418. InternalError(2012060205);
  1419. if sym.st_shndx=SHN_ABS then { ignore absolute symbols (should we really do it???) }
  1420. Continue
  1421. else if sym.st_shndx=SHN_COMMON then
  1422. bind:=AB_COMMON
  1423. else if (sym.st_shndx>=nsects) or
  1424. (
  1425. (sym.st_shndx>0) and
  1426. (FSecTbl[sym.st_shndx].sec=nil) and
  1427. (not dynobj)
  1428. ) then
  1429. begin
  1430. writeln(objdata.name,' ',i);
  1431. InternalError(2012060206)
  1432. end
  1433. else
  1434. case (sym.st_info shr 4) of
  1435. STB_LOCAL:
  1436. bind:=AB_LOCAL;
  1437. STB_GLOBAL:
  1438. if sym.st_shndx=SHN_UNDEF then
  1439. bind:=AB_EXTERNAL
  1440. else
  1441. bind:=AB_GLOBAL;
  1442. STB_WEAK:
  1443. bind:=AB_WEAK_EXTERNAL;
  1444. else
  1445. InternalError(2012060207);
  1446. end;
  1447. case (sym.st_info and $0F) of
  1448. STT_NOTYPE:
  1449. typ:=AT_NONE;
  1450. STT_OBJECT:
  1451. typ:=AT_DATA;
  1452. STT_FUNC:
  1453. typ:=AT_FUNCTION;
  1454. STT_SECTION:
  1455. typ:=AT_SECTION;
  1456. STT_FILE:
  1457. continue;
  1458. STT_TLS:
  1459. typ:=AT_TLS;
  1460. STT_GNU_IFUNC:
  1461. typ:=AT_GNU_IFUNC;
  1462. else
  1463. writeln(objdata.name,' ',sym.st_info and $0F);
  1464. InternalError(2012060208);
  1465. end;
  1466. { If reading DSO, we're interested only in global symbols defined there.
  1467. Symbols with non-current version should also be ignored. }
  1468. if dynobj then
  1469. begin
  1470. if assigned(symversions) then
  1471. begin
  1472. ver:=symversions[i];
  1473. if (ver=0) or (ver > $7FFF) then
  1474. continue;
  1475. end;
  1476. if (bind= AB_LOCAL) or (sym.st_shndx=SHN_UNDEF) then
  1477. continue;
  1478. end;
  1479. { validity of name and objsection has been checked above }
  1480. { !! all AT_SECTION symbols have duplicate (null) name,
  1481. therefore TObjSection.CreateSymbol cannot be used here }
  1482. objsym:=TObjSymbol.Create(objdata.ObjSymbolList,string(PChar(@strtab[sym.st_name])));
  1483. objsym.bind:=bind;
  1484. objsym.typ:=typ;
  1485. if bind<>AB_COMMON then
  1486. objsym.objsection:=FSecTbl[sym.st_shndx].sec;
  1487. objsym.offset:=sym.st_value;
  1488. objsym.size:=sym.st_size;
  1489. FSymTbl[i]:=objsym;
  1490. end;
  1491. end;
  1492. procedure TElfObjInput.LoadSection(const hdr;index:longint;objdata:tobjdata);
  1493. var
  1494. shdr: TElfsechdr absolute hdr;
  1495. sec: TElfObjSection;
  1496. secname: string;
  1497. begin
  1498. case shdr.sh_type of
  1499. SHT_NULL:
  1500. {ignore};
  1501. { SHT_STRTAB may appear for .stabstr and other debug sections.
  1502. .shstrtab and .strtab are processed separately and don't appear here. }
  1503. SHT_PROGBITS,SHT_NOBITS,SHT_NOTE,SHT_STRTAB:
  1504. begin
  1505. if shdr.sh_name>=shstrtablen then
  1506. InternalError(2012060210);
  1507. secname:=string(PChar(@shstrtab[shdr.sh_name]));
  1508. sec:=TElfObjSection.create_ext(objdata,secname,
  1509. shdr.sh_type,shdr.sh_flags,shdr.sh_addralign,shdr.sh_entsize);
  1510. if (Length(secname)>3) and (secname[2] in ['d','f','n','s']) then
  1511. begin
  1512. if (Pos('.stub',secname)=1) or
  1513. (Pos('.fpc',secname)=1) then
  1514. sec.SecOptions:=[oso_keep]
  1515. { ELF does not have any flags specific to debug sections,
  1516. but reserves names starting with '.debug' for this purpose }
  1517. else if (Pos('.debug',secname)=1) or
  1518. (secname='.stab') or
  1519. (secname='.stabstr') then
  1520. sec.SecOptions:=[oso_debug]
  1521. else if (secname='.note.GNU-stack') and (shdr.sh_type=SHT_PROGBITS) then
  1522. begin
  1523. if (shdr.sh_flags and SHF_EXECINSTR)=0 then
  1524. objdata.ExecStack:=False;
  1525. end;
  1526. end;
  1527. if (shdr.sh_type=SHT_NOTE) and (shdr.sh_size<>0) then
  1528. sec.SecOptions:=[oso_keep];
  1529. sec.index:=index;
  1530. sec.DataPos:=shdr.sh_offset;
  1531. sec.MemPos:=shdr.sh_addr;
  1532. sec.Size:=shdr.sh_size;
  1533. FSecTbl[index].sec:=sec;
  1534. end;
  1535. SHT_REL,SHT_RELA:
  1536. begin
  1537. if shdr.sh_info>=nsects then
  1538. InternalError(2012060211);
  1539. if shdr.sh_entsize<>longword((2+ord(shdr.sh_type=SHT_RELA))*sizeof(pint)) then
  1540. InternalError(2012060212);
  1541. with FSecTbl[shdr.sh_info] do
  1542. begin
  1543. relocpos:=shdr.sh_offset;
  1544. relocs:=shdr.sh_size div shdr.sh_entsize;
  1545. relentsize:=shdr.sh_entsize;
  1546. end;
  1547. end;
  1548. SHT_GROUP:
  1549. if (shdr.sh_size>=2*sizeof(longword)) and
  1550. (shdr.sh_entsize=sizeof(longword)) and
  1551. ((shdr.sh_size mod shdr.sh_entsize)=0) then
  1552. begin
  1553. { we need a dummy section to load the corresponding symbol later on }
  1554. secname:=string(PChar(@shstrtab[shdr.sh_name]));
  1555. sec:=TElfObjSection.create_ext(objdata,secname,
  1556. shdr.sh_type,shdr.sh_flags,shdr.sh_addralign,shdr.sh_entsize);
  1557. sec.index:=index;
  1558. FSecTbl[index].sec:=sec;
  1559. end;
  1560. else
  1561. InternalError(2012072603);
  1562. end;
  1563. FLoaded[index]:=True;
  1564. end;
  1565. function TElfObjInput.LoadHeader:word;
  1566. var
  1567. header:TElfHeader;
  1568. begin
  1569. result:=ET_NONE;
  1570. if not FReader.read(header,sizeof(header)) then
  1571. begin
  1572. InputError('Can''t read ELF header');
  1573. exit;
  1574. end;
  1575. if (header.magic[0]<>$7f) or (header.magic[1]<>$45) or
  1576. (header.magic[2]<>$4c) or (header.magic[3]<>$46) then
  1577. begin
  1578. InputError('Illegal ELF magic');
  1579. exit;
  1580. end;
  1581. if (header.file_version<>1) then
  1582. begin
  1583. InputError('Unknown ELF file version');
  1584. exit;
  1585. end;
  1586. if (header.file_class<>ELFCLASS) then
  1587. begin
  1588. InputError('Wrong ELF file class (32/64 bit mismatch)');
  1589. exit;
  1590. end;
  1591. if (header.data_encoding<>1+ord(target_info.endian=endian_big)) then
  1592. begin
  1593. InputError('ELF endianness does not match target');
  1594. exit;
  1595. end;
  1596. MaybeSwapHeader(header);
  1597. if (header.e_version<>1) then
  1598. begin
  1599. InputError('Unknown ELF data version');
  1600. exit;
  1601. end;
  1602. if (header.e_machine<>ELFMACHINE) then
  1603. begin
  1604. InputError('ELF file is for different CPU');
  1605. exit;
  1606. end;
  1607. nsects:=header.e_shnum;
  1608. shentsize:=header.e_shentsize;
  1609. shoffset:=header.e_shoff;
  1610. shstrndx:=header.e_shstrndx;
  1611. result:=header.e_type;
  1612. end;
  1613. procedure TElfObjInput.LoadDynamic(const hdr;objdata:TObjData);
  1614. var
  1615. shdr: TElfsechdr absolute hdr;
  1616. dt: TElfDyn;
  1617. i: longint;
  1618. begin
  1619. if (shdr.sh_entsize<>sizeof(TElfDyn)) then
  1620. InternalError(2012071403);
  1621. FReader.Seek(shdr.sh_offset);
  1622. for i:=0 to (shdr.sh_size div shdr.sh_entsize)-1 do
  1623. begin
  1624. FReader.Read(dt,sizeof(TElfDyn));
  1625. MaybeSwapElfDyn(dt);
  1626. case dt.d_tag of
  1627. DT_NULL:
  1628. break;
  1629. DT_SONAME:
  1630. TElfObjData(objdata).FName:=string(PChar(@strtab[dt.d_ptr]));
  1631. DT_NEEDED:
  1632. ;
  1633. end;
  1634. end;
  1635. end;
  1636. function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
  1637. var
  1638. i,j,symtabndx,strndx,dynndx,
  1639. versymndx,verdefndx,verneedndx: longint;
  1640. objsec: TElfObjSection;
  1641. shdrs: array of TElfsechdr;
  1642. begin
  1643. FReader:=AReader;
  1644. InputFileName:=AReader.FileName;
  1645. result:=false;
  1646. i:=LoadHeader;
  1647. if (i=ET_NONE) then { error message already given in this case }
  1648. exit;
  1649. if (i<>ET_REL) and (i<>ET_DYN) then
  1650. begin
  1651. InputError('Not a relocatable or dynamic ELF file');
  1652. exit;
  1653. end;
  1654. dynobj:=(i=ET_DYN);
  1655. if shentsize<>sizeof(TElfsechdr) then
  1656. InternalError(2012062701);
  1657. FSecTbl:=AllocMem(nsects*sizeof(TSectionRec));
  1658. FLoaded:=AllocMem(nsects*sizeof(boolean));
  1659. SetLength(shdrs,nsects);
  1660. FReader.Seek(shoffset);
  1661. if not FReader.Read(shdrs[0],nsects*sizeof(TElfsechdr)) then
  1662. begin
  1663. InputError('Can''t read ELF section headers');
  1664. exit;
  1665. end;
  1666. if source_info.endian<>target_info.endian then
  1667. for i:=0 to nsects-1 do
  1668. MaybeSwapSecHeader(shdrs[i]);
  1669. { First, load the .shstrtab section }
  1670. if shstrndx>=nsects then
  1671. InternalError(2012060201);
  1672. if shdrs[shstrndx].sh_type<>SHT_STRTAB then
  1673. InternalError(2012060202);
  1674. shstrtablen:=shdrs[shstrndx].sh_size;
  1675. GetMem(shstrtab,shstrtablen);
  1676. FReader.seek(shdrs[shstrndx].sh_offset);
  1677. FReader.read(shstrtab^,shstrtablen);
  1678. FLoaded[shstrndx]:=True;
  1679. { Locate the symtable, it is typically at the end so loop backwards.
  1680. Load the strings, postpone symtable itself until done with sections.
  1681. Note that is is legal to have no symtable.
  1682. For DSO, locate .dynsym instead, this one is near the beginning, but
  1683. overall number of sections won't be big. }
  1684. symtabndx:=-1;
  1685. for i:=nsects-1 downto 1 do
  1686. begin
  1687. if (shdrs[i].sh_type<>symsectypes[dynobj]) then
  1688. continue;
  1689. if (shdrs[i].sh_entsize<>sizeof(TElfSymbol)) then
  1690. InternalError(2012060213);
  1691. if shdrs[i].sh_link>=nsects then
  1692. InternalError(2012062702);
  1693. strndx:=shdrs[i].sh_link;
  1694. if shdrs[strndx].sh_type<>SHT_STRTAB then
  1695. InternalError(2012062703);
  1696. strtablen:=shdrs[strndx].sh_size;
  1697. GetMem(strtab,strtablen);
  1698. FReader.seek(shdrs[strndx].sh_offset);
  1699. FReader.read(strtab^,strtablen);
  1700. symtaboffset:=shdrs[i].sh_offset;
  1701. syms:=shdrs[i].sh_size div sizeof(TElfSymbol);
  1702. localsyms:=shdrs[i].sh_info;
  1703. FLoaded[i]:=True;
  1704. FLoaded[strndx]:=True;
  1705. symtabndx:=i;
  1706. break;
  1707. end;
  1708. if dynobj then
  1709. begin
  1710. { Locate .dynamic and version sections. Expect a single one of a kind. }
  1711. dynndx:=0;
  1712. versymndx:=0;
  1713. verdefndx:=0;
  1714. verneedndx:=0;
  1715. for i:=nsects-1 downto 0 do
  1716. begin
  1717. case shdrs[i].sh_type of
  1718. SHT_DYNAMIC:
  1719. begin
  1720. if dynndx<>0 then
  1721. InternalError(2012102001);
  1722. dynndx:=i;
  1723. if (shdrs[dynndx].sh_link<>strndx) then
  1724. InternalError(2012071402);
  1725. LoadDynamic(shdrs[dynndx],objdata);
  1726. end;
  1727. SHT_GNU_versym:
  1728. begin
  1729. if versymndx<>0 then
  1730. InternalError(2012102002);
  1731. versymndx:=i;
  1732. if shdrs[i].sh_entsize<>sizeof(word) then
  1733. InternalError(2012102003);
  1734. if shdrs[i].sh_link<>symtabndx then
  1735. InternalError(2012102004);
  1736. if shdrs[i].sh_size<>syms*sizeof(word) then
  1737. InternalError(2012102005);
  1738. GetMem(symversions,shdrs[i].sh_size);
  1739. FReader.seek(shdrs[i].sh_offset);
  1740. FReader.read(symversions^,shdrs[i].sh_size);
  1741. if source_info.endian<>target_info.endian then
  1742. for j:=0 to syms-1 do
  1743. SwapEndian(symversions[j]);
  1744. end;
  1745. SHT_GNU_verdef:
  1746. begin
  1747. if verdefndx<>0 then
  1748. InternalError(2012102006);
  1749. verdefndx:=i;
  1750. //sh_link->.dynstr
  1751. //sh_info->.hash
  1752. end;
  1753. SHT_GNU_verneed:
  1754. begin
  1755. if verneedndx<>0 then
  1756. InternalError(2012102007);
  1757. verneedndx:=i;
  1758. //sh_link->.dynstr
  1759. //sh_info->hash
  1760. end;
  1761. end;
  1762. end;
  1763. if dynndx=0 then
  1764. InternalError(2012071401);
  1765. { for DSO, we aren't interested in actual sections, but need to a dummy one
  1766. to maintain integrity. }
  1767. objsec:=TElfObjSection.create_ext(objdata,'*DSO*',SHT_PROGBITS,0,0,0);
  1768. for i:=1 to nsects-1 do
  1769. FSecTbl[i].sec:=objsec;
  1770. { load the symtable }
  1771. FReader.Seek(symtaboffset+sizeof(TElfSymbol));
  1772. LoadSymbols(objdata,syms,localsyms);
  1773. result:=True;
  1774. exit;
  1775. end;
  1776. { assume stack is executable until proven otherwise }
  1777. objdata.ExecStack:=True;
  1778. { Process section headers }
  1779. for i:=1 to nsects-1 do
  1780. if not FLoaded[i] then
  1781. LoadSection(shdrs[i],i,objdata);
  1782. { load the content }
  1783. ReadSectionContent(objdata);
  1784. { load the symtable }
  1785. FReader.Seek(symtaboffset+sizeof(TElfSymbol));
  1786. LoadSymbols(objdata,syms,localsyms);
  1787. { finish relocations }
  1788. for i:=0 to objdata.ObjSectionList.Count-1 do
  1789. begin
  1790. objsec:=TElfObjSection(objdata.ObjsectionList[i]);
  1791. { skip debug sections }
  1792. if (oso_debug in objsec.SecOptions) and
  1793. (cs_link_strip in current_settings.globalswitches) and
  1794. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1795. continue;
  1796. if FSecTbl[objsec.index].relocpos>0 then
  1797. LoadRelocations(FSecTbl[objsec.index]);
  1798. end;
  1799. result:=True;
  1800. end;
  1801. class function TElfObjInput.CanReadObjData(AReader:TObjectreader):boolean;
  1802. var
  1803. header: TElfHeader;
  1804. begin
  1805. result:=false;
  1806. if AReader.Read(header,sizeof(header)) then
  1807. begin;
  1808. if (header.magic[0]=$7f) and (header.magic[1]=$45) and
  1809. (header.magic[2]=$4c) and (header.magic[3]=$46) then
  1810. { TODO: check additional fields }
  1811. result:=true;
  1812. end;
  1813. AReader.Seek(0);
  1814. end;
  1815. {*****************************************************************************
  1816. TElfExeOutput
  1817. *****************************************************************************}
  1818. constructor TElfExeOutput.Create;
  1819. begin
  1820. inherited Create;
  1821. CObjData:=TElfObjData;
  1822. CExeSection:=TElfExeSection;
  1823. {$ifdef cpu64}
  1824. MaxMemPos:=Qword($FFFFFFFFFFFFFFFF);
  1825. //MaxMemPos:=$7EFFFFFF; { As specified by SysV AMD64 ABI for small memory model }
  1826. {$else cpu64}
  1827. MaxMemPos:=$7FFFFFFF;
  1828. {$endif cpu64}
  1829. SectionMemAlign:=$20;
  1830. SectionDataAlign:=$20;
  1831. segmentlist:=TFPObjectList.Create(True);
  1832. neededlist:=TFPHashList.Create;
  1833. end;
  1834. destructor TElfExeOutput.Destroy;
  1835. begin
  1836. neededlist.Free;
  1837. segmentlist.Free;
  1838. dynsymlist.Free;
  1839. if assigned(dynsymnames) then
  1840. FreeMem(dynsymnames);
  1841. inherited Destroy;
  1842. end;
  1843. function TElfExeOutput.AttachSection(objsec:TObjSection):TElfExeSection;
  1844. begin
  1845. objsec.SecOptions:=[oso_keep];
  1846. result:=TElfExeSection(FindExeSection(objsec.name));
  1847. if result=nil then
  1848. result:=TElfExeSection.Create(ExeSectionList,objsec.name);
  1849. result.AddObjSection(objsec);
  1850. end;
  1851. function TElfExeOutput.CreateSegment(atype,aflags,aalign:longword):TElfSegment;
  1852. begin
  1853. result:=TElfSegment.Create(atype,aflags,aalign);
  1854. segmentlist.add(result);
  1855. end;
  1856. procedure TElfExeOutput.WriteHeader;
  1857. var
  1858. header: TElfHeader;
  1859. begin
  1860. FillChar(header,sizeof(header),0);
  1861. header.magic[0]:=$7f; { = #127'ELF' }
  1862. header.magic[1]:=$45;
  1863. header.magic[2]:=$4c;
  1864. header.magic[3]:=$46;
  1865. header.file_class:=ELFCLASS;
  1866. if target_info.endian=endian_big then
  1867. header.data_encoding:=2
  1868. else
  1869. header.data_encoding:=1;
  1870. header.file_version:=1;
  1871. if IsSharedLibrary then
  1872. header.e_type:=ET_DYN
  1873. else
  1874. header.e_type:=ET_EXEC;
  1875. header.e_machine:=ELFMACHINE;
  1876. {$ifdef arm}
  1877. if (current_settings.fputype=fpu_soft) then
  1878. header.e_flags:=$600;
  1879. {$endif arm}
  1880. header.e_version:=1;
  1881. header.e_phoff:=sizeof(TElfHeader);
  1882. header.e_shoff:=shoffset;
  1883. header.e_shstrndx:=ExeSectionList.IndexOf(shstrtabsect.ExeSection)+1;
  1884. header.e_shnum:=ExeSectionList.Count+1;
  1885. header.e_phnum:=segmentlist.count;
  1886. header.e_ehsize:=sizeof(telfheader);
  1887. if assigned(EntrySym) then
  1888. header.e_entry:=EntrySym.Address;
  1889. header.e_shentsize:=sizeof(telfsechdr);
  1890. header.e_phentsize:=sizeof(telfproghdr);
  1891. MaybeSwapHeader(header);
  1892. FWriter.Write(header,sizeof(header));
  1893. end;
  1894. procedure TElfExeOutput.exesection_write_header(p:TObject;arg:Pointer);
  1895. var
  1896. shdr: TElfsechdr;
  1897. exesec: TElfExeSection absolute p;
  1898. begin
  1899. FillChar(shdr,sizeof(shdr),0);
  1900. shdr.sh_name:=exesec.shstridx;
  1901. if (ExeWriteMode=ewm_dbgonly) and
  1902. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  1903. shdr.sh_type:=SHT_NOBITS
  1904. else
  1905. shdr.sh_type:=exesec.shtype;
  1906. shdr.sh_flags:=exesec.shflags;
  1907. if (oso_load in exesec.SecOptions) then
  1908. shdr.sh_addr:=exesec.MemPos;
  1909. shdr.sh_offset:=exesec.DataPos;
  1910. shdr.sh_size:=exesec.Size;
  1911. shdr.sh_link:=exesec.shlink;
  1912. shdr.sh_info:=exesec.shinfo;
  1913. shdr.sh_addralign:=exesec.SecAlign;
  1914. shdr.sh_entsize:=exesec.shentsize;
  1915. MaybeSwapSecHeader(shdr);
  1916. FWriter.Write(shdr,sizeof(shdr));
  1917. end;
  1918. procedure TElfExeOutput.segment_write_header(p:TObject;arg:Pointer);
  1919. var
  1920. phdr: TElfproghdr;
  1921. seg: TElfSegment absolute p;
  1922. begin
  1923. FillChar(phdr,sizeof(phdr),0);
  1924. phdr.p_type:=seg.ptype;
  1925. phdr.p_flags:=seg.pflags;
  1926. phdr.p_align:=seg.align;
  1927. phdr.p_offset:=seg.DataPos;
  1928. phdr.p_filesz:=seg.DataSize;
  1929. phdr.p_memsz:=seg.MemSize;
  1930. phdr.p_vaddr:=seg.MemPos;
  1931. phdr.p_paddr:=seg.MemPos;
  1932. MaybeSwapHeader(phdr);
  1933. FWriter.Write(phdr,sizeof(phdr));
  1934. end;
  1935. procedure TElfExeOutput.WriteStaticSymtable;
  1936. var
  1937. i: longint;
  1938. sec: TElfExeSection;
  1939. exesym: TExeSymbol;
  1940. begin
  1941. for i:=0 to ExeSectionList.Count-1 do
  1942. begin
  1943. sec:=TElfExeSection(ExeSectionList[i]);
  1944. { Must not write symbols for internal sections like .symtab }
  1945. if (sec.shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
  1946. continue;
  1947. sec.secsymidx:=symtab.symidx;
  1948. symtab.writeInternalSymbol(sec.mempos,0,STT_SECTION,sec.secshidx);
  1949. end;
  1950. { local symbols first }
  1951. for i:=0 to ExeSymbolList.Count-1 do
  1952. begin
  1953. exesym:=TExeSymbol(ExeSymbolList[i]);
  1954. if (exesym.objsymbol.bind=AB_LOCAL) and (exesym.objsymbol.typ<>AT_LABEL) then
  1955. symtab.WriteSymbol(exesym.objsymbol);
  1956. end;
  1957. { Global Symbols }
  1958. for i:=0 to ExeSymbolList.Count-1 do
  1959. begin
  1960. exesym:=TExeSymbol(ExeSymbolList[i]);
  1961. if (exesym.objsymbol.bind<>AB_LOCAL) then
  1962. symtab.WriteSymbol(exesym.objsymbol);
  1963. end;
  1964. { update exe section properties }
  1965. symtab.ExeSection.size:=symtab.size;
  1966. TElfExeSection(symtab.ExeSection).shinfo:=symtab.shinfo;
  1967. TElfExeSection(symtab.ExeSection).shlink:=ExeSectionList.IndexOf(symtab.fstrsec.ExeSection)+1;
  1968. symtab.fstrsec.ExeSection.Size:=symtab.fstrsec.size;
  1969. end;
  1970. procedure TElfExeOutput.MapSectionsToSegments;
  1971. var
  1972. seg: TElfSegment;
  1973. exesec: TExeSection;
  1974. i: longint;
  1975. begin
  1976. if (not IsSharedLibrary) and assigned(interpobjsec) then
  1977. begin
  1978. phdrseg:=CreateSegment(PT_PHDR,PF_R or PF_X,sizeof(pint));
  1979. seg:=CreateSegment(PT_INTERP,PF_R,1);
  1980. seg.Add(interpobjsec.ExeSection);
  1981. end;
  1982. textseg:=CreateSegment(PT_LOAD,PF_X or PF_R,ELF_MAXPAGESIZE);
  1983. dataseg:=CreateSegment(PT_LOAD,PF_R or PF_W,ELF_MAXPAGESIZE);
  1984. for i:=0 to ExeSectionList.Count-1 do
  1985. begin
  1986. exesec:=TExeSection(ExeSectionList[i]);
  1987. if (oso_load in exesec.SecOptions) then
  1988. begin
  1989. if (TElfExeSection(exesec).shflags and SHF_TLS)<>0 then
  1990. begin
  1991. if tlsseg=nil then
  1992. tlsseg:=CreateSegment(PT_TLS,PF_R,sizeof(pint));
  1993. tlsseg.add(exesec);
  1994. end;
  1995. { TODO: at least on Linux, ld seems to drop .note.ABI-tag for static executables.
  1996. (Logic is as follows: there is no .note.ABI-tag section in ld script, so it
  1997. is processed as orphan section. As such, it is placed after .interp.
  1998. For static executables .interp is dropped, and it looks like there's nowhere to
  1999. place .note.ABI-tag in this case)
  2000. Always including it doesn't harm though (except increasing file size). }
  2001. if TElfExeSection(exesec).shtype=SHT_NOTE then
  2002. begin
  2003. if noteseg=nil then
  2004. noteseg:=CreateSegment(PT_NOTE,PF_R,4);
  2005. noteseg.Add(exesec);
  2006. Include(exesec.SecOptions,oso_debug_copy);
  2007. end;
  2008. if (oso_executable in exesec.SecOptions) or
  2009. not (oso_write in exesec.SecOptions) then
  2010. textseg.add(exesec)
  2011. else
  2012. dataseg.add(exesec);
  2013. end;
  2014. end;
  2015. if dynamiclink then
  2016. begin
  2017. seg:=CreateSegment(PT_DYNAMIC,PF_R or PF_W,sizeof(pint));
  2018. seg.add(dynamicsec.ExeSection);
  2019. end;
  2020. { stack flags }
  2021. CreateSegment(PT_GNU_STACK,PF_R or PF_W or (PF_X*ord(ExecStack)),sizeof(pint));
  2022. end;
  2023. procedure TElfExeOutput.PrepareGOT;
  2024. var
  2025. i,j,k: longint;
  2026. objsec: TElfObjSection;
  2027. exesec: TExeSection;
  2028. begin
  2029. for i:=0 to ExeSectionList.Count-1 do
  2030. begin
  2031. exesec:=TExeSection(ExeSectionList[i]);
  2032. for j:=0 to exesec.ObjSectionlist.count-1 do
  2033. begin
  2034. objsec:=TElfObjSection(exesec.ObjSectionlist[j]);
  2035. { ignore linker-generated and debug sections }
  2036. if (objsec.objdata=internalobjdata) or (oso_debug in objsec.SecOptions) then
  2037. continue;
  2038. if not objsec.Used then
  2039. internalerror(2012060901);
  2040. for k:=0 to objsec.ObjRelocations.Count-1 do
  2041. GOTRelocPass1(objsec,TObjRelocation(objsec.ObjRelocations[k]));
  2042. end;
  2043. end;
  2044. { remember sizes for sanity checking }
  2045. gotsize:=gotobjsec.size;
  2046. if assigned(dynrelocsec) then
  2047. dynrelsize:=dynrelocsec.size
  2048. else
  2049. dynrelsize:=0;
  2050. end;
  2051. procedure TElfExeOutput.Load_Start;
  2052. begin
  2053. inherited Load_Start;
  2054. dynsymlist:=TFPObjectList.Create(False);
  2055. gotpltobjsec:=TElfObjSection.create_ext(internalObjData,'.got.plt',
  2056. SHT_PROGBITS,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(pint));
  2057. gotobjsec:=TElfObjSection.create_ext(internalObjData,'.got',
  2058. SHT_PROGBITS,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(pint));
  2059. gotobjsec.SecOptions:=[oso_keep];
  2060. { GOT symbol and reserved .got.plt entries }
  2061. internalObjData.SetSection(gotpltobjsec);
  2062. gotsymbol:=internalObjData.SymbolDefine('_GLOBAL_OFFSET_TABLE_',AB_GLOBAL,AT_DATA);
  2063. gotpltobjsec.writeZeros(3*sizeof(pint));
  2064. end;
  2065. procedure TElfExeOutput.Load_DynamicObject(objdata:TObjData);
  2066. var
  2067. i: longint;
  2068. exesym: TExeSymbol;
  2069. objsym: TObjSymbol;
  2070. begin
  2071. Comment(v_debug,'Dynamic object: '+objdata.name);
  2072. if neededlist.Find(objdata.name)=nil then
  2073. neededlist.Add(objdata.name,objdata);
  2074. for i:=0 to UnresolvedExeSymbols.Count-1 do
  2075. begin
  2076. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2077. if exesym.State<>symstate_undefined then
  2078. continue;
  2079. objsym:=TObjSymbol(objdata.ObjSymbolList.Find(exesym.name));
  2080. if assigned(objsym) then
  2081. begin
  2082. exesym.State:=symstate_defined;
  2083. exesym.dynindex:=dynsymlist.Add(exesym)+1;
  2084. end;
  2085. end;
  2086. end;
  2087. procedure TElfExeOutput.Order_Start;
  2088. begin
  2089. inherited Order_Start;
  2090. dynamiclink:=IsSharedLibrary or (dynsymlist.count>0) or
  2091. (
  2092. (UnresolvedExeSymbols.Count>0) and
  2093. not (cs_link_staticflag in current_settings.globalswitches)
  2094. );
  2095. if dynamiclink then
  2096. InitDynlink;
  2097. if dynamiclink or (IndirectObjSymbols.Count>0) then
  2098. CreatePLT;
  2099. end;
  2100. procedure TElfExeOutput.Order_end;
  2101. procedure set_oso_keep(const s:string);
  2102. var
  2103. exesec:TExeSection;
  2104. objsec:TObjSection;
  2105. i:longint;
  2106. begin
  2107. exesec:=TExeSection(ExeSectionList.Find(s));
  2108. if assigned(exesec) then
  2109. begin
  2110. for i:=0 to exesec.ObjSectionList.Count-1 do
  2111. begin
  2112. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2113. { ignore sections used for symbol definition }
  2114. if oso_data in objsec.SecOptions then
  2115. objsec.SecOptions:=[oso_keep];
  2116. end;
  2117. end;
  2118. end;
  2119. begin
  2120. inherited Order_end;
  2121. set_oso_keep('.init');
  2122. set_oso_keep('.fini');
  2123. set_oso_keep('.jcr');
  2124. set_oso_keep('.ctors');
  2125. set_oso_keep('.dtors');
  2126. set_oso_keep('.preinit_array');
  2127. set_oso_keep('.init_array');
  2128. set_oso_keep('.fini_array');
  2129. set_oso_keep('.eh_frame');
  2130. { let .dynamic reference other dynamic sections so they aren't marked
  2131. for removal as unused }
  2132. if dynamiclink then
  2133. WriteDynamicTags;
  2134. end;
  2135. procedure TElfExeOutput.AfterUnusedSectionRemoval;
  2136. var
  2137. i:longint;
  2138. exesym:TExeSymbol;
  2139. objsym:TObjSymbol;
  2140. objsec: TObjSection;
  2141. begin
  2142. { Unused section removal changes state of referenced exesymbols
  2143. to symstate_dynamic. Remaining ones can be removed. }
  2144. for i:=0 to dynsymlist.count-1 do
  2145. begin
  2146. exesym:=TExeSymbol(dynsymlist[i]);
  2147. if assigned(exesym.ObjSymbol.ObjSection) then // an exported symbol
  2148. continue;
  2149. if exesym.state<>symstate_dynamic then
  2150. begin
  2151. dynsymlist[i]:=nil;
  2152. exesym.dynindex:=0;
  2153. end;
  2154. end;
  2155. dynsymlist.Pack;
  2156. { reindex }
  2157. for i:=0 to dynsymlist.count-1 do
  2158. TExeSymbol(dynsymlist[i]).dynindex:=i+1;
  2159. { Drop unresolved symbols that aren't referenced, assign dynamic
  2160. indices to remaining ones. }
  2161. for i:=0 to UnresolvedExeSymbols.Count-1 do
  2162. begin
  2163. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2164. if exesym.state=symstate_dynamic then
  2165. begin
  2166. if exesym.dynindex<>0 then
  2167. InternalError(2012062301);
  2168. exesym.dynindex:=dynsymlist.add(exesym)+1;
  2169. exesym.state:=symstate_defined;
  2170. end
  2171. else
  2172. UnresolvedExeSymbols[i]:=nil;
  2173. end;
  2174. UnresolvedExeSymbols.Pack;
  2175. { Scan relocations to determine size of GOT, dynamic reloc section, etc. }
  2176. PrepareGOT;
  2177. { Write required PLT entries }
  2178. for i:=0 to dynsymlist.Count-1 do
  2179. begin
  2180. exesym:=TExeSymbol(dynsymlist[i]);
  2181. if assigned(exesym.ObjSymbol.objsection) then // an exported symbol
  2182. continue;
  2183. { if there's no PLT references to symbol, then PLT entry isn't needed }
  2184. { !! Does not work correctly yet !! }
  2185. // if (exesym.objsymbol.refs and symref_plt)=0 then
  2186. // continue;
  2187. { This symbol has a valid address to which relocations are resolved,
  2188. but it remains (weak)external when written to dynamic symtable. }
  2189. objsym:=internalobjdata.CreateSymbol(exesym.name);
  2190. objsym.typ:=AT_FUNCTION;
  2191. objsym.bind:=exesym.ObjSymbol.bind; { AB_EXTERNAL or AB_WEAK_EXTERNAL }
  2192. objsym.offset:=pltobjsec.size;
  2193. objsym.objsection:=pltobjsec;
  2194. exesym.ObjSymbol:=objsym;
  2195. WritePLTEntry(exesym);
  2196. end;
  2197. { Handle indirect symbols }
  2198. for i:=0 to IndirectObjSymbols.Count-1 do
  2199. begin
  2200. objsym:=TObjSymbol(IndirectObjSymbols[i]);
  2201. objsec:=objsym.ExeSymbol.ObjSymbol.objsection;
  2202. objsym.bind:=AB_EXTERNAL; { cheat FixupSymbols }
  2203. if (oso_plt in objsec.SecOptions) then
  2204. continue;
  2205. WriteIndirectPLTEntry(objsym.ExeSymbol);
  2206. end;
  2207. FixupSymbols;
  2208. if dynamiclink then
  2209. WriteDynamicSymbolsHash;
  2210. { Create .shstrtab section, which is needed in both exe and .dbg files }
  2211. shstrtabsect:=TElfObjSection.Create_ext(internalObjData,'.shstrtab',SHT_STRTAB,0,1,0);
  2212. shstrtabsect.SecOptions:=[oso_debug_copy];
  2213. AttachSection(shstrtabsect);
  2214. { Create the static symtable (.symtab and .strtab) }
  2215. if (cs_link_separate_dbg_file in current_settings.globalswitches) or
  2216. not(cs_link_strip in current_settings.globalswitches) then
  2217. begin
  2218. symtab:=TElfSymtab.Create(internalObjData,esk_exe);
  2219. symtab.SecOptions:=[oso_debug];
  2220. symtab.fstrsec.SecOptions:=[oso_debug];
  2221. AttachSection(symtab);
  2222. AttachSection(symtab.fstrsec);
  2223. end;
  2224. { Re-enable sections which end up to contain some data
  2225. (.got, .rel[a].dyn, .rel[a].plt (includes .rel[a].iplt) and .hash }
  2226. if gotobjsec.size<>0 then
  2227. Exclude(gotobjsec.ExeSection.SecOptions,oso_disabled);
  2228. if assigned(dynrelocsec) and (dynrelocsec.size<>0) then
  2229. Exclude(dynrelocsec.ExeSection.SecOptions,oso_disabled);
  2230. if assigned(pltrelocsec) and (pltrelocsec.size>0) then
  2231. Exclude(pltrelocsec.ExeSection.SecOptions,oso_disabled);
  2232. if assigned(ipltrelocsec) and (ipltrelocsec.size>0) then
  2233. Exclude(ipltrelocsec.ExeSection.SecOptions,oso_disabled);
  2234. if assigned(hashobjsec) then
  2235. Exclude(hashobjsec.ExeSection.SecOptions,oso_disabled);
  2236. RemoveDisabledSections;
  2237. MapSectionsToSegments;
  2238. if dynamiclink then
  2239. FinishDynamicTags;
  2240. end;
  2241. procedure TElfExeOutput.MemPos_Start;
  2242. var
  2243. i,j: longint;
  2244. seg: TElfSegment;
  2245. exesec: TElfExeSection;
  2246. objsec: TObjSection;
  2247. tempmempos: qword;
  2248. begin
  2249. { Remove any existing .shstrtab contents }
  2250. if (shstrtabsect.size>0) then
  2251. begin
  2252. shstrtabsect.ReleaseData;
  2253. shstrtabsect.Size:=0;
  2254. shstrtabsect.SecOptions:=[oso_data];
  2255. end;
  2256. { Assign section indices and fill .shstrtab
  2257. List of sections cannot be modified after this point. }
  2258. shstrtabsect.writezeros(1);
  2259. for i:=0 to ExeSectionList.Count-1 do
  2260. begin
  2261. exesec:=TElfExeSection(ExeSectionList[i]);
  2262. exesec.shstridx:=shstrtabsect.writestr(exesec.Name);
  2263. exesec.secshidx:=i+1;
  2264. end;
  2265. if dynamiclink then
  2266. begin
  2267. { fixup sh_link/sh_info members of various dynamic sections }
  2268. TElfExeSection(hashobjsec.ExeSection).shlink:=TElfExeSection(dynsymtable.ExeSection).secshidx;
  2269. i:=TElfExeSection(dynsymtable.fstrsec.ExeSection).secshidx;
  2270. TElfExeSection(dynamicsec.ExeSection).shlink:=i;
  2271. TElfExeSection(dynsymtable.ExeSection).shlink:=i;
  2272. if assigned(pltrelocsec) then
  2273. begin
  2274. TElfExeSection(pltrelocsec.ExeSection).shlink:=TElfExeSection(dynsymtable.ExeSection).secshidx;
  2275. TElfExeSection(pltrelocsec.ExeSection).shinfo:=TElfExeSection(pltobjsec.ExeSection).secshidx;
  2276. end;
  2277. if assigned(dynrelocsec) and assigned(dynrelocsec.ExeSection) then
  2278. TElfExeSection(dynrelocsec.ExeSection).shlink:=TElfExeSection(dynsymtable.ExeSection).secshidx;
  2279. end
  2280. else if assigned(ipltrelocsec) then
  2281. TElfExeSection(ipltrelocsec.ExeSection).shinfo:=TElfExeSection(pltobjsec.ExeSection).secshidx;
  2282. { The actual layout }
  2283. if IsSharedLibrary then
  2284. CurrMemPos:=0
  2285. else
  2286. CurrMemPos:=TEXT_SEGMENT_START;
  2287. textseg.MemPos:=CurrMemPos;
  2288. if assigned(phdrseg) then
  2289. begin
  2290. phdrseg.Mempos:=CurrMemPos+sizeof(TElfHeader);
  2291. phdrseg.Memsize:=sizeof(TElfproghdr)*segmentlist.count;
  2292. end;
  2293. CurrMemPos:=CurrMemPos+sizeof(TElfHeader)+segmentlist.count*sizeof(TElfproghdr);
  2294. MemPos_Segment(textseg);
  2295. CurrMemPos:=Align(CurrMemPos,SectionDataAlign); {! Data,not MemAlign}
  2296. CurrMemPos:=CurrMemPos+ELF_MAXPAGESIZE;
  2297. dataseg.MemPos:=CurrMemPos;
  2298. MemPos_Segment(dataseg);
  2299. { Mempos of unmapped sections is forced to zero, but we have to set positions
  2300. of its objsections and update sizes }
  2301. for i:=0 to ExeSectionList.Count-1 do
  2302. begin
  2303. exesec:=TElfExeSection(ExeSectionList[i]);
  2304. if not (oso_load in exesec.SecOptions) then
  2305. begin
  2306. tempmempos:=0;
  2307. exesec.MemPos:=tempmempos;
  2308. for j:=0 to exesec.ObjSectionList.Count-1 do
  2309. begin
  2310. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2311. tempmempos:=objsec.setmempos(tempmempos);
  2312. end;
  2313. exesec.Size:=tempmempos;
  2314. end;
  2315. end;
  2316. { Update MemPos and MemSize of non-load segments,
  2317. in particular, TLS sizes are needed to resolve relocations }
  2318. for i:=0 to segmentlist.count-1 do
  2319. begin
  2320. seg:=TElfSegment(segmentlist[i]);
  2321. if (seg.ptype=PT_LOAD) or (seg.FSectionList.Count=0) then
  2322. continue;
  2323. seg.MemPos:=TExeSection(seg.FSectionList.First).MemPos;
  2324. for j:=0 to seg.FSectionList.Count-1 do
  2325. begin
  2326. exesec:=TElfExeSection(seg.FSectionList[j]);
  2327. seg.MemSize:=exesec.MemPos+exesec.Size-seg.MemPos;
  2328. end;
  2329. end;
  2330. if (not gotwritten) then
  2331. begin
  2332. { reset size of .got and .rel[a].dyn, they will be refilled while fixing up relocations }
  2333. if assigned(gotobjsec) then
  2334. gotobjsec.size:=0;
  2335. if assigned(dynrelocsec) then
  2336. begin
  2337. dynrelocsec.size:=0;
  2338. { write actual .dynsym content (needs valid symbol addresses) }
  2339. dynsymtable.size:=sizeof(TElfsymbol);
  2340. for i:=0 to dynsymlist.count-1 do
  2341. dynsymtable.writeSymbol(TExeSymbol(dynsymlist[i]).objsymbol,dynsymnames[i]);
  2342. end;
  2343. end;
  2344. end;
  2345. procedure TElfExeOutput.MemPos_Segment(seg:TElfSegment);
  2346. var
  2347. i: longint;
  2348. exesec: TElfExeSection;
  2349. begin
  2350. for i:=0 to seg.FSectionList.Count-1 do
  2351. begin
  2352. exesec:=TElfExeSection(seg.FSectionList[i]);
  2353. inherited MemPos_ExeSection(exesec);
  2354. { .tbss should not contribute to address space }
  2355. if (exesec.shtype=SHT_NOBITS) and ((exesec.shflags and SHF_TLS)<>0) then
  2356. CurrMemPos:=exesec.MemPos;
  2357. end;
  2358. { calculate size of the segment }
  2359. seg.MemSize:=CurrMemPos-seg.MemPos;
  2360. end;
  2361. procedure TElfExeOutput.MemPos_ExeSection(const aname:string);
  2362. begin
  2363. // Ignore. All layout is done in mempos_start
  2364. end;
  2365. procedure TElfExeOutput.DataPos_Start;
  2366. var
  2367. i,j: longint;
  2368. exesec: TExeSection;
  2369. seg: TElfSegment;
  2370. begin
  2371. gotwritten:=true;
  2372. { sanity checks }
  2373. if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
  2374. InternalError(2012092501);
  2375. if assigned(dynrelocsec) and (dynrelsize<>dynrelocsec.size) then
  2376. InternalError(2012092502);
  2377. if (ExeWriteMode=ewm_dbgonly) or
  2378. (
  2379. (ExeWriteMode=ewm_exefull) and
  2380. not(cs_link_strip in current_settings.globalswitches)
  2381. ) then
  2382. WriteStaticSymtable;
  2383. { first handle primary segments }
  2384. textseg.DataPos:=0;
  2385. CurrDataPos:=sizeof(TElfHeader)+sizeof(TElfproghdr)*segmentlist.count;
  2386. if assigned(phdrseg) then
  2387. begin
  2388. phdrseg.DataPos:=sizeof(TElfHeader);
  2389. phdrseg.DataSize:=sizeof(TElfproghdr)*segmentlist.count;
  2390. end;
  2391. DataPos_Segment(textseg);
  2392. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  2393. dataseg.DataPos:=CurrDataPos;
  2394. DataPos_Segment(dataseg);
  2395. { then unmapped sections }
  2396. for i:=0 to ExeSectionList.Count-1 do
  2397. begin
  2398. exesec:=TExeSection(ExeSectionList[i]);
  2399. if not (oso_load in exesec.SecOptions) then
  2400. inherited DataPos_ExeSection(exesec);
  2401. end;
  2402. { finally, update size/position of non-load segments }
  2403. for i:=0 to segmentlist.count-1 do
  2404. begin
  2405. seg:=TElfSegment(segmentlist[i]);
  2406. if (seg.ptype=PT_LOAD) or (seg.FSectionList.Count=0) then
  2407. continue;
  2408. seg.DataPos:=TExeSection(seg.FSectionList.First).DataPos;
  2409. for j:=0 to seg.FSectionList.Count-1 do
  2410. begin
  2411. exesec:=TExeSection(seg.FSectionList[j]);
  2412. if oso_data in exesec.SecOptions then
  2413. seg.DataSize:=exesec.DataPos+exesec.Size-seg.DataPos;
  2414. end;
  2415. end;
  2416. { place section headers after the data }
  2417. shoffset:=CurrDataPos;
  2418. CurrDataPos:=CurrDataPos+ExeSectionList.Count*sizeof(TElfsechdr);
  2419. end;
  2420. procedure TElfExeOutput.DataPos_Segment(seg:TElfSegment);
  2421. var
  2422. i: longint;
  2423. exesec: TElfExeSection;
  2424. begin
  2425. for i:=0 to seg.FSectionList.Count-1 do
  2426. begin
  2427. exesec:=TElfExeSection(seg.FSectionList[i]);
  2428. { ELF needs DataPos set to 'would-be' value for sections that
  2429. don't have data, and for non-debug sections in .dbg file, too.
  2430. This slightly differs from generic approach. }
  2431. if not (oso_data in exesec.SecOptions) or
  2432. (
  2433. (ExeWriteMode=ewm_dbgonly) and
  2434. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[])
  2435. ) then
  2436. begin
  2437. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  2438. exesec.DataPos:=CurrDataPos;
  2439. end
  2440. else
  2441. inherited DataPos_ExeSection(exesec);
  2442. end;
  2443. { calculate size of the segment }
  2444. seg.DataSize:=CurrDataPos-seg.DataPos;
  2445. end;
  2446. procedure TElfExeOutput.DataPos_ExeSection(const aname:string);
  2447. begin
  2448. // Ignore. Work is done entirely in datapos_start.
  2449. end;
  2450. procedure TElfExeOutput.InitDynlink;
  2451. begin
  2452. if not IsSharedLibrary then
  2453. begin
  2454. interpobjsec:=internalObjData.createsection('.interp',1,[oso_data,oso_load,oso_keep]);
  2455. { TODO: supply target-specific default }
  2456. {$ifdef x86_64}
  2457. interpobjsec.writestr('/lib64/ld-linux-x86-64.so.2');
  2458. {$else}
  2459. interpobjsec.writestr('/lib/ld-linux.so.2');
  2460. {$endif x86_64}
  2461. end;
  2462. hashobjsec:=TElfObjSection.create_ext(internalObjData,'.hash',
  2463. SHT_HASH,SHF_ALLOC,sizeof(pint),4);
  2464. hashobjsec.secoptions:=[oso_keep];
  2465. dynsymtable:=TElfSymtab.create(internalObjData,esk_dyn);
  2466. dynamicsec:=TElfObjSection.create_ext(internalObjData,'.dynamic',
  2467. SHT_DYNAMIC,SHF_ALLOC or SHF_WRITE,sizeof(pint),sizeof(TElfDyn));
  2468. dynamicsec.SecOptions:=[oso_keep];
  2469. dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
  2470. dynrelocsec.SecOptions:=[oso_keep];
  2471. end;
  2472. const
  2473. hashbuckets: array[0..15] of longint=(
  2474. 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
  2475. 16411, 32771);
  2476. {$push}{$r-,q-}
  2477. function elfhash(const name:string):longword;
  2478. var
  2479. g: longword;
  2480. i: longint;
  2481. begin
  2482. result:=0;
  2483. for i:=1 to length(name) do
  2484. begin
  2485. result:=(result shl 4)+ord(name[i]);
  2486. g:=result and $F0000000;
  2487. if g>0 then
  2488. result:=result xor (g shr 24);
  2489. result:=result and (not g);
  2490. end;
  2491. end;
  2492. {$pop}
  2493. procedure TElfExeOutput.WriteDynamicSymbolsHash;
  2494. var
  2495. nchains,nbuckets: longint;
  2496. i,j: longint;
  2497. hashdata: plongint;
  2498. sym: TExeSymbol;
  2499. begin
  2500. dynsymnames:=AllocMem(dynsymlist.count*sizeof(longword));
  2501. nchains:=dynsymlist.Count+1;
  2502. { determine suitable bucket count }
  2503. i:=high(hashbuckets);
  2504. while (i>=0) and (nchains<hashbuckets[i]) do
  2505. dec(i);
  2506. nbuckets:=hashbuckets[i];
  2507. hashdata:=AllocMem((2+nchains+nbuckets)*sizeof(longint));
  2508. hashdata[0]:=nbuckets;
  2509. hashdata[1]:=nchains;
  2510. { The contents of .dynsym can be written only after mempos pass
  2511. because it needs valid symbol virtual addresses and section indices.
  2512. Here we preset .dynsym size and write names, in order to get
  2513. correct size of .dynstr section. }
  2514. dynsymtable.size:=(dynsymlist.count+1)*sizeof(TElfsymbol);
  2515. for i:=0 to dynsymlist.Count-1 do
  2516. begin
  2517. sym:=TExeSymbol(dynsymlist[i]);
  2518. dynsymnames[i]:=dynsymtable.fstrsec.writestr(sym.objsymbol.name);
  2519. j:=(elfhash(sym.objsymbol.name) mod nbuckets)+2;
  2520. while hashdata[j]<>0 do
  2521. j:=2+nbuckets+hashdata[j];
  2522. hashdata[j]:=i+1;
  2523. end;
  2524. if source_info.endian<>target_info.endian then
  2525. for i:=0 to nchains+nbuckets+1 do
  2526. hashdata[i]:=swapendian(hashdata[i]);
  2527. hashobjsec.write(hashdata^,(2+nchains+nbuckets)*sizeof(longint));
  2528. freemem(hashdata);
  2529. end;
  2530. procedure TElfExeOutput.WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
  2531. var
  2532. rel:telfreloc;
  2533. begin
  2534. rel.address:=dataofs;
  2535. rel.info:=ELF_R_INFO(symidx,typ);
  2536. rel.addend:=addend;
  2537. MaybeSwapElfReloc(rel);
  2538. dynrelocsec.write(rel,dynrelocsec.shentsize);
  2539. end;
  2540. procedure TElfExeOutput.WriteDynTag(aTag:longword;aValue:longword);
  2541. var
  2542. d: TElfDyn;
  2543. begin
  2544. d.d_tag:=aTag;
  2545. d.d_val:=aValue;
  2546. MaybeSwapElfDyn(d);
  2547. dynamicsec.write(d,sizeof(TElfDyn));
  2548. end;
  2549. procedure TElfExeOutput.WriteDynTag(aTag:longword;aSection:TObjSection;aOffs:aword);
  2550. var
  2551. d: TElfDyn;
  2552. begin
  2553. d.d_tag:=aTag;
  2554. if source_info.endian<>target_info.endian then
  2555. d.d_tag:=swapendian(d.d_tag);
  2556. dynamicsec.write(d.d_tag,sizeof(d.d_tag));
  2557. { TODO: ignores endianness! }
  2558. dynamicsec.writeReloc_internal(aSection,aOffs,sizeof(d.d_ptr),RELOC_ABSOLUTE);
  2559. end;
  2560. procedure TElfExeOutput.WriteDynamicTags;
  2561. var
  2562. s: aword;
  2563. i: longint;
  2564. sym: TExeSymbol;
  2565. hs:string;
  2566. begin
  2567. for i:=0 to neededlist.Count-1 do
  2568. begin
  2569. s:=dynsymtable.fstrsec.writestr(neededlist.NameOfIndex(i));
  2570. WriteDynTag(DT_NEEDED,s);
  2571. end;
  2572. if IsSharedLibrary then
  2573. begin
  2574. s:=dynsymtable.fstrsec.writestr(ExtractFileName(current_module.sharedlibfilename));
  2575. WriteDynTag(DT_SONAME,s);
  2576. { TODO: names hardcoded here }
  2577. sym:=TExeSymbol(ExeSymbolList.Find('FPC_SHARED_LIB_START'));
  2578. if assigned(sym) then
  2579. WriteDynTag(DT_INIT,sym.objsymbol.objsection,sym.objsymbol.offset);
  2580. sym:=TExeSymbol(ExeSymbolList.Find('FPC_LIB_EXIT'));
  2581. if assigned(sym) then
  2582. WriteDynTag(DT_FINI,sym.objsymbol.objsection,sym.objsymbol.offset);
  2583. end;
  2584. { TODO: we need a dedicated parameter to pass runpath, instead of this hack
  2585. (-Xr is a different thing, it passes "-rpath-link"). }
  2586. if (ParaLinkOptions<>'') then
  2587. begin
  2588. hs:=ParaLinkOptions;
  2589. while (hs<>'') do
  2590. begin
  2591. if (GetToken(hs,' ')='-rpath') then
  2592. begin
  2593. s:=dynsymtable.fstrsec.writestr(GetToken(hs,' '));
  2594. WriteDynTag(DT_RPATH,s);
  2595. end;
  2596. end;
  2597. end;
  2598. writeDynTag(DT_HASH,hashobjsec);
  2599. writeDynTag(DT_STRTAB,dynsymtable.fstrsec);
  2600. writeDynTag(DT_SYMTAB,dynsymtable);
  2601. writeDynTag(DT_SYMENT,sizeof(TElfSymbol));
  2602. if Assigned(gotpltobjsec) then
  2603. writeDynTag(DT_PLTGOT,gotpltobjsec);
  2604. end;
  2605. const
  2606. pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
  2607. relsztags: array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
  2608. relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
  2609. procedure TElfExeOutput.FinishDynamicTags;
  2610. begin
  2611. if assigned(dynsymtable) then
  2612. writeDynTag(DT_STRSZ,dynsymtable.fstrsec.size);
  2613. if hastextrelocs then
  2614. writeDynTag(DT_TEXTREL,0);
  2615. if Assigned(pltrelocsec) and (pltrelocsec.size>0) then
  2616. begin
  2617. writeDynTag(DT_PLTRELSZ,pltrelocsec.Size);
  2618. writeDynTag(DT_PLTREL,pltreltags[relocs_use_addend]);
  2619. writeDynTag(DT_JMPREL,pltrelocsec);
  2620. end;
  2621. if Assigned(dynrelocsec) and (dynrelocsec.size>0) then
  2622. begin
  2623. writeDynTag(pltreltags[relocs_use_addend],dynrelocsec);
  2624. writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
  2625. writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
  2626. end;
  2627. writeDynTag(DT_NULL,0);
  2628. end;
  2629. procedure TElfExeOutput.CreatePLT;
  2630. var
  2631. reloc: TObjRelocation;
  2632. begin
  2633. pltobjsec:=TElfObjSection.create_ext(internalObjData,'.plt',
  2634. SHT_PROGBITS,SHF_ALLOC or SHF_EXECINSTR,4,16);
  2635. pltobjsec.SecOptions:=[oso_keep,oso_plt];
  2636. pltrelocsec:=TElfObjSection.create_reloc(internalObjData,'.plt',true);
  2637. pltrelocsec.SecOptions:=[oso_keep];
  2638. ipltrelocsec:=TElfObjSection.create_reloc(internalObjData,'.iplt',true);
  2639. ipltrelocsec.SecOptions:=[oso_keep];
  2640. { reference .dynamic from .got.plt, this isn't necessary if linking statically }
  2641. { TODO: maybe move writing initial .got.plt entries here completely
  2642. (needs testing --- GOT symbol may get lost if .got.plt is empty)}
  2643. if dynamiclink then
  2644. begin
  2645. reloc:=TObjRelocation.CreateSection(0,dynamicsec,RELOC_ABSOLUTE);
  2646. reloc.size:=sizeof(pint);
  2647. gotpltobjsec.ObjRelocations.Add(reloc);
  2648. end;
  2649. { Initial PLT entry, CPU-specific }
  2650. WriteFirstPLTEntry;
  2651. end;
  2652. procedure TElfExeOutput.WritePLTEntry(exesym:TExeSymbol);
  2653. begin
  2654. // must be implemented by CPU-specific descendant
  2655. InternalError(2012092102);
  2656. end;
  2657. procedure TElfExeOutput.WriteIndirectPLTEntry(exesym:TExeSymbol);
  2658. begin
  2659. // must be implemented by CPU-specific descendant
  2660. InternalError(2012092101);
  2661. end;
  2662. function TElfExeOutput.WriteData:boolean;
  2663. begin
  2664. WriteHeader;
  2665. segmentlist.ForEachCall(@segment_write_header,nil);
  2666. WriteExeSectionContent;
  2667. FWriter.WriteZeros(sizeof(TElfsechdr));
  2668. ExeSectionList.ForEachCall(@exesection_write_header,nil);
  2669. result:=true;
  2670. end;
  2671. procedure TElfExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2672. var
  2673. i:longint;
  2674. exportlist: TCmdStrList;
  2675. sym: TExeSymbol;
  2676. begin
  2677. { add exported symbols to dynamic list }
  2678. exportlist:=texportlibunix(exportlib).exportedsymnames;
  2679. if not exportlist.empty then
  2680. repeat
  2681. sym:=TExeSymbol(ExeSymbolList.Find(exportlist.getfirst));
  2682. if assigned(sym) then
  2683. begin
  2684. if assigned(sym.objsymbol.objsection) then
  2685. sym.objsymbol.objsection.SecOptions:=[oso_keep];
  2686. sym.dynindex:=dynsymlist.add(sym)+1
  2687. end
  2688. else
  2689. InternalError(2012071801);
  2690. until exportlist.empty;
  2691. { Mark unresolved weak symbols as defined, they will become dynamic further on.
  2692. If compiling a .so, make all symbols dynamic, since shared library may reference
  2693. symbols from executable which does not participate in linking. }
  2694. for i:=0 to UnresolvedExeSymbols.Count-1 do
  2695. begin
  2696. sym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2697. if (sym.objsymbol.bind=AB_WEAK_EXTERNAL) or IsSharedLibrary then
  2698. sym.state:=symstate_defined;
  2699. end;
  2700. end;
  2701. {****************************************************************************
  2702. TElfExeSection
  2703. ****************************************************************************}
  2704. procedure TElfExeSection.AddObjSection(objsec:TObjSection;ignoreprops:boolean);
  2705. begin
  2706. inherited AddObjSection(objsec,ignoreprops);
  2707. if ignoreprops then
  2708. exit;
  2709. if (shtype=SHT_NULL) then
  2710. begin
  2711. shtype:=TElfObjSection(objsec).shtype;
  2712. shflags:=TElfObjSection(objsec).shflags;
  2713. shentsize:=TElfObjSection(objsec).shentsize;
  2714. end;
  2715. end;
  2716. {****************************************************************************
  2717. TElfSegment
  2718. ****************************************************************************}
  2719. constructor TElfSegment.Create(atype,aflags,aalign:longword);
  2720. begin
  2721. ptype:=atype;
  2722. pflags:=aflags;
  2723. align:=aalign;
  2724. FSectionList:=TFPObjectList.Create(false);
  2725. end;
  2726. destructor TElfSegment.Destroy;
  2727. begin
  2728. FSectionList.Free;
  2729. inherited Destroy;
  2730. end;
  2731. procedure TElfSegment.Add(exesec:TExeSection);
  2732. begin
  2733. FSectionList.Add(exesec);
  2734. end;
  2735. end.