//-------------------------------------------------------------------------- static void load_dl_header(linput_t *li) { if ( first_text_subspace_fpos == -1 ) return; qlseek(li, first_text_subspace_fpos); dl_header dl; lread(li, &dl, sizeof(dl)); dl.swap(); switch ( dl.hdr_version ) { case OLD_HDR_VERSION: break; case HDR_VERSION : break; default: msg("Unknown DL header version, skipping...\n"); } if ( dl.string_table_size != 0 ) { dl_ssize = dl.string_table_size; dl_strings = (char *)qalloc(dl_ssize); if ( dl_strings == NULL ) nomem("dl_strings"); qlseek(li, first_text_subspace_fpos+dl.string_table_loc); lread(li, dl_strings, dl_ssize); } if ( dl.dreloc_count ) complain_fixup(); load_imports(li, dl); load_exports(li, dl); qfree(dl_strings); dl_strings = NULL; }
uint32 read_swf_matrix(linput_t *li, SWFMATRIX *matrix) { SWFMATRIX m; int32 position; if (matrix == NULL) matrix = &m; //save read position position = qltell(li); uint8 fByte = qlgetc(li); uint8 offset = 1; if (fByte & 0x80 /* hasScale */) { uint8 nScaleBits = (fByte & 0x7F) >> 2; offset = 6; if ( offset ) qlseek(li, -1, SEEK_CUR); matrix->scaleX = read_bits(li, offset, nScaleBits); offset = (offset + nScaleBits) % 8; //rewind input if needed if ( offset ) qlseek(li, -1, SEEK_CUR); matrix->scaleY = read_bits(li, offset, nScaleBits); offset = (offset + nScaleBits) % 8; //don't rewind, keep alignment //if ( offset ) qlseek(li, -1, SEEK_CUR); }
bool load_header(linput_t *li) { int headerversion; int size; qlseek(li, 3); if (qlread(li, &yssEndian, 1) != 1) { error("Truncated file"); return false; } qlread(li, &headerversion, 4); qlread(li, &size, 4); int headersize=0xC; if (headerversion == 2) { qlseek(li, 8, SEEK_CUR); headersize+=8; } // Make sure size variable matches actual size minus header if (size != (qlsize(li) - headersize)) { error("Header size isn't valid"); return false; } return true; }
void SH2LoadState(linput_t *li, bool isslave, sh2regs_struct *regs, int size) { if (isslave == 1) qlseek(li, 1, SEEK_CUR); // Read registers qlread(li, (void *)regs, sizeof(sh2regs_struct)); qlseek(li, size-sizeof(sh2regs_struct), SEEK_CUR); }
//------------------------------------------------------------------------ inline bool pe_loader_t::vseek(linput_t *li, uint32 rva) { ea_t fpos = get_linput_type(li) == LINPUT_PROCMEM ? rva : map_ea(rva); if ( fpos != BADADDR ) { qlseek(li, int32(fpos)); return true; } qlseek(li, rva, SEEK_SET); return false; }
void Vdp1LoadState(linput_t *li, int size) { int pos=qltell(li); // Skip registers qlseek(li, 52, SEEK_CUR); // Read VDP1 ram create_load_seg(li, 0x25C00000, 0x25C80000, 1, "VDP1RAM"); qlseek(li, size-(qltell(li)-pos), SEEK_CUR); }
void Vdp2LoadState(linput_t *li, int size) { int pos=qltell(li); // Skip registers qlseek(li, 288, SEEK_CUR); // Read VDP2 ram create_load_seg(li, 0x25E00000, 0x25E80000, 1, "VDP2RAM"); // Read CRAM create_load_seg(li, 0x25F00000, 0x25F01000, 2, "VDP2CRAM"); qlseek(li, size-(qltell(li)-pos), SEEK_CUR); }
//-------------------------------------------------------------------------- static char *get_name(linput_t *li, long tableoff, size_t tablesize, long nidx, char *buf, size_t bufsize) { if ( nidx >= tablesize ) return ""; long fpos = qltell(li); qlseek(li, tableoff+nidx-4); ulong len; lread(li, &len, sizeof(len)); len = swap32(len); if ( len >= bufsize ) len = bufsize-1; lread(li, buf, len); buf[len] = '\0'; qlseek(li, fpos); return buf; }
//---------------------------------------------------------------------------- int idaapi accept_file( linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if ( n > 0 ) return 0; int32 spc_file_size = qlsize(li); if ( spc_file_size < 0x10200 ) return 0; spc_file_t spc_info; if ( qlseek(li, 0) != 0 ) return 0; if ( qlread(li, &spc_info, sizeof(spc_file_t)) != sizeof(spc_file_t) ) return 0; if (memcmp(spc_info.signature, "SNES-SPC700 Sound File Data", 27) != 0 || spc_info.signature[0x21] != 0x1a || spc_info.signature[0x22] != 0x1a) return 0; qstrncpy(fileformatname, "SNES-SPC700 Sound File Data", MAX_FILE_FORMAT_NAME); return 1; }
//---------------------------------------------------------------------- // // store CHR ROM pages to netnode // static bool save_chr_rom_pages_as_blobs( linput_t *li, uchar count ) { netnode node; char chr_node_name[MAXSTR]; uchar *buffer = (uchar *)qalloc( CHR_PAGE_SIZE ); if( buffer == 0 ) return false; qlseek( li, INES_HDR_SIZE + (INES_MASK_TRAINER(hdr.rom_control_byte_0) ? TRAINER_SIZE : 0) + PRG_PAGE_SIZE * hdr.prg_page_count_16k ); for(int i=0; i<count; i++) { qlread( li, buffer, CHR_PAGE_SIZE ); qsnprintf( chr_node_name, sizeof(chr_node_name), "$ CHR-ROM page %d", i ); if( !node.create( chr_node_name ) ) { qfree( buffer ); return false; } if( !node.setblob( buffer, CHR_PAGE_SIZE, 0, 'I' ) ) msg("Could not store CHR-ROM pages to netnode!\n"); } qfree( buffer ); return true; }
/* verify if we can process the target file * return true if yes * false otherwise */ int idaapi accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if (n != 0) { return 0; } qlseek(li, 0); EFI_IMAGE_TE_HEADER teHeader = {0}; if (qlread(li, &teHeader, sizeof(EFI_IMAGE_TE_HEADER)) == sizeof(EFI_IMAGE_TE_HEADER) && teHeader.Signature == EFI_IMAGE_TE_SIGNATURE) { msg("Signature: 0x%hx\n", teHeader.Signature); msg("Machine: 0x%hx\n", teHeader.Machine); msg("Number of Sections: 0x%hhx\n", teHeader.NumberOfSections); msg("Subsystem: 0x%hhx\n", teHeader.Subsystem); msg("Stripped size: 0x%hx\n", teHeader.StrippedSize); msg("Address of EntryPoint: 0x%0x\n", teHeader.AddressOfEntryPoint); msg("Base of code: 0x%x\n", teHeader.BaseOfCode); msg("Image base: 0x%llx\n", teHeader.ImageBase); qstrncpy(fileformatname, "TE put.as Loader", MAX_FILE_FORMAT_NAME); return true; } return 0; }
//---------------------------------------------------------------------- // // store trainer to netnode // static bool save_trainer_as_blob( linput_t *li ) { netnode node; uchar *buffer; if( !INES_MASK_TRAINER( hdr.rom_control_byte_0 ) ) return false; buffer = (uchar *)qalloc( TRAINER_SIZE ); if( buffer == 0 ) return false; qlseek( li, INES_HDR_SIZE ); qlread( li, buffer, TRAINER_SIZE ); if( !node.create( "$ Trainer" ) ) { qfree( buffer ); return false; } if( !node.setblob( buffer, TRAINER_SIZE, 0, 'I' ) ) msg("Could not store trainer to netnode!\n"); qfree( buffer ); return true; }
//-------------------------------------------------------------------------- static void load_imports(linput_t *li, dl_header &dl) { if ( !dl.import_list_count ) return; qlseek(li, first_text_subspace_fpos+dl.import_list_loc); ea_t ea = data_start + dl.dlt_loc; int n = dl.dlt_count; char buf[MAXSTR]; for ( int i=0; i < dl.import_list_count; i++ ) { import_entry ie; lread(li, &ie, sizeof(ie)); ie.swap(); if ( n == 0 ) ea = data_start + dl.plt_loc; n--; buf[0] = '.'; get_text_name(ie.name, &buf[1], sizeof(buf)-1); do_name_anyway(ea, buf); doDwrd(ea, 4); set_offset(ea, 0, 0); if ( n > 0 ) { ea += 4; } else { ea_t ea2 = get_long(ea); do_name_anyway(ea2, &buf[1]); add_func(ea2, BADADDR); set_func_cmt(get_func(ea2), "THUNK", false); doDwrd(ea+4, 4); ea += 8; } } }
//---------------------------------------------------------------------- // // check input file format. if recognized, then return 1 // and fill 'fileformatname'. // otherwise return 0 // int accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if( n!= 0 ) return 0; // quit if file is smaller than size of iNes header if (qlsize(li) < sizeof(ines_hdr)) return 0; // set filepos to offset 0 qlseek(li, 0, SEEK_SET); // read NES header if(qlread(li, &hdr, INES_HDR_SIZE) != INES_HDR_SIZE) return 0; // is it a valid ROM image in iNes format? if( memcmp("NES", &hdr.id, sizeof(hdr.id)) != 0 || hdr.term != 0x1A ) return 0; // this is the name of the file format which will be // displayed in IDA's dialog qstrncpy(fileformatname, "Nintendo Entertainment System ROM", MAX_FILE_FORMAT_NAME); // set processor to 6502 if ( ph.id != PLFM_6502 ) { msg("Nintendo Entertainment System ROM detected: setting processor type to M6502.\n"); set_processor_type("M6502", SETPROC_ALL|SETPROC_FATAL); } return (1 | ACCEPT_FIRST); }
//-------------------------------------------------------------------------- static void load_subspaces(linput_t *li, header &h, long fpos, int n) { if ( !n ) return; char buf[MAXSTR]; for ( int i=0; i < n; i++ ) { subspace_dictionary_record sr; qlseek(li, fpos + i*sizeof(sr)); lread(li, &sr, sizeof(sr)); sr.swap(); if ( !sr.is_loadable() || !sr.subspace_length ) continue; if ( sr.fixup_request_quantity ) complain_fixup(); ea_t start = sr.subspace_start; ea_t end = start + sr.initialization_length; file2base(li, sr.file_loc_init_value, start, end, FILEREG_PATCHABLE); end = start + sr.subspace_length; char *name = get_space_name(li, h, sr.name.n_strx, buf, sizeof(buf)); set_selector(i, 0); const char *sclass = strstr(name, "CODE") ? CLASS_CODE : CLASS_DATA; add_segm(i, start, end, name, sclass); if ( i == first_text_subspace_idx ) first_text_subspace_fpos = sr.file_loc_init_value; // sr.alignment, } }
//----------------------------------------------------------------------- static void show_segdefs(linput_t *li, uint32 offset, uint32 length) { if ( offset == 0 || length == 0 ) return; qlseek(li, offset); int n = 0; for ( int i=0; i < length; ) { segdef s; const int size = offsetof(segdef, combine_name); lread(li, &s, size); int nlen = read_pstring(li, s.combine_name, sizeof(s.combine_name)); i += size + 1 + nlen; n++; const char *sname = s.combine_name; const char *sclas = sname; if ( strnicmp(sname, "CODE", 4) == 0 ) sclas = "CODE"; if ( strnicmp(sname, "DATA", 4) == 0 ) sclas = "DATA"; if ( strnicmp(sname, "CONST", 5) == 0 ) sclas = "CONST"; if ( stricmp(sname, "STACK") == 0 ) sclas = "STACK"; if ( strchr(sname, ':') != NULL ) continue; int segsize = s.slimit + 1; if ( strcmp(sname, "DATA") == 0 ) dsel = n; set_selector(n, 0); ea_t ea = freechunk(inf.maxEA, segsize, -(1<<s.align)); add_segm(n, ea, ea+segsize, sname, sclas); set_segm_addressing(getseg(ea), true); if ( strcmp(sclas, "STACK") == 0 ) doByte(ea, segsize); } }
//----------------------------------------------------------------------------- // load a macro assembler file in IDA. void load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) { // already read the 2 first bytes qlseek(li, 2); // initialize static variables qstrncpy(creator, "UNKNOWN", sizeof(creator)); entry_point = -1; bool finished = false; while (!finished) { uchar record_type = 0; // read the record type if (qlread(li, &record_type, 1) != 1) mas_error("unable to read the record type"); finished = process_record(li, record_type, true); } #if defined(DEBUG) msg("MAS: reading complete\n"); #endif mas_write_comments(); }
//-------------------------------------------------------------------------- int accept_file(linput_t *li,char fileformatname[MAX_FILE_FORMAT_NAME],int n) { if ( n ) return 0; header h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) return 0; if ( compute_som_checksum(&h) != 0 ) return 0; h.swap(); char *type; switch ( h.a_magic ) { case EXELIB_MAGIC : type = "Executable Library"; break; case REL_MAGIC : type = "Relocatable"; break; case EXE_MAGIC : type = "Non-sharable, executable"; break; case SHREXE_MAGIC : type = "Sharable, executable"; break; case SHREXELD_MAGIC: type = "Sharable, demand-loadable executable"; break; case DLL_MAGIC : type = "Dynamic Load Library"; break; case SHLIB_MAGIC : type = "Shared Library"; break; case RELLIB_MAGIC : type = "Relocatable Library"; break; default: return 0; } qsnprintf(fileformatname, MAX_FILE_FORMAT_NAME, "HP-UX SOM (%s)", type); return 1; }
//----------------------------------------------------------------------- static void show_extdefs(linput_t *li, uint32 offset, uint32 length) { if ( offset == 0 || length == 0 ) return; qlseek(li, offset); inf.specsegs = 1; int segsize = 4 * h.num_externals; sel_t sel = h.num_segs+1; set_selector(sel, 0); xea = freechunk(inf.maxEA, segsize, -15); add_segm(sel, xea, xea+segsize, "XTRN", "XTRN"); set_segm_addressing(getseg(xea), true); int n = 0; for ( int i=0; i < length; n++ ) { extdef p; const int size = offsetof(extdef, allocate_len); lread(li, &p, size); p.allocate_len.len_4 = 0; if ( p.allocate ) { ask_for_feedback("extdef.allocate\n"); lread(li, &p.allocate_len.len_4, sizeof(p.allocate_len.len_4)); } int nlen = read_pstring(li, p.sym_name, sizeof(p.sym_name)); i += size + 1 + nlen; ea_t a = xea + 4*n; set_name(a, p.sym_name); if ( p.allocate ) put_long(a, p.allocate_len.len_4); } }
//-------------------------------------------------------------------------- int idaapi accept_file(linput_t *li,char fileformatname[MAX_FILE_FORMAT_NAME],int n) { if ( n ) return 0; union { GEOSheader h1; GEOS2header h2; } h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) return false; int32 apppos; int version; if ( h.h1.ID == GEOS_ID && h.h1.fclass == 0 ) { apppos = 0xC8; version = 1; } else if ( h.h2.ID == GEOS2_ID && h.h2.fclass == 1 ) { apppos = sizeof(GEOS2header); version = 2; } else { return false; } GEOSappheader ah; qlseek(li, apppos, SEEK_SET); if ( qlread(li, &ah, sizeof(ah)) != sizeof(ah) ) return false; const char *stype; switch ( ah.type ) { case 1: stype = "Application"; break; case 2: stype = "Library"; break; case 3: stype = "Driver"; break; default: stype = "Unknown type";break; } qsnprintf(fileformatname, MAX_FILE_FORMAT_NAME, "GEOS%d %s", version, stype); return true; }
//-------------------------------------------------------------------------- bool is_elf_file(linput_t *li) { Elf32_Ehdr h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) || h.e_ident[EI_MAG0] != ELFMAG0 || h.e_ident[EI_MAG1] != ELFMAG1 || h.e_ident[EI_MAG2] != ELFMAG2 || h.e_ident[EI_MAG3] != ELFMAG3 ) return false; return true; }
//-------------------------------------------------------------------------- bool macho_file_t::parse_header() { qlseek(li, start_offset); uint32 magic; if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) ) return false; if ( magic == FAT_MAGIC || magic == FAT_CIGAM ) return parse_fat_header(); else return is_magic(magic) || is_cigam(magic); }
//----------------------------------------------------------------------- bool is_intelomf_file(linput_t *li) { uchar magic; lmh h; qlseek(li, 0); if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) || qlread(li, &h, sizeof(h)) != sizeof(h) ) return false; int fsize = qlsize(li); return magic == INTELOMF_MAGIC_BYTE && h.tot_length < fsize; }
//------------------------------------------------------------------------ inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent) { peoff = _peoff; qlseek(li, peoff); memset(&pe64, 0, sizeof(pe64)); qlseek(li, peoff); size_t size = qlread(li, &pe64, sizeof(pe64)); size_t minsize = pe64.magic == MAGIC_P32_PLUS ? qoffsetof(peheader64_t, subsys) : qoffsetof(peheader_t, subsys); bool ok = size > minsize && size <= sizeof(pe64) && (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID) && pe64_to_pe(pe, pe64, silent); if ( ok ) //initialize imagebase for loading set_imagebase((ea_t)pe.imagebase()); return ok; }
//-------------------------------------------------------------------------- static bool load_name2(ushort index, ulong offset) { uint64 off, size; if ( index == ushort(-1) ) { off = dynstr_off; size = dynstr_size; } else { off = elf64 ? shdr64[index].sh_offset : shdr32[index].sh_offset; size = elf64 ? shdr64[index].sh_size : shdr32[index].sh_size; } if ( offset >= size ) { qsnprintf(name, sizeof(name), "bad offset %08lx", low(offset+off)); return false; } ulong pos = qltell(li); offset = low(offset + off); qlseek(li, offset); register char *p; register int i, j; bool ok = true; for(i = 0, p = name; i < sizeof(name)-1; i++, p++) if((j = qlgetc(li)) == EOF) { qstrncpy(p, "{truncated name}", sizeof(name)-(p-name)); ok = false; break; } else if((*p = (char)j) == '\0') break; if(i == sizeof(name)-1) { qstrncpy(p-5, "...", 5); ok = false; } qlseek(li, pos); return ok; }
void SoundLoadState (linput_t *li, ea_t *pc, int size) { char IsM68KRunning; int pos=qltell(li); qlread(li, (void *)&IsM68KRunning, 1); qlseek(li, 4 * (8+8+1), SEEK_CUR); if (pc) qlread(li, (void *)pc, 4); else qlseek(li, 4, SEEK_CUR); qlseek (li, 0x1000, SEEK_CUR); if (pc) create_load_seg(li, 0, 0x80000, 2, "RAM"); else create_load_seg(li, 0x25A00000, 0x25A80000, 2, "SOUNDRAM"); qlseek(li, size-(qltell(li)-pos), SEEK_CUR); }
//-------------------------------------------------------------------------- static void load_exports(linput_t *li, dl_header &dl) { if ( !dl.export_list_count ) return; qlseek(li, first_text_subspace_fpos+dl.export_list_loc); for ( int i=0; i < dl.export_list_count; i++ ) { char buf[MAXSTR]; export_entry ee; lread(li, &ee, sizeof(ee)); ee.swap(); add_entry(ee.value, ee.value, get_text_name(ee.name, buf, sizeof(buf)), ee.type == ST_CODE); } }
//------------------------------------------------------------------------ inline bool pe_loader_t::read_header(linput_t *li, bool silent) { uint32 peoff = 0; link_ulink = false; qlseek(li, peoff); lread(li, &exe, sizeof(exe)); if ( exe.exe_ident != PEEXE_ID ) { if ( exe.exe_ident == EXE_ID ) { char tmp[8]; if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp) && memcmp(tmp, "UniLink", 8) == 0 ) { link_ulink = true; } } qlseek(li, PE_PTROFF); lread(li, &peoff, sizeof(peoff)); } return read_header(li, peoff, silent); }
//-------------------------------------------------------------------------- static void read_dyninfo(ulong offset, ulong size) { qlseek(li, offset); const int entsize = elf64 ? sizeof(Elf64_Dyn) : sizeof(Elf32_Dyn); for(int i = 1; i < size; i += entsize ) { Elf64_Dyn dyn; if ( elf64 ) { if(lread8bytes(li, &dyn.d_tag, mf) || lread8bytes(li, &dyn.d_un, mf)) errstruct(); } else { ulong tag, val; if(lread4bytes(li, &tag, mf) || lread4bytes(li, &val, mf)) errstruct(); dyn.d_tag = tag; dyn.d_un = val; } switch ( WC4(dyn.d_tag) ) { case DT_STRTAB: dynstr_off = map_ea(dyn.d_un); break; case DT_SYMTAB: dynsym_off = map_ea(dyn.d_un); break; case DT_REL: dynrel_off = map_ea(dyn.d_un); break; case DT_RELA: dynrela_off = map_ea(dyn.d_un); break; case DT_STRSZ: dynstr_size = ulong(dyn.d_un); break; case DT_RELSZ: dynrel_size = ulong(dyn.d_un); break; case DT_RELASZ: dynrela_size = ulong(dyn.d_un); break; } } ulong off = dynstr_off; if ( dynrel_off ) off = qmin(dynrel_off, off); if ( dynrela_off ) off = qmin(dynrela_off, off); dynsym_size = off - dynsym_off; }
//-------------------------------------------------------------------------- static void load_aux_headers(linput_t *li, long fpos, size_t size) { if ( !size ) return; qlseek(li, fpos); while ( size > 0 ) { char buf[4096]; aux_id aih; lread(li, &aih, sizeof(aih)); aih.swap(); size_t total = sizeof(aih) + aih.length; if ( total >= sizeof(buf) ) loader_failure("Too big aux_header size %u", total); if ( total > size ) return; // loader_failure("Illegal aux header size %u, rest %u", total, size); size -= total; qlseek(li, -sizeof(aih), SEEK_CUR); lread(li, buf, total); switch ( aih.type ) { case HPUX_AUX_ID: { som_exec_auxhdr *p = (som_exec_auxhdr*)buf; p->swap(); inf.start_cs = 0; inf.startIP = p->exec_entry; data_start = p->exec_dmem; } break; case VERSION_AUX_ID: case COPYRIGHT_AUX_ID: case SHLIB_VERSION_AUX_ID: default: break; } } }