commit fd1bb8148eca22696607c4be5511ff47865262a6
parent 1cf6ea7bcc71a08716b79ccef4f0bebe9de9d362
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Sat, 20 Dec 2014 19:28:12 -0500
start an ELF output module
Diffstat:
| A | elf.ml | | | 195 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 195 insertions(+), 0 deletions(-)
diff --git a/elf.ml b/elf.ml
@@ -0,0 +1,195 @@
+(* This is a module to spit simple ELF
+ object files that can afterwards be
+ linked to build an application.
+*)
+
+let hash s =
+ (* The ELF hash function. *)
+ let open Int64 in (* I doubt this is necessary... *)
+ let rec f p h =
+ if p = String.length s then to_int h else
+ let h = shift_left h 4 in
+ let h = add h (of_int (int_of_char s.[p])) in
+ let g = logand h (of_int 0xf0000000) in
+ let h = logxor h (shift_right g 24) in
+ f (p+1) (logand h (of_int 0x0fffffff)) in
+ f 0 (of_int 0)
+
+let le n x =
+ (* Make a string of bytes in little endian convention. *)
+ let b = Bytes.create n in
+ let rec f i x =
+ if i = n then () else
+ let d = char_of_int (x land 0xff) in
+ Bytes.set b i d;
+ f (i+1) (x lsr 8) in
+ f 0 x; Bytes.to_string b
+
+let stt_NOTYPE = 0
+let stt_OBJECT = 1
+let stt_FUNC = 2
+
+let stb_LOCAL = 0
+let stb_GLOBAL = 16
+let stb_WEAK = 32
+
+let sht_NULL = le 4 0
+let sht_PROGBITS = le 4 1
+let sht_SYMTAB = le 4 2
+let sht_STRTAB = le 4 3
+let sht_RELA = le 4 4
+let sht_NOTE = le 4 7
+let sht_NOBITS = le 4 8
+
+let shf_WRITE = 1
+let shf_ALLOC = 2
+let shf_EXECINSTR = 4
+
+let barebones_elf oc text =
+ let header = String.concat ""
+ [ "\x7fELF" (* e_ident, magic *)
+ ; "\x02" (* e_ident, ELFCLASS64 *)
+ ; "\x01" (* e_ident, ELFDATA2LSB *)
+ ; "\x01" (* e_indent, EV_CURRENT *)
+ ; "\x00" (* e_ident, ELFOSABI_SYSV *)
+ ; "\x00" (* e_ident, ABI version *)
+ ; "\x00\x00\x00\x00\x00\x00\x00" (* e_ident, padding *)
+ ; "\x01\x00" (* e_type, ET_REL *)
+ ; "\x3e\x00" (* e_machine, EM_X86_64 *)
+ ; "\x01\x00\x00\x00" (* e_version, EV_CURRENT *)
+ ; "\x00\x00\x00\x00\x00\x00\x00\x00" (* e_entry, unused *)
+ ; "\x00\x00\x00\x00\x00\x00\x00\x00" (* e_phoff, unused *)
+ ; "\x40\x00\x00\x00\x00\x00\x00\x00" (* e_shoff, 64 *)
+ ; "\x00\x00\x00\x00" (* e_flags, 0 *)
+ ; "\x40\x00" (* e_hsize, 64 *)
+ ; "\x00\x00" (* e_phentsize, 0 *)
+ ; "\x00\x00" (* e_phnum, 0 *)
+ ; "\x40\x00" (* e_shentsize, 64 *)
+ ; "\x07\x00" (* e_shnum, 7 *)
+ ; "\x06\x00" (* e_shstrndx, 6 *)
+ ] in
+
+ (* We will use the following section organization.
+ 1- .text PROGBITS
+ 2- .data PROGBITS
+ 3- .bss NOBITS
+ 4- .rela RELA
+ 5- .symtab SYMTAB
+ 6- .strtab STRTAB
+ *)
+
+ let adds s x = (String.length s, s ^ x ^ "\x00") in
+ (* section names *)
+ let textstr, strtab = adds "\x00" ".text" in
+ let datastr, strtab = adds strtab ".data" in
+ let bssstr , strtab = adds strtab ".bss" in
+ let relastr, strtab = adds strtab ".rela" in
+ let symtstr, strtab = adds strtab ".symt" in
+ let strtstr, strtab = adds strtab ".strt" in
+ (* function names *)
+ let mainstr, strtab = adds strtab "main" in
+
+ let symtab = String.concat ""
+ [ le 0x18 0 (* first symbol is reserved *)
+ ; le 4 mainstr (* st_name *)
+ ; le 1 (stt_FUNC lor stb_GLOBAL) (* st_info *)
+ ; "\x00" (* st_other *)
+ ; le 2 1 (* st_shndx, .text *)
+ ; le 8 0 (* st_value, offset in .text section *)
+ ; le 8 (String.length text) (* st_size *)
+ ] in
+
+ let textoff = 64 + 7 * 64 in
+ let dataoff = textoff + String.length text in
+ let bssoff = dataoff + 0 in
+ let relaoff = bssoff + 0 in
+ let symtoff = relaoff + 0 in
+ let strtoff = symtoff + String.length symtab in
+
+ let sh = String.concat ""
+ [ le 64 0 (* first section header is reserved *)
+ (* .text *)
+ ; le 4 textstr (* sh_name *)
+ ; sht_PROGBITS (* sh_type *)
+ ; le 8 (shf_ALLOC lor shf_EXECINSTR) (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 textoff (* sh_offset *)
+ ; le 8 (String.length text) (* sh_size *)
+ ; le 4 0 (* sh_link *)
+ ; le 4 0 (* sh_info *)
+ ; le 8 1 (* sh_addralign *)
+ ; le 8 0 (* sh_entsize *)
+ (* .data *)
+ ; le 4 datastr (* sh_name *)
+ ; sht_PROGBITS (* sh_type *)
+ ; le 8 (shf_ALLOC lor shf_WRITE) (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 dataoff (* sh_offset *)
+ ; le 8 0 (* sh_size *)
+ ; le 4 0 (* sh_link *)
+ ; le 4 0 (* sh_info *)
+ ; le 8 1 (* sh_addralign *)
+ ; le 8 0 (* sh_entsize *)
+ (* .bss *)
+ ; le 4 bssstr (* sh_name *)
+ ; sht_NOBITS (* sh_type *)
+ ; le 8 (shf_ALLOC lor shf_WRITE) (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 bssoff (* sh_offset *)
+ ; le 8 0 (* sh_size *)
+ ; le 4 0 (* sh_link *)
+ ; le 4 0 (* sh_info *)
+ ; le 8 1 (* sh_addralign *)
+ ; le 8 0 (* sh_entsize *)
+ (* .rela *)
+ ; le 4 relastr (* sh_name *)
+ ; sht_RELA (* sh_type *)
+ ; le 8 0 (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 relaoff (* sh_offset *)
+ ; le 8 0 (* sh_size *)
+ ; le 4 5 (* sh_link, symtab index *)
+ ; le 4 1 (* sh_info, text section *)
+ ; le 8 8 (* sh_addralign *)
+ ; le 8 0x18 (* sh_entsize *)
+ (* .symtab *)
+ ; le 4 symtstr (* sh_name *)
+ ; sht_SYMTAB (* sh_type *)
+ ; le 8 0 (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 symtoff (* sh_offset *)
+ ; le 8 (String.length symtab) (* sh_size *)
+ ; le 4 6 (* sh_link, strtab index *)
+ ; le 4 1 (* sh_info, first non-local symbol *)
+ ; le 8 8 (* sh_addralign *)
+ ; le 8 0x18 (* sh_entsize *)
+ (* .strtab *)
+ ; le 4 strtstr (* sh_name *)
+ ; sht_STRTAB (* sh_type *)
+ ; le 8 0 (* sh_flags *)
+ ; le 8 0 (* sh_addr *)
+ ; le 8 strtoff (* sh_offset *)
+ ; le 8 (String.length strtab) (* sh_size *)
+ ; le 4 0 (* sh_link *)
+ ; le 4 0 (* sh_info *)
+ ; le 8 1 (* sh_addralign *)
+ ; le 8 0x18 (* sh_entsize *)
+ ] in
+
+ List.iter (output_string oc)
+ [ header
+ ; sh
+ ; text
+ ; symtab
+ ; strtab
+ ]
+
+
+let _ =
+ let oc = open_out "test.o" in
+ let text = String.concat ""
+ [ "\xb8\x2a\x00\x00\x00" (* mov 42, %eax *)
+ ; "\xc3" (* retq *)
+ ; "\xc3\xc3" (* padding *)
+ ] in
+ barebones_elf oc text