ogelf.pas 115 KB

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