ogelf.pas 50 KB

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