ogelf.pas 42 KB

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