ogelf.pas 110 KB

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