ogelf.pas 120 KB

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