ogelf.pas 114 KB

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