ml_dwarf_write: write to a separate file

Don't try to write into the ELF file directly, use objcopy.

Updated README
This commit is contained in:
Théophile Bastian 2019-03-18 14:20:53 +01:00
parent 484b20c732
commit 8fa2bc5952
9 changed files with 87 additions and 31 deletions

View File

@ -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 []

View File

@ -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 $@

View File

@ -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;
}

View File

@ -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);

View File

@ -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));
}

View File

@ -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 <marshalled_data> <executable> *)
external write_dwarf : string -> string -> pre_c_pre_dwarf -> int
= "caml_write_dwarf"
(** ========== USAGE ========== **)
let use_string =
Sys.argv.(0) ^ " <marshalled_data> <executable> [<eh_file>]\n" ^
"<eh_file> defaults to `<executable>.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

View File

@ -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;
}

View File

@ -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`

View File

@ -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.(