ogelf.pas 114 KB

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