static int GetTypeOf(ea_t ea) { flags_t flags = getFlags(ea); if (isTail(flags)) { // check if it's a struct ptr ea_t head = get_item_head(ea); if (head == ea) return T_UNK; flags = getFlags(head); if (!isData(flags) || !isStruct(flags)) return T_UNK; return GetTypeOfStructInstance(ea, head, flags); } if (!isData(flags)) return T_UNK; if (isStruct(flags)) return GetTypeOfStructInstance(ea, ea, flags); if (isByte(flags)) { char s; if (has_cmt(flags) && (get_cmt(ea, false, &s, 1) != -1) && s == 'S') return T_I8; return T_U8; } if (isWord(flags)) { char s; if (has_cmt(flags) && (get_cmt(ea, false, &s, 1) != -1) && s == 'S') return T_I16; return T_U16; } if (isDwrd(flags)) return T_I32; return T_UNK; }
// Output a register static void out_reg(ushort reg) { out_register(ph.regNames[reg]); const char *cmt = get_general_register_description(reg); if ( cmt != NULL && !has_cmt(uFlag) ) { gr_cmt = cmt; } }
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); } }
// 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()"); } }
void idaapi run(int arg) { char buf[MAXSTR]; char cmt[MAXSTR]; char *valid_cmt = NULL; char ext[0x20]; FILE *f = NULL; short checkboxes = OPTION_NAMES | OPTION_COMMENTS; sval_t bank = 1; // default bool first = true; bool hasName = false; flags_t flags; ea_t ea = 0x0; if( AskUsingForm_c( madnes_options, &checkboxes, &bank ) != 1 || checkboxes == 0 ) return; // prepare filename for namelist (.nl) file get_input_file_path( buf, sizeof( buf ) ); qsnprintf( ext, sizeof( ext ),".%X.nl",--bank ); qstrncat( buf, ext, sizeof( buf )-strlen( buf ) ); // (always) create file f = qfopen( buf, "w" ); if( f == NULL ) { warning( "%s could not be created!", buf ); return; } msg( "Writing to file %s..", buf ); while( ea <= 0xFFFF ) { hasName = false; // get flags if( isCode( getFlags( ea ) ) ) flags = getFlags( ea ); else flags = getFlags( get_item_head( ea ) ); // if user either chose to export names or anynames if( ( ( checkboxes & OPTION_NAMES ) && has_name( flags ) ) || ( ( checkboxes & OPTION_ANYNAME ) && has_any_name( flags ) ) ) { // if current item is code or if current item is head of item if( isCode( flags ) || ea==get_item_head( ea ) ) { // get name get_name( ea, ea, buf, sizeof( buf ) ); // write to file qfprintf( f, "$%04X#%s#", ea, buf ); } else // if not code or not head of item (must be an array) { // get name of item start get_name( get_item_head( ea ), get_item_head( ea ), buf, sizeof( buf ) ); // calc displacement, write to file (example: "password+$04") qfprintf( f, "$%04X#%s+$%X#", ea, buf, ea-get_item_head( ea ) ); } hasName = true; } // if user chose to export cross references if( checkboxes & OPTION_XREFS ) { xrefblk_t xb; first = true; // cycle through all xrefs except ordinary flow xrefs for ( bool ok=xb.first_to( ea, XREF_FAR/*XREF_ALL*/); ok; ok=xb.next_to() ) { if( first ) // if first xref { if( !hasName ) // if this location hasn't a name yet, add symbol stub { qfprintf( f, "$%04X##", ea ); hasName = true; } qfprintf( f, "XREFS:\n\\"); // append XREFS first = false; } qfprintf( f, " $%04X\n\\", xb.from ); } } // if user chose to export comments if( checkboxes & OPTION_COMMENTS ) { if( has_cmt( flags ) ) // if current item has comment { // get comment // workaround for get_any_indeted_cmt() // -> unresolved external symbol "char * __stdcall get_any_indented_cmt(unsigned long,unsigned char *)" (?get_any_indented_cmt@@YGPADKPAE@Z) if( get_cmt( ea, false, cmt, sizeof( cmt ) ) == -1 ) get_cmt( ea, true, cmt, sizeof( cmt ) ); // validate comment (replace invalid chars, add room for additional chars) valid_cmt = validate_comment( cmt ); if( valid_cmt != NULL ) { if( !hasName ) { qfprintf( f, "$%04X##", ea ); // add symbol stub if no name yet hasName = true; } qfprintf( f, "%s", valid_cmt ); // write comment to file qfree( valid_cmt ); } } } if( hasName) qfprintf( f, "\n" ); ea++; // get name of each byte } qfclose( f ); msg( "done.\n" ); }
// 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; } }