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
9 changed files with 87 additions and 31 deletions
|
@ -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 []
|
||||
|
||||
|
||||
|
|
|
@ -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 $@
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
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
|
||||
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
|
||||
|
||||
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.(
|
||||
|
|
Loading…
Add table
Reference in a new issue