ogelf.pas 43 KB

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