ogelf.pas 48 KB

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