ogelf.pas 103 KB

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