ogelf.pas 99 KB

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