ogelf.pas 116 KB

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