void memory_disassemble(const struct dbg_lvalue* xstart, const struct dbg_lvalue* xend, int instruction_count) { static ADDRESS64 last = {0,0,0}; int stop = 0; int i; if (!xstart && !xend) { if (!last.Segment && !last.Offset) memory_get_current_pc(&last); } else { if (xstart) types_extract_as_address(xstart, &last); if (xend) stop = types_extract_as_integer(xend); } for (i = 0; (instruction_count == 0 || i < instruction_count) && (stop == 0 || last.Offset <= stop); i++) memory_disasm_one_insn(&last); }
/*********************************************************************** * dbg_exception_prolog * * Examine exception and decide if interactive mode is entered(return TRUE) * or exception is silently continued(return FALSE) * is_debug means the exception is a breakpoint or single step exception */ static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec) { ADDRESS64 addr; BOOL is_break; char hexbuf[MAX_OFFSET_TO_STR_LEN]; memory_get_current_pc(&addr); break_suspend_execution(); dbg_curr_thread->excpt_record = *rec; dbg_curr_thread->in_exception = TRUE; if (!is_debug) { switch (addr.Mode) { case AddrModeFlat: dbg_printf(" in 32-bit code (%s)", memory_offset_to_string(hexbuf, addr.Offset, 0)); break; case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset); break; default: dbg_printf(" bad address"); } dbg_printf(".\n"); } /* this will resynchronize builtin dbghelp's internal ELF module list */ SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0); if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break); /* * Do a quiet backtrace so that we have an idea of what the situation * is WRT the source files. */ stack_fetch_frames(); if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode)) return FALSE; if (addr.Mode != dbg_curr_thread->addr_mode) { const char* name = NULL; switch (addr.Mode) { case AddrMode1616: name = "16 bit"; break; case AddrMode1632: name = "32 bit"; break; case AddrModeReal: name = "vm86"; break; case AddrModeFlat: name = "32 bit"; break; } dbg_printf("In %s mode.\n", name); dbg_curr_thread->addr_mode = addr.Mode; } display_print(); if (!is_debug) { /* This is a real crash, dump some info */ be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); stack_backtrace(dbg_curr_tid); } else { static char* last_name; static char* last_file; char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; void* lin = memory_to_linear_addr(&addr); DWORD64 disp64; IMAGEHLP_LINE il; DWORD disp; si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; il.SizeOfStruct = sizeof(il); if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) && SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il)) { if ((!last_name || strcmp(last_name, si->Name)) || (!last_file || strcmp(last_file, il.FileName))) { HeapFree(GetProcessHeap(), 0, last_name); HeapFree(GetProcessHeap(), 0, last_file); last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name); last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName); dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber); } } } if (!is_debug || is_break || dbg_curr_thread->exec_mode == dbg_exec_step_over_insn || dbg_curr_thread->exec_mode == dbg_exec_step_into_insn) { ADDRESS64 tmp = addr; /* Show where we crashed */ memory_disasm_one_insn(&tmp); } source_list_from_addr(&addr, 0); return TRUE; }
/*********************************************************************** * memory_examine * * Implementation of the 'x' command. */ void memory_examine(const struct dbg_lvalue *lvalue, int count, char format) { int i; char buffer[256]; ADDRESS64 addr; void *linear; types_extract_as_address(lvalue, &addr); linear = memory_to_linear_addr(&addr); if (format != 'i' && count > 1) { print_address(&addr, FALSE); dbg_printf(": "); } switch (format) { case 'u': if (count == 1) count = 256; memory_get_string(dbg_curr_process, linear, TRUE, TRUE, buffer, min(count, sizeof(buffer))); dbg_printf("%s\n", buffer); return; case 's': if (count == 1) count = 256; memory_get_string(dbg_curr_process, linear, TRUE, FALSE, buffer, min(count, sizeof(buffer))); dbg_printf("%s\n", buffer); return; case 'i': while (count-- && memory_disasm_one_insn(&addr)); return; case 'g': while (count--) { GUID guid; if (!dbg_read_memory(linear, &guid, sizeof(guid))) { memory_report_invalid_addr(linear); break; } dbg_printf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); linear = (char*)linear + sizeof(guid); addr.Offset += sizeof(guid); if (count) { print_address(&addr, FALSE); dbg_printf(": "); } } return; #define DO_DUMP2(_t,_l,_f,_vv) { \ _t _v; \ for (i = 0; i < count; i++) { \ if (!dbg_read_memory(linear, &_v, sizeof(_t))) \ { memory_report_invalid_addr(linear); break; } \ dbg_printf(_f, (_vv)); \ addr.Offset += sizeof(_t); \ linear = (char*)linear + sizeof(_t); \ if ((i % (_l)) == (_l) - 1 && i != count - 1) \ { \ dbg_printf("\n"); \ print_address(&addr, FALSE); \ dbg_printf(": "); \ } \ } \ dbg_printf("\n"); \ } \ return #define DO_DUMP(_t,_l,_f) DO_DUMP2(_t,_l,_f,_v) case 'x': DO_DUMP(int, 4, " %8.8x"); case 'd': DO_DUMP(unsigned int, 4, " %10d"); case 'w': DO_DUMP(unsigned short, 8, " %04x"); case 'c': DO_DUMP2(char, 32, " %c", (_v < 0x20) ? ' ' : _v); case 'b': DO_DUMP2(char, 16, " %02x", (_v) & 0xff); } }