COFF: add ARMNT and ARM64 support ##bin (#17800)

This commit is contained in:
Paul I 2020-10-29 08:33:43 +03:00 committed by Florian Märkl
parent 9d72c7a1f3
commit f98460982f
5 changed files with 159 additions and 62 deletions

View file

@ -16,6 +16,8 @@ bool rz_coff_supported_arch(const ut8 *buf) {
case COFF_FILE_MACHINE_R4000:
case COFF_FILE_MACHINE_AMD29KBE:
case COFF_FILE_MACHINE_AMD29KLE:
case COFF_FILE_MACHINE_ARM64:
case COFF_FILE_MACHINE_ARMNT:
return true;
default:
return false;
@ -25,12 +27,12 @@ bool rz_coff_supported_arch(const ut8 *buf) {
char *rz_coff_symbol_name(struct rz_bin_coff_obj *obj, void *ptr) {
char n[256] = {0};
int len = 0, offset = 0;
union {
char name[8];
struct {
ut32 zero;
ut32 offset;
};
union {
char name[8];
struct {
ut32 zero;
ut32 offset;
};
} *p = ptr;
if (!ptr) {
return NULL;
@ -59,7 +61,7 @@ static int rz_coff_rebase_sym(struct rz_bin_coff_obj *obj, RzBinAddr *addr, stru
return 1;
}
/* Try to get a valid entrypoint using the methods outlined in
/* Try to get a valid entrypoint using the methods outlined in
* http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#SEC24 */
RzBinAddr *rz_coff_get_entry(struct rz_bin_coff_obj *obj) {
RzBinAddr *addr = RZ_NEW0 (RzBinAddr);
@ -147,7 +149,7 @@ static bool rz_bin_coff_init_opt_hdr(struct rz_bin_coff_obj *obj) {
static bool rz_bin_coff_init_scn_hdr(struct rz_bin_coff_obj *obj) {
int ret, size;
ut64 offset = sizeof (struct coff_hdr) + (obj->hdr.f_opthdr ? sizeof (struct coff_opt_hdr) : 0);
ut64 offset = sizeof (struct coff_hdr) + (obj->hdr.f_opthdr ? sizeof (struct coff_opt_hdr) : 0);
if (obj->hdr.f_magic == COFF_FILE_TI_COFF) {
offset += 2;
}
@ -155,7 +157,7 @@ static bool rz_bin_coff_init_scn_hdr(struct rz_bin_coff_obj *obj) {
if (offset > obj->size || offset + size > obj->size || size < 0) {
return false;
}
obj->scn_hdrs = calloc (1, size + sizeof (struct coff_scn_hdr));
obj->scn_hdrs = calloc (1, size + sizeof (struct coff_scn_hdr));
if (!obj->scn_hdrs) {
return false;
}
@ -179,7 +181,7 @@ static bool rz_bin_coff_init_symtable(struct rz_bin_coff_obj *obj) {
offset > obj->size ||
offset + size > obj->size) {
return false;
}
}
obj->symbols = calloc (1, size + sizeof (struct coff_symbol));
if (!obj->symbols) {
return false;
@ -192,6 +194,21 @@ static bool rz_bin_coff_init_symtable(struct rz_bin_coff_obj *obj) {
return true;
}
static bool rz_bin_coff_init_scn_va(struct rz_bin_coff_obj *obj) {
obj->scn_va = RZ_NEWS (ut64, obj->hdr.f_nscns);
if (!obj->scn_va) {
return false;
}
int i;
ut64 va = 0;
for (i = 0; i < obj->hdr.f_nscns; i++) {
obj->scn_va[i] = va;
va += obj->scn_hdrs[i].s_size;
va = RZ_ROUND (va, 16ULL);
}
return true;
}
static int rz_bin_coff_init(struct rz_bin_coff_obj *obj, RBuffer *buf, bool verbose) {
obj->b = rz_buf_ref (buf);
obj->size = rz_buf_size (buf);
@ -211,12 +228,17 @@ static int rz_bin_coff_init(struct rz_bin_coff_obj *obj, RBuffer *buf, bool verb
bprintf ("Warning: failed to init symtable\n");
return false;
}
if (!rz_bin_coff_init_scn_va (obj)) {
bprintf ("Warning: failed to init section VA table\n");
return false;
}
return true;
}
void rz_bin_coff_free(struct rz_bin_coff_obj *obj) {
ht_up_free (obj->sym_ht);
ht_up_free (obj->imp_ht);
free (obj->scn_va);
free (obj->scn_hdrs);
free (obj->symbols);
rz_buf_free (obj->b);

View file

@ -29,6 +29,7 @@ struct rz_bin_coff_obj {
bool verbose;
HtUP *sym_ht;
HtUP *imp_ht;
ut64 *scn_va;
};
bool rz_coff_supported_arch(const ut8 *buf); /* Reads two bytes from buf. */

View file

@ -153,6 +153,14 @@
#define COFF_REL_AMD64_REL32_4 8
#define COFF_REL_AMD64_REL32_5 9
#define COFF_REL_ARM_BRANCH24T 20
#define COFF_REL_ARM_BLX23T 21
#define COFF_REL_ARM64_ABSOLUTE 0
#define COFF_REL_ARM64_ADDR32 1
#define COFF_REL_ARM64_ADDR32NB 2
#define COFF_REL_ARM64_BRANCH26 3
RZ_PACKED(
struct coff_hdr {
ut16 f_magic; /* Magic number */

View file

@ -67,6 +67,7 @@ static bool _fill_bin_symbol(RzBin *rbin, struct rz_bin_coff_obj *bin, int idx,
//first index is 0 that is why -1
sc_hdr = &bin->scn_hdrs[s->n_scnum - 1];
ptr->paddr = sc_hdr->s_scnptr + s->n_value;
ptr->vaddr = bin->scn_va[s->n_scnum - 1] + s->n_value;
}
switch (s->n_sclass) {
@ -82,7 +83,7 @@ static bool _fill_bin_symbol(RzBin *rbin, struct rz_bin_coff_obj *bin, int idx,
case COFF_SYM_CLASS_EXTERNAL:
if (s->n_scnum == COFF_SYM_SCNUM_UNDEF) {
ptr->is_imported = true;
ptr->paddr = UT64_MAX;
ptr->paddr = ptr->vaddr = UT64_MAX;
ptr->bind = "NONE";
} else {
ptr->bind = RZ_BIN_BIND_GLOBAL_STR;
@ -94,7 +95,7 @@ static bool _fill_bin_symbol(RzBin *rbin, struct rz_bin_coff_obj *bin, int idx,
case COFF_SYM_CLASS_STATIC:
if (s->n_scnum == COFF_SYM_SCNUM_ABS) {
ptr->type = "ABS";
ptr->paddr = UT64_MAX;
ptr->paddr = ptr->vaddr = UT64_MAX;
ptr->name = rz_str_newf ("%s-0x%08x", coffname, s->n_value);
if (ptr->name) {
RZ_FREE (coffname);
@ -113,7 +114,6 @@ static bool _fill_bin_symbol(RzBin *rbin, struct rz_bin_coff_obj *bin, int idx,
ptr->type = rz_str_constpool_get (&rbin->constpool, sdb_fmt ("%i", s->n_sclass));
break;
}
ptr->vaddr = ptr->paddr;
ptr->size = 4;
ptr->ordinal = 0;
return true;
@ -192,6 +192,7 @@ static RzList *sections(RzBinFile *bf) {
ptr->size = obj->scn_hdrs[i].s_size;
ptr->vsize = obj->scn_hdrs[i].s_size;
ptr->paddr = obj->scn_hdrs[i].s_scnptr;
ptr->vaddr = obj->scn_va[i];
ptr->add = true;
ptr->perm = 0;
if (obj->scn_hdrs[i].s_flags & COFF_SCN_MEM_READ) {
@ -269,6 +270,14 @@ static ut32 _read_le32(RzBin *rbin, ut64 addr) {
return rz_read_le32 (data);
}
static ut16 _read_le16(RzBin *rbin, ut64 addr) {
ut8 data[2] = { 0 };
if (!rbin->iob.read_at (rbin->iob.io, addr, data, sizeof (data))) {
return UT16_MAX;
}
return rz_read_le16 (data);
}
#define BYTES_PER_IMP_RELOC 8
static RzList *_relocs_list(RzBin *rbin, struct rz_bin_coff_obj *bin, bool patch, ut64 imp_map) {
@ -321,12 +330,12 @@ static RzList *_relocs_list(RzBin *rbin, struct rz_bin_coff_obj *bin, bool patch
reloc->symbol = symbol;
reloc->paddr = bin->scn_hdrs[i].s_scnptr + rel[j].rz_vaddr;
reloc->vaddr = reloc->paddr;
reloc->vaddr = bin->scn_va[i] + rel[j].rz_vaddr;
reloc->type = rel[j].rz_type;
ut64 sym_vaddr = symbol->vaddr;
if (symbol->is_imported) {
reloc->import = (RzBinImport *)ht_up_find (bin->sym_ht, (ut64)rel[j].rz_symndx, NULL);
reloc->import = (RzBinImport *)ht_up_find (bin->imp_ht, (ut64)rel[j].rz_symndx, NULL);
if (patch_imports) {
bool found;
sym_vaddr = ht_uu_find (imp_vaddr_ht, (ut64)rel[j].rz_symndx, &found);
@ -334,6 +343,7 @@ static RzList *_relocs_list(RzBin *rbin, struct rz_bin_coff_obj *bin, bool patch
sym_vaddr = imp_map;
imp_map += BYTES_PER_IMP_RELOC;
ht_uu_insert (imp_vaddr_ht, (ut64)rel[j].rz_symndx, sym_vaddr);
symbol->vaddr = sym_vaddr;
}
}
}
@ -379,11 +389,50 @@ static RzList *_relocs_list(RzBin *rbin, struct rz_bin_coff_obj *bin, bool patch
break;
}
break;
case COFF_FILE_MACHINE_ARMNT:
switch (rel[j].rz_type) {
case COFF_REL_ARM_BRANCH24T:
case COFF_REL_ARM_BLX23T:
reloc->type = RZ_BIN_RELOC_32;
ut16 hiword = _read_le16 (rbin, reloc->vaddr);
if (hiword == UT16_MAX) {
break;
}
ut16 loword = _read_le16 (rbin, reloc->vaddr + 2);
if (loword == UT16_MAX) {
break;
}
ut64 dst = sym_vaddr - reloc->vaddr - 4;
if (dst & 1) {
break;
}
loword |= (ut16)(dst >> 1) & 0x7ff;
hiword |= (ut16)(dst >> 12) & 0x7ff;
rz_write_le16 (patch_buf, hiword);
rz_write_le16 (patch_buf + 2, loword);
plen = 4;
break;
}
break;
case COFF_FILE_MACHINE_ARM64:
switch (rel[j].rz_type) {
case COFF_REL_ARM64_BRANCH26:
reloc->type = RZ_BIN_RELOC_32;
ut32 data = _read_le32 (rbin, reloc->vaddr);
if (data == UT32_MAX) {
break;
}
ut64 dst = sym_vaddr - reloc->vaddr;
data |= (ut32)((dst >> 2) & 0x3ffffffULL);
rz_write_le32 (patch_buf, data);
plen = 4;
break;
}
break;
}
if (patch && plen) {
rbin->iob.write_at (rbin->iob.io, reloc->vaddr, patch_buf, plen);
if (symbol->is_imported) {
reloc->paddr = sym_vaddr;
reloc->vaddr = sym_vaddr;
}
}
@ -429,7 +478,15 @@ static RzList *patch_relocs(RzBin *b) {
}
ut64 m_vaddr = UT64_MAX;
if (nimports) {
m_vaddr = bin->size;
void **it;
ut64 offset = 0;
rz_pvector_foreach (&io->maps, it) {
RzIOMap *map = *it;
if ((map->itv.addr + map->itv.size) > offset) {
offset = map->itv.addr + map->itv.size;
}
}
m_vaddr = RZ_ROUND (offset, 16);
ut64 size = nimports * BYTES_PER_IMP_RELOC;
char *muri = rz_str_newf ("malloc://%" PFMT64u, size);
RzIODesc *desc = b->iob.open_at (io, muri, RZ_PERM_R, 0664, m_vaddr);
@ -459,7 +516,7 @@ static RzBinInfo *info(RzBinFile *bf) {
ret->os = strdup ("any");
ret->subsystem = strdup ("any");
ret->big_endian = obj->endian;
ret->has_va = false;
ret->has_va = true;
ret->dbg_info = 0;
ret->has_lit = true;
@ -500,6 +557,16 @@ static RzBinInfo *info(RzBinFile *bf) {
ret->arch = strdup ("amd29k");
ret->bits = 32;
break;
case COFF_FILE_MACHINE_ARMNT:
ret->machine = strdup ("arm");
ret->arch = strdup ("arm");
ret->bits = 32;
break;
case COFF_FILE_MACHINE_ARM64:
ret->machine = strdup ("arm");
ret->arch = strdup ("arm");
ret->bits = 64;
break;
case COFF_FILE_TI_COFF:
switch (obj->target_id) {
case COFF_FILE_MACHINE_TMS320C54:

View file

@ -39,17 +39,17 @@ nth vaddr bind type lib name
nth paddr size vaddr vsize perm name
---------------------------------------------------
0 0x000001cc 0x2f 0x000001cc 0x2f ---- .drectve_0
1 0x000001fb 0x8670 0x000001fb 0x8670 -r-- .debug_S_1
2 0x0000ad73 0x70 0x0000ad73 0x70 -r-- .debug_T_2
3 0x0000ade3 0x625 0x0000ade3 0x625 -rw- .data_3
4 0x0000b408 0x54 0x0000b408 0x54 -r-- .rdata_4
5 0x00000000 0x8 0x00000000 0x8 -rw- .bss_5
6 0x0000b45c 0x2895 0x0000b45c 0x2895 -r-x .text_mn_6
7 0x0000e967 0x8 0x0000e967 0x8 -r-- .rdata_7
8 0x0000e96f 0x4 0x0000e96f 0x4 -r-- .rdata_8
9 0x0000e973 0x8 0x0000e973 0x8 -r-- .rdata_9
10 0x0000e97b 0x4 0x0000e97b 0x4 -r-- .rdata_10
0 0x000001cc 0x2f 0x00000000 0x2f ---- .drectve_0
1 0x000001fb 0x8670 0x00000030 0x8670 -r-- .debug_S_1
2 0x0000ad73 0x70 0x000086a0 0x70 -r-- .debug_T_2
3 0x0000ade3 0x625 0x00008710 0x625 -rw- .data_3
4 0x0000b408 0x54 0x00008d40 0x54 -r-- .rdata_4
5 0x00000000 0x8 0x00008da0 0x8 -rw- .bss_5
6 0x0000b45c 0x2895 0x00008db0 0x2895 -r-x .text_mn_6
7 0x0000e967 0x8 0x0000b650 0x8 -r-- .rdata_7
8 0x0000e96f 0x4 0x0000b660 0x4 -r-- .rdata_8
9 0x0000e973 0x8 0x0000b670 0x8 -r-- .rdata_9
10 0x0000e97b 0x4 0x0000b680 0x4 -r-- .rdata_10
EOF
RUN
@ -58,26 +58,25 @@ NAME=tiny coff
FILE=bins/coff/coff.obj
CMDS=om;is;ir
EXPECT=<<EOF
3 fd: 3 +0x00000000 0x00000000 - 0x00000144 r-x
2 fd: 3 +0x00000064 0x00000064 - 0x0000008a r-x fmap..text_0
1 fd: 3 +0x0000008b 0x0000008b - 0x000000a6 r-- fmap..data_1
2 fd: 3 +0x00000064 0x00000000 - 0x00000026 r-x fmap..text_0
1 fd: 3 +0x0000008b 0x00000030 - 0x0000004b r-- fmap..data_1
[Symbols]
nth paddr vaddr bind type size lib name
------------------------------------------------------------
0 ---------- 0xffffffffffffffff NONE UNK 4 imp.MessageBoxA
0 ---------- 0xffffffffffffffff NONE UNK 4 imp.ExitProcess
0 0x00000064 0x00000064 LOCAL SECT 4 .text
0 0x00000064 0x00000064 GLOBAL FUNC 4 main
0 0x0000008b 0x0000008b LOCAL SECT 4 .data
0 0x00000064 0x00000000 LOCAL SECT 4 .text
0 0x00000064 0x00000000 GLOBAL FUNC 4 main
0 0x0000008b 0x00000030 LOCAL SECT 4 .data
[Relocations]
vaddr paddr type name
---------------------------------
0x0000006d 0x0000006d ADD_32 .data
0x00000074 0x00000074 ADD_32 .data
0x00000080 0x00000080 ADD_32 MessageBoxA
0x00000087 0x00000087 ADD_32 ExitProcess
0x00000009 0x0000006d ADD_32 .data
0x00000010 0x00000074 ADD_32 .data
0x0000001c 0x00000080 ADD_32 MessageBoxA
0x00000023 0x00000087 ADD_32 ExitProcess
4 relocations
@ -93,23 +92,22 @@ s sym.__1FooBar__QAE_XZ
pd 2
EOF
EXPECT=<<EOF
10 fd: 3 +0x00000000 0x00000000 - 0x000012f7 r-x
9 fd: 3 +0x0000017c 0x0000017c - 0x0000026a --- fmap..drectve_0
8 fd: 3 +0x0000026b 0x0000026b - 0x00000d1a r-- fmap..debug_S_1
7 fd: 3 +0x00000d1b 0x00000d1b - 0x00000d8e r-- fmap..debug_T_2
6 fd: 3 +0x00000d8f 0x00000d8f - 0x00000dbb r-x fmap..text_mn_3
5 fd: 3 +0x00000dbc 0x00000dbc - 0x00000e8f r-- fmap..debug_S_4
4 fd: 3 +0x00000ec2 0x00000ec2 - 0x00000eeb r-x fmap..text_mn_5
3 fd: 3 +0x00000eec 0x00000eec - 0x00000fbf r-- fmap..debug_S_6
2 fd: 3 +0x00000ff2 0x00000ff2 - 0x00000ff5 r-- fmap..rtc_IMZ_7
1 fd: 3 +0x00001000 0x00001000 - 0x00001003 r-- fmap..rtc_TMZ_8
0 0x00000d8f 0x00000d8f LOCAL SECT 4 .text$mn
0 0x00000ec2 0x00000ec2 LOCAL SECT 4 .text$mn
9 fd: 3 +0x0000017c 0x00000000 - 0x000000ee --- fmap..drectve_0
8 fd: 3 +0x0000026b 0x000000f0 - 0x00000b9f r-- fmap..debug_S_1
7 fd: 3 +0x00000d1b 0x00000ba0 - 0x00000c13 r-- fmap..debug_T_2
6 fd: 3 +0x00000d8f 0x00000c20 - 0x00000c4c r-x fmap..text_mn_3
5 fd: 3 +0x00000dbc 0x00000c50 - 0x00000d23 r-- fmap..debug_S_4
4 fd: 3 +0x00000ec2 0x00000d30 - 0x00000d59 r-x fmap..text_mn_5
3 fd: 3 +0x00000eec 0x00000d60 - 0x00000e33 r-- fmap..debug_S_6
2 fd: 3 +0x00000ff2 0x00000e40 - 0x00000e43 r-- fmap..rtc_IMZ_7
1 fd: 3 +0x00001000 0x00000e50 - 0x00000e53 r-- fmap..rtc_TMZ_8
0 0x00000d8f 0x00000c20 LOCAL SECT 4 .text$mn
0 0x00000ec2 0x00000d30 LOCAL SECT 4 .text$mn
;-- section..text_mn_5:
;-- .text$mn:
;-- ??1FooBar@@QAE@XZ:
0x00000ec2 55 push ebp ; [05] -r-x section size 42 named .text_mn_5
0x00000ec3 8bec mov ebp, esp
0x00000d30 55 push ebp ; [05] -r-x section size 42 named .text_mn_5
0x00000d31 8bec mov ebp, esp
EOF
RUN
@ -120,16 +118,17 @@ CMDS=<<EOF
af @ sym._TIFFGetField
pd 1 @ reloc._TIFFVGetField-1
axt @ sym._TIFFVGetField
pd 1 @ 0x0000b48a
pd 1 @ 0x0001000d
pd 1 @ sym._TIFFVGetField+0xe
pd 1 @ sym.imp._TIFFFindField
EOF
EXPECT=<<EOF
| 0x0000b469 e80e000000 call sym._TIFFVGetField ; RELOC 32 _TIFFVGetField @ 0x0000b47c
sym._TIFFGetField 0xb469 [CALL] call sym._TIFFVGetField
| 0x0000b48a e87e4b0000 call _TIFFFindField
; CALL XREF from sym._TIFFVGetField @ 0xb48a
| 0x00008dbd e80e000000 call sym._TIFFVGetField ; RELOC 32 _TIFFVGetField @ 0x00008dd0
sym._TIFFGetField 0x8dbd [CALL] call sym._TIFFVGetField
| 0x00008dde e8ad280000 call _TIFFFindField
; CALL XREF from sym._TIFFVGetField @ 0x8dde
;-- reloc._TIFFFindField:
0x0001000d .dword 0x00000000 ; RELOC 32 _TIFFFindField
;-- _TIFFFindField:
0x0000b690 .dword 0x00000000 ; RELOC 32 _TIFFFindField
EOF
RUN
@ -140,7 +139,7 @@ CMDS=<<EOF
pd 2 @ sym.main+6
EOF
EXPECT=<<EOF
0x0000006a 4c8d051a0000. lea r8, [0x0000008b] ; sym..data ; "Win64 assembly"; RELOC 32 .data @ 0x0000008b
0x00000071 488d15220000. lea rdx, [0x0000009a] ; str.Coffee_time ; "Coffee time!"; RELOC 32 .data @ 0x0000008b + 0xf
0x00000006 4c8d05230000. lea r8, [0x00000030] ; sym..data ; "Win64 assembly"; RELOC 32 .data @ 0x00000030
0x0000000d 488d152b0000. lea rdx, [0x0000003f] ; str.Coffee_time ; "Coffee time!"; RELOC 32 .data @ 0x00000030 + 0xf
EOF
RUN