ogelf.pas 44 KB

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