ogelf.pas 120 KB

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