rizin/libr/bin/format/coff/coff.c
2014-02-20 14:01:49 +04:00

287 lines
6.5 KiB
C

#include <r_util.h>
#include "coff.h"
int coff_supported_arch(const ut8 *buf)
{
ut16 arch = *(ut16*)buf;
int ret;
switch (arch) {
case IMAGE_FILE_MACHINE_AMD64:
case IMAGE_FILE_MACHINE_I386:
case IMAGE_FILE_MACHINE_H8300:
case IMAGE_FILE_TI_COFF:
ret = R_TRUE;
break;
default:
ret = R_FALSE;
}
return ret;
}
static int r_bin_coff_init_hdr(struct r_bin_coff_obj *obj)
{
size_t offset = 0;
obj->hdr.machine = *(ut16*)obj->b->buf;
switch(obj->hdr.machine) {
case IMAGE_FILE_MACHINE_H8300:
obj->endian = !LIL_ENDIAN;
break;
default:
obj->endian = LIL_ENDIAN;
}
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->hdr.sections_num), obj->b->buf + offset,
sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&obj->hdr.timestamp, obj->b->buf + offset,
sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&obj->hdr.symtable_offset, obj->b->buf + offset,
sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->hdr.symbols_num), obj->b->buf + offset,
sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->hdr.opt_hdr_size), obj->b->buf + offset,
sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->hdr.flags), obj->b->buf + offset,
sizeof(ut16), obj->endian);
if (obj->hdr.flags & IMAGE_FLAGS_TI_F_LITTLE) {
obj->endian = LIL_ENDIAN;
}
offset += sizeof(ut16);
if (obj->hdr.machine == IMAGE_FILE_TI_COFF) {
r_mem_copyendian((ut8*)&(obj->hdr.target_id), obj->b->buf + offset,
sizeof(ut16), obj->endian);
}
return R_TRUE;
}
static int r_bin_coff_init_opt_hdr(struct r_bin_coff_obj *obj)
{
size_t offset = 20;
if (obj->hdr.opt_hdr_size == 0)
return 0;
r_mem_copyendian((ut8*)&(obj->opt_hdr.magic), obj->b->buf + offset,
sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->opt_hdr.major_linker_version),
obj->b->buf + offset, sizeof(ut8), obj->endian);
offset += sizeof(ut8);
r_mem_copyendian((ut8*)&(obj->opt_hdr.minor_linker_version),
obj->b->buf + offset, sizeof(ut8), obj->endian);
offset += sizeof(ut8);
r_mem_copyendian((ut8*)&(obj->opt_hdr.size_of_code),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->opt_hdr.size_of_init_data),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->opt_hdr.size_of_uninit_data),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->opt_hdr.entry_point),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->opt_hdr.base_of_code),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
return 0;
}
static int r_bin_coff_init_scn_hdr(struct r_bin_coff_obj *obj)
{
size_t i, offset = obj->hdr.opt_hdr_size + 20;
if (obj->hdr.machine == IMAGE_FILE_TI_COFF) {
offset += 2;
}
obj->scn_hdrs = calloc(obj->hdr.sections_num,
sizeof(struct coff_scn_hdr));
for (i = 0; i < obj->hdr.sections_num; i++) {
strncpy(obj->scn_hdrs[i].name, (char*)(obj->b->buf + offset), 8);
offset += 8;
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].virtual_size),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].virtual_addr),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].raw_data_size),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].raw_data_pointer),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].reloc_pointer),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].linenum_pointer),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].reloc_num),
obj->b->buf + offset, sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].linenum_num),
obj->b->buf + offset, sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->scn_hdrs[i].flags),
obj->b->buf + offset, sizeof(ut32), obj->endian);
offset += sizeof(ut32);
}
return 0;
}
static int r_bin_coff_init_symtable(struct r_bin_coff_obj *obj)
{
size_t i, offset = obj->hdr.symtable_offset;
ut32 short_name, ofst;
obj->symbols = calloc(obj->hdr.symbols_num,
sizeof(struct coff_symbol));
for (i = 0; i < obj->hdr.symbols_num; i++) {
r_mem_copyendian((ut8*)&short_name, obj->b->buf + offset,
sizeof(ut32), obj->endian);
if (short_name) {
obj->symbols[i].name = malloc(sizeof(char) * 9);
strncpy(obj->symbols[i].name,
(char*)(obj->b->buf + offset), 8);
obj->symbols[i].name[8] = '\0';
offset += 8;
} else {
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&ofst, obj->b->buf + offset,
sizeof(ut32), obj->endian);
obj->symbols[i].name = strdup((char*)(obj->b->buf +
obj->hdr.symtable_offset + ofst +
obj->hdr.symbols_num * 18));
offset += sizeof(ut32);
}
r_mem_copyendian((ut8*)&(obj->symbols[i].value),
obj->b->buf + offset,
sizeof(ut32), obj->endian);
offset += sizeof(ut32);
r_mem_copyendian((ut8*)&(obj->symbols[i].scn_num),
obj->b->buf + offset,
sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->symbols[i].type),
obj->b->buf + offset,
sizeof(ut16), obj->endian);
offset += sizeof(ut16);
r_mem_copyendian((ut8*)&(obj->symbols[i].storage_class),
obj->b->buf + offset,
sizeof(ut8), obj->endian);
offset += sizeof(ut8);
r_mem_copyendian((ut8*)&(obj->symbols[i].aux_sym_num),
obj->b->buf + offset,
sizeof(ut8), obj->endian);
offset += sizeof(ut8);
}
return 0;
}
static int r_bin_coff_init(struct r_bin_coff_obj *obj, struct r_buf_t *buf)
{
obj->b = buf;
obj->size = buf->length;
r_bin_coff_init_hdr(obj);
r_bin_coff_init_opt_hdr(obj);
r_bin_coff_init_scn_hdr(obj);
r_bin_coff_init_symtable(obj);
return R_TRUE;
}
void r_bin_coff_free(struct r_bin_coff_obj *obj)
{
if (obj->scn_hdrs)
free(obj->scn_hdrs);
if (obj->symbols)
free(obj->symbols);
free(obj);
}
struct r_bin_coff_obj* r_bin_coff_new_buf(struct r_buf_t *buf)
{
struct r_bin_coff_obj* bin = R_NEW0(struct r_bin_coff_obj);
r_bin_coff_init(bin, buf);
return bin;
}