/* radare - LGPL - 2015 - pancake */ #include #include #include #include #include #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; itext_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; idata_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 = §ions, .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