ogelf.pas 99 KB

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