void LE32toHost(uint8_t *ptr) { uint32_t val; val = readLE32(ptr); *(uint32_t *)ptr = val; }
static RList* entries(RBinFile *bf) { RList* ret = r_list_newf (free); RBinAddr *ptr = NULL; if (ret) { if ((ptr = R_NEW0 (RBinAddr))) { ut64 entry = (ut64)readLE32(bf->buf, 0x80); ut64 size = (ut64)readLE32(bf->buf, 0x84); // eprintf ("0x%x 0x%x\n", entry, size); ptr->paddr = entry; ptr->vaddr = entry; r_list_append (ret, ptr); } else { r_list_free (ret); ret = NULL; } } return ret; }
static void parseMod (RBinFile *bf, RBinNROObj *bin, ut32 mod0, ut64 baddr) { ut32 ptr = readLE32 (bf->buf, mod0); eprintf ("magic %x at 0x%x\n", ptr, mod0); if (ptr == 0x30444f4d) { // MOD0 eprintf ("is mode0\n"); MODHeader mh = { .magic = readLE32 (bf->buf, mod0), .dynamic = readLE32 (bf->buf, mod0 + 4), .bss_start = readLE32 (bf->buf, mod0 + 8), .bss_end = readLE32 (bf->buf, mod0 + 12), .unwind_start = readLE32 (bf->buf, mod0 + 16), .unwind_end = readLE32 (bf->buf, mod0 + 20), .mod_object = readLE32 (bf->buf, mod0 + 24), }; mh.mod_object += mod0; eprintf ("magic 0x%x\n", mh.magic); eprintf ("dynamic 0x%x\n", mh.dynamic); eprintf ("bss 0x%x 0x%x\n", mh.bss_start, mh.bss_end); eprintf ("unwind 0x%x 0x%x\n", mh.unwind_start, mh.unwind_end); eprintf ("-------------\n"); eprintf ("mod 0x%x\n", mh.mod_object); #define MO_(x) readLE64(bf->buf, mh.mod_object + r_offsetof(MODObject, x)) MODObject mo = { .next = MO_(next), .prev = MO_(prev), .relplt = MO_(relplt), .reldyn = MO_(reldyn), .base = MO_(base), .dynamic = MO_(dynamic), .is_rela = MO_(is_rela), .relplt_size = MO_(relplt_size), .init = MO_(init), .fini = MO_(fini), .bucket = MO_(bucket), .chain = MO_(chain), .strtab = MO_(strtab), .symtab = MO_(symtab), .strtab_size = MO_(strtab_size) }; eprintf ("next 0x%llx\n", mo.next); eprintf ("prev 0x%llx\n", mo.prev); eprintf ("base 0x%llx\n", mo.base); eprintf ("init 0x%llx\n", mo.init); eprintf ("fini 0x%llx\n", mo.fini); eprintf ("relplt 0x%llx\n", mo.relplt - mo.base); eprintf ("symtab = 0x%llx\n", mo.symtab - mo.base); eprintf ("strtab = 0x%llx\n", mo.strtab - mo.base); eprintf ("strtabsz = 0x%llx\n", mo.strtab_size); //ut32 modo = mh.mod_object; ut64 strtab = mo.strtab - mo.base; ut64 symtab = mo.symtab - mo.base; walkSymbols (bf, bin, symtab, strtab, mo.strtab_size, mo.relplt - mo.base, baddr); } }
static void *load_bytes(RBinFile *bf, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { RBinNROObj *bin = R_NEW0 (RBinNROObj); if (!bin) { return NULL; } ut64 ba = baddr (bf); bin->methods_list = r_list_newf ((RListFree)free); bin->imports_list = r_list_newf ((RListFree)free); bin->classes_list = r_list_newf ((RListFree)free); ut32 mod0 = readLE32 (bf->buf, NRO_OFFSET_MODMEMOFF); parseMod (bf, bin, mod0, ba); return (void *) bin;//(size_t) check_bytes (buf, sz); }
static bool load_bytes(RBinFile *bf, void **bin_obj, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { RBinNXOObj *bin = R_NEW0 (RBinNXOObj); if (!bin) { return false; } ut64 ba = baddr (bf); bin->methods_list = r_list_newf ((RListFree)free); bin->imports_list = r_list_newf ((RListFree)free); bin->classes_list = r_list_newf ((RListFree)free); ut32 mod0 = readLE32 (bf->buf, NRO_OFFSET_MODMEMOFF); parseMod (bf->buf, bin, mod0, ba); *bin_obj = bin; return true; }
static RList* sections(RBinFile *bf) { RList *ret = NULL; RBinSection *ptr = NULL; if (!(ret = r_list_newf (free))) { return NULL; } if (!(ptr = R_NEW0 (RBinSection))) { return ret; } ut64 vaddr = (ut64)readLE32 (bf->buf, 0x80); ut64 psize = (ut64)readLE32(bf->buf, 0x84); ptr->name = strdup ("system"); ptr->size = psize; ptr->arch = strdup ("arm"); ptr->bits = 16; ptr->vsize = psize; ptr->paddr = 0x100; ptr->vaddr = vaddr; ptr->perm = R_PERM_RX; ptr->add = true; r_list_append (ret, ptr); return ret; }
int metaRead(int fd, unsigned int field_id, unsigned int *buf) { int convertTwoByteToSingleChar(unsigned int *, const unsigned int *, int); unsigned long audio_bytes, mdversion, numfields, fieldlen, wrk, savpos; unsigned int fid, nfv=0, i, j, ret, ret1 = 0; unsigned char tmpbuf[128]; // char msg[128], digits[16];; savpos = lseek(fd, 0, SEEK_CUR); // save current position wrk = lseek(fd, 0, SEEK_SET); ret = readLE32(fd, (long)&audio_bytes, CURRENT_POS); // printf("%s has %ld audio bytes\n",argv[n], wrk); wrk = lseek(fd, audio_bytes + 4, SEEK_SET); ret = readLE32(fd, (long)&mdversion, CURRENT_POS); if((mdversion == 0) || (mdversion > META_CURRENT_VERSION)) { goto failed; } ret = readLE32(fd, (long)&numfields, CURRENT_POS); // printf("num fields=%ld\n", numfields); // strcpy(msg,"metaRead numfields "); // unsignedlongToHexString((long)numfields,digits); // strcat(msg, digits); // logString(msg, ASAP); for(i=0; i<(int)numfields; i++) { ret = readLE16(fd, (long)&fid, CURRENT_POS); // printf("\n field id=%d\n",fid); ret = readLE32(fd, (long)&fieldlen, CURRENT_POS); // printf(" filed length=%d\n", fieldlen); ret = read(fd, (unsigned long)&nfv << 1, 1); nfv &= 1; // printf(" num field values=%d\n", nfv); for(j=0; j<nfv; j++) { unsigned int fl; ret = readLE16(fd, (long)&fl, CURRENT_POS); // printf(" field value length[%d]=%d\n",j,fl); ret = read(fd, (unsigned long) tmpbuf << 1, fl); if(field_id == fid) { ret1 = fl; goto foundit; } // printf(" field value[%d]=",j); /* for(k=0; k<fl; k++) { printf("0x%.2x ", buf[k]); } printf("\n"); */ // printf("'%s'",buf); /* if(fid == 0) { // categories unsigned int m = buf[0] - '0'; if((m >= 0 && m < 9)) { printf(" (%s) ", categories[m]); } } printf("\n"); */ } } failed: // strcpy(msg, "metaRead failed"); // logString(msg, ASAP); wrk = lseek(fd, savpos, SEEK_SET); return(-1); foundit: // strcpy(msg,"metaRead found item "); // unsignedlongToHexString((long)ret1,digits); // strcat(msg, digits); // logString(msg, ASAP); ret = convertTwoByteToSingleChar(buf,(const unsigned int *)tmpbuf,ret1); wrk = lseek(fd, savpos, SEEK_SET); return(ret1); }
static RList *sections(RBinFile *bf) { RList *ret = NULL; RBinSection *ptr = NULL; RBuffer *b = bf->buf; if (!bf->o->info) { return NULL; } if (!(ret = r_list_new ())) { return NULL; } ret->free = free; ut64 ba = baddr (bf); if (!(ptr = R_NEW0 (RBinSection))) { return ret; } strncpy (ptr->name, "header", R_BIN_SIZEOF_STRINGS); ptr->size = 0x80; ptr->vsize = 0x80; ptr->paddr = 0; ptr->vaddr = 0; ptr->srwx = R_BIN_SCN_READABLE; ptr->add = false; r_list_append (ret, ptr); int bufsz = r_buf_size (bf->buf); ut32 mod0 = readLE32 (bf->buf, NRO_OFFSET_MODMEMOFF); if (mod0 && mod0 + 8 < bufsz) { if (!(ptr = R_NEW0 (RBinSection))) { return ret; } ut32 mod0sz = readLE32 (bf->buf, mod0 + 4); strncpy (ptr->name, "mod0", R_BIN_SIZEOF_STRINGS); ptr->size = mod0sz; ptr->vsize = mod0sz; ptr->paddr = mod0; ptr->vaddr = mod0 + ba; ptr->srwx = R_BIN_SCN_READABLE; // rw- ptr->add = false; r_list_append (ret, ptr); } else { eprintf ("Invalid MOD0 address\n"); } ut32 sig0 = readLE32 (bf->buf, 0x18); if (sig0 && sig0 + 8 < bufsz) { if (!(ptr = R_NEW0 (RBinSection))) { return ret; } ut32 sig0sz = readLE32 (bf->buf, sig0 + 4); strncpy (ptr->name, "sig0", R_BIN_SIZEOF_STRINGS); ptr->size = sig0sz; ptr->vsize = sig0sz; ptr->paddr = sig0; ptr->vaddr = sig0 + ba; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP; // r-- ptr->add = true; r_list_append (ret, ptr); } else { eprintf ("Invalid SIG0 address\n"); } // add text segment if (!(ptr = R_NEW0 (RBinSection))) { return ret; } strncpy (ptr->name, "text", R_BIN_SIZEOF_STRINGS); ptr->vsize = readLE32 (b, NRO_OFF (text_size)); ptr->size = ptr->vsize; ptr->paddr = readLE32 (b, NRO_OFF (text_memoffset)); ptr->vaddr = ptr->paddr + ba; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x ptr->add = true; r_list_append (ret, ptr); // add ro segment if (!(ptr = R_NEW0 (RBinSection))) { return ret; } strncpy (ptr->name, "ro", R_BIN_SIZEOF_STRINGS); ptr->vsize = readLE32 (b, NRO_OFF (ro_size)); ptr->size = ptr->vsize; ptr->paddr = readLE32 (b, NRO_OFF (ro_memoffset)); ptr->vaddr = ptr->paddr + ba; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP; // r-x ptr->add = true; r_list_append (ret, ptr); // add data segment if (!(ptr = R_NEW0 (RBinSection))) { return ret; } strncpy (ptr->name, "data", R_BIN_SIZEOF_STRINGS); ptr->vsize = readLE32 (b, NRO_OFF (data_size)); ptr->size = ptr->vsize; ptr->paddr = readLE32 (b, NRO_OFF (data_memoffset)); ptr->vaddr = ptr->paddr + ba; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_WRITABLE | R_BIN_SCN_MAP; // rw- ptr->add = true; eprintf ("Base Address 0x%08"PFMT64x "\n", ba); eprintf ("BSS Size 0x%08"PFMT64x "\n", (ut64) readLE32 (bf->buf, NRO_OFF (bss_size))); r_list_append (ret, ptr); return ret; }
static void walkSymbols (RBinFile *bf, RBinNROObj *bin, ut64 symtab, ut64 strtab, ut64 strtab_size, ut64 relplt, ut64 baddr) { int i, import = 0; RBinSymbol *sym; RBinImport *imp; for (i = 8; i < 99999; i++) { ut64 addr = readLE64 (bf->buf, symtab + i); ut64 size = readLE64 (bf->buf, symtab + i + 8); i += 16; // NULL, NULL ut64 name = readLE32 (bf->buf, symtab + i); //ut64 type = readLE32 (bf->buf, symtab + i + 4); const char *symName = readString (bf->buf, strtab + name); if (!symName) { break; } sym = R_NEW0 (RBinSymbol); if (!sym) { break; } sym->type = r_str_const ("FUNC"); sym->bind = r_str_const ("NONE"); sym->size = size; if (addr == 0) { import ++; ut64 pltSym = readLE64 (bf->buf, relplt + (import * 24)); imp = R_NEW0 (RBinImport); if (!imp) { R_FREE (sym); break; } imp->name = strdup (symName); if (!imp->name) { goto out_walk_symbol; } imp->type = r_str_const ("FUNC"); if (!imp->type) { goto out_walk_symbol; } imp->bind = r_str_const ("NONE"); if (!imp->bind) { goto out_walk_symbol; } imp->ordinal = bin->imports_list->length; r_list_append (bin->imports_list, imp); sym->name = r_str_newf ("imp.%s", symName); if (!sym->name) { goto out_walk_symbol; } sym->paddr = pltSym - 8; sym->vaddr = sym->paddr + baddr; //eprintf ("f sym.imp.%s = 0x%"PFMT64x"\n", symName, pltSym - 8); } else { sym->name = strdup (symName); if (!sym->name) { R_FREE (sym); break; } sym->paddr = addr; sym->vaddr = sym->paddr + baddr; //eprintf ("f sym.%s %"PFMT64u "0x%"PFMT64x"\n", symName, size, addr); } r_list_append (bin->methods_list, sym); i += 8 - 1; } return; out_walk_symbol: R_FREE (sym); R_FREE (imp); return; }
static ut64 baddr(RBinFile *bf) { return bf? readLE32 (bf->buf, NRO_OFFSET_MODMEMOFF): 0; }
static ut64 baddr(RBinFile *bf) { ut64 vaddr = (ut64)readLE32(bf->buf, 0x80); return vaddr; }
static void decode_fnt2(fnt_decoder *decoder) { ok_fnt *fnt = decoder->fnt; uint8_t header[4]; if (!ok_read(decoder, header, sizeof(header))) { return; } if (memcmp("BMF", header, 3) != 0) { ok_fnt_error(fnt, "Not an AngelCode binary FNT file."); return; } if (header[3] != 3) { ok_fnt_error(fnt, "Version %i of AngelCode binary FNT file not supported (only version 3 supported).", header[3]); return; } uint32_t block_types_found = 0; while (true) { uint8_t block_header[5]; if (decoder->input_func(decoder->input_data, block_header, sizeof(block_header)) != sizeof(block_header)) { // Don't give an error if all required blocks have been found. const bool all_required_blocks_found = (block_types_found & 0x1E) == 0x1E; if (!all_required_blocks_found) { ok_fnt_error(decoder->fnt, "Read error: error calling input function."); } return; } block_type block_type = block_header[0]; uint32_t block_length = readLE32(block_header + 1); block_types_found |= (1 << block_type); switch (block_type) { case BLOCK_TYPE_INFO: { uint8_t info_header[14]; const int name_buffer_length = block_length - sizeof(info_header); if (name_buffer_length <= 0) { ok_fnt_error(fnt, "Invalid info block"); return; } if (!ok_read(decoder, info_header, sizeof(info_header))) { return; } // Get the fnt size, ignore the rest fnt->size = readLE16(info_header); // Get the fnt name fnt->name = malloc(name_buffer_length); if (!fnt->name) { ok_fnt_error(fnt, "Couldn't allocate font name"); return; } if (!ok_read(decoder, (uint8_t*)fnt->name, name_buffer_length)) { return; } // Sanity check - make sure the string has a null-terminator fnt->name[name_buffer_length - 1] = 0; break; } case BLOCK_TYPE_COMMON: { uint8_t common[15]; if (block_length != sizeof(common)) { ok_fnt_error(fnt, "Invalid common block"); return; } if (!ok_read(decoder, common, sizeof(common))) { return; } // Get the line height, base, and page count; ignore the rest fnt->line_height = readLE16(common); fnt->base = readLE16(common + 2); fnt->num_pages = readLE16(common + 8); break; } case BLOCK_TYPE_PAGES: { if (fnt->num_pages <= 0 || block_length == 0) { ok_fnt_error(fnt, "Couldn't get page names"); return; } else { fnt->page_names = calloc(fnt->num_pages, sizeof(char *)); if (!fnt->page_names) { fnt->num_pages = 0; ok_fnt_error(fnt, "Couldn't allocate memory for page name array"); return; } // Load everything into the first item; setup pointers below. fnt->page_names[0] = malloc(block_length); if (!fnt->page_names[0]) { fnt->num_pages = 0; ok_fnt_error(fnt, "Couldn't allocate memory for page names"); return; } if (!ok_read(decoder, (uint8_t*)fnt->page_names[0], block_length)) { return; } char *pos = fnt->page_names[0]; char * const end_pos = pos + block_length; // Sanity check - make sure there is a null terminator *(end_pos - 1) = 0; // Set up pointers for each page name int next_index = 1; while (pos + 1 < end_pos && next_index < fnt->num_pages) { if (*pos == 0) { fnt->page_names[next_index] = pos + 1; next_index++; } pos++; } // Sanity check - make sure the remaining page names, if any, point somewhere for (int i = next_index; i < fnt->num_pages; i++) { fnt->page_names[i] = end_pos - 1; } } break; } case BLOCK_TYPE_CHARS: { uint8_t data[20]; fnt->num_glyphs = block_length / sizeof(data); fnt->glyphs = malloc(fnt->num_glyphs * sizeof(ok_fnt_glyph)); if (!fnt->glyphs) { fnt->num_glyphs = 0; ok_fnt_error(fnt, "Couldn't allocate memory for glyphs"); return; } // On little-endian systems we could just load the entire block into memory, but we'll assume // the byte order is unknown here. for (int i = 0; i < fnt->num_glyphs; i++) { if (!ok_read(decoder, data, sizeof(data))) { return; } ok_fnt_glyph *glyph = &fnt->glyphs[i]; glyph->ch = readLE32(data); glyph->x = readLE16(data + 4); glyph->y = readLE16(data + 6); glyph->width = readLE16(data + 8); glyph->height = readLE16(data + 10); glyph->offset_x = readLE16(data + 12); glyph->offset_y = readLE16(data + 14); glyph->advance_x = readLE16(data + 16); glyph->page = data[18]; glyph->channel = data[19]; } break; } case BLOCK_TYPE_KERNING: { uint8_t data[10]; fnt->num_kerning_pairs = block_length / sizeof(data); fnt->kerning_pairs = malloc(fnt->num_kerning_pairs * sizeof(ok_fnt_kerning)); if (!fnt->kerning_pairs) { fnt->num_kerning_pairs = 0; ok_fnt_error(fnt, "Couldn't allocate memory for kerning"); return; } // On little-endian systems we could just load the entire block into memory, but we'll assume // the byte order is unknown here. for (int i = 0; i < fnt->num_kerning_pairs; i++) { if (!ok_read(decoder, data, sizeof(data))) { return; } ok_fnt_kerning *kerning = &fnt->kerning_pairs[i]; kerning->first_char = readLE32(data); kerning->second_char = readLE32(data + 4); kerning->amount = readLE16(data + 8); } break; } default: ok_fnt_error(fnt, "Unknown block type: %i", block_type); return; } } }