ogelf.pas 115 KB

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