/* radare - LGPL - 2015-2017 - pancake */ #include #include #include #include #include /* 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 */ #define N_TEXT 7 #define N_DATA 11 R_PACKED ( typedef struct { 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 bool 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 bool 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 } RBinPlugin r_bin_plugin_dol = { .name = "dol", .desc = "Nintendo Dolphin binary format", .license = "BSD", .load = &load, .baddr = &baddr, .check_bytes = &check_bytes, .entries = &entries, .sections = §ions, .info = &info, }; #ifndef CORELIB RLibStruct radare_plugin = { .type = R_LIB_TYPE_BIN, .data = &r_bin_plugin_dol, .version = R2_VERSION }; #endif