ogelf.pas 110 KB

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