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:
parent
484b20c732
commit
8fa2bc5952
|
@ -3,8 +3,6 @@ open Std
|
||||||
let main outfile proj =
|
let main outfile proj =
|
||||||
let pre_dwarf = Simplest.of_proj proj in
|
let pre_dwarf = Simplest.of_proj proj in
|
||||||
Format.printf "%a" Frontend.pp_pre_dwarf_readelf pre_dwarf;
|
Format.printf "%a" Frontend.pp_pre_dwarf_readelf pre_dwarf;
|
||||||
let pre_c_dwarf = PreCBinding.convert_pre_c pre_dwarf in
|
let pre_c_dwarf = PreCBinding.convert_pre_c pre_dwarf in
|
||||||
let fd = open_out_bin "tmp.marshal" in
|
let fd = open_out_bin outfile in
|
||||||
Marshal.to_channel fd pre_c_dwarf []
|
Marshal.to_channel fd pre_c_dwarf []
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
CDEFINE =
|
CDEFINE =
|
||||||
CFLAGS = -Wall -Wextra -std=c11 -O2 -g $(CDEFINE) -I/home/zappa/.opam/bap/lib/ocaml
|
CFLAGS = -Wall -Wextra -std=c11 -O2 -g $(CDEFINE) -I$(OPAM_SWITCH_PREFIX)/lib/ocaml
|
||||||
LIBDWARFW_DIR=../../libdwarfw/build
|
LIBDWARFW_DIR=$(shell readlink -f ../../libdwarfw/build)
|
||||||
CLIBS = -L$(LIBDWARFW_DIR) -Wl,-rpath,$(LIBDWARFW_DIR) -lz -lelf -ldwarf -ldwarfw
|
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
|
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
|
all: test_dw.bin ml_dwarf_write.bin
|
||||||
|
|
||||||
test_%.bin: test_%.o dwarf_write.o
|
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
|
%.o: %.c
|
||||||
gcc $(CFLAGS) -c $< -o $@
|
gcc $(CFLAGS) -c $< -o $@
|
||||||
|
|
|
@ -256,8 +256,8 @@ static int write_all_fde_instructions(struct dwarfw_fde *fde,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_section(struct internal_state* state,
|
static int process_section(struct internal_state* state,
|
||||||
struct pre_dwarf* pre_dwarf, Elf_Scn *s, FILE *f, size_t *written /*,
|
struct pre_dwarf* pre_dwarf, Elf_Scn *s, FILE *f,
|
||||||
FILE *rela_f */)
|
size_t *written /*, FILE *rela_f */)
|
||||||
{
|
{
|
||||||
size_t shndx = elf_ndxscn(s);
|
size_t shndx = elf_ndxscn(s);
|
||||||
fprintf(stderr, "Processing section %lu\n", shndx); //D
|
fprintf(stderr, "Processing section %lu\n", shndx); //D
|
||||||
|
@ -357,9 +357,13 @@ static int process_section(struct internal_state* state,
|
||||||
return 0;
|
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);
|
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);
|
int fd = open(objname, O_RDWR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fprintf(stderr, "cannot open file\n");
|
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 };
|
struct internal_state state = { .elf = elf };
|
||||||
|
|
||||||
|
/*
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
FILE *f = open_memstream(&buf, &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");
|
fprintf(stderr, "open_memstream() failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
char *rela_buf;
|
char *rela_buf;
|
||||||
|
@ -426,19 +432,21 @@ int write_dwarf(char* objname, struct pre_dwarf* pre_dwarf) {
|
||||||
continue;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
// fclose(f);
|
||||||
/* fclose(rela_f); */
|
/* fclose(rela_f); */
|
||||||
|
|
||||||
// Create the .eh_frame section
|
// Create the .eh_frame section
|
||||||
|
/*
|
||||||
Elf_Scn *scn = create_debug_frame_section(elf, ".eh_frame", buf, len);
|
Elf_Scn *scn = create_debug_frame_section(elf, ".eh_frame", buf, len);
|
||||||
if (scn == NULL) {
|
if (scn == NULL) {
|
||||||
fprintf(stderr, "create_debug_frame_section() failed\n");
|
fprintf(stderr, "create_debug_frame_section() failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Create the .eh_frame.rela section
|
// 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
|
// Write the modified ELF object
|
||||||
|
/*
|
||||||
elf_flagelf(elf, ELF_C_SET, ELF_F_DIRTY);
|
elf_flagelf(elf, ELF_C_SET, ELF_F_DIRTY);
|
||||||
if (elf_update(elf, ELF_C_WRITE) < 0) {
|
if (elf_update(elf, ELF_C_WRITE) < 0) {
|
||||||
fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1));
|
fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
free(buf);
|
// free(buf);
|
||||||
/* free(rela_buf); */
|
/* free(rela_buf); */
|
||||||
|
|
||||||
elf_end(elf);
|
elf_end(elf);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
fclose(out_dwarf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,5 +55,5 @@ struct pre_dwarf {
|
||||||
struct pre_dwarf_fde* fdes;
|
struct pre_dwarf_fde* fdes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Writes the provided `pre_dwarf` as DWARF in the ELF file at `obj_path`
|
/// 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, struct pre_dwarf* pre_dwarf);
|
int write_dwarf(char* obj_path, char* eh_path, struct pre_dwarf* pre_dwarf);
|
||||||
|
|
|
@ -142,9 +142,9 @@ struct pre_dwarf * convert_pre_dwarf(value oc_pre_dwarf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OCaml type: string -> pre_c_dwarf -> int
|
// 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;
|
struct pre_dwarf *pre_dwarf;
|
||||||
|
|
||||||
CAMLparam2(oc_obj_path, oc_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);
|
obj_path = String_val(oc_obj_path);
|
||||||
|
|
||||||
|
eh_path = String_val(oc_eh_path);
|
||||||
|
|
||||||
pre_dwarf = convert_pre_dwarf(oc_pre_dwarf);
|
pre_dwarf = convert_pre_dwarf(oc_pre_dwarf);
|
||||||
|
|
||||||
dump_pre_dwarf(*pre_dwarf);
|
dump_pre_dwarf(*pre_dwarf);
|
||||||
|
|
||||||
CAMLreturn(write_dwarf(obj_path, pre_dwarf));
|
CAMLreturn(write_dwarf(obj_path, eh_path, pre_dwarf));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,27 +21,38 @@ type pre_c_pre_dwarf = {
|
||||||
|
|
||||||
let dump_pre_c_pre_dwarf_entry e =
|
let dump_pre_c_pre_dwarf_entry e =
|
||||||
Printf.printf " %8Lx %d+%Ld \n" e.location e.cfa_offset_reg e.cfa_offset
|
Printf.printf " %8Lx %d+%Ld \n" e.location e.cfa_offset_reg e.cfa_offset
|
||||||
|
|
||||||
let dump_pre_c_pre_dwarf_fde f =
|
let dump_pre_c_pre_dwarf_fde f =
|
||||||
Printf.printf "%s %Lx %Lx\n" f.name f.initial_location f.end_location;
|
Printf.printf "%s %Lx %Lx\n" f.name f.initial_location f.end_location;
|
||||||
for i = 0 to Array.length f.entries - 1 do
|
for i = 0 to Array.length f.entries - 1 do
|
||||||
dump_pre_c_pre_dwarf_entry f.entries.(i)
|
dump_pre_c_pre_dwarf_entry f.entries.(i)
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
let dump_pre_c_pre_dwarf p =
|
let dump_pre_c_pre_dwarf p =
|
||||||
for i = 0 to Array.length p.fdes - 1 do
|
for i = 0 to Array.length p.fdes - 1 do
|
||||||
dump_pre_c_pre_dwarf_fde p.fdes.(i)
|
dump_pre_c_pre_dwarf_fde p.fdes.(i)
|
||||||
done
|
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 _ =
|
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 fd = open_in_bin Sys.argv.(1) in
|
||||||
let pre_c_dwarf = ((Marshal.from_channel fd): pre_c_pre_dwarf) in
|
let pre_c_dwarf = ((Marshal.from_channel fd): pre_c_pre_dwarf) in
|
||||||
dump_pre_c_pre_dwarf pre_c_dwarf;
|
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
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,6 @@ int main() {
|
||||||
};
|
};
|
||||||
struct pre_dwarf dwarf_data = {1, &fde};
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
32
README.md
32
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
|
This tool relies on [BAP](https://github.com/BinaryAnalysisPlatform/bap), which
|
||||||
is available through OPAM.
|
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`
|
||||||
|
|
|
@ -14,9 +14,10 @@ module Cmdline = struct
|
||||||
module Cnf = Self.Config
|
module Cnf = Self.Config
|
||||||
|
|
||||||
let outfile = Cnf.(
|
let outfile = Cnf.(
|
||||||
param (some string) "output"
|
param (string) "output"
|
||||||
~doc:("The file in which the output ELF will be written. Output goes "
|
~doc:("The file in which the output marshalled data will be written. "
|
||||||
^ "to stdout by default.")
|
^ "Output goes to ./tmp.marshal by default.")
|
||||||
|
~default:"tmp.marshal"
|
||||||
)
|
)
|
||||||
|
|
||||||
let () = Cnf.(
|
let () = Cnf.(
|
||||||
|
|
Loading…
Reference in a new issue