2
0

ogelf.pas 115 KB

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