From 8fa2bc5952a4f689dd7c349198964335c0d3bf9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Mon, 18 Mar 2019 14:20:53 +0100 Subject: [PATCH] ml_dwarf_write: write to a separate file Don't try to write into the ELF file directly, use objcopy. Updated README --- DwarfSynth/Main.ml | 6 ++--- DwarfSynth/c_bindings/Makefile | 7 ++--- DwarfSynth/c_bindings/dwarf_write.c | 23 +++++++++++----- DwarfSynth/c_bindings/dwarf_write.h | 4 +-- DwarfSynth/c_bindings/dwarf_write_stubs.c | 10 ++++--- DwarfSynth/c_bindings/ml_dwarf_write.ml | 27 +++++++++++++------ DwarfSynth/c_bindings/test_dw.c | 2 +- README.md | 32 +++++++++++++++++++++++ dwarfsynth.ml | 7 ++--- 9 files changed, 87 insertions(+), 31 deletions(-) diff --git a/DwarfSynth/Main.ml b/DwarfSynth/Main.ml index c9f4ff5..da10d48 100644 --- a/DwarfSynth/Main.ml +++ b/DwarfSynth/Main.ml @@ -3,8 +3,6 @@ open Std let main outfile proj = let pre_dwarf = Simplest.of_proj proj in Format.printf "%a" Frontend.pp_pre_dwarf_readelf pre_dwarf; - let pre_c_dwarf = PreCBinding.convert_pre_c pre_dwarf in - let fd = open_out_bin "tmp.marshal" in + let pre_c_dwarf = PreCBinding.convert_pre_c pre_dwarf in + let fd = open_out_bin outfile in Marshal.to_channel fd pre_c_dwarf [] - - diff --git a/DwarfSynth/c_bindings/Makefile b/DwarfSynth/c_bindings/Makefile index 02047a6..4c55f0f 100644 --- a/DwarfSynth/c_bindings/Makefile +++ b/DwarfSynth/c_bindings/Makefile @@ -1,14 +1,15 @@ CDEFINE = -CFLAGS = -Wall -Wextra -std=c11 -O2 -g $(CDEFINE) -I/home/zappa/.opam/bap/lib/ocaml -LIBDWARFW_DIR=../../libdwarfw/build +CFLAGS = -Wall -Wextra -std=c11 -O2 -g $(CDEFINE) -I$(OPAM_SWITCH_PREFIX)/lib/ocaml +LIBDWARFW_DIR=$(shell readlink -f ../../libdwarfw/build) CLIBS = -L$(LIBDWARFW_DIR) -Wl,-rpath,$(LIBDWARFW_DIR) -lz -lelf -ldwarf -ldwarfw +#CLIBELF = /usr/lib/x86_64-linux-gnu/libelf.a OCAMLCLIBS = -ccopt -L$(LIBDWARFW_DIR) -ccopt -Wl,-rpath,$(LIBDWARFW_DIR) -cclib -lz -cclib -lelf -cclib -ldwarf -cclib -ldwarfw all: test_dw.bin ml_dwarf_write.bin test_%.bin: test_%.o dwarf_write.o - gcc $(CFLAGS) $^ /usr/lib/x86_64-linux-gnu/libelf.a $(CLIBS) -o $@ + gcc $(CFLAGS) $^ $(CLIBELF) $(CLIBS) -o $@ %.o: %.c gcc $(CFLAGS) -c $< -o $@ diff --git a/DwarfSynth/c_bindings/dwarf_write.c b/DwarfSynth/c_bindings/dwarf_write.c index fe84671..e09db20 100644 --- a/DwarfSynth/c_bindings/dwarf_write.c +++ b/DwarfSynth/c_bindings/dwarf_write.c @@ -256,8 +256,8 @@ static int write_all_fde_instructions(struct dwarfw_fde *fde, } static int process_section(struct internal_state* state, - struct pre_dwarf* pre_dwarf, Elf_Scn *s, FILE *f, size_t *written /*, - FILE *rela_f */) + struct pre_dwarf* pre_dwarf, Elf_Scn *s, FILE *f, + size_t *written /*, FILE *rela_f */) { size_t shndx = elf_ndxscn(s); fprintf(stderr, "Processing section %lu\n", shndx); //D @@ -357,9 +357,13 @@ static int process_section(struct internal_state* state, return 0; } -int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) { +int write_dwarf(char* objname, char* eh_path, struct pre_dwarf* pre_dwarf) { elf_version(EV_CURRENT); + FILE* out_dwarf = fopen(eh_path, "a"); // Create file + fclose(out_dwarf); + out_dwarf = fopen(eh_path, "w"); // Truncate and open for writing + int fd = open(objname, O_RDWR); if (fd == -1) { fprintf(stderr, "cannot open file\n"); @@ -392,6 +396,7 @@ int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) { struct internal_state state = { .elf = elf }; + /* char *buf; size_t len; FILE *f = open_memstream(&buf, &len); @@ -399,6 +404,7 @@ int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) { fprintf(stderr, "open_memstream() failed\n"); return 1; } + */ /* char *rela_buf; @@ -426,19 +432,21 @@ int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) { continue; } - if (process_section(&state, pre_dwarf, s, f, &written /*, rela_f*/)) { + if (process_section(&state, pre_dwarf, s, out_dwarf, &written /*, rela_f*/)) { return 1; } } - fclose(f); + // fclose(f); /* fclose(rela_f); */ // Create the .eh_frame section + /* Elf_Scn *scn = create_debug_frame_section(elf, ".eh_frame", buf, len); if (scn == NULL) { fprintf(stderr, "create_debug_frame_section() failed\n"); return 1; } + */ /* // Create the .eh_frame.rela section @@ -451,17 +459,20 @@ int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) { */ // Write the modified ELF object + /* elf_flagelf(elf, ELF_C_SET, ELF_F_DIRTY); if (elf_update(elf, ELF_C_WRITE) < 0) { fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1)); return 1; } + */ - free(buf); + // free(buf); /* free(rela_buf); */ elf_end(elf); close(fd); + fclose(out_dwarf); return 0; } diff --git a/DwarfSynth/c_bindings/dwarf_write.h b/DwarfSynth/c_bindings/dwarf_write.h index 3230e44..7f4b7dc 100644 --- a/DwarfSynth/c_bindings/dwarf_write.h +++ b/DwarfSynth/c_bindings/dwarf_write.h @@ -55,5 +55,5 @@ struct pre_dwarf { struct pre_dwarf_fde* fdes; }; -/// Writes the provided `pre_dwarf` as DWARF in the ELF file at `obj_path` -int write_dwarf(char* obj_path, struct pre_dwarf* pre_dwarf); +/// Writes the provided `pre_dwarf` as DWARF in the file `eh_path`, for the ELF file at `obj_path` +int write_dwarf(char* obj_path, char* eh_path, struct pre_dwarf* pre_dwarf); diff --git a/DwarfSynth/c_bindings/dwarf_write_stubs.c b/DwarfSynth/c_bindings/dwarf_write_stubs.c index 7f66615..936d97c 100644 --- a/DwarfSynth/c_bindings/dwarf_write_stubs.c +++ b/DwarfSynth/c_bindings/dwarf_write_stubs.c @@ -142,9 +142,9 @@ struct pre_dwarf * convert_pre_dwarf(value oc_pre_dwarf) { } // OCaml type: string -> pre_c_dwarf -> int -value caml_write_dwarf (value oc_obj_path, value oc_pre_dwarf) { +value caml_write_dwarf (value oc_obj_path, value oc_eh_path, value oc_pre_dwarf) { - char *obj_path; + char *obj_path, *eh_path; struct pre_dwarf *pre_dwarf; CAMLparam2(oc_obj_path, oc_pre_dwarf); @@ -153,9 +153,11 @@ value caml_write_dwarf (value oc_obj_path, value oc_pre_dwarf) { obj_path = String_val(oc_obj_path); + eh_path = String_val(oc_eh_path); + pre_dwarf = convert_pre_dwarf(oc_pre_dwarf); dump_pre_dwarf(*pre_dwarf); - - CAMLreturn(write_dwarf(obj_path, pre_dwarf)); + + CAMLreturn(write_dwarf(obj_path, eh_path, pre_dwarf)); } diff --git a/DwarfSynth/c_bindings/ml_dwarf_write.ml b/DwarfSynth/c_bindings/ml_dwarf_write.ml index ec21a7f..ea03f28 100644 --- a/DwarfSynth/c_bindings/ml_dwarf_write.ml +++ b/DwarfSynth/c_bindings/ml_dwarf_write.ml @@ -21,27 +21,38 @@ type pre_c_pre_dwarf = { let dump_pre_c_pre_dwarf_entry e = Printf.printf " %8Lx %d+%Ld \n" e.location e.cfa_offset_reg e.cfa_offset - + let dump_pre_c_pre_dwarf_fde f = Printf.printf "%s %Lx %Lx\n" f.name f.initial_location f.end_location; for i = 0 to Array.length f.entries - 1 do dump_pre_c_pre_dwarf_entry f.entries.(i) done - - + + let dump_pre_c_pre_dwarf p = for i = 0 to Array.length p.fdes - 1 do dump_pre_c_pre_dwarf_fde p.fdes.(i) done - -external write_dwarf : string -> pre_c_pre_dwarf -> int = "caml_write_dwarf" -(* use: ml_dwarf_write *) - +external write_dwarf : string -> string -> pre_c_pre_dwarf -> int + = "caml_write_dwarf" + +(** ========== USAGE ========== **) +let use_string = + Sys.argv.(0) ^ " []\n" ^ + " defaults to `.eh_frame`\n" ;; + let _ = + if Array.length Sys.argv <= 2 then ( + Format.eprintf "Error: missing argument(s). Usage:\n%s" use_string ; + exit 1 + ) ; + let eh_path = (if Array.length Sys.argv <= 3 + then (Sys.argv.(2) ^ ".eh_frame") + else Sys.argv.(3)) in let fd = open_in_bin Sys.argv.(1) in let pre_c_dwarf = ((Marshal.from_channel fd): pre_c_pre_dwarf) in dump_pre_c_pre_dwarf pre_c_dwarf; - write_dwarf Sys.argv.(2) pre_c_dwarf + write_dwarf Sys.argv.(2) eh_path pre_c_dwarf diff --git a/DwarfSynth/c_bindings/test_dw.c b/DwarfSynth/c_bindings/test_dw.c index 071e23c..5f7b8eb 100644 --- a/DwarfSynth/c_bindings/test_dw.c +++ b/DwarfSynth/c_bindings/test_dw.c @@ -13,6 +13,6 @@ int main() { }; struct pre_dwarf dwarf_data = {1, &fde}; - write_dwarf("test.bin", &dwarf_data); + write_dwarf("test.bin", "test.bin.eh_frame", &dwarf_data); return 0; } diff --git a/README.md b/README.md index b36675c..857f0d7 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,35 @@ examine its assembly code and, based solely on that, generate the corresponding This tool relies on [BAP](https://github.com/BinaryAnalysisPlatform/bap), which is available through OPAM. + +## Running + +First, run `make` to compile and install the BAP plugin. + +### Running the BAP plugin + +`bap prog_to_analyze.bin -p dwarfsynth --dwarfsynth-output tmp.marshal` + +### Running `ml_dwarf_write` + +You can get a help text with `./ml_dwarf_write.bin`. Otherwise, you can run + +``` +./ml_dwarf_write.bin tmp.marshal prog_to_analyze.bin eh_frame_section` +``` + +### Stitching the section into a binary + +``` +objcopy --add-section .eh_frame=eh_frame_section prog_to_analyze.bin prog_to_analyze.eh.bin +``` + +## Commonly used commands + +### List a binary sections + +`objdump -h blah.bin` + +### Strip a binary of its `eh_frame` + +`objcopy --remove-section '.eh_frame' --remove-section '.eh_frame_hdr' blah.bin` diff --git a/dwarfsynth.ml b/dwarfsynth.ml index 4043df5..8093420 100644 --- a/dwarfsynth.ml +++ b/dwarfsynth.ml @@ -14,9 +14,10 @@ module Cmdline = struct module Cnf = Self.Config let outfile = Cnf.( - param (some string) "output" - ~doc:("The file in which the output ELF will be written. Output goes " - ^ "to stdout by default.") + param (string) "output" + ~doc:("The file in which the output marshalled data will be written. " + ^ "Output goes to ./tmp.marshal by default.") + ~default:"tmp.marshal" ) let () = Cnf.(