ogelf.pas 99 KB

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