ogelf.pas 116 KB

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