radare2/libr/bin/p/bin_dol.c
2015-12-16 11:40:23 +01:00

211 lines
4.7 KiB
C

/* radare - LGPL - 2015 - pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
#include <string.h>
#if 0
Start End Length Description
0x0 0x3 4 File offset to start of Text0
0x04 0x1b 24 File offsets for Text1..6
0x1c 0x47 44 File offsets for Data0..10
0x48 0x4B 4 Loading address for Text0
0x4C 0x8F 68 Loading addresses for Text1..6, Data0..10
0x90 0xD7 72 Section sizes for Text0..6, Data0..10
0xD8 0xDB 4 BSS address
0xDC 0xDF 4 BSS size
0xE0 0xE3 4 Entry point
0xE4 0xFF padding
#endif
#define N_TEXT 7
#define N_DATA 11
typedef struct __attribute__((packed)) {
ut32 text_paddr[N_TEXT];
ut32 data_paddr[N_DATA];
ut32 text_vaddr[N_TEXT];
ut32 data_vaddr[N_DATA];
ut32 text_size[N_TEXT];
ut32 data_size[N_DATA];
ut32 bss_addr;
ut32 bss_size;
ut32 entrypoint;
ut32 padding[10];
// 0x100 -- start of data section
} DolHeader;
static int check(RBinFile *arch);
static int check_bytes(const ut8 *buf, ut64 length);
static int check(RBinFile *arch) {
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
return check_bytes (bytes, sz);
}
static int check_bytes(const ut8 *buf, ut64 length) {
if (!buf || length < 6) return false;
return (!memcmp (buf, "\x00\x00\x01\x00\x00\x00", 6));
}
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) {
bool has_dol_extension = false;
DolHeader * dol;
char *lowername, *ext;
if (!arch || sz < sizeof (DolHeader)) {
return NULL;
}
dol = R_NEW0 (DolHeader);
if (!dol) return NULL;
lowername = strdup (arch->file);
if (!lowername) {
free (dol);
return NULL;
}
r_str_case (lowername, 0);
ext = strstr (lowername, ".dol");
if (ext && ext[4] == 0) {
has_dol_extension = true;
}
free (lowername);
if (has_dol_extension) {
r_buf_fread_at (arch->buf, 0, (void*)dol, "67I", 1);
//r_buf_fread_at (arch->buf, 0, (void*)dol, "67i", 1);
if (arch && arch->o && arch->o->bin_obj) {
arch->o->bin_obj = dol;
}
return (void*)dol;
}
free (dol);
return NULL;
}
static int load(RBinFile *arch) {
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
if (!arch || !arch->o)
return false;
arch->o->bin_obj = load_bytes (arch, bytes,
sz, arch->o->loadaddr, arch->sdb);
return check_bytes (bytes, sz);
}
static RList* sections(RBinFile *arch) {
int i;
RList *ret;
RBinSection *s;
DolHeader *dol;
if (!arch || !arch->o || !arch->o->bin_obj)
return NULL;
dol = arch->o->bin_obj;
if (!(ret = r_list_new ())) {
return NULL;
}
/* text sections */
for (i=0; i<N_TEXT; i++) {
if (!dol->text_paddr[i] || !dol->text_vaddr[i])
continue;
s = R_NEW0 (RBinSection);
snprintf (s->name, sizeof (s->name), "text_%d", i);
s->paddr = dol->text_paddr[i];
s->vaddr = dol->text_vaddr[i];
s->size = dol->text_size[i];
s->vsize = s->size;
s->srwx = r_str_rwx ("mr-x");
s->add = true;
r_list_append (ret, s);
}
/* data sections */
for (i=0; i<N_DATA; i++) {
if (!dol->data_paddr[i] || !dol->data_vaddr[i])
continue;
s = R_NEW0 (RBinSection);
snprintf (s->name, sizeof (s->name), "data_%d", i);
s->paddr = dol->data_paddr[i];
s->vaddr = dol->data_vaddr[i];
s->size = dol->data_size[i];
s->vsize = s->size;
s->srwx = r_str_rwx ("mr--");
s->add = true;
r_list_append (ret, s);
}
/* bss section */
s = R_NEW0 (RBinSection);
strcpy (s->name, "bss");
s->paddr = 0;
s->vaddr = dol->bss_addr;
s->size = dol->bss_size;
s->vsize = s->size;
s->srwx = r_str_rwx ("-rw-");
s->add = true;
r_list_append (ret, s);
return ret;
}
static RList* entries(RBinFile *arch) {
RList *ret;
RBinAddr *addr;
DolHeader *dol;
if (!arch || !arch->o || !arch->o->bin_obj) {
return NULL;
}
ret = r_list_new ();
addr = R_NEW0 (RBinAddr);
dol = arch->o->bin_obj;
addr->vaddr = (ut64)dol->entrypoint;
addr->paddr = addr->vaddr & 0xFFFF;
r_list_append (ret, addr);
return ret;
}
static RBinInfo* info(RBinFile *arch) {
RBinInfo *ret = R_NEW0 (RBinInfo);
if (!ret) return NULL;
if (!arch || !arch->buf) {
free (ret);
return NULL;
}
ret->file = strdup (arch->file);
ret->big_endian = true;
ret->type = strdup ("ROM");
ret->machine = strdup ("Nintendo Wii");
ret->os = strdup ("wii-ios");
ret->arch = strdup ("ppc");
ret->has_va = true;
ret->bits = 32;
return ret;
}
static ut64 baddr(RBinFile *arch) {
return 0x80b00000; // XXX
}
struct r_bin_plugin_t r_bin_plugin_dol = {
.name = "dol",
.desc = "Nintendo Dolphin binary format",
.license = "BSD",
.load = &load,
.check = &check,
.baddr = &baddr,
.check_bytes = &check_bytes,
.entries = &entries,
.sections = &sections,
.info = &info,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_BIN,
.data = &r_bin_plugin_dol,
.version = R2_VERSION
};
#endif