ogelf.pas 119 KB

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