diff --git a/libr/bin/format/coff/coff.c b/libr/bin/format/coff/coff.c index 1858491d2c..00a0f65d7d 100644 --- a/libr/bin/format/coff/coff.c +++ b/libr/bin/format/coff/coff.c @@ -4,7 +4,7 @@ #include "coff.h" -bool r_coff_supported_arch (const ut8 *buf) { +bool r_coff_supported_arch(const ut8 *buf) { ut16 arch = *(ut16*)buf; switch (arch) { case COFF_FILE_MACHINE_AMD64: @@ -17,12 +17,12 @@ bool r_coff_supported_arch (const ut8 *buf) { } } -int r_coff_is_stripped (struct r_bin_coff_obj *obj) { +int r_coff_is_stripped(struct r_bin_coff_obj *obj) { return !!(obj->hdr.f_flags & (COFF_FLAGS_TI_F_RELFLG | \ COFF_FLAGS_TI_F_LNNO | COFF_FLAGS_TI_F_LSYMS)); } -const char *r_coff_symbol_name (struct r_bin_coff_obj *obj, void *ptr) { +char *r_coff_symbol_name(struct r_bin_coff_obj *obj, void *ptr) { char n[256] = {0}; int len = 0, offset = 0; union { @@ -49,7 +49,7 @@ const char *r_coff_symbol_name (struct r_bin_coff_obj *obj, void *ptr) { return strdup (n); } -static int r_coff_rebase_sym (struct r_bin_coff_obj *obj, RBinAddr *addr, struct coff_symbol *sym) { +static int r_coff_rebase_sym(struct r_bin_coff_obj *obj, RBinAddr *addr, struct coff_symbol *sym) { if (sym->n_scnum < 1 || sym->n_scnum > obj->hdr.f_nscns) { return 0; } diff --git a/libr/bin/format/coff/coff.h b/libr/bin/format/coff/coff.h index 1e0d268d3e..561bfd8925 100644 --- a/libr/bin/format/coff/coff.h +++ b/libr/bin/format/coff/coff.h @@ -28,7 +28,7 @@ bool r_coff_supported_arch(const ut8 *buf); /* Reads two bytes from buf. */ struct r_bin_coff_obj* r_bin_coff_new_buf(struct r_buf_t *buf); void r_bin_coff_free(struct r_bin_coff_obj *obj); RBinAddr *r_coff_get_entry(struct r_bin_coff_obj *obj); -const char *r_coff_symbol_name (struct r_bin_coff_obj *obj, void *ptr); +char *r_coff_symbol_name (struct r_bin_coff_obj *obj, void *ptr); int r_coff_is_stripped (struct r_bin_coff_obj *obj); #endif /* COFF_H */ diff --git a/libr/bin/format/coff/coff_specs.h b/libr/bin/format/coff/coff_specs.h index a096b415c4..5a62f76330 100644 --- a/libr/bin/format/coff/coff_specs.h +++ b/libr/bin/format/coff/coff_specs.h @@ -172,4 +172,11 @@ struct coff_symbol { ut8 n_numaux; /* Auxiliary Count */ } __attribute__((packed)); + +struct coff_reloc { + ut32 r_vaddr; /* Reference Address */ + ut32 r_symndx; /* Symbol index */ + ut16 r_type; /* Type of relocation */ +} __attribute__((packed)); + #endif /* COFF_SPECS_H */ diff --git a/libr/bin/p/bin_coff.c b/libr/bin/p/bin_coff.c index c5da884ec2..4f6518ac7d 100644 --- a/libr/bin/p/bin_coff.c +++ b/libr/bin/p/bin_coff.c @@ -59,6 +59,51 @@ static RBinAddr *binsym(RBinFile *arch, int sym) { return NULL; } + +static bool _fill_bin_symbol(struct r_bin_coff_obj *bin, int idx, RBinSymbol **sym) { + RBinSymbol *ptr = *sym; + char * coffname = NULL; + struct coff_symbol *s = NULL; + if (idx > bin->hdr.f_nsyms) { + return false; + } + s = &bin->symbols[idx]; + coffname = r_coff_symbol_name (bin, s); + if (!coffname) { + return false; + } + ptr->name = strdup (coffname); + free (coffname); + ptr->forwarder = r_str_const ("NONE"); + + switch (s->n_sclass) { + case COFF_SYM_CLASS_FUNCTION: + ptr->type = r_str_const ("FUNC"); + break; + case COFF_SYM_CLASS_FILE: + ptr->type = r_str_const ("FILE"); + break; + case COFF_SYM_CLASS_SECTION: + ptr->type = r_str_const ("SECTION"); + break; + case COFF_SYM_CLASS_EXTERNAL: + ptr->type = r_str_const ("EXTERNAL"); + break; + case COFF_SYM_CLASS_STATIC: + ptr->type = r_str_const ("STATIC"); + break; + default: + ptr->type = r_str_const (sdb_fmt (0, "%i", s->n_sclass)); + break; + } + if (bin->symbols[idx].n_scnum < bin->hdr.f_nscns) { + ptr->paddr = bin->scn_hdrs[s->n_scnum].s_scnptr + s->n_value; + } + ptr->size = 4; + ptr->ordinal = 0; + return true; +} + static RList *entries(RBinFile *arch) { struct r_bin_coff_obj *obj = (struct r_bin_coff_obj*)arch->o->bin_obj; RList *ret; @@ -119,61 +164,26 @@ static RList *sections(RBinFile *arch) { } static RList *symbols(RBinFile *arch) { - const char *coffname; - size_t i; + int i; RList *ret = NULL; RBinSymbol *ptr = NULL; - struct r_bin_coff_obj *obj = (struct r_bin_coff_obj*)arch->o->bin_obj; - if (!(ret = r_list_newf (free))) { + struct r_bin_coff_obj *obj = (struct r_bin_coff_obj*)arch->o->bin_obj; + if (!(ret = r_list_new ())) { return ret; } - + ret->free = free; if (obj->symbols) { for (i = 0; i < obj->hdr.f_nsyms; i++) { if (!(ptr = R_NEW0 (RBinSymbol))) { break; } - coffname = r_coff_symbol_name (obj, &obj->symbols[i]); - if (!coffname) { - free (ptr); - break; + if (_fill_bin_symbol (obj, i, &ptr)) { + r_list_append (ret, ptr); } - ptr->name = strdup (coffname); - ptr->forwarder = r_str_const ("NONE"); - - switch (obj->symbols[i].n_sclass) { - case COFF_SYM_CLASS_FUNCTION: - ptr->type = r_str_const ("FUNC"); - break; - case COFF_SYM_CLASS_FILE: - ptr->type = r_str_const ("FILE"); - break; - case COFF_SYM_CLASS_SECTION: - ptr->type = r_str_const ("SECTION"); - break; - case COFF_SYM_CLASS_EXTERNAL: - ptr->type = r_str_const ("EXTERNAL"); - break; - case COFF_SYM_CLASS_STATIC: - ptr->type = r_str_const ("STATIC"); - break; - default: - ptr->type = r_str_const (sdb_fmt(0, "%i", obj->symbols[i].n_sclass)); - break; - } - - if (obj->symbols[i].n_scnum < obj->hdr.f_nscns) { - ptr->paddr = obj->scn_hdrs[obj->symbols[i].n_scnum].s_scnptr + - obj->symbols[i].n_value; - } - ptr->size = 4; - ptr->ordinal = 0; - r_list_append (ret, ptr); i += obj->symbols[i].n_numaux; } } - return ret; } @@ -186,7 +196,58 @@ static RList *libs(RBinFile *arch) { } static RList *relocs(RBinFile *arch) { - return NULL; + struct r_bin_coff_obj *bin = (struct r_bin_coff_obj*)arch->o->bin_obj; + RBinReloc *reloc; + struct coff_reloc *rel; + int j, i = 0; + RList *list_rel; + list_rel = r_list_new (); + if (!list_rel || !bin || !bin->scn_hdrs) { + return NULL; + } + for (i = 0; i < bin->hdr.f_nscns; i++) { + if (bin->scn_hdrs[i].s_nreloc) { + int len = 0, size = bin->scn_hdrs[i].s_nreloc * sizeof (struct coff_reloc); + if (size < 0) { + return list_rel; + } + rel = calloc (1, size + 1); + if (!rel) { + return list_rel; + } + if (bin->scn_hdrs[i].s_relptr > bin->size || + bin->scn_hdrs[i].s_relptr + size > bin->size) { + return list_rel; + } + len = r_buf_read_at (bin->b, bin->scn_hdrs[i].s_relptr, (ut8*)rel, size); + if (len != size) { + free (rel); + return list_rel; + } + for (j = 0; j < bin->scn_hdrs[i].s_nreloc; j++) { + RBinSymbol *symbol = R_NEW0 (RBinSymbol); + if (!symbol) { + continue; + } + if (!_fill_bin_symbol (bin, rel[j].r_symndx, &symbol)) { + free (symbol); + continue; + } + reloc = R_NEW0 (RBinReloc); + if (!reloc) { + free (symbol); + continue; + } + reloc->type = rel[j].r_type; //XXX the type if different from what r2 expects + reloc->symbol = symbol; + reloc->paddr = bin->scn_hdrs[i].s_scnptr + rel[j].r_vaddr; + reloc->vaddr = reloc->paddr; + r_list_append (list_rel, reloc); + } + + } + } + return list_rel; } static RBinInfo *info(RBinFile *arch) {