ogelf.pas 115 KB

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