From 88949b2c59f5613ff1a3964e7ce538474578d6c3 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 4 Apr 2012 22:30:38 +0200 Subject: [PATCH] winedbg: Fix set instruction when sizeof(int) <> sizeof register. --- programs/winedbg/be_arm.c | 8 ++++++++ programs/winedbg/be_cpu.h | 2 ++ programs/winedbg/be_i386.c | 8 ++++++++ programs/winedbg/be_ppc.c | 8 ++++++++ programs/winedbg/be_sparc.c | 8 ++++++++ programs/winedbg/be_x86_64.c | 8 ++++++++ programs/winedbg/dbg.y | 2 +- programs/winedbg/debugger.h | 3 ++- programs/winedbg/memory.c | 4 ++-- programs/winedbg/types.c | 37 ++++++++++++++++++++++++++++-------- 10 files changed, 76 insertions(+), 12 deletions(-) diff --git a/programs/winedbg/be_arm.c b/programs/winedbg/be_arm.c index 6c1cc05e2ba..9db785f4f1f 100644 --- a/programs/winedbg/be_arm.c +++ b/programs/winedbg/be_arm.c @@ -255,6 +255,13 @@ static int be_arm_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, return TRUE; } +static int be_arm_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned is_signed, LONGLONG val) +{ + dbg_printf("be_arm_store_integer: not done\n"); + return FALSE; +} + struct backend_cpu be_arm = { IMAGE_FILE_MACHINE_ARMV7, @@ -280,5 +287,6 @@ struct backend_cpu be_arm = be_arm_adjust_pc_for_break, be_arm_fetch_integer, be_arm_fetch_float, + be_arm_store_integer, }; #endif diff --git a/programs/winedbg/be_cpu.h b/programs/winedbg/be_cpu.h index ce9c32feaaa..356980a4b5f 100644 --- a/programs/winedbg/be_cpu.h +++ b/programs/winedbg/be_cpu.h @@ -112,6 +112,8 @@ struct backend_cpu int (*fetch_integer)(const struct dbg_lvalue* lvalue, unsigned size, unsigned is_signed, LONGLONG*); /* Reads a real from memory and stores it inside a long double */ int (*fetch_float)(const struct dbg_lvalue* lvalue, unsigned size, long double*); + /* Writes an integer to memory */ + int (*store_integer)(const struct dbg_lvalue* lvalue, unsigned size, unsigned is_signed, LONGLONG); }; extern struct backend_cpu* be_cpu; diff --git a/programs/winedbg/be_i386.c b/programs/winedbg/be_i386.c index c294f2d222a..d9fb67c5985 100644 --- a/programs/winedbg/be_i386.c +++ b/programs/winedbg/be_i386.c @@ -772,6 +772,13 @@ static int be_i386_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, return TRUE; } +static int be_i386_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned is_signed, LONGLONG val) +{ + /* this is simple as we're on a little endian CPU */ + return memory_write_value(lvalue, size, &val); +} + struct backend_cpu be_i386 = { IMAGE_FILE_MACHINE_I386, @@ -797,5 +804,6 @@ struct backend_cpu be_i386 = be_i386_adjust_pc_for_break, be_i386_fetch_integer, be_i386_fetch_float, + be_i386_store_integer, }; #endif diff --git a/programs/winedbg/be_ppc.c b/programs/winedbg/be_ppc.c index 0d076bc3c2f..3de5d9d7e76 100644 --- a/programs/winedbg/be_ppc.c +++ b/programs/winedbg/be_ppc.c @@ -173,6 +173,13 @@ static int be_ppc_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, return FALSE; } +static int be_ppc_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned is_signed, LONGLONG val) +{ + dbg_printf("be_ppc_store_integer: not done\n"); + return FALSE; +} + struct backend_cpu be_ppc = { IMAGE_FILE_MACHINE_POWERPC, @@ -198,5 +205,6 @@ struct backend_cpu be_ppc = be_ppc_adjust_pc_for_break, be_ppc_fetch_integer, be_ppc_fetch_float, + be_ppc_store_integer, }; #endif diff --git a/programs/winedbg/be_sparc.c b/programs/winedbg/be_sparc.c index 3435759c92d..3d5ce366f96 100644 --- a/programs/winedbg/be_sparc.c +++ b/programs/winedbg/be_sparc.c @@ -148,6 +148,13 @@ static int be_sparc_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, return FALSE; } +static int be_sparc_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned is_signed, LONGLONG val) +{ + dbg_printf("be_sparc_store_integer: not done\n"); + return FALSE; +} + struct backend_cpu be_sparc = { IMAGE_FILE_MACHINE_SPARC, @@ -173,5 +180,6 @@ struct backend_cpu be_sparc = be_sparc_adjust_pc_for_break, be_sparc_fetch_integer, be_sparc_fetch_float, + be_sparc_store_integer, }; #endif diff --git a/programs/winedbg/be_x86_64.c b/programs/winedbg/be_x86_64.c index 7dbd301fa6e..0dd11c2a86b 100644 --- a/programs/winedbg/be_x86_64.c +++ b/programs/winedbg/be_x86_64.c @@ -638,6 +638,13 @@ static int be_x86_64_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, return TRUE; } +static int be_x86_64_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned is_signed, LONGLONG val) +{ + /* this is simple as we're on a little endian CPU */ + return memory_write_value(lvalue, size, &val); +} + struct backend_cpu be_x86_64 = { IMAGE_FILE_MACHINE_AMD64, @@ -663,5 +670,6 @@ struct backend_cpu be_x86_64 = be_x86_64_adjust_pc_for_break, be_x86_64_fetch_integer, be_x86_64_fetch_float, + be_x86_64_store_integer, }; #endif diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 26f4a79248c..5929b87cc3d 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -204,7 +204,7 @@ disassemble_command: ; set_command: - tSET lvalue_addr '=' expr_rvalue { memory_write_value(&$2, sizeof(int), &$4); } + tSET lvalue_addr '=' expr_lvalue { types_store_value(&$2, &$4); } | tSET '+' tIDENTIFIER { info_wine_dbg_channel(TRUE, NULL, $3); } | tSET '+' tALL { info_wine_dbg_channel(TRUE, NULL, "all"); } | tSET '-' tIDENTIFIER { info_wine_dbg_channel(FALSE, NULL, $3); } diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 6e6d465fdeb..a776d27586d 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -437,8 +437,9 @@ extern void print_value(const struct dbg_lvalue* addr, char format, extern int types_print_type(const struct dbg_type*, BOOL details); extern int print_types(void); extern long int types_extract_as_integer(const struct dbg_lvalue*); -extern LONGLONG types_extract_as_longlong(const struct dbg_lvalue*, unsigned* psize); +extern LONGLONG types_extract_as_longlong(const struct dbg_lvalue*, unsigned* psize, BOOL *pissigned); extern void types_extract_as_address(const struct dbg_lvalue*, ADDRESS64*); +extern BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from); extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name, long int* tmpbuf); extern BOOL types_array_index(const struct dbg_lvalue* value, int index, struct dbg_lvalue* result); extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_TYPE_INFO, void*); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 7a0b0850565..735ef53e667 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -524,7 +524,7 @@ void print_basic(const struct dbg_lvalue* lvalue, char format) if (format != 0) { unsigned size; - LONGLONG res = types_extract_as_longlong(lvalue, &size); + LONGLONG res = types_extract_as_longlong(lvalue, &size, NULL); WCHAR wch; switch (format) @@ -557,7 +557,7 @@ void print_basic(const struct dbg_lvalue* lvalue, char format) } if (lvalue->type.id == dbg_itype_segptr) { - dbg_print_longlong(types_extract_as_longlong(lvalue, NULL), TRUE); + dbg_print_longlong(types_extract_as_longlong(lvalue, NULL, NULL), TRUE); } else print_typed_basic(lvalue); } diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 6d50c81598a..9ac49f2f5ad 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -53,12 +53,14 @@ BOOL types_get_real_type(struct dbg_type* type, DWORD* tag) * Given a lvalue, try to get an integral (or pointer/address) value * out of it */ -LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, unsigned* psize) +LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, + unsigned* psize, BOOL *issigned) { LONGLONG rtn; DWORD tag, bt; DWORD64 size; struct dbg_type type = lvalue->type; + BOOL s = FALSE; if (!types_get_real_type(&type, &tag)) RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL); @@ -69,6 +71,7 @@ LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, unsigned* ps } if (psize) *psize = 0; + if (issigned) *issigned = FALSE; switch (tag) { case SymTagBaseType: @@ -87,30 +90,31 @@ LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, unsigned* ps { case btChar: case btInt: - if (!be_cpu->fetch_integer(lvalue, (unsigned)size, TRUE, &rtn)) + if (!be_cpu->fetch_integer(lvalue, (unsigned)size, s = TRUE, &rtn)) RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); break; case btUInt: - if (!be_cpu->fetch_integer(lvalue, (unsigned)size, FALSE, &rtn)) + if (!be_cpu->fetch_integer(lvalue, (unsigned)size, s = FALSE, &rtn)) RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); break; case btFloat: RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL); } if (psize) *psize = (unsigned)size; + if (issigned) *issigned = s; break; case SymTagPointerType: - if (!be_cpu->fetch_integer(lvalue, sizeof(void*), FALSE, &rtn)) + if (!be_cpu->fetch_integer(lvalue, sizeof(void*), s = FALSE, &rtn)) RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); break; case SymTagArrayType: case SymTagUDT: - if (!be_cpu->fetch_integer(lvalue, sizeof(unsigned), FALSE, &rtn)) + if (!be_cpu->fetch_integer(lvalue, sizeof(unsigned), s = FALSE, &rtn)) RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); break; case SymTagEnum: /* FIXME: we don't handle enum size */ - if (!be_cpu->fetch_integer(lvalue, sizeof(unsigned), FALSE, &rtn)) + if (!be_cpu->fetch_integer(lvalue, sizeof(unsigned), s = FALSE, &rtn)) RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); break; case SymTagFunctionType: @@ -133,7 +137,7 @@ LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, unsigned* ps */ long int types_extract_as_integer(const struct dbg_lvalue* lvalue) { - return types_extract_as_longlong(lvalue, NULL); + return types_extract_as_longlong(lvalue, NULL, NULL); } /****************************************************************** @@ -150,10 +154,27 @@ void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS64* addr) else { addr->Mode = AddrModeFlat; - addr->Offset = types_extract_as_longlong(lvalue, NULL); + addr->Offset = types_extract_as_longlong(lvalue, NULL, NULL); } } +BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from) +{ + LONGLONG val; + DWORD64 size; + BOOL is_signed; + + if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE; + if (sizeof(val) < size) + { + dbg_printf("Unsufficient size\n"); + return FALSE; + } + /* FIXME: should support floats as well */ + val = types_extract_as_longlong(lvalue_from, NULL, &is_signed); + return be_cpu->store_integer(lvalue_to, size, is_signed, val); +} + /****************************************************************** * types_get_udt_element_lvalue *