//-------------------------------------------------------------------------- bool win32_debmod_t::create_process(const char *path, const char *args, const char * /*startdir*/, bool is_gui, PROCESS_INFORMATION *ProcessInformation) { wchar_t wpath[MAXSTR]; wchar_t wargs_buffer[MAXSTR]; wchar_t *wargs = NULL; if ( args != NULL ) { cwstr(wargs_buffer, args, qnumber(wargs_buffer)); wargs = wargs_buffer; } cwstr(wpath, path, qnumber(wpath)); return CreateProcess( wpath, // pointer to name of executable module wargs, // pointer to command line string NULL, // pointer to process security attributes NULL, // pointer to thread security attributes false, // handle inheritance flag (is_gui ? 0 : CREATE_NEW_CONSOLE) // creation flags |DEBUG_ONLY_THIS_PROCESS |DEBUG_PROCESS, NULL, // pointer to new environment block NULL, // pointer to current directory name NULL, // pointer to STARTUPINFO ProcessInformation); // pointer to PROCESS_INFORMATION }
//-------------------------------------------------------------------------- // The assembler and the compiler generate lots of meaningless symbols. // We will ignore them. static bool special_name(const char *name) { int i; if ( name[0] == '\0' ) return true; if ( name[0] == '$' ) return true; const char *ptr = strchr(name,'$'); if ( ptr != NULL && ptr[1] == '$' ) return true; static const char *const ex[] = { "_etext", "_edata", "_end", "!!!" }; for ( i=0; i < qnumber(ex); i++ ) if ( strcmp(ex[i],name) == 0 ) return true; static const char *const data_names[] = { "x$constdata", "x$litpool" }; for ( i=0; i < qnumber(data_names); i++ ) if ( strncmp(name,data_names[i],strlen(data_names[i])) == 0 ) return true; return false; }
//-------------------------------------------------------------------------- void segstart(ea_t ea) { segment_t *Sarea = getseg(ea); if ( is_spec_segm(Sarea->type) ) return; char sname[MAXNAMELEN]; char sclas[MAXNAMELEN]; get_true_segm_name(Sarea, sname, sizeof(sname)); get_segm_class(Sarea, sclas, sizeof(sclas)); if ( ash.uflag & UAS_GNU ) { const char *const predefined[] = { ".text", // Text section ".data", // Data sections ".rdata", ".comm", }; int i; for ( i=0; i < qnumber(predefined); i++ ) if ( strcmp(sname, predefined[i]) == 0 ) break; if ( i != qnumber(predefined) ) printf_line(inf.indent, COLSTR("%s", SCOLOR_ASMDIR), sname); else printf_line(inf.indent, COLSTR(".section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), sname, ash.cmnt, sclas); } else { if ( strcmp(sname, "XMEM") == 0 ) { char buf[MAX_NUMBUF]; btoa(buf, sizeof(buf), ea-get_segm_base(Sarea)); printf_line(inf.indent, COLSTR("%s %c:%s", SCOLOR_ASMDIR), ash.origin, tolower(sname[0]), buf); } else { printf_line(inf.indent, COLSTR("section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), sname, ash.cmnt, sclas); } } }
// detect special instructions, whose we can't detect using the table and the // get_opcode() routine static bool ana_special(int byte) { bool special = false; const struct { uint16 insn; // instruction ID uchar val; // (20i + val) m740_addr_mode_t addr; // which addressing mode ? } specials[] = { { m740_bbc, 0x13, A_ACCBREL }, { m740_bbc, 0x17, A_ZPBREL }, { m740_bbs, 0x03, A_ACCBREL }, { m740_bbs, 0x07, A_ZPBREL }, { m740_clb, 0x1B, A_ACCB }, { m740_clb, 0x1F, A_ZPB }, { m740_seb, 0x0B, A_ACCB }, { m740_seb, 0x0F, A_ZPB } }; for (int i = 0; i < qnumber(specials); i++) { int t = (uchar) byte - specials[i].val; if ( (t % 0x20) != 0 ) continue; cmd.itype = specials[i].insn; set_op_imm(cmd.Op1, t / 0x20); cmd.Op1.specflag1 |= OP_IMM_BIT; fill_cmd(specials[i].addr, get_opcode_flags(specials[i].insn)); special = true; break; } return special; }
//---------------------------------------------------------------------- int jump_pattern_t::find_reg(int reg) { for ( int i=0; i < qnumber(r); i++ ) if ( r[i] == reg ) return i; return -1; }
static const char *tdb_event_name(int ev) { static const char *const names[] = { "READY", // 1 "SLEEP", // 2 "SWITCHTO", // 3 "SWITCHFROM", // 4 "LOCK_TRY", // 5 "CATCHSIG", // 6 "IDLE", // 7 "CREATE", // 8 "DEATH", // 9 "PREEMPT", // 10 "PRI_INHERIT", // 11 "REAP", // 12 "CONCURRENCY", // 13 "TIMEOUT", // 14 }; if ( ev > 0 && ev <= qnumber(names) ) return names[ev-1]; static char buf[16]; qsnprintf(buf, sizeof(buf), "%u", ev); return buf; }
static void display_matched(deng_t * eng) { choose2(CH_ATTRS, -1, -1, -1, -1, // position is determined by Windows eng, // pass the created function list to the window qnumber(header_match),// number of columns widths_match, // widths of columns sizer_match, // function that returns number of lines desc_match, // function that generates a line title_match, // window title -1, // use the default icon for the window 1, // position the cursor on the first line NULL, // "kill" callback NULL, // "new" callback NULL, // "update" callback graph_match, // "edit" callback enter_match, // function to call when the user pressed Enter close_window, // function to call when the window is closed popup_match, // use default popup menu items NULL); eng->wnum++; add_chooser_command(title_match, "Unmatch", res_munmatch, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); add_chooser_command(title_match, "Set as identical", res_mtoi, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); add_chooser_command(title_match, "Flag/unflag", res_flagged, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); add_chooser_command(title_match, "Import Symbol", transfer_sym_match, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); }
static void DEBUG_REGVALS(regval_t *values) { for (int i = 0; i < qnumber(registers); i++) { msg("%s = ", registers[i].name); switch ( registers[i].dtyp ) { case dt_qword: msg("%016LX\n", values[i].ival); break; case dt_dword: msg("%08X\n", values[i].ival); break; case dt_word: msg("%04X\n", values[i].ival); break; case dt_tbyte: { for (int j = 0; j < sizeof(regval_t); j++) { if ( j == 10) msg(" - " ); // higher bytes are not used by x86 floats msg("%02X ", ((unsigned char*)&values[i])[j]); } // msg("%02X ", (unsigned short)values[i].fval[j]); msg("\n"); break; } } } msg("\n"); }
static void display_unmatched(deng_t * eng) { choose2(0, -1, -1, -1, -1, // position is determined by Windows eng, // pass the created function list to the window qnumber(header_unmatch),// number of columns widths_unmatch, // widths of columns sizer_unmatch, // function that returns number of lines desc_unmatch, // function that generates a line title_unmatch, // window title -1, // use the default icon for the window 1, // position the cursor on the first line NULL, // "kill" callback NULL, // "new" callback NULL, // "update" callback graph_unmatch, // "edit" callback enter_unmatch, // function to call when the user pressed Enter close_window, // function to call when the window is closed popup_unmatch, // use default popup menu items NULL); // use the same icon for all lines eng->wnum++; add_chooser_command(title_unmatch, "Set match", res_match, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); }
void idaapi function_list::get_line(void *obj,uint32 n,char * const *arrptr) { if ( n == 0 ) // generate the column headers { for ( int i=0; i < qnumber(header); i++ ) qstrncpy(arrptr[i], header[i], MAXSTR); return; } function_list & ms = *(function_list*)obj; ea_t ea = ms.functions[n-1]; qsnprintf(arrptr[0], MAXSTR, "%08a", ea); get_func_name(ea, arrptr[1], MAXSTR); //get_short_name(BADADDR, ea, arrptr[1], MAXSTR); //get_demangled_name(BADADDR, ea, arrptr[1], MAXSTR, inf.long_demnames, DEMNAM_NAME, 0); func_t * f = get_func(ea); if(f) { const char * cmt = get_func_cmt(f, true); if(cmt) { qstrncpy(arrptr[2], cmt, MAXSTR); } } }
static const uchar get_opcode_flags(const uint16 insn) { for (int i = 0; i < qnumber(opcodes_flags); i++) { if ( opcodes_flags[i].insn != insn ) continue; return opcodes_flags[i].flags; } return 0; }
// try to find an opcode in our table from the fetched byte static const struct opcode * get_opcode(int byte) { for (int i = 0; i < qnumber(opcodes); i++) { if ( opcodes[i].code != byte ) continue; return &opcodes[i]; } return NULL; }
//-------------------------------------------------------------------------- void segstart(ea_t ea) { const char *predefined[] = { ".text", // Text section ".rdata", // Read-only data section ".data", // Data sections ".lit8", // Data sections ".lit4", // Data sections ".sdata", // Small data section, addressed through register $gp ".sbss", // Small bss section, addressed through register $gp ".bss", // bss (block started by storage) section, which loads zero-initialized data }; segment_t *Sarea = getseg(ea); if ( is_spec_segm(Sarea->type) ) return; char sname[MAXNAMELEN]; char sclas[MAXNAMELEN]; get_true_segm_name(Sarea, sname, sizeof(sname)); get_segm_class(Sarea, sclas, sizeof(sclas)); int i; for ( i=0; i < qnumber(predefined); i++ ) if ( strcmp(sname, predefined[i]) == 0 ) break; if ( i != qnumber(predefined) ) printf_line(inf.indent, COLSTR("%s", SCOLOR_ASMDIR), sname); else printf_line(inf.indent, COLSTR("%s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT), strcmp(sclas,"CODE") == 0 ? ".text" : strcmp(sclas,"BSS") == 0 ? ".bss" : ".data", ash.cmnt, sname); if ( Sarea->orgbase != 0 ) { char buf[MAX_NUMBUF]; btoa(buf, sizeof(buf), Sarea->orgbase); printf_line(inf.indent, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); } }
//-------------------------------------------------------------------------- // Unpacker might use some Win32 functions to perform their function // This function verifies whether we must switch to the trace mode // or continue to wait for GetProcAddress() of some other interesting function static bool ignore_win32_api(const char *name) { static const char *const ignore_names[] = { "VirtualAlloc", "VirtualFree" }; for ( size_t i=0; i<qnumber(ignore_names); i++ ) { if ( strcmp(name, ignore_names[i]) == 0 ) return true; } return false; }
void jump_pattern_t::mark_switch_insns(void) { // we do not mark the indirect jmp as ignored // it will be used to recognize switch idioms for ( int i=1; i < qnumber(eas); i++ ) { ea_t ea = eas[i]; if ( ea != BADADDR && !remote_code.has(ea) ) mark_switch_insn(ea); } }
//-------------------------------------------------------------------------- // get path+name from a mapped file in the debugged process bool win32_debmod_t::get_mapped_filename(HANDLE process_handle, ea_t imagebase, char *buf, size_t bufsize) { if ( _GetMappedFileName != NULL ) { TCHAR name[QMAXPATH]; name[0] = '\0'; if ( !can_access(imagebase) ) imagebase += MEMORY_PAGE_SIZE; if ( _GetMappedFileName(process_handle, (LPVOID)imagebase, name, qnumber(name)) ) { // translate path with device name to drive letters. // based on http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/obtaining_a_file_name_from_a_file_handle.asp TCHAR szTemp[MAX_PATH]; szTemp[0] = '\0'; if ( GetLogicalDriveStrings(sizeof(szTemp), szTemp) ) { char szName[MAX_PATH]; char szDrive[3] = " :"; bool bFound = FALSE; char *p = szTemp; do { // Copy the drive letter to the template string szDrive[0] = *p; // Look up each device name if ( QueryDosDevice(szDrive, szName, MAX_PATH) ) { size_t uNameLen = strlen(szName); if ( uNameLen < MAX_PATH ) { bFound = strnicmp(name, szName, uNameLen) == 0; if ( bFound ) { // Reconstruct pszFilename using szTemp // Replace device path with DOS path qstrncpy(name, szDrive, sizeof(name)); qstrncat(name, name+uNameLen, sizeof(name)); } } } // Go to the next NULL character. while ( *p++ ); } while ( !bFound && *p ); // end of string } wcstr(buf, name, bufsize); return true; } } return false; }
static bool is_true_text_symbol(dsym_t *ds,const char *name) { if ( ds->is_text() ) { static const char *const data_names[] = { "x$constdata", "x$litpool" }; for ( int i=0; i < qnumber(data_names); i++ ) if ( strncmp(name,data_names[i],strlen(data_names[i])) == 0 ) return false; return true; } return false; }
//--------------------------------------------------------------------------- static const char *pdberr(int code) { switch ( code ) { // tab in first pos is flag for replace warning to msg case E_INVALIDARG: return "Invalid parameter."; case E_UNEXPECTED: return "Data source has already been prepared."; default: if ( code >= E_PDB_OK && (code - E_PDB_OK) < qnumber(g_pdb_errors) ) return g_pdb_errors[code - E_PDB_OK]; } return winerr(code); }
//-------------------------------------------------------------------------- arm_debmod_t::arm_debmod_t() { static const uchar bpt[] = ARM_BPT_CODE; bpt_code.append(bpt, sizeof(bpt)); sp_idx = R_SP; pc_idx = R_PC; nregs = qnumber(arm_registers); is_xscale = false; databpts[0] = databpts[1] = BADADDR; codebpts[0] = codebpts[1] = BADADDR; dbcon = 0; }
//----------------------------------------------------------------------------- // set the current processor type according to "cpu_type". static bool mas_set_cpu(uchar cpu_type) { for (int i = 0; i < qnumber(families); i++) { if (families[i].code != cpu_type) continue; set_processor_type(families[i].processor, SETPROC_ALL|SETPROC_FATAL); #if defined(DEBUG) msg("MAS: detected processor %s\n", families[i].processor); #endif return true; } return false; }
static void idaapi getl_mapping(areacb_t *,uint32 n,char * const *arrptr) { if ( n == 0 ) { for ( int i=0; i < qnumber(maphdr); i++ ) qstrncpy(arrptr[i], maphdr[i], MAXSTR); return; } mapping_t *m = (mapping_t *)mapping.getn_area(n-1); qsnprintf(arrptr[0], MAXSTR, "%08a", m->startEA); qsnprintf(arrptr[1], MAXSTR, "%08a", m->endEA); qsnprintf(arrptr[2], MAXSTR, "%08a", m->target); }
//------------------------------------------------------------------------- // function that generates the list line static void idaapi desc(void *obj,uint32 n,char * const *arrptr) { if ( n == 0 ) // generate the column headers { for ( int i=0; i < qnumber(header); i++ ) qstrncpy(arrptr[i], header[i], MAXSTR); return; } netnode *node = (netnode *)obj; ea_t ea = node->altval(n-1); generate_disasm_line(ea, arrptr[1], MAXSTR, 0); tag_remove(arrptr[1], arrptr[1], MAXSTR); // remove the color coding qsnprintf(arrptr[0], MAXSTR, "%08a", ea); }
static void idaapi remove_mapping(TView *fields[], int) { mapping_t *m = (mapping_t *)mapping.choose_area2(true, qnumber(widths), widths, getl_mapping, "Please select mapping to remove", -1); if ( m != NULL ) { mapping.del_area(m->startEA); noUsed(inf.minEA, inf.maxEA); close_form(fields, true); } }
//-------------------------------------------------------------------------- // The only reason why we load and use kernel stub is to ignore // hardware breakpoints in foreign applications. If the user puts // a breakpoint in a shared DLL, we don't want other applications // to be aware of it - exceptions in these applications should be ignored. static bool load_kdstub(void) { bool ok = false; if ( g_global_server == NULL ) return false; __try { static const char stubname[] = "\\Windows\\ida_kdstub.dll"; // 01234567 8 ok = g_global_server->rpc_sync_stub(stubname, &stubname[9]); if ( !ok ) { g_global_server->dwarning("Failed to synchronize kernel debugger stub"); } else { wchar_t wname[80]; cwstr(wname, stubname, qnumber(wname)); ok = AttachDebugger(wname); if ( !ok ) { //Likely error codes: //ERROR_FILE_NOT_FOUND (2) - if LoadKernelLibrary failed // This may happen if the DLL is not found or cannot be // loaded. The DLL will fail to load if it is for a // wrong platform or if it is linked to any other DLL. //ERROR_INVALID_PARAMETER (87) -if ConnectDebugger failed // This may happen if IOCTL_DBG_INIT was not called // by the DLL initialization routing or if some module // in the system is marked as non-debuggable int code = GetLastError(); g_global_server->dwarning("Failed to attach kernel debugger stub: %s", winerr(code)); } else { g_global_server->dmsg("Successfully attached kernel debugger stub\n"); // win420_module_t wm; // if ( find_module_by_name("ida_kdstub", (wince_module_t*)&wm) ) // msg("%x: kernel stub\n", int(wm.BasePtr)+0x1000); } } } __except( EXCEPTION_EXECUTE_HANDLER ) { } return ok; }
//-------------------------------------------------------------------------- static const char *get_thread_type_name(td_thr_type_e type) { static const char *const names[] = { "ANY_STATE", // 0 "USER", // 1 "SYSTEM", // 2 }; if ( type >= 0 && type < qnumber(names) ) return names[type]; static char buf[16]; qsnprintf(buf, sizeof(buf), "%u", type); return buf; }
sk3wldbg_aarch64::sk3wldbg_aarch64() : sk3wldbg("ARM", UC_ARCH_ARM64, UC_MODE_ARM) { //reset any overridden function pointers and setup register name fields if (debug_mode & UC_MODE_BIG_ENDIAN) { processor = "ARMB"; } register_classes = arm_register_classes; register_classes_default = 1; ///< Mask of default printed register classes _registers = aarch64_regs; ///< Array of registers. Use registers() to access it registers_size = qnumber(aarch64_regs); ///< Number of registers reg_map = arm64_reg_map; bpt_bytes = NULL; ///< Array of bytes for a breakpoint instruction bpt_size = 0; ///< Size of this array }
sk3wldbg_mips::sk3wldbg_mips() : sk3wldbg("mipsl", UC_ARCH_MIPS, UC_MODE_32) { //reset any overridden function pointers and setup register name fields if (debug_mode & UC_MODE_BIG_ENDIAN) { processor = "mipsb"; } register_classes = mips_register_classes; register_classes_default = MIPS_GENERAL; ///< Mask of default printed register classes _registers = mips_regs; ///< Array of registers. Use registers() to access it registers_size = qnumber(mips_regs); ///< Number of registers reg_map = mips_reg_map; bpt_bytes = NULL; ///< Array of bytes for a breakpoint instruction bpt_size = 0; ///< Size of this array }
//---------------------------------------------------------------------- bool jump_pattern_t::match(ea_t ea) { // unfortunately we can not do this in the constructor check[0x00] = &jump_pattern_t::jpi0; check[0x01] = &jump_pattern_t::jpi1; check[0x02] = &jump_pattern_t::jpi2; check[0x03] = &jump_pattern_t::jpi3; check[0x04] = &jump_pattern_t::jpi4; check[0x05] = &jump_pattern_t::jpi5; check[0x06] = &jump_pattern_t::jpi6; check[0x07] = &jump_pattern_t::jpi7; check[0x08] = &jump_pattern_t::jpi8; check[0x09] = &jump_pattern_t::jpi9; check[0x0a] = &jump_pattern_t::jpia; check[0x0b] = &jump_pattern_t::jpib; check[0x0c] = &jump_pattern_t::jpic; check[0x0d] = &jump_pattern_t::jpid; check[0x0e] = &jump_pattern_t::jpie; check[0x0f] = &jump_pattern_t::jpif; memset(skip, 0, sizeof(skip)); memset(eas, -1, sizeof(eas)); memset(r, -1, sizeof(r)); eas[0] = ea; failed = false; func_t *pfn = get_fchunk(ea); if ( pfn == NULL ) pfn = get_prev_fchunk(ea); minea = pfn != NULL ? pfn->startEA : getseg(ea)->startEA; if ( !(this->*check[0])() ) return false; while ( *roots ) { memset(spoiled, 0, sizeof(spoiled)); if ( !follow_tree(eas[0], *roots++) || failed ) return false; } ea_t start = eas[0]; for ( int i=1; i < qnumber(eas); i++ ) start = qmin(start, eas[i]); si.startea = start; return !failed; }
//------------------------------------------------------------------------- // function that generates the list line static void idaapi desc(void *obj,uint32 n,char * const *arrptr) { if ( n == 0 ) // generate the column headers { for ( int i=0; i < qnumber(header); i++ ) qstrncpy(arrptr[i], header[i], MAXSTR); return; } n--; entrylist_t &li = *(entrylist_t *)obj; qsnprintf(arrptr[0], MAXSTR, "%d", li[n].ord); qsnprintf(arrptr[1], MAXSTR, "%08a", li[n].ea); if ( li[n].argsize != 0 ) qsnprintf(arrptr[2], MAXSTR, "%04x", li[n].argsize); qsnprintf(arrptr[3], MAXSTR, "%s", li[n].decl.c_str()); }
//-------------------------------------------------------------------------- int pc_debmod_t::get_regidx(const char *regname, int *clsmask) { static const char *const regnames[] = { #ifdef __EA64__ "RAX", "RBX", "RCX", "RDX", "RSI", "RDI", "RBP", "RSP", "RIP", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", #else "EAX", "EBX", "ECX", "EDX", "ESI", "EDI", "EBP", "ESP", "EIP", #endif }; for ( int i=0; i < qnumber(regnames); i++ ) { if ( stricmp(regname, regnames[i]) == 0 ) { if ( clsmask != NULL ) *clsmask = X86_RC_GENERAL; return R_EAX + i; } } return -1; }