winedbg: Move bitfield extraction to extract_lgint.
Signed-off-by: Eric Pouech <eric.pouech@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
10eba8784f
commit
0a16dbc730
|
@ -487,7 +487,7 @@ extern dbg_lgint_t types_extract_as_integer(const struct dbg_lvalue*);
|
||||||
extern dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue*, unsigned* psize, BOOL *pissigned);
|
extern dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue*, unsigned* psize, BOOL *pissigned);
|
||||||
extern void types_extract_as_address(const struct dbg_lvalue*, ADDRESS64*);
|
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_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, ULONG *tmpbuf);
|
extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name);
|
||||||
extern BOOL types_array_index(const struct dbg_lvalue* value, int index, struct dbg_lvalue* result);
|
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*);
|
extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_TYPE_INFO, void*);
|
||||||
extern BOOL types_get_real_type(struct dbg_type* type, DWORD* tag);
|
extern BOOL types_get_real_type(struct dbg_type* type, DWORD* tag);
|
||||||
|
|
|
@ -83,7 +83,6 @@ struct expr
|
||||||
{
|
{
|
||||||
struct expr* exp1;
|
struct expr* exp1;
|
||||||
const char* element_name;
|
const char* element_name;
|
||||||
ULONG /* FIXME */ result;
|
|
||||||
} structure;
|
} structure;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -361,8 +360,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
|
||||||
if (exp1.type.id == dbg_itype_none || !types_array_index(&exp1, 0, &rtn) ||
|
if (exp1.type.id == dbg_itype_none || !types_array_index(&exp1, 0, &rtn) ||
|
||||||
rtn.type.id == dbg_itype_none)
|
rtn.type.id == dbg_itype_none)
|
||||||
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
|
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
|
||||||
if (!types_udt_find_element(&rtn, exp->un.structure.element_name,
|
if (!types_udt_find_element(&rtn, exp->un.structure.element_name))
|
||||||
&exp->un.structure.result))
|
|
||||||
{
|
{
|
||||||
dbg_printf("%s\n", exp->un.structure.element_name);
|
dbg_printf("%s\n", exp->un.structure.element_name);
|
||||||
RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL);
|
RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL);
|
||||||
|
@ -372,8 +370,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
|
||||||
exp1 = expr_eval(exp->un.structure.exp1);
|
exp1 = expr_eval(exp->un.structure.exp1);
|
||||||
if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
|
if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
|
||||||
rtn = exp1;
|
rtn = exp1;
|
||||||
if (!types_udt_find_element(&rtn, exp->un.structure.element_name,
|
if (!types_udt_find_element(&rtn, exp->un.structure.element_name))
|
||||||
&exp->un.structure.result))
|
|
||||||
{
|
{
|
||||||
dbg_printf("%s\n", exp->un.structure.element_name);
|
dbg_printf("%s\n", exp->un.structure.element_name);
|
||||||
RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL);
|
RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL);
|
||||||
|
|
|
@ -237,15 +237,47 @@ BOOL memory_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size,
|
||||||
/* size must fit in ret and be a power of two */
|
/* size must fit in ret and be a power of two */
|
||||||
if (size > sizeof(*ret) || (size & (size - 1))) return FALSE;
|
if (size > sizeof(*ret) || (size & (size - 1))) return FALSE;
|
||||||
|
|
||||||
/* we are on little endian CPU */
|
if (lvalue->bitlen)
|
||||||
memset(ret, 0, sizeof(*ret)); /* clear unread bytes */
|
|
||||||
if (!memory_read_value(lvalue, size, ret)) return FALSE;
|
|
||||||
|
|
||||||
/* propagate sign information */
|
|
||||||
if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0)
|
|
||||||
{
|
{
|
||||||
dbg_lguint_t neg = -1;
|
struct dbg_lvalue alt_lvalue = *lvalue;
|
||||||
*ret |= neg << (size * 8);
|
dbg_lguint_t mask;
|
||||||
|
DWORD bt;
|
||||||
|
/* FIXME: this test isn't sufficient, depending on start of bitfield
|
||||||
|
* (ie a 64 bit field can spread across 9 bytes)
|
||||||
|
*/
|
||||||
|
if (lvalue->bitlen > 8 * sizeof(dbg_lgint_t)) return FALSE;
|
||||||
|
alt_lvalue.addr.Offset += lvalue->bitstart >> 3;
|
||||||
|
/*
|
||||||
|
* Bitfield operation. We have to extract the field.
|
||||||
|
*/
|
||||||
|
if (!memory_read_value(&alt_lvalue, sizeof(*ret), ret)) return FALSE;
|
||||||
|
mask = ~(dbg_lguint_t)0 << lvalue->bitlen;
|
||||||
|
*ret >>= lvalue->bitstart & 7;
|
||||||
|
*ret &= ~mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OK, now we have the correct part of the number.
|
||||||
|
* Check to see whether the basic type is signed or not, and if so,
|
||||||
|
* we need to sign extend the number.
|
||||||
|
*/
|
||||||
|
if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) &&
|
||||||
|
(bt == btInt || bt == btLong) && (*ret & (1 << (lvalue->bitlen - 1))))
|
||||||
|
{
|
||||||
|
*ret |= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* we are on little endian CPU */
|
||||||
|
memset(ret, 0, sizeof(*ret)); /* clear unread bytes */
|
||||||
|
if (!memory_read_value(lvalue, size, ret)) return FALSE;
|
||||||
|
|
||||||
|
/* propagate sign information */
|
||||||
|
if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0)
|
||||||
|
{
|
||||||
|
dbg_lguint_t neg = -1;
|
||||||
|
*ret |= neg << (size * 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue* lvalue,
|
||||||
{
|
{
|
||||||
return (LONG_PTR)memory_to_linear_addr(&lvalue->addr);
|
return (LONG_PTR)memory_to_linear_addr(&lvalue->addr);
|
||||||
}
|
}
|
||||||
|
if (tag != SymTagBaseType && lvalue->bitlen) dbg_printf("Unexpected bitfield on tag %d\n", tag);
|
||||||
|
|
||||||
if (psize) *psize = 0;
|
if (psize) *psize = 0;
|
||||||
if (issigned) *issigned = FALSE;
|
if (issigned) *issigned = FALSE;
|
||||||
|
@ -180,15 +181,11 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv
|
||||||
*
|
*
|
||||||
* Implement a structure derefencement
|
* Implement a structure derefencement
|
||||||
*/
|
*/
|
||||||
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue,
|
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, const struct dbg_type* type)
|
||||||
const struct dbg_type* type, ULONG *tmpbuf)
|
|
||||||
{
|
{
|
||||||
DWORD offset, bitoffset;
|
DWORD offset, bitoffset;
|
||||||
DWORD bt;
|
|
||||||
DWORD64 length;
|
DWORD64 length;
|
||||||
|
|
||||||
unsigned mask;
|
|
||||||
|
|
||||||
types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
|
types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
|
||||||
lvalue->type.module = type->module;
|
lvalue->type.module = type->module;
|
||||||
if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
|
if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
|
||||||
|
@ -197,38 +194,17 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue,
|
||||||
if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
|
if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
|
||||||
{
|
{
|
||||||
types_get_info(type, TI_GET_LENGTH, &length);
|
types_get_info(type, TI_GET_LENGTH, &length);
|
||||||
/* FIXME: this test isn't sufficient, depending on start of bitfield
|
lvalue->bitlen = length;
|
||||||
* (ie a 32 bit field can spread across 5 bytes)
|
lvalue->bitstart = bitoffset;
|
||||||
*/
|
if (lvalue->bitlen != length || lvalue->bitstart != bitoffset)
|
||||||
if (length > 8 * sizeof(*tmpbuf)) return FALSE;
|
|
||||||
lvalue->addr.Offset += bitoffset >> 3;
|
|
||||||
/*
|
|
||||||
* Bitfield operation. We have to extract the field and store
|
|
||||||
* it in a temporary buffer so that we get it all right.
|
|
||||||
*/
|
|
||||||
if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
|
|
||||||
mask = 0xffffffff << (DWORD)length;
|
|
||||||
*tmpbuf >>= bitoffset & 7;
|
|
||||||
*tmpbuf &= ~mask;
|
|
||||||
|
|
||||||
lvalue->in_debuggee = 0;
|
|
||||||
lvalue->addr.Offset = (ULONG_PTR)tmpbuf;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OK, now we have the correct part of the number.
|
|
||||||
* Check to see whether the basic type is signed or not, and if so,
|
|
||||||
* we need to sign extend the number.
|
|
||||||
*/
|
|
||||||
if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) &&
|
|
||||||
bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1))))
|
|
||||||
{
|
{
|
||||||
*tmpbuf |= mask;
|
dbg_printf("too wide bitfields\n"); /* shouldn't happen */
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
lvalue->bitlen = lvalue->bitstart = 0;
|
||||||
if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +212,7 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue,
|
||||||
* types_udt_find_element
|
* types_udt_find_element
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, ULONG *tmpbuf)
|
BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name)
|
||||||
{
|
{
|
||||||
DWORD tag, count;
|
DWORD tag, count;
|
||||||
char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
|
char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
|
||||||
|
@ -266,7 +242,7 @@ BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, ULONG *
|
||||||
WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
|
WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
|
||||||
HeapFree(GetProcessHeap(), 0, ptr);
|
HeapFree(GetProcessHeap(), 0, ptr);
|
||||||
if (!strcmp(tmp, name))
|
if (!strcmp(tmp, name))
|
||||||
return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
|
return types_get_udt_element_lvalue(lvalue, &type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,7 +451,6 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
|
||||||
char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
|
char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
|
||||||
TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
|
TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
|
||||||
WCHAR* ptr;
|
WCHAR* ptr;
|
||||||
ULONG tmpbuf;
|
|
||||||
struct dbg_type sub_type;
|
struct dbg_type sub_type;
|
||||||
|
|
||||||
dbg_printf("{");
|
dbg_printf("{");
|
||||||
|
@ -493,7 +468,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
|
||||||
dbg_printf("%ls=", ptr);
|
dbg_printf("%ls=", ptr);
|
||||||
HeapFree(GetProcessHeap(), 0, ptr);
|
HeapFree(GetProcessHeap(), 0, ptr);
|
||||||
lvalue_field = *lvalue;
|
lvalue_field = *lvalue;
|
||||||
if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf))
|
if (types_get_udt_element_lvalue(&lvalue_field, &sub_type))
|
||||||
{
|
{
|
||||||
print_value(&lvalue_field, format, level + 1);
|
print_value(&lvalue_field, format, level + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,9 @@
|
||||||
* - type management:
|
* - type management:
|
||||||
* + some bits of internal types are missing (like type casts and the address
|
* + some bits of internal types are missing (like type casts and the address
|
||||||
* operator)
|
* operator)
|
||||||
* + all computations should be made on long long
|
* + all computations should be made on 64bit
|
||||||
* o expr computations are in int:s
|
* o bitfield spreading on more bytes than dbg_lgint_t isn't supported
|
||||||
* o bitfield size is on a 4-bytes
|
* (can happen on 128bit integers, of an ELF build...)
|
||||||
* - execution:
|
* - execution:
|
||||||
* + set a better fix for gdb (proxy mode) than the step-mode hack
|
* + set a better fix for gdb (proxy mode) than the step-mode hack
|
||||||
* + implement function call in debuggee
|
* + implement function call in debuggee
|
||||||
|
|
Loading…
Reference in New Issue