diff --git a/debugger/dbg.y b/debugger/dbg.y index e4626970204..49e363a74fe 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -86,7 +86,7 @@ int yyerror(char *); %nonassoc ':' %type expr lval lvalue -%type type_cast type_expr +%type type_expr %type expr_addr lval_addr %type expr_value %type pathname identifier @@ -266,11 +266,8 @@ noprocess_state: | tNOPROCESS tSTRING tEOL { DEBUG_Printf(DBG_CHN_MESG, "No process loaded, cannot execute '%s'\n", $2); } ; -type_cast: '(' type_expr ')' { $$ = $2; } - ; - type_expr: - type_expr '*' { $$ = DEBUG_FindOrMakePointerType($1); } + type_expr '*' { $$ = $1 ? DEBUG_FindOrMakePointerType($1) : NULL; } | tINT { $$ = DEBUG_GetBasicType(DT_BASIC_INT); } | tCHAR { $$ = DEBUG_GetBasicType(DT_BASIC_CHAR); } | tLONG tINT { $$ = DEBUG_GetBasicType(DT_BASIC_LONGINT); } @@ -344,7 +341,7 @@ expr: | '(' expr ')' { $$ = $2; } | '*' expr %prec OP_DEREF { $$ = DEBUG_UnopExpr(EXP_OP_DEREF, $2); } | '&' expr %prec OP_DEREF { $$ = DEBUG_UnopExpr(EXP_OP_ADDR, $2); } - | type_cast expr %prec OP_DEREF { $$ = DEBUG_TypeCastExpr($1, $2); } + | '(' type_expr ')' expr %prec OP_DEREF { $$ = DEBUG_TypeCastExpr($2, $4); } ; /* diff --git a/debugger/debugger.h b/debugger/debugger.h index d3a10d964cd..ff5e2bfc931 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -419,6 +419,8 @@ extern enum dbg_mode DEBUG_GetSelectorType( WORD sel ); extern void DEBUG_FixAddress( DBG_ADDR *address, DWORD def ); extern int DEBUG_IsSelectorSystem( WORD sel ); #endif +extern int DEBUG_PrintStringA( int chnl, const DBG_ADDR* address, int len ); +extern int DEBUG_PrintStringW( int chnl, const DBG_ADDR* address, int len ); /* debugger/module.c */ extern int DEBUG_LoadEntryPoints( const char * prefix ); @@ -513,7 +515,8 @@ extern struct datatype * DEBUG_GetBasicType(enum debug_type_basic); #define DBG_CHN_WARN 4 #define DBG_CHN_FIXME 8 #define DBG_CHN_TRACE 16 -extern void DEBUG_Output(int chn, const char* buffer, int len); +extern void DEBUG_OutputA(int chn, const char* buffer, int len); +extern void DEBUG_OutputW(int chn, const WCHAR* buffer, int len); #ifdef __GNUC__ extern int DEBUG_Printf(int chn, const char* format, ...) __attribute__((format (printf,2,3))); #else diff --git a/debugger/expr.c b/debugger/expr.c index 2144a44b98b..727a65990e5 100644 --- a/debugger/expr.c +++ b/debugger/expr.c @@ -323,6 +323,11 @@ DBG_VALUE DEBUG_EvalExpr(struct expr * exp) case EXPR_TYPE_CAST: rtn = DEBUG_EvalExpr(exp->un.cast.expr); rtn.type = exp->un.cast.cast; + if (!rtn.type) + { + DEBUG_Printf(DBG_CHN_MESG, "Can't cast to unknown type\n"); + RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); + } if (DEBUG_GetType(rtn.type) == DT_POINTER) rtn.cookie = DV_TARGET; break; diff --git a/debugger/info.c b/debugger/info.c index 149004959e3..d17b0600354 100644 --- a/debugger/info.c +++ b/debugger/info.c @@ -36,97 +36,107 @@ */ void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format ) { - char * default_format; - long long int res; - - assert(value->cookie == DV_TARGET || value->cookie == DV_HOST); - if( value->type == NULL ) + char * default_format; + long long int res; + + assert(value->cookie == DV_TARGET || value->cookie == DV_HOST); + if (value->type == NULL) { - DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression\n"); - return; + DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression\n"); + return; } - - default_format = NULL; - res = DEBUG_GetExprValue(value, &default_format); - - switch(format) + + default_format = NULL; + res = DEBUG_GetExprValue(value, &default_format); + + switch (format) { case 'x': - if (value->addr.seg) + if (value->addr.seg) { - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", (long unsigned int) res ); + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "0x%04lx", (long unsigned int)res); } - else + else { - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", (long unsigned int) res ); + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "0x%08lx", (long unsigned int)res); } - break; - + break; + case 'd': - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%ld\n", (long int) res ); - break; - + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "%ld\n", (long int)res); + break; + case 'c': - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%d = '%c'", - (char)(res & 0xff), (char)(res & 0xff) ); - break; - + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "%d = '%c'", + (char)(res & 0xff), (char)(res & 0xff)); + break; + + case 'u': + { + WCHAR wch = (WCHAR)(res & 0xFFFF); + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "%d = '", (unsigned)(res & 0xffff)); + DEBUG_OutputW(DBG_CHN_MESG, &wch, 1); + DEBUG_Printf(DBG_CHN_MESG, "'"); + } + break; + case 'i': case 's': case 'w': case 'b': - DEBUG_Printf( DBG_CHN_MESG, "Format specifier '%c' is meaningless in 'print' command\n", format ); + DEBUG_Printf(DBG_CHN_MESG, "Format specifier '%c' is meaningless in 'print' command\n", format); case 0: - if( default_format != NULL ) + if (default_format != NULL) { - if (strstr(default_format, "%S") != NULL) + if (strstr(default_format, "%S") != NULL) { - char* ptr; - int state = 0; - - /* FIXME: simplistic implementation for default_format being - * foo%Sbar => will print foo, then string then bar - */ - for (ptr = default_format; *ptr; ptr++) - { - if (*ptr == '%') state++; - else if (state == 1) + char* ptr; + int state = 0; + + /* FIXME: simplistic implementation for default_format being + * foo%Sbar => will print foo, then string then bar + */ + for (ptr = default_format; *ptr; ptr++) + { + if (*ptr == '%') + { + state++; + } + else if (state == 1) { - if (*ptr == 'S') - { - char ch; - char* str = (char*)(long)res; - - for (; DEBUG_READ_MEM(str, &ch, 1) && ch; str++) { - DEBUG_Output(DBG_CHN_MESG, &ch, 1); - DEBUG_nchar++; - } - } - else - { + if (*ptr == 'S') + { + DBG_ADDR addr; + + addr.seg = 0; + addr.off = (long)res; + DEBUG_nchar += DEBUG_PrintStringA(DBG_CHN_MESG, &addr, -1); + } + else + { /* shouldn't happen */ DEBUG_Printf(DBG_CHN_MESG, "%%%c", *ptr); DEBUG_nchar += 2; - } - state = 0; + } + state = 0; } - else + else { - DEBUG_Output(DBG_CHN_MESG, ptr, 1); - DEBUG_nchar++; + DEBUG_OutputA(DBG_CHN_MESG, ptr, 1); + DEBUG_nchar++; } - } + } } - else if (strcmp(default_format, "%B") == 0) + else if (strcmp(default_format, "%B") == 0) { - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%s", res ? "true" : "false"); + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "%s", res ? "true" : "false"); } - else + else { - DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, default_format, res ); + DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, default_format, res); } } - break; + break; } } diff --git a/debugger/memory.c b/debugger/memory.c index fc2f9901ab7..ea622d8000a 100644 --- a/debugger/memory.c +++ b/debugger/memory.c @@ -276,33 +276,15 @@ void DEBUG_ExamineMemory( const DBG_VALUE *_value, int count, char format ) switch(format) { - case 'u': { - WCHAR wch; - if (count == 1) count = 256; - while (count--) - { - if (!DEBUG_READ_MEM_VERBOSE(pnt, &wch, sizeof(wch)) || !wch) - break; - pnt += sizeof(wch); - DEBUG_Printf(DBG_CHN_MESG, "%c", (char)wch); - } - DEBUG_Printf(DBG_CHN_MESG,"\n"); + case 'u': + if (count == 1) count = 256; + DEBUG_nchar += DEBUG_PrintStringW(DBG_CHN_MESG, &value.addr, count); + DEBUG_Printf(DBG_CHN_MESG, "\n"); return; - } - case 's': { - char ch; - - if (count == 1) count = 256; - while (count--) - { - if (!DEBUG_READ_MEM_VERBOSE(pnt, &ch, sizeof(ch)) || !ch) - break; - pnt++; - DEBUG_Output(DBG_CHN_MESG, &ch, 1); - } - DEBUG_Printf(DBG_CHN_MESG,"\n"); + case 's': + DEBUG_nchar += DEBUG_PrintStringA(DBG_CHN_MESG, &value.addr, count); + DEBUG_Printf(DBG_CHN_MESG, "\n"); return; - } case 'i': while (count-- && DEBUG_DisassembleInstruction( &value.addr )); return; @@ -330,3 +312,50 @@ void DEBUG_ExamineMemory( const DBG_VALUE *_value, int count, char format ) case 'b': DO_DUMP2(char, 16, " %02x", (_v) & 0xff); } } + +/****************************************************************** + * DEBUG_PrintStringA + * + * Prints on channel chnl, the string starting at address in target + * address space. The string stops when either len chars (if <> -1) + * have been printed, or the '\0' char is printed + */ +int DEBUG_PrintStringA(int chnl, const DBG_ADDR* address, int len) +{ + char* lin = (void*)DEBUG_ToLinear(address); + char ach[16+1]; + int i, l; + + if (len == -1) len = 32767; /* should be big enough */ + + /* so that the ach is always terminated */ + ach[sizeof(ach) - 1] = '\0'; + for (i = len; i >= 0; i -= sizeof(ach) - 1) + { + l = min(sizeof(ach) - 1, i); + DEBUG_READ_MEM_VERBOSE(lin, ach, l); + l = strlen(ach); + DEBUG_OutputA(chnl, ach, l); + lin += l; + if (l < sizeof(ach) - 1) break; + } + return len - i; /* number of actually written chars */ +} + +int DEBUG_PrintStringW(int chnl, const DBG_ADDR* address, int len) +{ + char* lin = (void*)DEBUG_ToLinear(address); + WCHAR wch; + int ret = 0; + + if (len == -1) len = 32767; /* should be big enough */ + while (len--) + { + if (!DEBUG_READ_MEM_VERBOSE(lin, &wch, sizeof(wch)) || !wch) + break; + lin += sizeof(wch); + DEBUG_OutputW(chnl, &wch, 1); + ret++; + } + return ret; +} diff --git a/debugger/types.c b/debugger/types.c index c8cd76dd13e..298e5af8b75 100644 --- a/debugger/types.c +++ b/debugger/types.c @@ -875,7 +875,6 @@ DEBUG_Print( const DBG_VALUE *value, int count, char format, int level ) size = DEBUG_GetObjectSize(value->type->un.array.basictype); if( size == 1 ) { - char ach[16]; int len, clen; /* @@ -883,21 +882,17 @@ DEBUG_Print( const DBG_VALUE *value, int count, char format, int level ) */ pnt = (char *) value->addr.off; len = value->type->un.array.end - value->type->un.array.start + 1; - clen = (DEBUG_nchar + len < DEBUG_maxchar) + clen = (DEBUG_nchar + len < DEBUG_maxchar) ? len : (DEBUG_maxchar - DEBUG_nchar); DEBUG_nchar += DEBUG_Printf(DBG_CHN_MESG, "\""); switch (value->cookie) { case DV_TARGET: - for (i = clen; i > 0; i -= sizeof(ach)) - { - DEBUG_READ_MEM(pnt, ach, min(sizeof(ach), i)); - DEBUG_Output(DBG_CHN_MESG, ach, min(sizeof(ach), i)); - } + clen = DEBUG_PrintStringA(DBG_CHN_MESG, &value->addr, clen); break; case DV_HOST: - DEBUG_Output(DBG_CHN_MESG, pnt, clen); + DEBUG_OutputA(DBG_CHN_MESG, pnt, clen); break; default: assert(0); } diff --git a/debugger/winedbg.c b/debugger/winedbg.c index a9305306bc7..a85920da4df 100644 --- a/debugger/winedbg.c +++ b/debugger/winedbg.c @@ -48,7 +48,7 @@ static DBG_PROCESS* DEBUG_ProcessList = NULL; static int automatic_mode; DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST]; -void DEBUG_Output(int chn, const char* buffer, int len) +void DEBUG_OutputA(int chn, const char* buffer, int len) { if (DBG_IVAR(ConChannelMask) & chn) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL); @@ -56,6 +56,16 @@ void DEBUG_Output(int chn, const char* buffer, int len) fwrite(buffer, len, 1, stderr); } +void DEBUG_OutputW(int chn, const WCHAR* buffer, int len) +{ + /* FIXME: this won't work is std output isn't attached to a console */ + if (DBG_IVAR(ConChannelMask) & chn) + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL); + /* simplistic Unicode to ANSI conversion */ + if (DBG_IVAR(StdChannelMask) & chn) + while (len--) fputc((char)*buffer++, stderr); +} + int DEBUG_Printf(int chn, const char* format, ...) { static char buf[4*1024]; @@ -71,7 +81,7 @@ static char buf[4*1024]; buf[len] = 0; buf[len - 1] = buf[len - 2] = buf[len - 3] = '.'; } - DEBUG_Output(chn, buf, len); + DEBUG_OutputA(chn, buf, len); return len; }