ogelf.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508
  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. { output }
  28. ogbase,
  29. owbase;
  30. type
  31. TElfObjSection = class(TObjSection)
  32. public
  33. shstridx,
  34. shtype,
  35. shflags,
  36. shlink,
  37. shinfo,
  38. shentsize : longint;
  39. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  40. constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags:longint;Aalign:shortint;Aentsize:longint);
  41. constructor create_reloc(aobjdata:TObjData;const Aname:string;allocflag:boolean);
  42. end;
  43. TElfSymtabKind = (esk_obj,esk_exe,esk_dyn);
  44. TElfSymtab = class(TElfObjSection)
  45. public
  46. kind: TElfSymtabKind;
  47. fstrsec: TObjSection;
  48. symidx: longint;
  49. constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce;
  50. procedure writeSymbol(objsym:TObjSymbol;nameidx:longword=0);
  51. procedure writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word);
  52. end;
  53. TElfObjData = class(TObjData)
  54. public
  55. constructor create(const n:string);override;
  56. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  57. procedure CreateDebugSections;override;
  58. procedure writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);override;
  59. end;
  60. TElfObjectOutput = class(tObjOutput)
  61. private
  62. symtabsect: TElfSymtab;
  63. shstrtabsect: TElfObjSection;
  64. procedure createrelocsection(s:TElfObjSection;data:TObjData);
  65. procedure createshstrtab(data:TObjData);
  66. procedure createsymtab(data: TObjData);
  67. procedure writesectionheader(s:TElfObjSection);
  68. procedure section_write_symbol(p:TObject;arg:pointer);
  69. procedure section_write_sh_string(p:TObject;arg:pointer);
  70. procedure section_count_sections(p:TObject;arg:pointer);
  71. procedure section_create_relocsec(p:TObject;arg:pointer);
  72. procedure section_write_sechdr(p:TObject;arg:pointer);
  73. protected
  74. function writedata(data:TObjData):boolean;override;
  75. public
  76. constructor Create(AWriter:TObjectWriter);override;
  77. end;
  78. TElfAssembler = class(tinternalassembler)
  79. constructor create(smart:boolean);override;
  80. end;
  81. implementation
  82. uses
  83. SysUtils,
  84. verbose,
  85. cutils,globals,fmodule;
  86. const
  87. symbolresize = 200*18;
  88. const
  89. { Relocation types }
  90. {$ifdef i386}
  91. R_386_32 = 1; { ordinary absolute relocation }
  92. R_386_PC32 = 2; { PC-relative relocation }
  93. R_386_GOT32 = 3; { an offset into GOT }
  94. R_386_PLT32 = 4; { a PC-relative offset into PLT }
  95. R_386_COPY = 5;
  96. R_386_GLOB_DAT = 6;
  97. R_386_JUMP_SLOT = 7;
  98. R_386_RELATIVE = 8;
  99. R_386_GOTOFF = 9; { an offset from GOT base }
  100. R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
  101. R_386_GNU_VTINHERIT = 250;
  102. R_386_GNU_VTENTRY = 251;
  103. {$endif i386}
  104. {$ifdef sparc}
  105. R_SPARC_32 = 3;
  106. R_SPARC_WDISP30 = 7;
  107. R_SPARC_HI22 = 9;
  108. R_SPARC_LO10 = 12;
  109. R_SPARC_GNU_VTINHERIT = 250;
  110. R_SPARC_GNU_VTENTRY = 251;
  111. {$endif sparc}
  112. {$ifdef x86_64}
  113. R_X86_64_NONE = 0;
  114. R_X86_64_64 = 1; { Direct 64 bit }
  115. R_X86_64_PC32 = 2; { PC relative 32 bit signed }
  116. R_X86_64_GOT32 = 3; { 32 bit GOT entry }
  117. R_X86_64_PLT32 = 4; { 32 bit PLT address }
  118. R_X86_64_COPY = 5; { Copy symbol at runtime }
  119. R_X86_64_GLOB_DAT = 6; { Create GOT entry }
  120. R_X86_64_JUMP_SLOT = 7; { Create PLT entry }
  121. R_X86_64_RELATIVE = 8; { Adjust by program base }
  122. R_X86_64_GOTPCREL = 9; { 32 bit signed PC relative offset to GOT }
  123. R_X86_64_32 = 10; { Direct 32 bit zero extended }
  124. R_X86_64_32S = 11; { Direct 32 bit sign extended }
  125. R_X86_64_16 = 12; { Direct 16 bit zero extended }
  126. R_X86_64_PC16 = 13; { 16 bit sign extended PC relative }
  127. R_X86_64_8 = 14; { Direct 8 bit sign extended }
  128. R_X86_64_PC8 = 15; { 8 bit sign extended PC relative }
  129. R_X86_64_DTPMOD64 = 16; { ID of module containing symbol }
  130. R_X86_64_DTPOFF64 = 17; { Offset in module's TLS block }
  131. R_X86_64_TPOFF64 = 18; { Offset in initial TLS block }
  132. { 32 bit signed PC relative offset to two GOT entries for GD symbol }
  133. R_X86_64_TLSGD = 19;
  134. { 32 bit signed PC relative offset to two GOT entries for LD symbol }
  135. R_X86_64_TLSLD = 20;
  136. R_X86_64_DTPOFF32 = 21; { Offset in TLS block }
  137. { 32 bit signed PC relative offset to GOT entry for IE symbol }
  138. R_X86_64_GOTTPOFF = 22;
  139. R_X86_64_TPOFF32 = 23; { Offset in initial TLS block }
  140. R_X86_64_PC64 = 24; { PC relative 64-bit signed }
  141. R_X86_64_GOTOFF64 = 25; { 64-bit offset from GOT base }
  142. R_X86_64_GOTPC32 = 26; { PC-relative offset GOT }
  143. R_X86_64_GOT64 = 27; { 64-bit GOT entry offset }
  144. R_X86_64_GOTPCREL64 = 28; { 64-bit PC relative offset to GOT entry }
  145. R_X86_64_GOTPC64 = 29; { 64-bit PC relative offset to GOT }
  146. R_X86_64_GOTPLT64 = 30; { Like GOT64, indicates that PLT entry needed }
  147. R_X86_64_PLTOFF64 = 31; { 64-bit GOT relative offset to PLT entry }
  148. R_X86_64_SIZE32 = 32;
  149. R_X86_64_SIZE64 = 33;
  150. R_X86_64_GOTPC32_TLSDESC = 34;
  151. R_X86_64_TLSDESC_CALL = 35;
  152. R_X86_64_TLSDESC = 36;
  153. R_X86_64_IRELATIVE = 37;
  154. R_X86_64_GNU_VTINHERIT = 250; { GNU extension to record C++ vtable hierarchy }
  155. R_X86_64_GNU_VTENTRY = 251; { GNU extension to record C++ vtable member usage }
  156. {$endif x86_64}
  157. { ELFHeader.file_class }
  158. ELFCLASSNONE = 0;
  159. ELFCLASS32 = 1;
  160. ELFCLASS64 = 2;
  161. { ELFHeader.e_type }
  162. ET_NONE = 0;
  163. ET_REL = 1;
  164. ET_EXEC = 2;
  165. ET_DYN = 3;
  166. ET_CORE = 4;
  167. { ELFHeader.e_machine }
  168. EM_SPARC = 2;
  169. EM_386 = 3;
  170. EM_M68K = 4;
  171. EM_PPC = 20;
  172. EM_ARM = 40;
  173. EM_X86_64 = 62;
  174. {$ifdef sparc}
  175. ELFMACHINE = EM_SPARC;
  176. {$endif sparc}
  177. {$ifdef i386}
  178. ELFMACHINE = EM_386;
  179. {$endif i386}
  180. {$ifdef m68k}
  181. ELFMACHINE = EM_M68K;
  182. {$endif m68k}
  183. {$ifdef powerpc}
  184. ELFMACHINE = EM_PPC;
  185. {$endif powerpc}
  186. {$ifdef arm}
  187. ELFMACHINE = EM_ARM;
  188. {$endif arm}
  189. {$ifdef x86_64}
  190. ELFMACHINE = EM_X86_64;
  191. {$endif x86_64}
  192. SHN_UNDEF = 0;
  193. SHN_ABS = $fff1;
  194. SHN_COMMON = $fff2;
  195. SHT_NULL = 0;
  196. SHT_PROGBITS = 1;
  197. SHT_SYMTAB = 2;
  198. SHT_STRTAB = 3;
  199. SHT_RELA = 4;
  200. SHT_HASH = 5;
  201. SHT_DYNAMIC = 6;
  202. SHT_NOTE = 7;
  203. SHT_NOBITS = 8;
  204. SHT_REL = 9;
  205. SHT_SHLIB = 10;
  206. SHT_DYNSYM = 11;
  207. SHF_WRITE = 1;
  208. SHF_ALLOC = 2;
  209. SHF_EXECINSTR = 4;
  210. STB_LOCAL = 0;
  211. STB_GLOBAL = 1;
  212. STB_WEAK = 2;
  213. STT_NOTYPE = 0;
  214. STT_OBJECT = 1;
  215. STT_FUNC = 2;
  216. STT_SECTION = 3;
  217. STT_FILE = 4;
  218. STT_COMMON = 5;
  219. STT_TLS = 6;
  220. STT_GNU_IFUNC = 10;
  221. { program header types }
  222. PT_NULL = 0;
  223. PT_LOAD = 1;
  224. PT_DYNAMIC = 2;
  225. PT_INTERP = 3;
  226. PT_NOTE = 4;
  227. PT_SHLIB = 5;
  228. PT_PHDR = 6;
  229. PT_LOOS = $60000000;
  230. PT_HIOS = $6FFFFFFF;
  231. PT_LOPROC = $70000000;
  232. PT_HIPROC = $7FFFFFFF;
  233. PT_GNU_EH_FRAME = PT_LOOS + $474e550; { Frame unwind information }
  234. PT_GNU_STACK = PT_LOOS + $474e551; { Stack flags }
  235. PT_GNU_RELRO = PT_LOOS + $474e552; { Read-only after relocation }
  236. { program header flags }
  237. PF_X = 1;
  238. PF_W = 2;
  239. PF_R = 4;
  240. PF_MASKOS = $0FF00000; { OS-specific reserved bits }
  241. PF_MASKPROC = $F0000000; { Processor-specific reserved bits }
  242. { .dynamic tags }
  243. DT_NULL = 0;
  244. DT_NEEDED = 1;
  245. DT_PLTRELSZ = 2;
  246. DT_PLTGOT = 3;
  247. DT_HASH = 4;
  248. DT_STRTAB = 5;
  249. DT_SYMTAB = 6;
  250. DT_RELA = 7;
  251. DT_RELASZ = 8;
  252. DT_RELAENT = 9;
  253. DT_STRSZ = 10;
  254. DT_SYMENT = 11;
  255. DT_INIT = 12;
  256. DT_FINI = 13;
  257. DT_SONAME = 14;
  258. DT_RPATH = 15;
  259. DT_SYMBOLIC = 16;
  260. DT_REL = 17;
  261. DT_RELSZ = 18;
  262. DT_RELENT = 19;
  263. DT_PLTREL = 20;
  264. DT_DEBUG = 21;
  265. DT_TEXTREL = 22;
  266. DT_JMPREL = 23;
  267. DT_BIND_NOW = 24;
  268. DT_INIT_ARRAY = 25;
  269. DT_FINI_ARRAY = 26;
  270. DT_INIT_ARRAYSZ = 27;
  271. DT_FINI_ARRAYSZ = 28;
  272. DT_RUNPATH = 29;
  273. DT_FLAGS = 30;
  274. DT_ENCODING = 32;
  275. DT_PREINIT_ARRAY = 32;
  276. DT_PREINIT_ARRAYSZ = 33;
  277. DT_NUM = 34;
  278. DT_LOOS = $6000000D;
  279. DT_HIOS = $6ffff000;
  280. DT_LOPROC = $70000000;
  281. DT_HIPROC = $7fffffff;
  282. DT_RELACOUNT = $6ffffff9;
  283. DT_RELCOUNT = $6ffffffa;
  284. DT_FLAGS_1 = $6ffffffb;
  285. DT_VERDEF = $6ffffffc;
  286. DT_VERDEFNUM = $6ffffffd;
  287. DT_VERNEED = $6ffffffe;
  288. DT_VERNEEDNUM = $6fffffff;
  289. type
  290. { Structures which are written directly to the output file }
  291. TElf32header=packed record
  292. magic : array[0..3] of byte;
  293. file_class : byte;
  294. data_encoding : byte;
  295. file_version : byte;
  296. padding : array[$07..$0f] of byte;
  297. e_type : word;
  298. e_machine : word;
  299. e_version : longword;
  300. e_entry : longword; { entrypoint }
  301. e_phoff : longword; { program header offset }
  302. e_shoff : longword; { sections header offset }
  303. e_flags : longword;
  304. e_ehsize : word; { elf header size in bytes }
  305. e_phentsize : word; { size of an entry in the program header array }
  306. e_phnum : word; { 0..e_phnum-1 of entrys }
  307. e_shentsize : word; { size of an entry in sections header array }
  308. e_shnum : word; { 0..e_shnum-1 of entrys }
  309. e_shstrndx : word; { index of string section header }
  310. end;
  311. TElf32sechdr=packed record
  312. sh_name : longword;
  313. sh_type : longword;
  314. sh_flags : longword;
  315. sh_addr : longword;
  316. sh_offset : longword;
  317. sh_size : longword;
  318. sh_link : longword;
  319. sh_info : longword;
  320. sh_addralign : longword;
  321. sh_entsize : longword;
  322. end;
  323. TElf32proghdr=packed record
  324. p_type : longword;
  325. p_offset : longword;
  326. p_vaddr : longword;
  327. p_paddr : longword;
  328. p_filesz : longword;
  329. p_memsz : longword;
  330. p_flags : longword;
  331. p_align : longword;
  332. end;
  333. TElf32reloc=packed record
  334. address : longword;
  335. info : longword; { bit 0-7: type, 8-31: symbol }
  336. addend : longint;
  337. end;
  338. TElf32symbol=packed record
  339. st_name : longword;
  340. st_value : longword;
  341. st_size : longword;
  342. st_info : byte; { bit 0-3: type, 4-7: bind }
  343. st_other : byte;
  344. st_shndx : word;
  345. end;
  346. TElf32Dyn=packed record
  347. d_tag: longword;
  348. case integer of
  349. 0: (d_val: longword);
  350. 1: (d_ptr: longword);
  351. end;
  352. telf64header=packed record
  353. magic : array[0..3] of byte;
  354. file_class : byte;
  355. data_encoding : byte;
  356. file_version : byte;
  357. padding : array[$07..$0f] of byte;
  358. e_type : word;
  359. e_machine : word;
  360. e_version : longword;
  361. e_entry : qword; { entrypoint }
  362. e_phoff : qword; { program header offset }
  363. e_shoff : qword; { sections header offset }
  364. e_flags : longword;
  365. e_ehsize : word; { elf header size in bytes }
  366. e_phentsize : word; { size of an entry in the program header array }
  367. e_phnum : word; { 0..e_phnum-1 of entrys }
  368. e_shentsize : word; { size of an entry in sections header array }
  369. e_shnum : word; { 0..e_shnum-1 of entrys }
  370. e_shstrndx : word; { index of string section header }
  371. end;
  372. telf64sechdr=packed record
  373. sh_name : longword;
  374. sh_type : longword;
  375. sh_flags : qword;
  376. sh_addr : qword;
  377. sh_offset : qword;
  378. sh_size : qword;
  379. sh_link : longword;
  380. sh_info : longword;
  381. sh_addralign : qword;
  382. sh_entsize : qword;
  383. end;
  384. telf64proghdr=packed record
  385. p_type : longword;
  386. p_flags : longword;
  387. p_offset : qword;
  388. p_vaddr : qword;
  389. p_paddr : qword;
  390. p_filesz : qword;
  391. p_memsz : qword;
  392. p_align : qword;
  393. end;
  394. telf64reloc=packed record
  395. address : qword;
  396. info : qword; { bit 0-31: type, 32-63: symbol }
  397. addend : int64; { signed! }
  398. end;
  399. telf64symbol=packed record
  400. st_name : longword;
  401. st_info : byte; { bit 0-3: type, 4-7: bind }
  402. st_other : byte;
  403. st_shndx : word;
  404. st_value : qword;
  405. st_size : qword;
  406. end;
  407. TElf64Dyn=packed record
  408. d_tag: qword;
  409. case integer of
  410. 0: (d_val: qword);
  411. 1: (d_ptr: qword);
  412. end;
  413. TElfVerdef=record { same for 32 and 64 bits }
  414. vd_version: word; { =1 }
  415. vd_flags: word;
  416. vd_ndx: word;
  417. vd_cnt: word; { number of verdaux records }
  418. vd_hash: longword; { ELF hash of version name }
  419. vd_aux: longword; { offset to verdaux records }
  420. vd_next: longword; { offset to next verdef record }
  421. end;
  422. TElfVerdaux=record
  423. vda_name: longword;
  424. vda_next: longword;
  425. end;
  426. TElfVerneed=record
  427. vn_version: word; { =VER_NEED_CURRENT }
  428. vn_cnt: word;
  429. vn_file: longword;
  430. vn_aux: longword;
  431. vn_next: longword;
  432. end;
  433. TElfVernaux=record
  434. vna_hash: longword;
  435. vna_flags: word;
  436. vna_other: word;
  437. vna_name: longword;
  438. vna_next: longword;
  439. end;
  440. {$ifdef cpu64bitaddr}
  441. const
  442. ELFCLASS = ELFCLASS64;
  443. type
  444. telfheader = telf64header;
  445. telfreloc = telf64reloc;
  446. telfsymbol = telf64symbol;
  447. telfsechdr = telf64sechdr;
  448. telfproghdr = telf64proghdr;
  449. telfdyn = telf64dyn;
  450. function ELF_R_INFO(sym:longword;typ:byte):qword;inline;
  451. begin
  452. result:=(qword(sym) shl 32) or typ;
  453. end;
  454. {$else cpu64bitaddr}
  455. const
  456. ELFCLASS = ELFCLASS32;
  457. type
  458. telfheader = telf32header;
  459. telfreloc = telf32reloc;
  460. telfsymbol = telf32symbol;
  461. telfsechdr = telf32sechdr;
  462. telfproghdr = telf32proghdr;
  463. telfdyn = telf32dyn;
  464. function ELF_R_INFO(sym:longword;typ:byte):longword;inline;
  465. begin
  466. result:=(sym shl 8) or typ;
  467. end;
  468. {$endif cpu64bitaddr}
  469. {$ifdef x86_64}
  470. const
  471. relocs_use_addend:Boolean=True;
  472. {$else x86_64}
  473. const
  474. relocs_use_addend:Boolean=False;
  475. {$endif x86_64}
  476. procedure MayBeSwapHeader(var h : telf32header);
  477. begin
  478. if source_info.endian<>target_info.endian then
  479. with h do
  480. begin
  481. e_type:=swapendian(e_type);
  482. e_machine:=swapendian(e_machine);
  483. e_version:=swapendian(e_version);
  484. e_entry:=swapendian(e_entry);
  485. e_phoff:=swapendian(e_phoff);
  486. e_shoff:=swapendian(e_shoff);
  487. e_flags:=swapendian(e_flags);
  488. e_ehsize:=swapendian(e_ehsize);
  489. e_phentsize:=swapendian(e_phentsize);
  490. e_phnum:=swapendian(e_phnum);
  491. e_shentsize:=swapendian(e_shentsize);
  492. e_shnum:=swapendian(e_shnum);
  493. e_shstrndx:=swapendian(e_shstrndx);
  494. end;
  495. end;
  496. procedure MayBeSwapHeader(var h : telf64header);
  497. begin
  498. if source_info.endian<>target_info.endian then
  499. with h do
  500. begin
  501. e_type:=swapendian(e_type);
  502. e_machine:=swapendian(e_machine);
  503. e_version:=swapendian(e_version);
  504. e_entry:=swapendian(e_entry);
  505. e_phoff:=swapendian(e_phoff);
  506. e_shoff:=swapendian(e_shoff);
  507. e_flags:=swapendian(e_flags);
  508. e_ehsize:=swapendian(e_ehsize);
  509. e_phentsize:=swapendian(e_phentsize);
  510. e_phnum:=swapendian(e_phnum);
  511. e_shentsize:=swapendian(e_shentsize);
  512. e_shnum:=swapendian(e_shnum);
  513. e_shstrndx:=swapendian(e_shstrndx);
  514. end;
  515. end;
  516. procedure MayBeSwapHeader(var h : telf32proghdr);
  517. begin
  518. if source_info.endian<>target_info.endian then
  519. with h do
  520. begin
  521. p_align:=swapendian(p_align);
  522. p_filesz:=swapendian(p_filesz);
  523. p_flags:=swapendian(p_flags);
  524. p_memsz:=swapendian(p_memsz);
  525. p_offset:=swapendian(p_offset);
  526. p_paddr:=swapendian(p_paddr);
  527. p_type:=swapendian(p_type);
  528. p_vaddr:=swapendian(p_vaddr);
  529. end;
  530. end;
  531. procedure MayBeSwapHeader(var h : telf64proghdr);
  532. begin
  533. if source_info.endian<>target_info.endian then
  534. with h do
  535. begin
  536. p_align:=swapendian(p_align);
  537. p_filesz:=swapendian(p_filesz);
  538. p_flags:=swapendian(p_flags);
  539. p_memsz:=swapendian(p_memsz);
  540. p_offset:=swapendian(p_offset);
  541. p_paddr:=swapendian(p_paddr);
  542. p_type:=swapendian(p_type);
  543. p_vaddr:=swapendian(p_vaddr);
  544. end;
  545. end;
  546. procedure MaybeSwapSecHeader(var h : telf32sechdr);
  547. begin
  548. if source_info.endian<>target_info.endian then
  549. with h do
  550. begin
  551. sh_name:=swapendian(sh_name);
  552. sh_type:=swapendian(sh_type);
  553. sh_flags:=swapendian(sh_flags);
  554. sh_addr:=swapendian(sh_addr);
  555. sh_offset:=swapendian(sh_offset);
  556. sh_size:=swapendian(sh_size);
  557. sh_link:=swapendian(sh_link);
  558. sh_info:=swapendian(sh_info);
  559. sh_addralign:=swapendian(sh_addralign);
  560. sh_entsize:=swapendian(sh_entsize);
  561. end;
  562. end;
  563. procedure MaybeSwapSecHeader(var h : telf64sechdr);
  564. begin
  565. if source_info.endian<>target_info.endian then
  566. with h do
  567. begin
  568. sh_name:=swapendian(sh_name);
  569. sh_type:=swapendian(sh_type);
  570. sh_flags:=swapendian(sh_flags);
  571. sh_addr:=swapendian(sh_addr);
  572. sh_offset:=swapendian(sh_offset);
  573. sh_size:=swapendian(sh_size);
  574. sh_link:=swapendian(sh_link);
  575. sh_info:=swapendian(sh_info);
  576. sh_addralign:=swapendian(sh_addralign);
  577. sh_entsize:=swapendian(sh_entsize);
  578. end;
  579. end;
  580. procedure MaybeSwapElfSymbol(var h : telf32symbol);
  581. begin
  582. if source_info.endian<>target_info.endian then
  583. with h do
  584. begin
  585. st_name:=swapendian(st_name);
  586. st_value:=swapendian(st_value);
  587. st_size:=swapendian(st_size);
  588. st_shndx:=swapendian(st_shndx);
  589. end;
  590. end;
  591. procedure MaybeSwapElfSymbol(var h : telf64symbol);
  592. begin
  593. if source_info.endian<>target_info.endian then
  594. with h do
  595. begin
  596. st_name:=swapendian(st_name);
  597. st_value:=swapendian(st_value);
  598. st_size:=swapendian(st_size);
  599. st_shndx:=swapendian(st_shndx);
  600. end;
  601. end;
  602. procedure MaybeSwapElfReloc(var h : telf32reloc);
  603. begin
  604. if source_info.endian<>target_info.endian then
  605. with h do
  606. begin
  607. address:=swapendian(address);
  608. info:=swapendian(info);
  609. addend:=swapendian(addend);
  610. end;
  611. end;
  612. procedure MaybeSwapElfReloc(var h : telf64reloc);
  613. begin
  614. if source_info.endian<>target_info.endian then
  615. with h do
  616. begin
  617. address:=swapendian(address);
  618. info:=swapendian(info);
  619. addend:=swapendian(addend);
  620. end;
  621. end;
  622. procedure MaybeSwapElfDyn(var h : telf32dyn);
  623. begin
  624. if source_info.endian<>target_info.endian then
  625. with h do
  626. begin
  627. d_tag:=swapendian(d_tag);
  628. d_val:=swapendian(d_val);
  629. end;
  630. end;
  631. procedure MaybeSwapElfDyn(var h : telf64dyn);
  632. begin
  633. if source_info.endian<>target_info.endian then
  634. with h do
  635. begin
  636. d_tag:=swapendian(d_tag);
  637. d_val:=swapendian(d_val);
  638. end;
  639. end;
  640. {****************************************************************************
  641. Helpers
  642. ****************************************************************************}
  643. procedure encodesechdrflags(aoptions:TObjSectionOptions;out AshType:longint;out Ashflags:longint);
  644. begin
  645. { Section Type }
  646. AshType:=SHT_PROGBITS;
  647. if oso_strings in aoptions then
  648. AshType:=SHT_STRTAB
  649. else if not(oso_data in aoptions) then
  650. AshType:=SHT_NOBITS;
  651. { Section Flags }
  652. Ashflags:=0;
  653. if oso_load in aoptions then
  654. Ashflags:=Ashflags or SHF_ALLOC;
  655. if oso_executable in aoptions then
  656. Ashflags:=Ashflags or SHF_EXECINSTR;
  657. if oso_write in aoptions then
  658. Ashflags:=Ashflags or SHF_WRITE;
  659. end;
  660. procedure decodesechdrflags(AshType:longint;Ashflags:longint;out aoptions:TObjSectionOptions);
  661. begin
  662. aoptions:=[];
  663. { Section Type }
  664. if AshType<>SHT_NOBITS then
  665. include(aoptions,oso_data);
  666. if AshType=SHT_STRTAB then
  667. include(aoptions,oso_strings);
  668. { Section Flags }
  669. if Ashflags and SHF_ALLOC<>0 then
  670. include(aoptions,oso_load);
  671. if Ashflags and SHF_WRITE<>0 then
  672. include(aoptions,oso_write);
  673. if Ashflags and SHF_EXECINSTR<>0 then
  674. include(aoptions,oso_executable);
  675. end;
  676. {****************************************************************************
  677. TElfObjSection
  678. ****************************************************************************}
  679. constructor TElfObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
  680. begin
  681. inherited create(AList,Aname,Aalign,aoptions);
  682. index:=0;
  683. shstridx:=0;
  684. encodesechdrflags(aoptions,shtype,shflags);
  685. shlink:=0;
  686. shinfo:=0;
  687. if name='.stab' then
  688. shentsize:=sizeof(TObjStabEntry);
  689. end;
  690. constructor TElfObjSection.create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags:longint;Aalign:shortint;Aentsize:longint);
  691. var
  692. aoptions : TObjSectionOptions;
  693. begin
  694. decodesechdrflags(Ashtype,Ashflags,aoptions);
  695. inherited create(aobjdata.ObjSectionList,Aname,Aalign,aoptions);
  696. objdata:=aobjdata;
  697. index:=0;
  698. shstridx:=0;
  699. shtype:=AshType;
  700. shflags:=AshFlags;
  701. shentsize:=Aentsize;
  702. end;
  703. const
  704. relsec_prefix:array[boolean] of string[5] = ('.rel','.rela');
  705. relsec_shtype:array[boolean] of longword = (SHT_REL,SHT_RELA);
  706. constructor TElfObjSection.create_reloc(aobjdata:TObjData;const Aname:string;allocflag:boolean);
  707. begin
  708. create_ext(aobjdata,
  709. relsec_prefix[relocs_use_addend]+aname,
  710. relsec_shtype[relocs_use_addend],
  711. SHF_ALLOC*ord(allocflag),
  712. sizeof(pint),
  713. (2+ord(relocs_use_addend))*sizeof(pint));
  714. end;
  715. {****************************************************************************
  716. TElfObjData
  717. ****************************************************************************}
  718. constructor TElfObjData.create(const n:string);
  719. begin
  720. inherited create(n);
  721. CObjSection:=TElfObjSection;
  722. { we need at least the following sections }
  723. createsection(sec_code);
  724. { always a non-PIC data section (will remain empty if doing PIC) }
  725. createsection('.data',sectiontype2align(sec_data),sectiontype2options(sec_data));
  726. createsection(sec_bss);
  727. if (cs_create_pic in current_settings.moduleswitches) and
  728. not(target_info.system in systems_darwin) then
  729. createsection(sec_data);
  730. if tf_section_threadvars in target_info.flags then
  731. createsection(sec_threadvar);
  732. if (tf_needs_dwarf_cfi in target_info.flags) and
  733. (af_supports_dwarf in target_asm.flags) then
  734. createsection(sec_debug_frame);
  735. end;
  736. function TElfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  737. const
  738. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  739. {$ifdef userodata}
  740. '.text','.data','.data','.rodata','.bss','.threadvar',
  741. {$else userodata}
  742. '.text','.data','.data','.data','.bss','.threadvar',
  743. {$endif userodata}
  744. '.pdata',
  745. '.text', { darwin stubs }
  746. '__DATA,__nl_symbol_ptr',
  747. '__DATA,__la_symbol_ptr',
  748. '__DATA,__mod_init_func',
  749. '__DATA,__mod_term_func',
  750. '.stab','.stabstr',
  751. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  752. '.eh_frame',
  753. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  754. '.fpc',
  755. '.toc',
  756. '.init',
  757. '.fini',
  758. '.objc_class',
  759. '.objc_meta_class',
  760. '.objc_cat_cls_meth',
  761. '.objc_cat_inst_meth',
  762. '.objc_protocol',
  763. '.objc_string_object',
  764. '.objc_cls_meth',
  765. '.objc_inst_meth',
  766. '.objc_cls_refs',
  767. '.objc_message_refs',
  768. '.objc_symbols',
  769. '.objc_category',
  770. '.objc_class_vars',
  771. '.objc_instance_vars',
  772. '.objc_module_info',
  773. '.objc_class_names',
  774. '.objc_meth_var_types',
  775. '.objc_meth_var_names',
  776. '.objc_selector_strs',
  777. '.objc_protocol_ext',
  778. '.objc_class_ext',
  779. '.objc_property',
  780. '.objc_image_info',
  781. '.objc_cstring_object',
  782. '.objc_sel_fixup',
  783. '__DATA,__objc_data',
  784. '__DATA,__objc_const',
  785. '.objc_superrefs',
  786. '__DATA, __datacoal_nt,coalesced',
  787. '.objc_classlist',
  788. '.objc_nlclasslist',
  789. '.objc_catlist',
  790. '.obcj_nlcatlist',
  791. '.objc_protolist'
  792. );
  793. secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  794. '.text',
  795. '.data.rel',
  796. '.data.rel',
  797. '.data.rel',
  798. '.bss',
  799. '.threadvar',
  800. '.pdata',
  801. '', { stubs }
  802. '__DATA,__nl_symbol_ptr',
  803. '__DATA,__la_symbol_ptr',
  804. '__DATA,__mod_init_func',
  805. '__DATA,__mod_term_func',
  806. '.stab',
  807. '.stabstr',
  808. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  809. '.eh_frame',
  810. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  811. '.fpc',
  812. '.toc',
  813. '.init',
  814. '.fini',
  815. '.objc_class',
  816. '.objc_meta_class',
  817. '.objc_cat_cls_meth',
  818. '.objc_cat_inst_meth',
  819. '.objc_protocol',
  820. '.objc_string_object',
  821. '.objc_cls_meth',
  822. '.objc_inst_meth',
  823. '.objc_cls_refs',
  824. '.objc_message_refs',
  825. '.objc_symbols',
  826. '.objc_category',
  827. '.objc_class_vars',
  828. '.objc_instance_vars',
  829. '.objc_module_info',
  830. '.objc_class_names',
  831. '.objc_meth_var_types',
  832. '.objc_meth_var_names',
  833. '.objc_selector_strs',
  834. '.objc_protocol_ext',
  835. '.objc_class_ext',
  836. '.objc_property',
  837. '.objc_image_info',
  838. '.objc_cstring_object',
  839. '.objc_sel_fixup',
  840. '__DATA,__objc_data',
  841. '__DATA,__objc_const',
  842. '.objc_superrefs',
  843. '__DATA, __datacoal_nt,coalesced',
  844. '.objc_classlist',
  845. '.objc_nlclasslist',
  846. '.objc_catlist',
  847. '.obcj_nlcatlist',
  848. '.objc_protolist'
  849. );
  850. var
  851. sep : string[3];
  852. secname : string;
  853. begin
  854. { section type user gives the user full controll on the section name }
  855. if atype=sec_user then
  856. result:=aname
  857. else
  858. begin
  859. if (cs_create_pic in current_settings.moduleswitches) and
  860. not(target_info.system in systems_darwin) then
  861. secname:=secnames_pic[atype]
  862. else
  863. secname:=secnames[atype];
  864. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  865. begin
  866. result:=secname+'.'+aname;
  867. exit;
  868. end;
  869. if create_smartlink_sections and (aname<>'') then
  870. begin
  871. case aorder of
  872. secorder_begin :
  873. sep:='.b_';
  874. secorder_end :
  875. sep:='.z_';
  876. else
  877. sep:='.n_';
  878. end;
  879. result:=secname+sep+aname
  880. end
  881. else
  882. result:=secname;
  883. end;
  884. end;
  885. procedure TElfObjData.CreateDebugSections;
  886. begin
  887. if target_dbg.id=dbg_stabs then
  888. begin
  889. stabssec:=createsection(sec_stab);
  890. stabstrsec:=createsection(sec_stabstr);
  891. end;
  892. end;
  893. procedure TElfObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);
  894. var
  895. symaddr : aint;
  896. objreloc: TObjRelocation;
  897. begin
  898. if CurrObjSec=nil then
  899. internalerror(200403292);
  900. objreloc:=nil;
  901. if assigned(p) then
  902. begin
  903. { real address of the symbol }
  904. symaddr:=p.address;
  905. { Local ObjSymbols can be resolved already or need a section reloc }
  906. if (p.bind=AB_LOCAL) and
  907. (reltype in [RELOC_RELATIVE,RELOC_ABSOLUTE{$ifdef x86_64},RELOC_ABSOLUTE32{$endif x86_64}]) then
  908. begin
  909. { For a reltype relocation in the same section the
  910. value can be calculated }
  911. if (p.objsection=CurrObjSec) and
  912. (reltype=RELOC_RELATIVE) then
  913. inc(data,symaddr-len-CurrObjSec.Size)
  914. else
  915. begin
  916. objreloc:=TObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,reltype);
  917. CurrObjSec.ObjRelocations.Add(objreloc);
  918. inc(data,symaddr);
  919. end;
  920. end
  921. else
  922. begin
  923. objreloc:=TObjRelocation.CreateSymbol(CurrObjSec.Size,p,reltype);
  924. CurrObjSec.ObjRelocations.Add(objreloc);
  925. { If target is a local label and it isn't handled above,
  926. patch its type in order to get it written to symtable.
  927. This may happen e.g. when taking address of Pascal label in PIC mode. }
  928. if (p.bind=AB_LOCAL) and (p.typ=AT_LABEL) then
  929. p.typ:=AT_ADDR;
  930. end;
  931. end;
  932. if assigned(objreloc) then
  933. begin
  934. objreloc.size:=len;
  935. if reltype in [RELOC_RELATIVE,RELOC_PLT32{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then
  936. dec(data,len);
  937. if relocs_use_addend then
  938. begin
  939. objreloc.orgsize:=data;
  940. data:=0;
  941. end;
  942. end;
  943. CurrObjSec.write(data,len);
  944. end;
  945. {****************************************************************************
  946. TElfSymtab
  947. ****************************************************************************}
  948. const
  949. symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym');
  950. strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr');
  951. symsectypes: array[boolean] of longint = (SHT_SYMTAB,SHT_DYNSYM);
  952. symsecattrs: array[boolean] of longint = (0,SHF_ALLOC);
  953. constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind);
  954. var
  955. dyn:boolean;
  956. begin
  957. dyn:=(aKind=esk_dyn);
  958. create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],sizeof(pint),sizeof(TElfSymbol));
  959. fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],1,0);
  960. fstrsec.writestr(#0);
  961. writezeros(sizeof(TElfSymbol));
  962. symidx:=1;
  963. shinfo:=1;
  964. kind:=aKind;
  965. end;
  966. procedure TElfSymtab.writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word);
  967. var
  968. elfsym:TElfSymbol;
  969. begin
  970. fillchar(elfsym,sizeof(elfsym),0);
  971. elfsym.st_name:=astridx;
  972. elfsym.st_info:=ainfo;
  973. elfsym.st_shndx:=ashndx;
  974. inc(symidx);
  975. inc(shinfo);
  976. MaybeSwapElfSymbol(elfsym);
  977. write(elfsym,sizeof(elfsym));
  978. end;
  979. procedure TElfSymtab.writeSymbol(objsym:TObjSymbol;nameidx:longword);
  980. var
  981. elfsym:TElfSymbol;
  982. begin
  983. fillchar(elfsym,sizeof(elfsym),0);
  984. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  985. if nameidx=0 then
  986. begin
  987. elfsym.st_name:=fstrsec.writestr(objsym.name);
  988. fstrsec.writestr(#0);
  989. end
  990. else
  991. elfsym.st_name:=nameidx;
  992. elfsym.st_size:=objsym.size;
  993. case objsym.bind of
  994. AB_LOCAL :
  995. begin
  996. elfsym.st_value:=objsym.address;
  997. elfsym.st_info:=STB_LOCAL shl 4;
  998. inc(shinfo);
  999. end;
  1000. AB_COMMON :
  1001. begin
  1002. elfsym.st_value:=$10; { ?? should not be hardcoded }
  1003. elfsym.st_info:=STB_GLOBAL shl 4;
  1004. elfsym.st_shndx:=SHN_COMMON;
  1005. end;
  1006. AB_EXTERNAL :
  1007. elfsym.st_info:=STB_GLOBAL shl 4;
  1008. AB_WEAK_EXTERNAL :
  1009. elfsym.st_info:=STB_WEAK shl 4;
  1010. AB_GLOBAL :
  1011. begin
  1012. elfsym.st_value:=objsym.address;
  1013. elfsym.st_info:=STB_GLOBAL shl 4;
  1014. end;
  1015. end;
  1016. if (objsym.bind<>AB_EXTERNAL) {and
  1017. not(assigned(objsym.objsection) and
  1018. not(oso_data in objsym.objsection.secoptions))} then
  1019. begin
  1020. case objsym.typ of
  1021. AT_FUNCTION :
  1022. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  1023. AT_DATA :
  1024. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  1025. end;
  1026. end;
  1027. if objsym.bind<>AB_COMMON then
  1028. begin
  1029. if kind<>esk_obj then
  1030. begin
  1031. { TODO }
  1032. end
  1033. else
  1034. begin
  1035. if assigned(objsym.objsection) then
  1036. elfsym.st_shndx:=objsym.objsection.index
  1037. else
  1038. elfsym.st_shndx:=SHN_UNDEF;
  1039. objsym.symidx:=symidx;
  1040. end;
  1041. end;
  1042. inc(symidx);
  1043. MaybeSwapElfSymbol(elfsym);
  1044. write(elfsym,sizeof(TElfSymbol));
  1045. end;
  1046. {****************************************************************************
  1047. TElfObjectOutput
  1048. ****************************************************************************}
  1049. constructor TElfObjectOutput.create(AWriter:TObjectWriter);
  1050. begin
  1051. inherited Create(AWriter);
  1052. CObjData:=TElfObjData;
  1053. end;
  1054. procedure TElfObjectOutput.createrelocsection(s:TElfObjSection;data:TObjData);
  1055. var
  1056. i : longint;
  1057. rel : telfreloc;
  1058. objreloc : TObjRelocation;
  1059. relsym,
  1060. reltyp : longint;
  1061. relocsect : TElfObjSection;
  1062. begin
  1063. with data do
  1064. begin
  1065. { create the reloc section }
  1066. relocsect:=TElfObjSection.create_reloc(data,s.name,false);
  1067. relocsect.shlink:=symtabsect.index;
  1068. relocsect.shinfo:=s.index;
  1069. { add the relocations }
  1070. for i:=0 to s.Objrelocations.count-1 do
  1071. begin
  1072. objreloc:=TObjRelocation(s.Objrelocations[i]);
  1073. fillchar(rel,sizeof(rel),0);
  1074. rel.address:=objreloc.dataoffset;
  1075. rel.addend:=objreloc.orgsize;
  1076. { when things settle down, we can create processor specific
  1077. derived classes }
  1078. case objreloc.typ of
  1079. {$ifdef i386}
  1080. RELOC_RELATIVE :
  1081. reltyp:=R_386_PC32;
  1082. RELOC_ABSOLUTE :
  1083. reltyp:=R_386_32;
  1084. RELOC_GOT32 :
  1085. reltyp:=R_386_GOT32;
  1086. RELOC_GOTPC :
  1087. reltyp:=R_386_GOTPC;
  1088. RELOC_PLT32 :
  1089. reltyp:=R_386_PLT32;
  1090. {$endif i386}
  1091. {$ifdef sparc}
  1092. RELOC_ABSOLUTE :
  1093. reltyp:=R_SPARC_32;
  1094. {$endif sparc}
  1095. {$ifdef x86_64}
  1096. { Note: 8 and 16-bit relocations are known to be non-conformant with
  1097. AMD64 ABI, so they aren't handled. }
  1098. RELOC_RELATIVE :
  1099. if objreloc.size=8 then
  1100. reltyp:=R_X86_64_PC64
  1101. else if objreloc.size=4 then
  1102. reltyp:=R_X86_64_PC32
  1103. else
  1104. InternalError(2012061900);
  1105. RELOC_ABSOLUTE :
  1106. if objreloc.size=8 then
  1107. reltyp:=R_X86_64_64
  1108. else if objreloc.size=4 then
  1109. reltyp:=R_X86_64_32
  1110. else
  1111. InternalError(2012061901);
  1112. RELOC_ABSOLUTE32 :
  1113. reltyp:=R_X86_64_32S;
  1114. RELOC_GOTPCREL :
  1115. reltyp:=R_X86_64_GOTPCREL;
  1116. RELOC_PLT32 :
  1117. reltyp:=R_X86_64_PLT32;
  1118. {$endif x86_64}
  1119. else
  1120. internalerror(200602261);
  1121. end;
  1122. { Symbol }
  1123. if assigned(objreloc.symbol) then
  1124. begin
  1125. if objreloc.symbol.symidx=-1 then
  1126. begin
  1127. writeln(objreloc.symbol.Name);
  1128. internalerror(200603012);
  1129. end;
  1130. relsym:=objreloc.symbol.symidx;
  1131. end
  1132. else
  1133. begin
  1134. if objreloc.objsection<>nil then
  1135. relsym:=objreloc.objsection.secsymidx
  1136. else
  1137. relsym:=SHN_UNDEF;
  1138. end;
  1139. rel.info:=ELF_R_INFO(relsym,reltyp);
  1140. { write reloc }
  1141. { ElfXX_Rel is essentially ElfXX_Rela without the addend field. }
  1142. MaybeSwapElfReloc(rel);
  1143. relocsect.write(rel,relocsect.shentsize);
  1144. end;
  1145. end;
  1146. end;
  1147. procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
  1148. begin
  1149. { Must not write symbols for internal sections like .symtab }
  1150. { TODO: maybe use inclusive list of section types instead }
  1151. if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
  1152. exit;
  1153. TObjSection(p).secsymidx:=symtabsect.symidx;
  1154. symtabsect.writeInternalSymbol(0,STT_SECTION,TObjSection(p).index);
  1155. end;
  1156. procedure TElfObjectOutput.createsymtab(data: TObjData);
  1157. var
  1158. i : longint;
  1159. objsym : TObjSymbol;
  1160. begin
  1161. with data do
  1162. begin
  1163. { filename entry }
  1164. symtabsect.writeInternalSymbol(1,STT_FILE,SHN_ABS);
  1165. { section }
  1166. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1167. { First the Local Symbols, this is required by ELF. The localsyms
  1168. count stored in shinfo is used to skip the local symbols
  1169. when traversing the symtab }
  1170. for i:=0 to ObjSymbolList.Count-1 do
  1171. begin
  1172. objsym:=TObjSymbol(ObjSymbolList[i]);
  1173. if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
  1174. symtabsect.WriteSymbol(objsym);
  1175. end;
  1176. { Global Symbols }
  1177. for i:=0 to ObjSymbolList.Count-1 do
  1178. begin
  1179. objsym:=TObjSymbol(ObjSymbolList[i]);
  1180. if (objsym.bind<>AB_LOCAL) then
  1181. symtabsect.WriteSymbol(objsym);
  1182. end;
  1183. { update the .symtab section header }
  1184. symtabsect.shlink:=symtabsect.fstrsec.index;
  1185. end;
  1186. end;
  1187. procedure TElfObjectOutput.section_write_sh_string(p:TObject;arg:pointer);
  1188. begin
  1189. TElfObjSection(p).shstridx:=shstrtabsect.writestr(TObjSection(p).name+#0);
  1190. end;
  1191. procedure TElfObjectOutput.createshstrtab(data: TObjData);
  1192. begin
  1193. with data do
  1194. begin
  1195. shstrtabsect.writestr(#0);
  1196. ObjSectionList.ForEachCall(@section_write_sh_string,nil);
  1197. end;
  1198. end;
  1199. procedure TElfObjectOutput.writesectionheader(s:TElfObjSection);
  1200. var
  1201. sechdr : telfsechdr;
  1202. begin
  1203. fillchar(sechdr,sizeof(sechdr),0);
  1204. sechdr.sh_name:=s.shstridx;
  1205. sechdr.sh_type:=s.shtype;
  1206. sechdr.sh_flags:=s.shflags;
  1207. sechdr.sh_offset:=s.datapos;
  1208. sechdr.sh_size:=s.Size;
  1209. sechdr.sh_link:=s.shlink;
  1210. sechdr.sh_info:=s.shinfo;
  1211. sechdr.sh_addralign:=s.secalign;
  1212. sechdr.sh_entsize:=s.shentsize;
  1213. MaybeSwapSecHeader(sechdr);
  1214. writer.write(sechdr,sizeof(sechdr));
  1215. end;
  1216. procedure TElfObjectOutput.section_count_sections(p:TObject;arg:pointer);
  1217. begin
  1218. TElfObjSection(p).index:=pword(arg)^;
  1219. inc(pword(arg)^);
  1220. end;
  1221. procedure TElfObjectOutput.section_create_relocsec(p:TObject;arg:pointer);
  1222. begin
  1223. if (TElfObjSection(p).ObjRelocations.count>0) then
  1224. createrelocsection(TElfObjSection(p),TObjData(arg));
  1225. end;
  1226. procedure TElfObjectOutput.section_write_sechdr(p:TObject;arg:pointer);
  1227. begin
  1228. writesectionheader(TElfObjSection(p));
  1229. end;
  1230. function TElfObjectOutput.writedata(data:TObjData):boolean;
  1231. var
  1232. header : telfheader;
  1233. shoffset,
  1234. datapos : aword;
  1235. nsections : word;
  1236. begin
  1237. result:=false;
  1238. with data do
  1239. begin
  1240. { default sections }
  1241. symtabsect:=TElfSymtab.create(data,esk_obj);
  1242. shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,1,0);
  1243. { "no executable stack" marker for Linux }
  1244. if (target_info.system in systems_linux) and
  1245. not(cs_executable_stack in current_settings.moduleswitches) then
  1246. TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,1,0);
  1247. { insert filename as first in strtab }
  1248. symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
  1249. symtabsect.fstrsec.writestr(#0);
  1250. { calc amount of sections we have }
  1251. nsections:=1;
  1252. { also create the index in the section header table }
  1253. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1254. { create .symtab and .strtab }
  1255. createsymtab(data);
  1256. { Create the relocation sections, this needs valid secidx and symidx }
  1257. ObjSectionList.ForEachCall(@section_create_relocsec,data);
  1258. { recalc nsections to incude the reloc sections }
  1259. nsections:=1;
  1260. ObjSectionList.ForEachCall(@section_count_sections,@nsections);
  1261. { create .shstrtab }
  1262. createshstrtab(data);
  1263. { Calculate the filepositions }
  1264. datapos:=$40; { elfheader + alignment }
  1265. { section data }
  1266. layoutsections(datapos);
  1267. { section headers }
  1268. shoffset:=datapos;
  1269. inc(datapos,(nsections+1)*sizeof(telfsechdr));
  1270. { Write ELF Header }
  1271. fillchar(header,sizeof(header),0);
  1272. header.magic[0]:=$7f; { = #127'ELF' }
  1273. header.magic[1]:=$45;
  1274. header.magic[2]:=$4c;
  1275. header.magic[3]:=$46;
  1276. header.file_class:=ELFCLASS;
  1277. if target_info.endian=endian_big then
  1278. header.data_encoding:=2
  1279. else
  1280. header.data_encoding:=1;
  1281. header.file_version:=1;
  1282. header.e_type:=ET_REL;
  1283. header.e_machine:=ELFMACHINE;
  1284. {$ifdef arm}
  1285. if (current_settings.fputype=fpu_soft) then
  1286. header.e_flags:=$600;
  1287. {$endif arm}
  1288. header.e_version:=1;
  1289. header.e_shoff:=shoffset;
  1290. header.e_shstrndx:=shstrtabsect.index;
  1291. header.e_shnum:=nsections;
  1292. header.e_ehsize:=sizeof(telfheader);
  1293. header.e_shentsize:=sizeof(telfsechdr);
  1294. MaybeSwapHeader(header);
  1295. writer.write(header,sizeof(header));
  1296. writer.writezeros($40-sizeof(header)); { align }
  1297. { Sections }
  1298. WriteSectionContent(data);
  1299. { section headers, start with an empty header for sh_undef }
  1300. writer.writezeros(sizeof(telfsechdr));
  1301. ObjSectionList.ForEachCall(@section_write_sechdr,nil);
  1302. end;
  1303. result:=true;
  1304. end;
  1305. {****************************************************************************
  1306. TELFAssembler
  1307. ****************************************************************************}
  1308. constructor TElfAssembler.Create(smart:boolean);
  1309. begin
  1310. inherited Create(smart);
  1311. CObjOutput:=TElfObjectOutput;
  1312. end;
  1313. {*****************************************************************************
  1314. Initialize
  1315. *****************************************************************************}
  1316. {$ifdef i386}
  1317. const
  1318. as_i386_elf32_info : tasminfo =
  1319. (
  1320. id : as_i386_elf32;
  1321. idtxt : 'ELF';
  1322. asmbin : '';
  1323. asmcmd : '';
  1324. supported_targets : [system_i386_linux,system_i386_beos,
  1325. system_i386_freebsd,system_i386_haiku,
  1326. system_i386_openbsd,system_i386_netbsd,
  1327. system_i386_Netware,system_i386_netwlibc,
  1328. system_i386_solaris,system_i386_embedded];
  1329. flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
  1330. labelprefix : '.L';
  1331. comment : '';
  1332. dollarsign: '$';
  1333. );
  1334. {$endif i386}
  1335. {$ifdef x86_64}
  1336. const
  1337. as_x86_64_elf64_info : tasminfo =
  1338. (
  1339. id : as_x86_64_elf64;
  1340. idtxt : 'ELF';
  1341. asmbin : '';
  1342. asmcmd : '';
  1343. supported_targets : [system_x86_64_linux,system_x86_64_freebsd,
  1344. system_x86_64_openbsd,system_x86_64_netbsd];
  1345. flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
  1346. labelprefix : '.L';
  1347. comment : '';
  1348. dollarsign: '$';
  1349. );
  1350. {$endif x86_64}
  1351. {$ifdef sparc}
  1352. const
  1353. as_sparc_elf32_info : tasminfo =
  1354. (
  1355. id : as_sparc_elf32;
  1356. idtxt : 'ELF';
  1357. asmbin : '';
  1358. asmcmd : '';
  1359. supported_targets : [];
  1360. // flags : [af_outputbinary,af_smartlink_sections];
  1361. flags : [af_outputbinary,af_supports_dwarf];
  1362. labelprefix : '.L';
  1363. comment : '';
  1364. dollarsign: '$';
  1365. );
  1366. {$endif sparc}
  1367. initialization
  1368. {$ifdef i386}
  1369. RegisterAssembler(as_i386_elf32_info,TElfAssembler);
  1370. {$endif i386}
  1371. {$ifdef sparc}
  1372. RegisterAssembler(as_sparc_elf32_info,TElfAssembler);
  1373. {$endif sparc}
  1374. {$ifdef x86_64}
  1375. RegisterAssembler(as_x86_64_elf64_info,TElfAssembler);
  1376. {$endif x86_64}
  1377. end.