ogelf.pas 113 KB

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