ogelf.pas 108 KB

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