winedbg: Add display for floating point status.
Added code to examine and display floating point unit status into be_i386.c as info all-regs command.
This commit is contained in:
parent
ef4440ad1b
commit
0994126701
|
@ -34,7 +34,7 @@ static void be_alpha_single_step(CONTEXT* ctx, unsigned enable)
|
|||
dbg_printf("not done\n");
|
||||
}
|
||||
|
||||
static void be_alpha_print_context(HANDLE hThread, const CONTEXT* ctx)
|
||||
static void be_alpha_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
|
||||
{
|
||||
dbg_printf("Context printing for Alpha not done yet\n");
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ struct backend_cpu
|
|||
/* Enables/disables CPU single step mode (depending on enable) */
|
||||
void (*single_step)(CONTEXT* ctx, unsigned enable);
|
||||
/* Dumps out the content of the context */
|
||||
void (*print_context)(HANDLE hThread, const CONTEXT* ctx);
|
||||
void (*print_context)(HANDLE hThread, const CONTEXT* ctx, int all_regs);
|
||||
/* Prints information about segments. Non segmented CPU should leave this
|
||||
* function empty
|
||||
*/
|
||||
|
|
|
@ -116,7 +116,74 @@ static void be_i386_single_step(CONTEXT* ctx, unsigned enable)
|
|||
else ctx->EFlags &= ~STEP_FLAG;
|
||||
}
|
||||
|
||||
static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx)
|
||||
static void be_i386_all_print_context(HANDLE hThread, const CONTEXT* ctx)
|
||||
{
|
||||
long double ST[8]; /* These are for floating regs */
|
||||
int cnt;
|
||||
|
||||
/* Break out the FPU state and the floating point registers */
|
||||
dbg_printf("Floating Point Unit status:\n");
|
||||
dbg_printf(" FLCW:%04x ", LOWORD(ctx->FloatSave.ControlWord));
|
||||
dbg_printf(" FLTW:%04x ", LOWORD(ctx->FloatSave.TagWord));
|
||||
dbg_printf(" FLEO:%08x ", (unsigned int) ctx->FloatSave.ErrorOffset);
|
||||
dbg_printf(" FLSW:%04x", LOWORD(ctx->FloatSave.StatusWord));
|
||||
|
||||
/* Isolate the condition code bits - note they are not contiguous */
|
||||
dbg_printf("(CC:%ld%ld%ld%ld", (ctx->FloatSave.StatusWord & 0x00004000) >> 14,
|
||||
(ctx->FloatSave.StatusWord & 0x00000400) >> 10,
|
||||
(ctx->FloatSave.StatusWord & 0x00000200) >> 9,
|
||||
(ctx->FloatSave.StatusWord & 0x00000100) >> 8);
|
||||
|
||||
/* Now pull out hte 3 bit of the TOP stack pointer */
|
||||
dbg_printf(" TOP:%01x", (unsigned int) (ctx->FloatSave.StatusWord & 0x00003800) >> 11);
|
||||
|
||||
/* Lets analyse the error bits and indicate the status
|
||||
* the Invalid Op flag has sub status which is tested as follows */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000001) { /* Invalid Fl OP */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000040) { /* Stack Fault */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000200) /* C1 says Overflow */
|
||||
dbg_printf(" #IE(Stack Overflow)");
|
||||
else
|
||||
dbg_printf(" #IE(Stack Underflow)"); /* Underflow */
|
||||
}
|
||||
else dbg_printf(" #IE(Arthimetic error)"); /* Invalid Fl OP */
|
||||
}
|
||||
|
||||
if (ctx->FloatSave.StatusWord & 0x00000002) dbg_printf(" #DE"); /* Denormalised OP */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000004) dbg_printf(" #ZE"); /* Zero Divide */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000008) dbg_printf(" #OE"); /* Overflow */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000010) dbg_printf(" #UE"); /* Underflow */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000020) dbg_printf(" #PE"); /* Precision error */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000040)
|
||||
if (!(ctx->FloatSave.StatusWord & 0x00000001))
|
||||
dbg_printf(" #SE"); /* Stack Fault (don't think this can occur) */
|
||||
if (ctx->FloatSave.StatusWord & 0x00000080) dbg_printf(" #ES"); /* Error Summary */
|
||||
if (ctx->FloatSave.StatusWord & 0x00008000) dbg_printf(" #FB"); /* FPU Busy */
|
||||
dbg_printf(")\n");
|
||||
|
||||
/* Here are the rest of the registers */
|
||||
dbg_printf(" FLES:%08x ", (unsigned int) ctx->FloatSave.ErrorSelector);
|
||||
dbg_printf(" FLDO:%08x ", (unsigned int) ctx->FloatSave.DataOffset);
|
||||
dbg_printf(" FLDS:%08x ", (unsigned int) ctx->FloatSave.DataSelector);
|
||||
dbg_printf(" FLCNS:%08x \n", (unsigned int) ctx->FloatSave.Cr0NpxState);
|
||||
|
||||
/* Now for the floating point registers */
|
||||
dbg_printf("Floating Point Registers:\n");
|
||||
for (cnt = 0; cnt < 4; cnt++)
|
||||
{
|
||||
memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
|
||||
dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
|
||||
}
|
||||
dbg_printf("\n");
|
||||
for (cnt = 4; cnt < 8; cnt++)
|
||||
{
|
||||
memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
|
||||
dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
|
||||
}
|
||||
dbg_printf("\n");
|
||||
}
|
||||
|
||||
static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
|
||||
{
|
||||
char buf[33];
|
||||
char* pt;
|
||||
|
@ -173,6 +240,9 @@ static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx)
|
|||
ctx->Esi, ctx->Edi);
|
||||
break;
|
||||
}
|
||||
|
||||
if (all_regs) be_i386_all_print_context(hThread, ctx); /* print floating regs */
|
||||
|
||||
}
|
||||
|
||||
static void be_i386_print_segment_info(HANDLE hThread, const CONTEXT* ctx)
|
||||
|
|
|
@ -47,7 +47,7 @@ static void be_ppc_single_step(CONTEXT* ctx, unsigned enable)
|
|||
else ctx->Msr &= ~MSR_SE;
|
||||
}
|
||||
|
||||
static void be_ppc_print_context(HANDLE hThread, const CONTEXT* ctx)
|
||||
static void be_ppc_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
|
||||
{
|
||||
dbg_printf("Context printing for PPC not done yet\n");
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ int yyerror(const char*);
|
|||
%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tALL tINFO tUP tDOWN
|
||||
%token tENABLE tDISABLE tBREAK tHBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM
|
||||
%token tABORT tVM86 tECHO
|
||||
%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tWND tQUEUE tLOCAL tEXCEPTION
|
||||
%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tQUEUE tLOCAL tEXCEPTION
|
||||
%token tPROCESS tTHREAD tMODREF tEOL tEOF
|
||||
%token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
|
||||
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
|
||||
|
@ -256,7 +256,8 @@ info_command:
|
|||
tINFO tBREAK { break_info(); }
|
||||
| tINFO tSHARE { info_win32_module(0); }
|
||||
| tINFO tSHARE expr_rvalue { info_win32_module($3); }
|
||||
| tINFO tREGS { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context); }
|
||||
| tINFO tREGS { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); }
|
||||
| tINFO tALLREGS { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 1); }
|
||||
| tINFO tSEGMENTS expr_rvalue { info_win32_segments($3 >> 3, 1); }
|
||||
| tINFO tSEGMENTS { info_win32_segments(0, -1); }
|
||||
| tINFO tSTACK { stack_info(); }
|
||||
|
|
|
@ -189,6 +189,8 @@ STRING \"[^\n"]+\"
|
|||
<INFO_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
|
||||
<INFO_CMD>exception|except|exc|ex { return tEXCEPTION; }
|
||||
<INFO_CMD>registers|regs|reg|re { return tREGS; }
|
||||
<INFO_CMD>allregs|allreg|allre { return tALLREGS; }
|
||||
<INFO_CMD>"all-registers"|"all-regs"|"all-reg"|"all-re" { return tALLREGS; }
|
||||
<INFO_CMD>segments|segment|segm|seg|se { return tSEGMENTS; }
|
||||
<INFO_CMD>stack|stac|sta|st { return tSTACK; }
|
||||
<INFO_CMD>symbol|symbo|symb|sym { BEGIN(ASTRING_EXPECTED); return tSYMBOL; }
|
||||
|
|
|
@ -101,7 +101,8 @@ void info_help(void)
|
|||
" info locals Displays values of all local vars for current frame",
|
||||
" info maps <pid> Shows virtual mappings (in a given process)",
|
||||
" info process Shows all running processes",
|
||||
" info reg Displays values in all registers at top of stack",
|
||||
" info reg Displays values of the general registers at top of stack",
|
||||
" info all-reg Displays the general and floating point registers",
|
||||
" info segments <pid> Displays information about all known segments",
|
||||
" info share Displays all loaded modules",
|
||||
" info share <addr> Displays internal module state",
|
||||
|
|
|
@ -171,7 +171,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
|
|||
if (!is_debug)
|
||||
{
|
||||
/* This is a real crash, dump some info */
|
||||
be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
|
||||
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);
|
||||
|
|
|
@ -348,7 +348,7 @@ static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data)
|
|||
min(sizeof(dbg_context), mes->ThreadContext.DataSize));
|
||||
memory_get_current_pc(&addr);
|
||||
stack_fetch_frames();
|
||||
be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
|
||||
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(mes->ThreadId);
|
||||
|
|
|
@ -348,6 +348,8 @@ Lists all the dynamic libraries loaded in the debugged program
|
|||
Prints information on module at address \fBN\fR
|
||||
.IP \fBinfo\ regs\fR
|
||||
Prints the value of the CPU registers
|
||||
.IP \fBinfo\ all-regs\fR
|
||||
Prints the value of the CPU and Floating Point registers
|
||||
.IP \fBinfo\ segment\fR
|
||||
Lists all allocated segments (i386 only)
|
||||
.IP \fBinfo\ segment\ N\fR
|
||||
|
|
Loading…
Reference in New Issue