From 0994126701b8f1612db054dc9c74559c049b14ba Mon Sep 17 00:00:00 2001 From: Jeff Latimer Date: Tue, 21 Mar 2006 23:54:41 +1100 Subject: [PATCH] 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. --- programs/winedbg/be_alpha.c | 2 +- programs/winedbg/be_cpu.h | 2 +- programs/winedbg/be_i386.c | 72 ++++++++++++++++++++++++++++++++++++++++- programs/winedbg/be_ppc.c | 2 +- programs/winedbg/dbg.y | 5 +-- programs/winedbg/debug.l | 2 ++ programs/winedbg/info.c | 3 +- programs/winedbg/tgt_active.c | 2 +- programs/winedbg/tgt_minidump.c | 2 +- programs/winedbg/winedbg.man.in | 2 ++ 10 files changed, 85 insertions(+), 9 deletions(-) diff --git a/programs/winedbg/be_alpha.c b/programs/winedbg/be_alpha.c index 221fd46ea29..748e070dc08 100644 --- a/programs/winedbg/be_alpha.c +++ b/programs/winedbg/be_alpha.c @@ -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"); } diff --git a/programs/winedbg/be_cpu.h b/programs/winedbg/be_cpu.h index 988a147d5b1..59333bed9ea 100644 --- a/programs/winedbg/be_cpu.h +++ b/programs/winedbg/be_cpu.h @@ -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 */ diff --git a/programs/winedbg/be_i386.c b/programs/winedbg/be_i386.c index 3f0fb6acad0..0b838f160e4 100644 --- a/programs/winedbg/be_i386.c +++ b/programs/winedbg/be_i386.c @@ -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) diff --git a/programs/winedbg/be_ppc.c b/programs/winedbg/be_ppc.c index 2ea716405ba..ea1653de2f4 100644 --- a/programs/winedbg/be_ppc.c +++ b/programs/winedbg/be_ppc.c @@ -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"); } diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 66145ee1346..ecbb3fa9f7b 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -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(); } diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l index 71d10f07fa2..dd18a894261 100644 --- a/programs/winedbg/debug.l +++ b/programs/winedbg/debug.l @@ -189,6 +189,8 @@ STRING \"[^\n"]+\" threads|thread|threa|thre|thr|th { return tTHREAD; } exception|except|exc|ex { return tEXCEPTION; } registers|regs|reg|re { return tREGS; } +allregs|allreg|allre { return tALLREGS; } +"all-registers"|"all-regs"|"all-reg"|"all-re" { return tALLREGS; } segments|segment|segm|seg|se { return tSEGMENTS; } stack|stac|sta|st { return tSTACK; } symbol|symbo|symb|sym { BEGIN(ASTRING_EXPECTED); return tSYMBOL; } diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index c58b3e7721c..7799af8fc14 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -101,7 +101,8 @@ void info_help(void) " info locals Displays values of all local vars for current frame", " info maps 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 Displays information about all known segments", " info share Displays all loaded modules", " info share Displays internal module state", diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index 7c83d853c7a..cdd50ad36f5 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -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); diff --git a/programs/winedbg/tgt_minidump.c b/programs/winedbg/tgt_minidump.c index 750efe439d4..d067470d374 100644 --- a/programs/winedbg/tgt_minidump.c +++ b/programs/winedbg/tgt_minidump.c @@ -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); diff --git a/programs/winedbg/winedbg.man.in b/programs/winedbg/winedbg.man.in index a064b5c3859..c9922c75f7c 100644 --- a/programs/winedbg/winedbg.man.in +++ b/programs/winedbg/winedbg.man.in @@ -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 -- 2.11.4.GIT