ogelf.pas 116 KB

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