ogelf.pas 118 KB

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