ogelf.pas 113 KB

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