ogelf.pas 48 KB

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