static int r_bin_coff_init_hdr(struct r_bin_coff_obj *obj) { ut16 magic = *(ut16 *)obj->b->buf; obj->endian = (magic == COFF_FILE_MACHINE_H8300)?1:0; (void)r_buf_fread_at (obj->b, 0, (ut8 *)&obj->hdr, obj->endian? "2S3I2S": "2s3i2s", 1); if (obj->hdr.f_magic == COFF_FILE_TI_COFF) (void)r_buf_fread_at (obj->b, R_BUF_CUR, (ut8 *)&obj->target_id, obj->endian? "S": "s", 1); return true; }
static RList* entries(RBinFile* bf) { RList* ret = NULL; RBinAddr* addr = NULL; psxexe_header psxheader; if (!(ret = r_list_new ())) return NULL; if (!(addr = R_NEW0 (RBinAddr))) { r_list_free (ret); return NULL; } if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) < sizeof (psxexe_header)) { eprintf ("PSXEXE Header truncated\n"); r_list_free (ret); free (addr); return NULL; } addr->paddr = (psxheader.pc0 - psxheader.t_addr) + PSXEXE_TEXTSECTION_OFFSET; addr->vaddr = psxheader.pc0; r_list_append (ret, addr); return ret; }
static int r_bin_coff_init_opt_hdr(struct r_bin_coff_obj *obj) { if (!obj->hdr.f_opthdr) return 0; (void)r_buf_fread_at (obj->b, obj->hdr.f_opthdr, (ut8 *)&obj->opt_hdr, obj->endian? "2S6I": "2s6i", 1); return 0; }
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 r_bin_coff_init_scn_hdr(struct r_bin_coff_obj *obj) { ut64 offset = sizeof (struct coff_hdr) + (obj->hdr.f_opthdr * sizeof (struct coff_opt_hdr)); if (obj->hdr.f_magic == COFF_FILE_TI_COFF) offset += 2; obj->scn_hdrs = calloc(obj->hdr.f_nscns, sizeof(struct coff_scn_hdr)); (void)r_buf_fread_at (obj->b, offset, (ut8 *)obj->scn_hdrs, obj->endian? "8c6I2S1I": "8c6i2s1i", obj->hdr.f_nscns); return 0; }
static int r_bin_dyldcache_init(struct r_bin_dyldcache_obj_t* bin) { int len = r_buf_fread_at (bin->b, 0, (ut8*)&bin->hdr, "16c4il", 1); if (len == -1) { perror ("read (cache_header)"); return R_FALSE; } bin->nlibs = bin->hdr.numlibs; return R_TRUE; }
static int r_bin_coff_init_symtable(struct r_bin_coff_obj *obj) { if (obj->hdr.f_nsyms >= 0xffff) // too much symbols, probably not allocatable return 0; obj->symbols = calloc (obj->hdr.f_nsyms, sizeof(struct coff_symbol)); if (obj->symbols == NULL) return 0; (void)r_buf_fread_at (obj->b, obj->hdr.f_symptr, (ut8 *)obj->symbols, obj->endian? "8c1I2S2c": "8c1i2s2c", obj->hdr.f_nsyms); return 1; }
static RList* sections(RBinFile *arch) { RBinSection *ptr = NULL; RList *ret = NULL; int rc; if (!(ret = r_list_new ())) return NULL; ret->free = free; rc = r_buf_fread_at (arch->buf, 0, (ut8*)&sb, "10i", 1); if (!rc) return false; // add text segment if (!(ptr = R_NEW0 (RBinSection))) return ret; strncpy (ptr->name, "text", R_BIN_SIZEOF_STRINGS); ptr->size = sb.psize; ptr->vsize = sb.psize; ptr->paddr = sb.paddr + 40; ptr->vaddr = sb.vaddr; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x ptr->add = true; ptr->has_strings = true; r_list_append (ret, ptr); if (!(ptr = R_NEW0 (RBinSection))) return ret; strncpy (ptr->name, "sign", R_BIN_SIZEOF_STRINGS); ptr->size = sb.sign_sz; ptr->vsize = sb.sign_sz; ptr->paddr = sb.sign_va - sb.vaddr; ptr->vaddr = sb.sign_va; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP; // r-- ptr->has_strings = true; ptr->add = true; r_list_append (ret, ptr); if (sb.cert_sz && sb.cert_va > sb.vaddr) { if (!(ptr = R_NEW0 (RBinSection))) return ret; strncpy (ptr->name, "cert", R_BIN_SIZEOF_STRINGS); ptr->size = sb.cert_sz; ptr->vsize = sb.cert_sz; ptr->paddr = sb.cert_va - sb.vaddr; ptr->vaddr = sb.cert_va; ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP; // r-- ptr->has_strings = true; ptr->add = true; r_list_append (ret, ptr); } return ret; }
static int art_header_load(ARTHeader *art, RBuffer *buf, Sdb *db) { /* TODO: handle read errors here */ (void)r_buf_fread_at (buf, 0, (ut8*)art, "IIiiiiiiiiiii", 1); sdb_set (db, "img.base", sdb_fmt (0, "0x%x", art->image_base), 0); sdb_set (db, "img.size", sdb_fmt (0, "0x%x", art->image_size), 0); sdb_set (db, "art.checksum", sdb_fmt (0, "0x%x", art->checksum), 0); sdb_set (db, "art.version", sdb_fmt (0, "%c%c%c", art->version[0], art->version[1], art->version[2]), 0); sdb_set (db, "oat.begin", sdb_fmt (0, "0x%x", art->oat_begin), 0); sdb_set (db, "oat.end", sdb_fmt (0, "0x%x", art->oat_end), 0); sdb_set (db, "oat_data.begin", sdb_fmt (0, "0x%x", art->oat_data_begin), 0); sdb_set (db, "oat_data.end", sdb_fmt (0, "0x%x", art->oat_data_end), 0); sdb_set (db, "patch_delta", sdb_fmt (0, "0x%x", art->patch_delta), 0); sdb_set (db, "image_roots", sdb_fmt (0, "0x%x", art->image_roots), 0); return R_TRUE; }
static int art_header_load(ARTHeader *art, RBuffer *buf, Sdb *db) { /* TODO: handle read errors here */ if (r_buf_size (buf) < sizeof (ARTHeader)) { return false; } (void) r_buf_fread_at (buf, 0, (ut8 *) art, "IIiiiiiiiiiiii", 1); sdb_set (db, "img.base", sdb_fmt ("0x%x", art->image_base), 0); sdb_set (db, "img.size", sdb_fmt ("0x%x", art->image_size), 0); sdb_set (db, "art.checksum", sdb_fmt ("0x%x", art->checksum), 0); sdb_set (db, "art.version", sdb_fmt ("%c%c%c", art->version[0], art->version[1], art->version[2]), 0); sdb_set (db, "oat.begin", sdb_fmt ("0x%x", art->oat_file_begin), 0); sdb_set (db, "oat.end", sdb_fmt ("0x%x", art->oat_file_end), 0); sdb_set (db, "oat_data.begin", sdb_fmt ("0x%x", art->oat_data_begin), 0); sdb_set (db, "oat_data.end", sdb_fmt ("0x%x", art->oat_data_end), 0); sdb_set (db, "patch_delta", sdb_fmt ("0x%x", art->patch_delta), 0); sdb_set (db, "image_roots", sdb_fmt ("0x%x", art->image_roots), 0); sdb_set (db, "compile_pic", sdb_fmt ("0x%x", art->compile_pic), 0); return true; }
static int lmf_header_load(lmf_header *lmfh, RBuffer *buf, Sdb *db) { if (r_buf_size (buf) < sizeof (lmf_header)) { return false; } if (r_buf_fread_at (buf, QNX_HEADER_ADDR, (ut8 *) lmfh, "iiiiiiiicccciiiicc", 1) < QNX_HDR_SIZE) { return false; } sdb_set (db, "qnx.version", sdb_fmt ("0x%xH", lmfh->version), 0); sdb_set (db, "qnx.cflags", sdb_fmt ("0x%xH", lmfh->cflags), 0); sdb_set (db, "qnx.cpu", sdb_fmt ("0x%xH", lmfh->cpu), 0); sdb_set (db, "qnx.fpu", sdb_fmt ("0x%xH", lmfh->fpu), 0); sdb_set (db, "qnx.code_index", sdb_fmt ("0x%x", lmfh->code_index), 0); sdb_set (db, "qnx.stack_index", sdb_fmt ("0x%x", lmfh->stack_index), 0); sdb_set (db, "qnx.heap_index", sdb_fmt ("0x%x", lmfh->heap_index), 0); sdb_set (db, "qnx.argv_index", sdb_fmt ("0x%x", lmfh->argv_index), 0); sdb_set (db, "qnx.code_offset", sdb_fmt ("0x%x", lmfh->code_offset), 0); sdb_set (db, "qnx.stack_nbytes", sdb_fmt ("0x%x", lmfh->stack_nbytes), 0); sdb_set (db, "qnx.heap_nbytes", sdb_fmt ("0x%x", lmfh->heap_nbytes), 0); sdb_set (db, "qnx.image_base", sdb_fmt ("0x%x", lmfh->image_base), 0); return true; }
static int check_bytes(const ut8 *buf, ut64 bufsz) { if (buf && bufsz >= sizeof (SBLHDR)) { RBuffer *b = r_buf_new_with_pointers (buf, bufsz); int ret = r_buf_fread_at (b, 0, (ut8*)&sb, "10i", 1); r_buf_free (b); if (!ret) { return false; } if (sb.version != 3) { // NAND return false; } if (sb.paddr + sizeof (SBLHDR) > bufsz) { // NAND return false; } if (sb.vaddr < 0x100 || sb.psize > bufsz) { // NAND return false; } if (sb.cert_va < sb.vaddr) return false; if (sb.cert_sz >= 0xf0000) return false; if (sb.sign_va < sb.vaddr) return false; if (sb.sign_sz >= 0xf0000) return false; if (sb.load_index < 0x10 || sb.load_index > 0x40) return false; // should be 0x19 ? #if 0 eprintf ("V=%d\n", sb.version); eprintf ("PA=0x%08x sz=0x%x\n", sb.paddr, sb.psize); eprintf ("VA=0x%08x sz=0x%x\n", sb.vaddr, sb.psize); eprintf ("CODE=0x%08x\n", sb.code_pa + sb.vaddr+40); eprintf ("SIGN=0x%08x sz=0x%x\n", sb.sign_va, sb.sign_sz); if (sb.cert_sz > 0) { eprintf ("CERT=0x%08x sz=0x%x\n", sb.cert_va, sb.cert_sz); } else { eprintf ("No certificate found.\n"); } #endif // TODO: Add more checks here return true; } return false; }
static RList* sections(RBinFile* bf) { RList* ret = NULL; RBinSection* sect = NULL; psxexe_header psxheader; ut64 sz = 0; if (!(ret = r_list_new ())) { return NULL; } if(!(sect = R_NEW0 (RBinSection))) { r_list_free (ret); return NULL; } if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) < sizeof (psxexe_header)) { eprintf ("Truncated Header\n"); free (sect); r_list_free (ret); return NULL; } sz = r_buf_size (bf->buf); strcpy (sect->name, "TEXT"); sect->paddr = PSXEXE_TEXTSECTION_OFFSET; sect->size = sz - PSXEXE_TEXTSECTION_OFFSET; sect->vaddr = psxheader.t_addr; sect->vsize = psxheader.t_size; sect->srwx = R_BIN_SCN_EXECUTABLE; sect->add = true; sect->has_strings = true; r_list_append (ret, sect); return ret; }
static void *load_buffer(RBinFile *bf, RBuffer *buf, ut64 loadaddr, Sdb *sdb) { QnxObj *qo = R_NEW0 (QnxObj); lmf_record lrec; lmf_resource lres; lmf_data ldata; ut64 offset = QNX_RECORD_SIZE; RList *sections = NULL; RList *fixups = NULL; if (!qo) { goto beach; } if (!(sections = r_list_newf ((RListFree)r_bin_section_free)) || !(fixups = r_list_new ())) { goto beach; } qo->kv = sdb_new0 (); if (!qo->kv) { free (qo); goto beach; } // Read the first record if (r_buf_fread_at (bf->buf, 0, (ut8 *)&lrec, "ccss", 1) < QNX_RECORD_SIZE) { goto beach; } // Load the header lmf_header_load (&qo->lmfh, bf->buf, qo->kv); offset += lrec.data_nbytes; for (;;) { if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lrec, "ccss", 1) < QNX_RECORD_SIZE) { goto beach; } offset += sizeof (lmf_record); if (lrec.rec_type == LMF_IMAGE_END_REC) { break; } else if (lrec.rec_type == LMF_RESOURCE_REC) { RBinSection *ptr = R_NEW0 (RBinSection); if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lres, "ssss", 1) < sizeof (lmf_resource)) { goto beach; } if (!ptr) { goto beach; } ptr->name = strdup ("LMF_RESOURCE"); ptr->paddr = offset; ptr->vsize = lrec.data_nbytes - sizeof (lmf_resource); ptr->size = ptr->vsize; ptr->add = true; r_list_append (sections, ptr); } else if (lrec.rec_type == LMF_LOAD_REC) { RBinSection *ptr = R_NEW0 (RBinSection); if (r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) { goto beach; } if (!ptr) { goto beach; } ptr->name = strdup ("LMF_LOAD"); ptr->paddr = offset; ptr->vaddr = ldata.offset; ptr->vsize = lrec.data_nbytes - sizeof (lmf_data); ptr->size = ptr->vsize; ptr->add = true; r_list_append (sections, ptr); } else if (lrec.rec_type == LMF_FIXUP_REC) { RBinReloc *ptr = R_NEW0 (RBinReloc); if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) { goto beach; } ptr->vaddr = ptr->paddr = ldata.offset; ptr->type = 'f'; // "LMF_FIXUP"; r_list_append (fixups, ptr); } else if (lrec.rec_type == LMF_8087_FIXUP_REC) { RBinReloc *ptr = R_NEW0 (RBinReloc); if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) { goto beach; } ptr->vaddr = ptr->paddr = ldata.offset; ptr->type = 'F'; // "LMF_8087_FIXUP"; r_list_append (fixups, ptr); } else if (lrec.rec_type == LMF_RW_END_REC) { r_buf_fread_at (bf->buf, offset, (ut8 *)&qo->rwend, "si", 1); } offset += lrec.data_nbytes; } sdb_ns_set (sdb, "info", qo->kv); qo->sections = sections; qo->fixups = fixups; return qo; beach: return NULL; }
static int r_bin_coff_init_symtable(struct r_bin_coff_obj *obj) { obj->symbols = calloc(obj->hdr.f_nsyms, sizeof(struct coff_symbol)); (void)r_buf_fread_at (obj->b, obj->hdr.f_symptr, (ut8 *)obj->symbols, obj->endian? "8c1I2S2c": "8c1i2s2c", obj->hdr.f_nsyms); return 0; }