ogelf.pas 119 KB

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