//---------------------------------------------------------------------- static void apply_symbols(void) { free_mappings(); if ( dataseg != BADADDR ) { for ( int i=0; i < numports; i++ ) { ea_t ea = calc_data_mem(ports[i].address); segment_t *s = getseg(ea); if ( s == NULL || s->type != SEG_IMEM ) continue; doByte(ea, 1); const char *name = ports[i].name; if ( !set_name(ea, name, SN_NOWARN) ) set_cmt(ea, name, 0); } ea_t ea = dataseg; segment_t *d = getseg(dataseg); if ( d != NULL ) { ea_t dataend = d->endEA; while ( 1 ) { ea = next_unknown(ea, dataend); if ( ea == BADADDR ) break; ea_t end = nextthat(ea, dataend, f_isHead, NULL); if ( end == BADADDR ) end = dataend; doByte(ea, end-ea); } create_mappings(); } } }
//---------------------------------------------------------------------- // // defines, names and comments an item // static void define_item( ushort address, asize_t size, char *shortdesc, char *comment ) { do_unknown( address, true ); do_data_ex( address, (size == IOREG_16 ? wordflag() : byteflag() ), size, BADNODE ); set_name( address, shortdesc ); set_cmt( address, comment, true ); }
void applyPEHeaderTemplates(unsigned int mz_addr) { #if (IDA_SDK_VERSION < 520) tid_t idh = til2idb(-1, "IMAGE_DOS_HEADER"); tid_t inth = til2idb(-1, "IMAGE_NT_HEADERS"); tid_t ish = til2idb(-1, "IMAGE_SECTION_HEADER"); #else tid_t idh = import_type(ti, -1, "IMAGE_DOS_HEADER"); tid_t inth = import_type(ti, -1, "IMAGE_NT_HEADERS"); tid_t ish = import_type(ti, -1, "IMAGE_SECTION_HEADER"); #endif doStruct(mz_addr, sizeof(_IMAGE_DOS_HEADER), idh); unsigned short e_lfanew = get_word(mz_addr + 0x3C); mz_addr += e_lfanew; if (doStruct(mz_addr, sizeof(_IMAGE_NT_HEADERS), inth) == 0) { do_unknown(mz_addr, 0); set_cmt(mz_addr - e_lfanew, "!!Warning, MZ Header overlaps PE header!!", 0); doStruct(mz_addr, sizeof(_IMAGE_NT_HEADERS), inth); } unsigned short num_sects = get_word(mz_addr + 6); mz_addr += sizeof(_IMAGE_NT_HEADERS); for (unsigned short i = 0; i < num_sects; i++) { doStruct(mz_addr + i * sizeof(_IMAGE_SECTION_HEADER), sizeof(_IMAGE_SECTION_HEADER), ish); } }
//------------------------------------------------------------------ static bool apply_config_file(int _respect_info) { if ( strcmp(device, NONEPROC) == 0 ) // processor not selected return true; char cfgfile[QMAXFILE]; char cfgpath[QMAXPATH]; get_cfg_filename(cfgfile, sizeof(cfgfile)); if ( getsysfile(cfgpath, sizeof(cfgpath), cfgfile, CFG_SUBDIR) == NULL ) { #ifndef SILENT warning("ICON ERROR\n" "Can not open %s, I/O port definitions are not loaded", cfgfile); #endif return false; } deviceparams[0] = '\0'; if ( !CHECK_IORESP ) _respect_info = 0; respect_info = _respect_info; free_ioports(ports, numports); ports = read_ioports(&numports, cfgpath, device, sizeof(device), callback); if ( respect_info & IORESP_PORT ) { for ( int i=0; i < numports; i++ ) { ioport_t *p = ports + i; #ifdef I8051 segment_t *s = get_segm_by_name("FSR"); if ( s != NULL ) { set_name(p->address + s->startEA - 0x80, p->name); set_cmt(p->address + s->startEA - 0x80, p->cmt, true); } #else set_name(p->address, p->name); set_cmt(p->address, p->cmt, true); #endif } } return true; }
static void load_symbols(int _respect_info) { if ( cfgname != NULL ) { deviceparams[0] = '\0'; respect_info = _respect_info; if ( !inf.like_binary() ) respect_info &= ~2; free_ioports(ports, numports); ports = read_ioports(&numports, cfgname, device, sizeof(device), callback); if ( respect_info ) { for ( int i=0; i < numports; i++ ) { ea_t ea = ports[i].address; doByte(ea, 1); const char *name = ports[i].name; if ( !set_name(ea, name, SN_NOWARN) ) set_cmt(ea, name, 0); else set_cmt(ea, ports[i].cmt, true); } } } }
/* * helper function to find GUIDs in data segment and label them */ void find_guids(ea_t start, ea_t end) { uint32_t table_size = sizeof(guid_table)/sizeof(*guid_table); ea_t current_addr = start; int match = 0; /* go over all the data segment searching for GUIDs */ while (current_addr < end) { /* match against table entries */ for (uint32_t i = 0; i < table_size; i++) { EFI_GUID tmp; get_many_bytes(current_addr, &tmp, sizeof(EFI_GUID)); if (tmp.Data1 == guid_table[i].guid.Data1 && tmp.Data2 == guid_table[i].guid.Data2 && tmp.Data3 == guid_table[i].guid.Data3 && memcmp(tmp.Data4, guid_table[i].guid.Data4, sizeof(tmp.Data4)) == 0) { set_name(current_addr, (const char*)guid_table[i].name, SN_CHECK); doDwrd(current_addr, 4); doDwrd(current_addr+4, 4); doDwrd(current_addr+8, 4); doDwrd(current_addr+12, 4); static char string[256] = {0}; qsnprintf(string, sizeof(string), "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid_table[i].guid.Data1, guid_table[i].guid.Data2, guid_table[i].guid.Data3, guid_table[i].guid.Data4[0], guid_table[i].guid.Data4[1], guid_table[i].guid.Data4[2], guid_table[i].guid.Data4[3], guid_table[i].guid.Data4[4], guid_table[i].guid.Data4[5], guid_table[i].guid.Data4[6], guid_table[i].guid.Data4[7]); set_cmt(current_addr, string, 0); match = 1; break; } } /* no need to check all 16 bytes if we found a match */ if (match) { current_addr += sizeof(EFI_GUID); match = 0; } else { current_addr++; } } }
/* * 模式说明 * 1、MODE_ARMOP_Code -> 使用ARM指令修改CODE * 2、MODE_ARMOP_SysCall -> 注释系统调用 */ int Arm_Moudle(int inFlag){ static int Mode_Bit = MODE_ARMOPC32_JMP; static int ModeOption = 0; ea_t _ThisEa = get_screen_ea(); if (inFlag != Flag_Again) if (AskUsingForm_c(ASK_ARM_UI, &ModeOption) == 0) return NULL; if (MODE_ARMOP_Code == ModeOption){ if (inFlag != Flag_Again) if (AskUsingForm_c(ASK_CODE_UI, &Mode_Bit) == 0) return NULL; if (MODE_ARMOPC16_JMP == Mode_Bit){ _ThisEa &= 0xFFFFFFFE; patch_long(_ThisEa, 0xE7FE); } else if (MODE_ARMOPC16_NOP == Mode_Bit){ _ThisEa &= 0xFFFFFFFE; patch_word(_ThisEa, 0xC046); } else if (MODE_ARMOPC32_JMP == Mode_Bit){ _ThisEa &= 0xFFFFFFFC; patch_long(_ThisEa, 0xEAFFFFFE); } else if (MODE_ARMOPC32_NOP == Mode_Bit){ _ThisEa &= 0xFFFFFFFC; patch_long(_ThisEa, 0xE1A00000); } } else if(MODE_ARMOP_SysCall == ModeOption){ //自动获取, ulong Sys_No = get_32bit(get_screen_ea()) & 0xFFF; if (AskUsingForm_c(ASK_SYSCALL_UI, &Sys_No) == 0)return 0; if (SysCall::getName(Sys_No) != NULL){ set_cmt(get_screen_ea(), SysCall::getName(Sys_No), 1); } } return NULL; }
// Emulate an instruction. int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = ((feature & CF_STOP) == 0); if ( cmd.Op1.type != o_void) handle_operand(cmd.Op1, (feature & CF_CHG1) != 0 ); if ( cmd.Op2.type != o_void) handle_operand(cmd.Op2, (feature & CF_CHG2) != 0 ); if ( cmd.Op3.type != o_void) handle_operand(cmd.Op3, (feature & CF_CHG3) != 0 ); if ( flow ) ua_add_cref(0, cmd.ea + cmd.size, fl_F); // Following code will update the current value of the two virtual // segment registers: RW (register window) and RP (register page). bool rw_has_changed = false; bool rp_has_changed = false; switch ( cmd.itype ) { case st9_srp: { sel_t val = cmd.Op1.value; if ( val % 2 ) val--; // even reduced splitSRarea1(cmd.ea, rRW, val | (val << 8), SR_auto); } rw_has_changed = true; break; case st9_srp0: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, cmd.Op1.value | (RW & 0xFF00), SR_auto); } rw_has_changed = true; break; case st9_srp1: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, (cmd.Op1.value << 8) | (RW & 0x00FF), SR_auto); } rw_has_changed = true; break; case st9_spp: splitSRarea1(cmd.ea, rRP, cmd.Op1.value, SR_auto); rp_has_changed = true; break; } // If RW / RP registers have changed, print a comment which explains the new mapping of // the general registers. if ( rw_has_changed && !has_cmt(uFlag) ) { char buf[MAXSTR]; sel_t RW = getSR(cmd.ea, rRW); int low = RW & 0x00FF; int high = (RW & 0xFF00) >> 8; low *= 8; high *= 8; const char *fmt = "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n" "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d"; qsnprintf(buf, sizeof buf, fmt, 0 + low, 1 + low, 2 + low, 3 + low, 4 + low, 5 + low, 6 + low, 7 + low, 8 + high, 9 + high, 10 + high, 11 + high, 12 + high, 13 + high, 14 + high, 15 + high ); set_cmt(cmd.ea, buf, false); }
// Emulate an operand. static void handle_operand(op_t &op, bool write) { switch ( op.type ) { // Code address case o_near: { cref_t mode; ea_t ea = toEA(cmd.cs, op.addr); // call or jump ? if ( cmd.itype == st9_call || cmd.itype == st9_calls ) { if ( !func_does_return(ea) ) flow = false; mode = fl_CN; } else { mode = fl_JN; } ua_add_cref(op.offb, ea, mode); } break; // Memory address case o_mem: { enum dref_t mode; mode = write ? dr_W: dr_R; ua_add_dref(op.offb, toEA(cmd.cs, op.addr), mode); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // Immediate value case o_imm: doImmd(cmd.ea); // create a comment if this immediate is represented in the .cfg file { const ioport_t * port = find_sym(op.value); if ( port != NULL && !has_cmt(uFlag) ) { set_cmt(cmd.ea, port->cmt, false); } } // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, 0); break; // Displacement case o_displ: doImmd(cmd.ea); if ( isOff(uFlag, op.n) ) { ua_add_off_drefs2(op, dr_O, OOF_ADDR); ua_dodata2(op.offb, op.addr, op.dtyp); } // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); if ( cmd.Op2.type == o_reg ) { regvar_t *r = find_regvar(pfn, cmd.ea, ph.regNames[cmd.Op2.reg]); if ( r != NULL ) { struc_t *s = get_frame(pfn); member_t *m = get_stkvar(op, op.addr, NULL); char b[20]; qsnprintf(b, sizeof b, "%scopy", r->user); set_member_name(s, m->soff, b); } } } } } break; // Register - Phrase - Void: do nothing case o_reg: case o_phrase: case o_void: break; default: IDA_ERROR("Invalid op.type in handle_operand()"); } }
GCCTypeInfo *GCCTypeInfo::parseTypeInfo(ea_t ea) { if (g_KnownTypes.count(ea)) return g_KnownTypes[ea]; GCC_RTTI::type_info tmp; if (!get_bytes(&tmp, sizeof(GCC_RTTI::type_info), ea)) return 0; ea_t name_ea = tmp.__type_info_name; size_t length = get_max_strlit_length(name_ea, STRTYPE_C, ALOPT_IGNHEADS); qstring buffer; if (!get_strlit_contents(&buffer, name_ea, length, STRTYPE_C)) { return 0; } qstring name(buffer); qstring demangled_name; name = qstring("_ZTS") + name; int32 res = demangle_name(&demangled_name, name.c_str(), 0); if (res != (MT_GCC3 | M_AUTOCRT | MT_RTTI)) { return 0; } demangled_name = demangled_name.substr(19); GCCTypeInfo * result = new GCCTypeInfo(); result->ea = ea; result->typeName = demangled_name; result->vtbl = tmp.__type_info_vtable; setUnknown(ea + ea_t(offsetof(GCC_RTTI::type_info, __type_info_vtable)), sizeof(void*)); op_plain_offset(ea + ea_t(offsetof(GCC_RTTI::type_info, __type_info_vtable)), 0, ea); setUnknown(ea + ea_t(offsetof(GCC_RTTI::type_info, __type_info_name)), sizeof(void*)); op_plain_offset(ea + ea_t(offsetof(GCC_RTTI::type_info, __type_info_name)), 0, ea); MakeName(ea, demangled_name, "RTTI_", ""); if (tmp.__type_info_vtable == class_type_info_vtbl) { g_KnownTypes[ea] = result; return result; } if (tmp.__type_info_vtable == si_class_type_info_vtbl) { GCC_RTTI::__si_class_type_info si_class; if (!get_bytes(&si_class, sizeof(GCC_RTTI::__si_class_type_info), ea)) { delete result; return 0; } GCCTypeInfo *base = parseTypeInfo(si_class.base); if (base == 0) { delete result; return 0; } setUnknown(ea + ea_t(offsetof(GCC_RTTI::__si_class_type_info, base)), sizeof(void*)); op_plain_offset(ea + ea_t(offsetof(GCC_RTTI::__si_class_type_info, base)), 0, ea); result->parentsCount = 1; result->parentsTypes = new GCCParentType*[1]; result->parentsTypes[0] = new GCCParentType(); result->parentsTypes[0]->ea = base->ea; result->parentsTypes[0]->info = base; result->parentsTypes[0]->flags = 0; g_KnownTypes[ea] = result; return result; } if (tmp.__type_info_vtable != vmi_class_type_info_vtbl) { // Unknown type, ignore it delete result; return 0; } GCC_RTTI::__vmi_class_type_info vmi_class; if (!get_bytes(&vmi_class, sizeof(GCC_RTTI::__vmi_class_type_info), ea)) return 0; // vmi_class.vmi_flags; // WTF?? result->parentsCount = vmi_class.vmi_base_count; result->parentsTypes = new GCCParentType*[result->parentsCount]; ea_t addr = ea + ea_t(offsetof(GCC_RTTI::__vmi_class_type_info, vmi_bases)); setUnknown(ea + ea_t(offsetof(GCC_RTTI::__vmi_class_type_info, vmi_flags)), sizeof(void*)); create_dword(ea + ea_t(offsetof(GCC_RTTI::__vmi_class_type_info, vmi_flags)), sizeof(void *)); setUnknown(ea + ea_t(offsetof(GCC_RTTI::__vmi_class_type_info, vmi_base_count)), sizeof(int)); create_dword(ea + ea_t(offsetof(GCC_RTTI::__vmi_class_type_info, vmi_base_count)), sizeof(int)); GCC_RTTI::__base_class_info baseInfo; for (int i = 0; i < vmi_class.vmi_base_count; ++i, addr += sizeof(baseInfo)) { if (!get_bytes(&baseInfo, sizeof(baseInfo), addr)) { delete result; return 0; } GCCTypeInfo *base = parseTypeInfo(baseInfo.base); if (base == 0) { delete result; return 0; } setUnknown(addr + ea_t(offsetof(GCC_RTTI::__base_class_info, base)), sizeof(void*)); op_plain_offset(addr + offsetof(GCC_RTTI::__base_class_info, base), 0, addr); setUnknown(addr + ea_t(offsetof(GCC_RTTI::__base_class_info, vmi_offset_flags)), sizeof(void*)); create_dword(addr + ea_t(offsetof(GCC_RTTI::__base_class_info, vmi_offset_flags)), sizeof(int)); result->parentsTypes[i] = new GCCParentType(); result->parentsTypes[i]->ea = base->ea; result->parentsTypes[i]->ea = base->ea; result->parentsTypes[i]->info = base; result->parentsTypes[i]->flags = static_cast<unsigned>(baseInfo.vmi_offset_flags); qstring flags; if (baseInfo.vmi_offset_flags & baseInfo.virtual_mask) flags += " virtual_mask "; if (baseInfo.vmi_offset_flags & baseInfo.public_mask) flags += " public_mask "; if (baseInfo.vmi_offset_flags & baseInfo.offset_shift) flags += " offset_shift "; set_cmt(addr + ea_t(offsetof(GCC_RTTI::__base_class_info, vmi_offset_flags)), flags.c_str(), false); } g_KnownTypes[ea] = result; return result; }
//------------------------------------------------------------------------ static void TouchArg(op_t &x,int isAlt,int isload) { ea_t jmpa; switch ( x.type ) { case o_near: // Jcc/ [jmp/call 37/67] case o_mem: // 37/67/77 case o_far: jmpa = toEA(x.type == o_far ? x.segval : codeSeg(x.addr16,x.n), x.addr16); if ( x.phrase == 0) { ua_add_cref(x.offb,jmpa,fl_JN ); break; } //Jcc extxref: if ( (x.phrase & 070) == 070 ) goto xrefset; if ( cmd.itype == pdp_jmp) ua_add_cref(x.offb,jmpa,fl_JF ); else if ( cmd.itype == pdp_jsr || cmd.itype == pdp_call ) { ua_add_cref(x.offb,jmpa,fl_CF); if ( !func_does_return(jmpa) ) flow = false; } else { xrefset: ua_dodata2(x.offb, jmpa, x.dtyp); ua_add_dref(x.offb, jmpa, isload ? dr_R : dr_W); } break; case o_displ: // 6x/7x (!67/!77) doImmdValue(); if ( !isload && x.phrase == (060 + rR0) && x.addr16 <= 1 ) loadR0data(&x, x.addr16); if ( !isAlt && isOff(emuFlg,x.n ) && (jmpa = get_offbase(cmd.ea, x.n)) != BADADDR) { jmpa += x.addr16; goto extxref; } break; case o_imm: // 27 if ( !x.ill_imm ) { doImmdValue(); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); } break; case o_number: // EMT/TRAP/MARK/SPL if ( cmd.itype == pdp_emt && get_cmt(cmd.ea, false, NULL, 0) <= 0 ) { if ( x.value >= 0374 && x.value <= 0375 ) { cmd.Op2.value = (x.value == 0375) ? emuR0data.b[1] : (emuR0 >> 8); cmd.Op2.type = o_imm; } char buf[MAXSTR]; if ( get_predef_insn_cmt(cmd, buf, sizeof(buf)) > 0 ) set_cmt(cmd.ea, buf, false); cmd.Op2.type = o_void; } break; case o_reg: // 0 if ( x.reg == rR0 ) { if ( cmd.Op2.type == o_void ) { // one operand cmd if ( cmd.itype != pdp_clr ) { goto undefall; } else { if ( cmd.bytecmd ) emuR0 &= 0xFF00; else emuR0 = 0; goto undefdata; } } if ( &x == &cmd.Op2 ) { if ( cmd.itype != pdp_mov ) { if ( cmd.bytecmd ) { emuR0 |= 0xFF; goto undefdata; } else goto undefall; } if ( cmd.bytecmd ) goto undefall; if ( cmd.Op1.type == o_imm ) { if ( (emuR0 = (ushort)cmd.Op1.value) & 1 ) goto undefdata; emuR0data.w = get_word(toEA(cmd.cs, emuR0)); } else { undefall: emuR0 = 0xFFFF; undefdata: emuR0data.w = 0xFFFF; } } } break; case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) if ( (x.phrase & 7) == rR0 ) { if ( !isload && x.phrase == (010 + rR0)) loadR0data(&x, 0 ); else if ( cmd.Op2.type == o_void || &x == &cmd.Op2 ) goto undefall; } case o_fpreg: // FPP break; default: warning("%" FMT_EA "o (%s): bad optype %d", cmd.ip, cmd.get_canon_mnem(), x.type); break; }
static void idaapi run(int /* arg */) { static char mapFileName[_MAX_PATH] = { 0 }; // If user press shift key, show options dialog if (GetAsyncKeyState(VK_SHIFT) & 0x8000) { ShowOptionsDlg(); } ulong numOfSegs = (ulong) get_segm_qty(); if (0 == numOfSegs) { warning("Not found any segments"); return; } if ('\0' == mapFileName[0]) { // First run strncpy(mapFileName, get_input_file_path(), sizeof(mapFileName)); WIN32CHECK(PathRenameExtension(mapFileName, ".map")); } // Show open map file dialog char *fname = askfile_c(0, mapFileName, "Open MAP file"); if (NULL == fname) { msg("LoadMap: User cancel\n"); return; } // Open the map file LPSTR pMapStart = NULL; DWORD mapSize = INVALID_FILE_SIZE; MAP_OPEN_ERROR eRet = MapFileOpen(fname, pMapStart, mapSize); switch (eRet) { case WIN32_ERROR: warning("Could not open file '%s'.\nWin32 Error Code = 0x%08X", fname, GetLastError()); return; case FILE_EMPTY_ERROR: warning("File '%s' is empty, zero size", fname); return; case FILE_BINARY_ERROR: warning("File '%s' seem to be a binary or Unicode file", fname); return; case OPEN_NO_ERROR: default: break; } bool foundHdr = false; ulong validSyms = 0; ulong invalidSyms = 0; // The mark pointer to the end of memory map file // all below code must not read or write at and over it LPSTR pMapEnd = pMapStart + mapSize; show_wait_box("Parsing and applying symbols from the Map file '%s'", fname); __try { LPSTR pLine = pMapStart; LPSTR pEOL = pMapStart; while (pLine < pMapEnd) { // Skip the spaces, '\r', '\n' characters, blank lines, seek to the // non space character at the beginning of a non blank line pLine = SkipSpaces(pEOL, pMapEnd); // Find the EOL '\r' or '\n' characters pEOL = FindEOL(pLine, pMapEnd); size_t lineLen = (size_t) (pEOL - pLine); if (lineLen < g_minLineLen) { continue; } if (!foundHdr) { if ((0 == strnicmp(pLine, VC_HDR_START , lineLen)) || (0 == strnicmp(pLine, BL_HDR_NAME_START , lineLen)) || (0 == strnicmp(pLine, BL_HDR_VALUE_START, lineLen))) { foundHdr = true; } } else { ulong seg = SREG_NUM; ulong addr = BADADDR; char name[MAXNAMELEN + 1]; char fmt[80]; name[0] = '\0'; fmt[0] = '\0'; // Get segment number, address, name, by pass spaces at beginning, // between ':' character, between address and name int ret = _snscanf(pLine, min(lineLen, MAXNAMELEN + g_minLineLen), " %04X : %08X %s", &seg, &addr, name); if (3 != ret) { // we have parsed to end of value/name symbols table or reached EOF _snprintf(fmt, sizeof(fmt), "Parsing finished at line: '%%.%ds'.\n", lineLen); ShowMsg(fmt, pLine); break; } else if ((0 == seg) || (--seg >= numOfSegs) || (BADADDR == addr) || ('\0' == name[0])) { sprintf(fmt, "Invalid map line: %%.%ds.\n", lineLen); ShowMsg(fmt, pLine); invalidSyms++; } else { // Ensure name is NULL terminated name[MAXNAMELEN] = '\0'; // Determine the DeDe map file bool bNameApply = g_options.bNameApply; char *pname = name; if (('<' == pname[0]) && ('-' == pname[1])) { // Functions indicator symbol of DeDe map pname += 2; bNameApply = true; } else if ('*' == pname[0]) { // VCL controls indicator symbol of DeDe map pname++; bNameApply = false; } else if (('-' == pname[0]) && ('>' == pname[1])) { // VCL methods indicator symbol of DeDe map pname += 2; bNameApply = false; } ulong la = addr + getnseg((int) seg)->startEA; flags_t f = getFlags(la); if (bNameApply) // Apply symbols for name { // Add name if there's no meaningful name assigned. if (g_options.bReplace || (!has_name(f) || has_dummy_name(f) || has_auto_name(f))) { if (set_name(la, pname, SN_NOWARN)) { ShowMsg("%04X:%08X - Change name to '%s' successed\n", seg, la, pname); validSyms++; } else { ShowMsg("%04X:%08X - Change name to '%s' failed\n", seg, la, pname); invalidSyms++; } } } else if (g_options.bReplace || !has_cmt(f)) { // Apply symbols for comment if (set_cmt(la, pname, false)) { ShowMsg("%04X:%08X - Change comment to '%s' successed\n", seg, la, pname); validSyms++; } else { ShowMsg("%04X:%08X - Change comment to '%s' failed\n", seg, la, pname); invalidSyms++; } } } } } } __finally { MapFileClose(pMapStart); hide_wait_box(); } if (!foundHdr) { warning("File '%s' is not a valid Map file", fname); } else { // Save file name for next askfile_c dialog strncpy(mapFileName, fname, sizeof(mapFileName)); // Show the result msg("Result of loading and parsing the Map file '%s'\n" " Number of Symbols applied: %d\n" " Number of Invalid Symbols: %d\n\n", fname, validSyms, invalidSyms); } }
static int notify(processor_t::idp_notify msgid, ...) { // Various messages: va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch(msgid) { case processor_t::init: inf.mf = 1; // MSB first default: break; case processor_t::newfile: { segment_t *sptr = get_first_seg(); if( sptr != NULL ) { if( sptr->startEA - get_segm_base( sptr ) == 0 ) { inf.beginEA = sptr->startEA + 0xC; inf.startIP = 0xC; for( int i = 0; i < qnumber(entries); i++ ) { ea_t ea = sptr->startEA + entries[i].off; if( isEnabled(ea) ) { doWord( ea, 2 ); // ig: set_op_type - внутренняя функция, ее нельзя использовать // set_op_type( ea, offflag(), 0 ); set_offset( ea, 0, sptr->startEA ); ea_t ea1 = sptr->startEA + get_word( ea ); auto_make_proc( ea1 ); set_name( ea, entries[i].name ); // ig: так получше будет? set_cmt( sptr->startEA+get_word(ea), entries[i].cmt, 1 ); } } } set_segm_class( sptr, "CODE" ); } segment_t s; ea_t bottom = toEA( inf.baseaddr, 0 ); intmem = s.startEA = freechunk( bottom, 256, 0xF ); s.endEA = s.startEA + 256; s.sel = allocate_selector( s.startEA >> 4 ); s.type = SEG_IMEM; // internal memory add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE); const predefined_t *ptr; for( ptr = iregs; ptr->name != NULL; ptr++ ) { ea_t ea = intmem + ptr->addr; ea_t oldea = get_name_ea( BADADDR, ptr->name ); if( oldea != ea ) { if( oldea != BADADDR ) set_name( oldea, NULL ); do_unknown( ea, DOUNK_EXPAND ); set_name( ea, ptr->name ); } if( ptr->cmt != NULL ) set_cmt( ea, ptr->cmt, 1 ); } } break; case processor_t::oldfile: sel_t sel; if( atos( "INTMEM", &sel) ) intmem = specialSeg(sel); break; case processor_t::newseg: { // default DS is equal to CS segment_t *sptr = va_arg(va, segment_t *); sptr->defsr[rVds-ph.regFirstSreg] = sptr->sel; } } va_end(va); return(1); }
int idaapi emu() { char szLabel[MAXSTR]; insn_t saved; segment_t* pSegment; ea_t ea, length, offset; flags_t flags; uint32 dwFeature, i; dwFeature = cmd.get_canon_feature(); fFlow = !(dwFeature & CF_STOP); if (dwFeature & CF_USE1) op_emu(cmd.Op1, 1); if (dwFeature & CF_USE2) op_emu(cmd.Op2, 1); if (dwFeature & CF_CHG1) op_emu(cmd.Op1, 0); if (dwFeature & CF_CHG2) op_emu(cmd.Op2, 0); saved = cmd; switch (cmd.itype) { case M8B_MOV: if (!cmd.Op1.is_reg(rPSP)) break; case M8B_SWAP: if (cmd.itype == M8B_SWAP && !cmd.Op2.is_reg(rDSP)) break; for (i = 0; i < 5; ++i) { ea = decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.itype == M8B_MOV && cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { ea = toRAM(cmd.Op2.value); if (ea != BADADDR) { qsnprintf(szLabel, sizeof(szLabel), "%s_%0.2X", cmd.itype == M8B_MOV ? "psp" : "dsp", cmd.Op2.value); ua_add_dref(cmd.Op2.offb, ea, dr_O); set_name(ea, szLabel, SN_NOWARN); } break; } } break; case M8B_JACC: pSegment = getseg(cmd.ea); if (!pSegment) break; length = pSegment->endEA - cmd.ea; if (length > 256) length = 256; for (offset = 2; offset < length; offset += 2) { ea = toROM(saved.Op1.addr + offset); if (ea == BADADDR) break; flags = getFlags(ea); if (!hasValue(flags) || (has_any_name(flags) || hasRef(flags)) || !create_insn(ea)) break; switch (cmd.itype) { case M8B_JMP: case M8B_RET: case M8B_RETI: case M8B_IPRET: add_cref(saved.ea, ea, fl_JN); break; default: offset = length; } } break; case M8B_IORD: case M8B_IOWR: case M8B_IOWX: for (i = 0; i < 5; ++i) { ea = (saved.itype == M8B_IORD) ? decode_insn(cmd.ea + cmd.size) : decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { qsnprintf(szLabel, sizeof(szLabel), "[A=%0.2Xh] ", cmd.Op2.value); if (get_portbits_sym(szLabel + qstrlen(szLabel), saved.Op1.addr, cmd.Op2.value)) set_cmt(saved.ea, szLabel, false); break; } } } cmd = saved; if ((cmd.ea & 0xFF) == 0xFF) { switch (cmd.itype) { case M8B_RET: case M8B_RETI: case M8B_XPAGE: break; default: QueueMark(Q_noValid, cmd.ea); } } if (fFlow) ua_add_cref(0, cmd.ea + cmd.size, fl_F); return 1; }
static int notify(processor_t::idp_notify msgid, ...) { static int first_time = 1; va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: helper.create("$ intel 8051"); inf.mf = 1; // Set a big endian mode of the IDA kernel default: break; case processor_t::term: free_ioports(ports, numports); break; case processor_t::newfile: { segment_t *sptr = get_first_seg(); if ( sptr != NULL ) { if ( sptr->startEA-get_segm_base(sptr) == 0 ) { inf.beginEA = sptr->startEA; inf.startIP = 0; for ( int i=0; i < qnumber(entries); i++ ) { if ( entries[i].proc > ptype ) continue; ea_t ea = inf.beginEA+entries[i].off; if ( isEnabled(ea) && get_byte(ea) != 0xFF ) { add_entry(ea, ea, entries[i].name, 1); set_cmt(ea, entries[i].cmt, 1); } } } } segment_t *scode = get_first_seg(); set_segm_class(scode, "CODE"); if ( ptype > prc_51 ) { AdditionalSegment(0x10000-256-128, 256+128, "RAM"); if ( scode != NULL ) { ea_t align = (scode->endEA + 0xFFF) & ~0xFFF; if ( getseg(align-7) == scode ) // the code segment size is { // multiple of 4K or near it uchar b0 = get_byte(align-8); // 251: // 0 : 1-source, 0-binary mode // 6,7: must be 1s // 82930: // 0 : 1-source, 0-binary mode // 7 : must be 1s // uchar b1 = get_byte(align-7); // 251 // 0: eprommap 0 - FE2000..FE4000 is mapped into 00E000..100000 // 1 - .............. is not mapped ............... // 1: must be 1 // 3: // 2: must be 1 // 4: intr 1 - upon interrupt PC,PSW are pushed into stack // 0 - upon interrupt only PC is pushed into stack // 5: must be 1 // 6: must be 1 // 7: must be 1 // 82930: // 3: must be 1 // 5: must be 1 // 6: must be 1 // 7: must be 1 // msg("b0=%x b1=%x\n", b0, b1); // if ( (b0 & 0x80) == 0x80 && (b1 & 0xEA) == 0xEA ) { // the init bits are correct char pname[sizeof(inf.procName)+1]; inf.get_proc_name(pname); char ntype = (b0 & 1) ? 's' : 'b'; char *ptr = tail(pname)-1; if ( ntype != *ptr && askyn_c(1, "HIDECANCEL\n" "The input file seems to be for the %s mode of the processor. " "Do you want to change the current processor type?", ntype == 's' ? "source" : "binary") > 0 ) { *ptr = ntype; first_time = 1; set_processor_type(pname, SETPROC_COMPAT); } } } } } // the default data segment will be INTMEM { segment_t *s = getseg(intmem); if ( s != NULL ) set_default_dataseg(s->sel); } if ( choose_ioport_device(cfgname, device, sizeof(device), parse_area_line0) ) set_device_name(device, IORESP_ALL); if ( get_segm_by_name("RAM") == NULL ) AdditionalSegment(256, 0, "RAM"); if ( get_segm_by_name("FSR") == NULL ) AdditionalSegment(128, 128, "FSR"); setup_data_segment_pointers(); } break; case processor_t::oldfile: setup_data_segment_pointers(); break; case processor_t::newseg: // make the default DS point to INTMEM // (8051 specific issue) { segment_t *newseg = va_arg(va, segment_t *); segment_t *intseg = getseg(intmem); if ( intseg != NULL ) newseg->defsr[rVds-ph.regFirstSreg] = intseg->sel; } break; case processor_t::newprc: { processor_subtype_t prcnum = processor_subtype_t(va_arg(va, int)); if ( !first_time && prcnum != ptype ) { warning("Sorry, it is not possible to change" // (this is 8051 specific) " the processor mode on the fly." " Please reload the input file" " if you want to change the processor."); return 0; } first_time = 0; ptype = prcnum; } break; case processor_t::newasm: // new assembler type { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_NONE); } break; case processor_t::move_segm:// A segment is moved // Fix processor dependent address sensitive information // args: ea_t from - old segment address // segment_t - moved segment { // ea_t from = va_arg(va, ea_t); // segment_t *s = va_arg(va, segment_t *); // Add commands to adjust your internal variables here // Most of the time this callback will be empty // // If you keep information in a netnode's altval array, you can use // node.altshift(from, s->startEA, s->endEA - s->startEA); // // If you have a variables pointing to somewhere in the disassembled program memory, // you can adjust it like this: // // asize_t size = s->endEA - s->startEA; // if ( var >= from && var < from+size ) // var += s->startEA - from; } break; case processor_t::is_sane_insn: // is the instruction sane for the current file type? // arg: int no_crefs // 1: the instruction has no code refs to it. // ida just tries to convert unexplored bytes // to an instruction (but there is no other // reason to convert them into an instruction) // 0: the instruction is created because // of some coderef, user request or another // weighty reason. // The instruction is in 'cmd' // returns: 1-ok, <=0-no, the instruction isn't // likely to appear in the program { int no_crefs = va_arg(va, int); return is_sane_insn(no_crefs); } } va_end(va); return(1); }
// emulate operand static void handle_operand(op_t &op, bool loading) { switch ( op.type ) { // Address case o_near: // branch label - create code reference (call or jump // according to the instruction) { ea_t ea = toEA(cmd.cs, op.addr); cref_t ftype = fl_JN; if ( cmd.itype == m32r_bl ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(op.offb, ea, ftype); } break; // Immediate case o_imm: if ( !loading ) { interr1("handle_operand(): o_imm with CF_CHG"); } handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, OOFW_IMM|OOF_SIGNED); // create a comment if this immediate is represented in the .cfg file { const ioport_t * port = find_sym(op.value); if ( port != NULL && !has_cmt(uFlag) ) set_cmt(cmd.ea, port->cmt, false); } break; // Displ case o_displ: handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, loading ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR|OOFW_32); // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; case o_phrase: /* create stack variables if required */ if ( op.specflag1 == fRI && may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, 0, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; // Phrase - register - void : do nothing case o_reg: case o_void: break; // Others types should never be called default: interr2("handle_operand(): unknown type %d", op.type); break; } }
static int notify(processor_t::idp_notify msgid, ...) // Various messages { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::newfile: { // ig: вообще у меня теперь такая точка зрения: // не надо в коде задавать вид имен. // при желании это можно сделать в ida.cfg: // #ifdef __80196__ // DUMMY_NAMES_TYPE = NM_SHORT // #endif segment_t *sptr = get_first_seg(); if( sptr != NULL ) set_segm_class( sptr, "CODE" ); ea_t ea, ea1; for( int i = 0; i < qnumber(entries); i++ ) { ea = toEA( inf.baseaddr, entries[i].off ); if( isEnabled(ea) ) { switch( entries[i].type ) { case I196F_BTS: doByte( ea, entries[i+1].off-entries[i].off ); set_cmt( ea, entries[i].cmt, 0 ); break; case I196F_CMT: if( entries[i].cmt ) add_long_cmt( ea, 1, "%s", entries[i].cmt ); else describe( ea, 1, "" ); break; case I196F_OFF: doWord( ea, 2 ); set_offset( ea, 0, toEA( inf.baseaddr, 0 ) ); ea1 = toEA( inf.baseaddr, get_word( ea ) ); auto_make_proc( ea1 ); //dash: long_cmt здесь не смотрится, так как рисуется до заголовка // хорошо бы поставить func_cmt, но к этому моменту функций еще нет // как быть? //ig: воспользоваться простым комментарием // при создании функции комментарий перетащится set_cmt( ea1, entries[i].cmt, 1 ); } set_name( ea, entries[i].name ); } } ea = toEA( inf.baseaddr, 0x2080 ); if( isEnabled( ea ) ) { inf.beginEA = ea; inf.startIP = 0x2080; } segment_t s; s.startEA = toEA( inf.baseaddr, 0 ); s.endEA = toEA( inf.baseaddr, 0x400 ); s.sel = inf.baseaddr; s.type = SEG_IMEM; // internal memory // ig: лучше искать дырку не от нуля, а от базы загрузки // ea_t bottom = toEA( inf.baseaddr, 0 ); // intmem = s.startEA = freechunk( bottom, 1024, 0xF ); // s.endEA = s.startEA + 1024; // s.sel = ushort(s.startEA >> 4); // dash: дырку искать не пришлось, но я оставил это как пример на будущее add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE); predefined_t *ptr; for( ptr = iregs; ptr->name != NULL; ptr++ ) { ea_t ea = toEA( inf.baseaddr, ptr->addr ); ea_t oldea = get_name_ea( BADADDR, ptr->name ); if( oldea != ea ) { if( oldea != BADADDR ) set_name( oldea, NULL ); do_unknown( ea, DOUNK_EXPAND ); set_name( ea, ptr->name ); } if( ptr->cmt != NULL ) set_cmt( ea, ptr->cmt, 1 ); } } // do16bit( 0x18, 2 ); // SP always word break; case processor_t::oldfile: for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( getSRarea(s->startEA) == NULL ) { segreg_t sr; sr.startEA = s->startEA; sr.endEA = s->endEA; sr.reg(WSR) = 0; sr.reg(WSR1) = 0; sr.reg(rVds) = inf.baseaddr; sr.settags(SR_autostart); SRareas.create_area(&sr); } } break; case processor_t::newseg: // default DS is equal to Base Address (va_arg(va, segment_t *))->defsr[rVds-ph.regFirstSreg] = inf.baseaddr; break; case processor_t::newprc: extended = va_arg(va,int) != 0; if ( !extended ) ph.flag &= ~PR_SEGS; else ph.flag |= PR_SEGS; default: break; } va_end(va); return(1); }
//---------------------------------------------------------------------- static void attach_bit_comment(ea_t addr, int bit) { const ioport_bit_t *predef = find_bit(addr, bit); if ( predef != NULL && get_cmt(cmd.ea, false, NULL, 0) <= 0 ) set_cmt(cmd.ea, predef->cmt, false); }
static bool entry_processing(ea_t ea, const char *name, const char *cmt) { set_name(ea, name); set_cmt(ea, cmt, 0); return true; }
//------------------------------------------------------------------ static const char *idaapi standard_callback(const ioport_t *, size_t, const char *line) { char word[MAXSTR]; ea_t ea1; int len; if ( sscanf(line, "interrupt %s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) { if ( (respect_info & IORESP_INT) != 0 ) { ea_t proc, wrong; segment_t *s = getseg(ea1); if ( s != NULL && s->use32() ) { doDwrd(ea1, 4); proc = get_long(ea1); wrong = 0xFFFFFFFF; } else { doWord(ea1, 2); proc = get_word(ea1); wrong = 0xFFFF; } if ( proc != wrong && isEnabled(proc) ) { set_offset(ea1, 0, 0); add_entry(proc, proc, word, true); } else { set_name(ea1, word); } const char *ptr = &line[len]; ptr = skipSpaces(ptr); if ( ptr[0] != '\0' ) set_cmt(ea1, ptr, true); } return NULL; } if ( sscanf(line, "entry %s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) { if ( (respect_info & IORESP_INT) != 0 ) { if ( isEnabled(ea1) ) { const char *ptr = &line[len]; ptr = skipSpaces(ptr); #ifdef ENTRY_PROCESSING if ( !ENTRY_PROCESSING(ea1, word, ptr) ) #endif { add_entry(ea1, ea1, word, true); if ( ptr[0] != '\0' ) set_cmt(ea1, ptr, true); } } } return NULL; } return parse_area_line(line, deviceparams, sizeof(deviceparams)); }