ogelf.pas 101 KB

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