- fixed breakpoint enabled/disabled state management

- fixed recursion in type printing
- now all type-id are stored with the base address of the module which
  defines the type (struct dbg_type takes care of this pairing)
- fixed a couple of bugs in display handling
- fixed strings print and examination
This commit is contained in:
Eric Pouech 2004-08-22 22:35:36 +00:00 committed by Alexandre Julliard
parent 07a805127a
commit 926f66186f
12 changed files with 427 additions and 368 deletions

View file

@ -1683,17 +1683,19 @@ set $BreakAllThreadsStartup = 1
<tbody> <tbody>
<row> <row>
<entry> <entry>
<msgtext> <command>info&nbsp;display</command>
<simplelist type="inline">
<member><command>display</command></member>
<member>
<command>info&nbsp;display</command>
</member>
</simplelist>
</msgtext>
</entry> </entry>
<entry>lists the active displays</entry> <entry>lists the active displays</entry>
</row> </row>
<row>
<entry>
<command>display</command>
</entry>
<entry>
print the active displays' values (as done each
time the debugger stops)
</entry>
</row>
<row> <row>
<entry> <entry>
<command>display&nbsp;&lt;expr&gt;</command> <command>display&nbsp;&lt;expr&gt;</command>

View file

@ -59,8 +59,7 @@ void break_set_xpoints(BOOL set)
for (i = 0; i < dbg_curr_process->next_bp; i++) for (i = 0; i < dbg_curr_process->next_bp; i++)
{ {
if (!bp[i].refcount && !bp[i].enabled) if (!bp[i].refcount || !bp[i].enabled) continue;
continue;
if (bp[i].xpoint_type == be_xpoint_break) if (bp[i].xpoint_type == be_xpoint_break)
size = 0; size = 0;
@ -78,8 +77,9 @@ void break_set_xpoints(BOOL set)
bp[i].info, size); bp[i].info, size);
if (!ret) if (!ret)
{ {
dbg_printf("Invalid address (%p) for breakpoint %d, disabling it\n", dbg_printf("Invalid address (");
addr, i); print_address(&bp[i].addr, FALSE);
dbg_printf(") for breakpoint %d, disabling it\n", i);
bp[i].enabled = FALSE; bp[i].enabled = FALSE;
} }
} }
@ -375,10 +375,9 @@ void break_add_watch(const struct dbg_lvalue* lvalue, BOOL is_write)
&lvalue->addr); &lvalue->addr);
if (num == -1) return; if (num == -1) return;
if (lvalue->typeid != dbg_itype_none) if (lvalue->type.id != dbg_itype_none)
{ {
if (types_get_info((DWORD)memory_to_linear_addr(&lvalue->addr), if (types_get_info(&lvalue->type, TI_GET_LENGTH, &l))
lvalue->typeid, TI_GET_LENGTH, &l))
{ {
switch (l) switch (l)
{ {
@ -679,7 +678,7 @@ static BOOL should_stop(int bpnum)
{ {
struct dbg_lvalue lvalue = expr_eval(bp->condition); struct dbg_lvalue lvalue = expr_eval(bp->condition);
if (lvalue.typeid == dbg_itype_none) if (lvalue.type.id == dbg_itype_none)
{ {
/* /*
* Something wrong - unable to evaluate this expression. * Something wrong - unable to evaluate this expression.

View file

@ -133,7 +133,7 @@ command:
| tSOURCE pathname { parser($2); } | tSOURCE pathname { parser($2); }
| tSYMBOLFILE pathname { symbol_read_symtable($2, 0); } | tSYMBOLFILE pathname { symbol_read_symtable($2, 0); }
| tSYMBOLFILE pathname expr_rvalue { symbol_read_symtable($2, $3); } | tSYMBOLFILE pathname expr_rvalue { symbol_read_symtable($2, $3); }
| tWHATIS expr_lvalue { types_print_type((DWORD)memory_to_linear_addr(&$2.addr), $2.typeid, FALSE); dbg_printf("\n"); } | tWHATIS expr_lvalue { types_print_type(&$2.type, FALSE); dbg_printf("\n"); }
| tATTACH tNUM { dbg_attach_debuggee($2, FALSE, TRUE); } | tATTACH tNUM { dbg_attach_debuggee($2, FALSE, TRUE); }
| tDETACH { dbg_detach_debuggee(); } | tDETACH { dbg_detach_debuggee(); }
| run_command | run_command
@ -202,8 +202,8 @@ set_command:
; ;
x_command: x_command:
tEXAM expr_lvalue { memory_examine(&$2, 1, 'x'); } tEXAM expr_rvalue { memory_examine((void*)$2, 1, 'x'); }
| tEXAM tFORMAT expr_lvalue { memory_examine(&$3, $2 >> 8, $2 & 0xff); } | tEXAM tFORMAT expr_rvalue { memory_examine((void*)$3, $2 >> 8, $2 & 0xff); }
; ;
print_command: print_command:
@ -231,7 +231,7 @@ watch_command:
; ;
display_command: display_command:
tDISPLAY { display_info(); } tDISPLAY { display_print(); }
| tDISPLAY expr { display_add($2, 1, 0, FALSE); } | tDISPLAY expr { display_add($2, 1, 0, FALSE); }
| tDISPLAY tFORMAT expr { display_add($3, $2 >> 8, $2 & 0xff, FALSE); } | tDISPLAY tFORMAT expr { display_add($3, $2 >> 8, $2 & 0xff, FALSE); }
| tLOCAL tDISPLAY expr { display_add($3, 1, 0, TRUE); } | tLOCAL tDISPLAY expr { display_add($3, 1, 0, TRUE); }
@ -280,27 +280,27 @@ noprocess_state:
; ;
type_expr: type_expr:
tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_char; } tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_char; }
| tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_int; } | tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_int; }
| tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_long_int; } | tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
| tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_long_int; } | tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
| tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_int; } | tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
| tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_int; } | tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
| tLONG tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_long_int; } | tLONG tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
| tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_long_int; } | tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
| tSHORT tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_short_int; } | tSHORT tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
| tSHORT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_short_int; } | tSHORT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
| tSHORT tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_short_int; } | tSHORT tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
| tSHORT tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_short_int; } | tSHORT tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
| tSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_char_int; } | tSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_char_int; }
| tUNSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_char_int; } | tUNSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_char_int; }
| tLONG tLONG tUNSIGNED tINT{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_longlong_int; } | tLONG tLONG tUNSIGNED tINT{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
| tLONG tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_unsigned_longlong_int; } | tLONG tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
| tLONG tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_longlong_int; } | tLONG tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
| tLONG tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_signed_longlong_int; } | tLONG tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
| tFLOAT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_short_real; } | tFLOAT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_short_real; }
| tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_real; } | tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_real; }
| tLONG tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.typeid = dbg_itype_long_real; } | tLONG tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_long_real; }
| type_expr '*' { $$ = $1; $$.deref_count++; } | type_expr '*' { $$ = $1; $$.deref_count++; }
| tCLASS identifier { $$.type = type_expr_udt_class; $$.deref_count = 0; $$.u.name = lexeme_alloc($2); } | tCLASS identifier { $$.type = type_expr_udt_class; $$.deref_count = 0; $$.u.name = lexeme_alloc($2); }
| tSTRUCT identifier { $$.type = type_expr_udt_struct; $$.deref_count = 0; $$.u.name = lexeme_alloc($2); } | tSTRUCT identifier { $$.type = type_expr_udt_struct; $$.deref_count = 0; $$.u.name = lexeme_alloc($2); }

View file

@ -82,6 +82,18 @@ enum dbg_internal_types
dbg_itype_none = 0xffffffff dbg_itype_none = 0xffffffff
}; };
/* type description (in the following order):
* - if 'id' is dbg_itype_none (whatever 'module' value), the type isn't known
* - if 'module' is 0, it's an internal type (id is one of dbg_itype...)
* - if 'module' is non 0, then 'id' is a type ID referring to module (loaded in
* dbghelp) which (linear) contains address 'module'.
*/
struct dbg_type
{
unsigned long id;
DWORD module;
};
struct dbg_lvalue /* structure to hold left-values... */ struct dbg_lvalue /* structure to hold left-values... */
{ {
int cookie; /* DLV_??? */ int cookie; /* DLV_??? */
@ -91,7 +103,7 @@ struct dbg_lvalue /* structure to hold left-values... */
# define DLV_TARGET 0xF00D # define DLV_TARGET 0xF00D
# define DLV_HOST 0x50DA # define DLV_HOST 0x50DA
ADDRESS addr; ADDRESS addr;
unsigned long typeid; struct dbg_type type;
}; };
enum dbg_exec_mode enum dbg_exec_mode
@ -202,7 +214,7 @@ struct dbg_internal_var
DWORD val; DWORD val;
const char* name; const char* name;
LPDWORD pval; LPDWORD pval;
unsigned long typeid; unsigned long typeid; /* always internal type */
}; };
enum sym_get_lval {sglv_found, sglv_unknown, sglv_aborted}; enum sym_get_lval {sglv_found, sglv_unknown, sglv_aborted};
@ -222,7 +234,7 @@ struct type_expr_t
unsigned deref_count; unsigned deref_count;
union union
{ {
unsigned long typeid; struct dbg_type type;
const char* name; const char* name;
} u; } u;
}; };
@ -293,15 +305,15 @@ extern void info_win32_segments(DWORD start, int length);
extern void info_wine_dbg_channel(BOOL add, const char* chnl, const char* name); extern void info_wine_dbg_channel(BOOL add, const char* chnl, const char* name);
/* memory.c */ /* memory.c */
extern BOOL memory_read_value(const struct dbg_lvalue* val, DWORD size, void* result); extern BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result);
extern BOOL memory_write_value(const struct dbg_lvalue* val, DWORD size, void* value); extern BOOL memory_write_value(const struct dbg_lvalue* val, DWORD size, void* value);
extern void memory_examine(const struct dbg_lvalue* addr, int count, char format); extern void memory_examine(void* linear, int count, char format);
extern void memory_report_invalid_addr(const void* addr); extern void memory_report_invalid_addr(const void* addr);
extern void* memory_to_linear_addr(const ADDRESS* address); extern void* memory_to_linear_addr(const ADDRESS* address);
extern BOOL memory_get_current_pc(ADDRESS* address); extern BOOL memory_get_current_pc(ADDRESS* address);
extern BOOL memory_get_current_stack(ADDRESS* address); extern BOOL memory_get_current_stack(ADDRESS* address);
extern BOOL memory_get_current_frame(ADDRESS* address); extern BOOL memory_get_current_frame(ADDRESS* address);
extern BOOL memory_get_string(HANDLE hp, void* addr, unsigned cookie, BOOL unicode, char* buffer, int size); extern BOOL memory_get_string(HANDLE hp, void* addr, BOOL in_debuggee, BOOL unicode, char* buffer, int size);
extern BOOL memory_get_string_indirect(HANDLE hp, void* addr, BOOL unicode, char* buffer, int size); extern BOOL memory_get_string_indirect(HANDLE hp, void* addr, BOOL unicode, char* buffer, int size);
extern void memory_disassemble(const struct dbg_lvalue*, const struct dbg_lvalue*, int offset); extern void memory_disassemble(const struct dbg_lvalue*, const struct dbg_lvalue*, int offset);
extern BOOL memory_disasm_one_insn(ADDRESS* addr); extern BOOL memory_disasm_one_insn(ADDRESS* addr);
@ -333,16 +345,15 @@ extern int symbol_info_locals(void);
/* types.c */ /* types.c */
extern void print_value(const struct dbg_lvalue* addr, char format, int level); extern void print_value(const struct dbg_lvalue* addr, char format, int level);
extern int types_print_type(DWORD linear, DWORD typeid, BOOL details); extern int types_print_type(const struct dbg_type*, BOOL details);
extern int print_types(void); extern int print_types(void);
extern long int types_extract_as_integer(const struct dbg_lvalue*); extern long int types_extract_as_integer(const struct dbg_lvalue*);
extern BOOL types_deref(const struct dbg_lvalue* value, struct dbg_lvalue* result); extern BOOL types_deref(const struct dbg_lvalue* value, struct dbg_lvalue* result);
extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name, long int* tmpbuf); 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_array_index(const struct dbg_lvalue* value, int index, struct dbg_lvalue* result);
extern BOOL types_get_info(unsigned long, unsigned long, extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_TYPE_INFO, void*);
IMAGEHLP_SYMBOL_TYPE_INFO, void*); extern struct dbg_type types_find_pointer(const struct dbg_type* type);
extern unsigned long types_find_pointer(unsigned long linear, unsigned long typeid); extern struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag);
extern unsigned long types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag);
/* winedbg.c */ /* winedbg.c */
extern void dbg_outputA(const char* buffer, int len); extern void dbg_outputA(const char* buffer, int len);

View file

@ -43,10 +43,18 @@ struct display
static struct display *displaypoints = NULL; static struct display *displaypoints = NULL;
static unsigned int maxdisplays = 0, ndisplays = 0; static unsigned int maxdisplays = 0, ndisplays = 0;
#define OFFSET_OF(_f,_s) ((unsigned)(&(((_s*)NULL)->_f)))
static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2) static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
{ {
if (si1->NameLen != si2->NameLen) return FALSE; /* FIXME: !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen)
return !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen); * is wrong because sizeof(SYMBOL_INFO) can be aligned on 4-byte boundary
* Note: we also need to zero out the structures before calling
* stack_get_frame, so that un-touched fields by stack_get_frame
* get the same value!!
*/
return !memcmp(si1, si2, OFFSET_OF(Name, SYMBOL_INFO)) &&
!memcmp(si1->Name, si2->Name, si1->NameLen);
} }
int display_add(struct expr *exp, int count, char format, int in_frame) int display_add(struct expr *exp, int count, char format, int in_frame)
@ -74,6 +82,7 @@ int display_add(struct expr *exp, int count, char format, int in_frame)
if (in_frame) if (in_frame)
{ {
displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer; displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer;
memset(displaypoints[i].func, 0, sizeof(SYMBOL_INFO));
displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO); displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO);
displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) - displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) -
sizeof(*displaypoints[i].func); sizeof(*displaypoints[i].func);
@ -97,6 +106,7 @@ int display_info(void)
const char* info; const char* info;
func = (SYMBOL_INFO*)buffer; func = (SYMBOL_INFO*)buffer;
memset(func, 0, sizeof(SYMBOL_INFO));
func->SizeOfStruct = sizeof(SYMBOL_INFO); func->SizeOfStruct = sizeof(SYMBOL_INFO);
func->MaxNameLen = sizeof(buffer) - sizeof(*func); func->MaxNameLen = sizeof(buffer) - sizeof(*func);
if (!stack_get_frame(func, NULL)) return FALSE; if (!stack_get_frame(func, NULL)) return FALSE;
@ -105,6 +115,9 @@ int display_info(void)
{ {
if (displaypoints[i].exp == NULL) continue; if (displaypoints[i].exp == NULL) continue;
dbg_printf("%d: ", i + 1);
expr_print(displaypoints[i].exp);
if (displaypoints[i].enabled) if (displaypoints[i].enabled)
{ {
if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func)) if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
@ -114,10 +127,9 @@ int display_info(void)
} }
else else
info = " (disabled)"; info = " (disabled)";
dbg_printf("%d in %s%s: ", if (displaypoints[i].func)
i + 1, func ? displaypoints[i].func->Name : "", info); dbg_printf(" in %s", displaypoints[i].func->Name);
expr_print(displaypoints[i].exp); dbg_printf("%s\n", info);
dbg_printf("\n");
} }
return TRUE; return TRUE;
} }
@ -129,7 +141,7 @@ static void print_one_display(int i)
if (displaypoints[i].enabled) if (displaypoints[i].enabled)
{ {
lvalue = expr_eval(displaypoints[i].exp); lvalue = expr_eval(displaypoints[i].exp);
if (lvalue.typeid == dbg_itype_none) if (lvalue.type.id == dbg_itype_none)
{ {
dbg_printf("Unable to evaluate expression "); dbg_printf("Unable to evaluate expression ");
expr_print(displaypoints[i].exp); expr_print(displaypoints[i].exp);
@ -146,7 +158,8 @@ static void print_one_display(int i)
dbg_printf("(disabled)\n"); dbg_printf("(disabled)\n");
else else
if (displaypoints[i].format == 'i') if (displaypoints[i].format == 'i')
memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format); memory_examine((void*)types_extract_as_integer(&lvalue),
displaypoints[i].count, displaypoints[i].format);
else else
print_value(&lvalue, displaypoints[i].format, 0); print_value(&lvalue, displaypoints[i].format, 0);
} }
@ -158,6 +171,7 @@ int display_print(void)
SYMBOL_INFO* func; SYMBOL_INFO* func;
func = (SYMBOL_INFO*)buffer; func = (SYMBOL_INFO*)buffer;
memset(func, 0, sizeof(SYMBOL_INFO));
func->SizeOfStruct = sizeof(SYMBOL_INFO); func->SizeOfStruct = sizeof(SYMBOL_INFO);
func->MaxNameLen = sizeof(buffer) - sizeof(*func); func->MaxNameLen = sizeof(buffer) - sizeof(*func);
if (!stack_get_frame(func, NULL)) return FALSE; if (!stack_get_frame(func, NULL)) return FALSE;
@ -226,6 +240,7 @@ int display_enable(int displaynum, int enable)
SYMBOL_INFO* func; SYMBOL_INFO* func;
func = (SYMBOL_INFO*)buffer; func = (SYMBOL_INFO*)buffer;
memset(func, 0, sizeof(SYMBOL_INFO));
func->SizeOfStruct = sizeof(SYMBOL_INFO); func->SizeOfStruct = sizeof(SYMBOL_INFO);
func->MaxNameLen = sizeof(buffer) - sizeof(*func); func->MaxNameLen = sizeof(buffer) - sizeof(*func);
if (!stack_get_frame(func, NULL)) return FALSE; if (!stack_get_frame(func, NULL)) return FALSE;

View file

@ -282,13 +282,13 @@ struct dbg_lvalue expr_eval(struct expr* exp)
struct dbg_lvalue exp2; struct dbg_lvalue exp2;
unsigned int cexp[5]; unsigned int cexp[5];
DWORD scale1, scale2, scale3; DWORD scale1, scale2, scale3;
DWORD type1, type2; struct dbg_type type1, type2;
DWORD linear1, linear2;
DWORD tag; DWORD tag;
const struct dbg_internal_var* div; const struct dbg_internal_var* div;
rtn.typeid = dbg_itype_none;
rtn.cookie = 0; rtn.cookie = 0;
rtn.type.id = dbg_itype_none;
rtn.type.module = 0;
rtn.addr.Mode = AddrModeFlat; rtn.addr.Mode = AddrModeFlat;
rtn.addr.Offset = 0; rtn.addr.Offset = 0;
rtn.addr.Segment = 0; rtn.addr.Segment = 0;
@ -300,30 +300,31 @@ struct dbg_lvalue expr_eval(struct expr* exp)
* checking if this is right or not * checking if this is right or not
*/ */
rtn = expr_eval(exp->un.cast.expr); rtn = expr_eval(exp->un.cast.expr);
linear1 = (DWORD)memory_to_linear_addr(&rtn.addr);
switch (exp->un.cast.cast_to.type) switch (exp->un.cast.cast_to.type)
{ {
case type_expr_type_id: case type_expr_type_id:
if (exp->un.cast.cast_to.u.typeid == dbg_itype_none) if (exp->un.cast.cast_to.u.type.id == dbg_itype_none)
{ {
dbg_printf("Can't cast to unknown type\n"); dbg_printf("Can't cast to unknown type\n");
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
} }
rtn.typeid = exp->un.cast.cast_to.u.typeid; rtn.type = exp->un.cast.cast_to.u.type;
break; break;
case type_expr_udt_class: case type_expr_udt_class:
case type_expr_udt_struct: case type_expr_udt_struct:
case type_expr_udt_union: case type_expr_udt_union:
rtn.typeid = types_find_type(linear1, exp->un.cast.cast_to.u.name, SymTagUDT); rtn.type = types_find_type((DWORD)memory_to_linear_addr(&rtn.addr),
if (rtn.typeid == dbg_itype_none) exp->un.cast.cast_to.u.name, SymTagUDT);
if (rtn.type.id == dbg_itype_none)
{ {
dbg_printf("Can't cast to UDT %s\n", exp->un.cast.cast_to.u.name); dbg_printf("Can't cast to UDT %s\n", exp->un.cast.cast_to.u.name);
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
} }
break; break;
case type_expr_enumeration: case type_expr_enumeration:
rtn.typeid = types_find_type(linear1, exp->un.cast.cast_to.u.name, SymTagEnum); rtn.type = types_find_type((DWORD)memory_to_linear_addr(&rtn.addr),
if (rtn.typeid == dbg_itype_none) exp->un.cast.cast_to.u.name, SymTagEnum);
if (rtn.type.id == dbg_itype_none)
{ {
dbg_printf("Can't cast to enumeration %s\n", exp->un.cast.cast_to.u.name); dbg_printf("Can't cast to enumeration %s\n", exp->un.cast.cast_to.u.name);
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
@ -335,8 +336,8 @@ struct dbg_lvalue expr_eval(struct expr* exp)
} }
for (i = 0; i < exp->un.cast.cast_to.deref_count; i++) for (i = 0; i < exp->un.cast.cast_to.deref_count; i++)
{ {
rtn.typeid = types_find_pointer(linear1, rtn.typeid); rtn.type = types_find_pointer(&rtn.type);
if (rtn.typeid == dbg_itype_none) if (rtn.type.id == dbg_itype_none)
{ {
dbg_printf("Cannot find pointer type\n"); dbg_printf("Cannot find pointer type\n");
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
@ -344,18 +345,21 @@ struct dbg_lvalue expr_eval(struct expr* exp)
} }
break; break;
case EXPR_TYPE_STRING: case EXPR_TYPE_STRING:
rtn.typeid = dbg_itype_astring; rtn.cookie = DLV_HOST;
rtn.cookie = DLV_HOST; rtn.type.id = dbg_itype_astring;
rtn.type.module = 0;
rtn.addr.Offset = (unsigned int)&exp->un.string.str; rtn.addr.Offset = (unsigned int)&exp->un.string.str;
break; break;
case EXPR_TYPE_U_CONST: case EXPR_TYPE_U_CONST:
rtn.typeid = dbg_itype_unsigned_int;
rtn.cookie = DLV_HOST; rtn.cookie = DLV_HOST;
rtn.type.id = dbg_itype_unsigned_int;
rtn.type.module = 0;
rtn.addr.Offset = (unsigned int)&exp->un.u_const.value; rtn.addr.Offset = (unsigned int)&exp->un.u_const.value;
break; break;
case EXPR_TYPE_S_CONST: case EXPR_TYPE_S_CONST:
rtn.typeid = dbg_itype_signed_int;
rtn.cookie = DLV_HOST; rtn.cookie = DLV_HOST;
rtn.type.id = dbg_itype_signed_int;
rtn.type.module = 0;
rtn.addr.Offset = (unsigned int)&exp->un.s_const.value; rtn.addr.Offset = (unsigned int)&exp->un.s_const.value;
break; break;
case EXPR_TYPE_SYMBOL: case EXPR_TYPE_SYMBOL:
@ -373,8 +377,8 @@ struct dbg_lvalue expr_eval(struct expr* exp)
break; break;
case EXPR_TYPE_PSTRUCT: case EXPR_TYPE_PSTRUCT:
exp1 = expr_eval(exp->un.structure.exp1); exp1 = expr_eval(exp->un.structure.exp1);
if (exp1.typeid == dbg_itype_none || !types_deref(&exp1, &rtn) || if (exp1.type.id == dbg_itype_none || !types_deref(&exp1, &rtn) ||
rtn.typeid == 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)) &exp->un.structure.result))
@ -385,7 +389,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
break; break;
case EXPR_TYPE_STRUCT: case EXPR_TYPE_STRUCT:
exp1 = expr_eval(exp->un.structure.exp1); exp1 = expr_eval(exp->un.structure.exp1);
if (exp1.typeid == 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)) &exp->un.structure.result))
@ -402,7 +406,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
for (i = 0; i < exp->un.call.nargs; i++) for (i = 0; i < exp->un.call.nargs; i++)
{ {
exp1 = expr_eval(exp->un.call.arg[i]); exp1 = expr_eval(exp->un.call.arg[i]);
if (exp1.typeid == dbg_itype_none) if (exp1.type.id == dbg_itype_none)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
cexp[i] = types_extract_as_integer(&exp1); cexp[i] = types_extract_as_integer(&exp1);
} }
@ -458,93 +462,93 @@ struct dbg_lvalue expr_eval(struct expr* exp)
*/ */
exp->un.call.result = 0; exp->un.call.result = 0;
#endif #endif
linear1 = (DWORD)memory_to_linear_addr(&rtn.addr);
/* get function signature type */
types_get_info(linear1, rtn.typeid, TI_GET_TYPE, &rtn.typeid);
/* and now, return type */
types_get_info(linear1, rtn.typeid, TI_GET_TYPE, &rtn.typeid);
rtn.cookie = DLV_HOST; rtn.cookie = DLV_HOST;
rtn.addr.Mode = AddrModeFlat; /* get function signature type */
types_get_info(&rtn.type, TI_GET_TYPE, &rtn.type);
/* and now, return type */
types_get_info(&rtn.type, TI_GET_TYPE, &rtn.type);
rtn.addr.Offset = (unsigned int)&exp->un.call.result; rtn.addr.Offset = (unsigned int)&exp->un.call.result;
break; break;
case EXPR_TYPE_INTVAR: case EXPR_TYPE_INTVAR:
rtn.cookie = DLV_HOST;
if (!(div = dbg_get_internal_var(exp->un.intvar.name))) if (!(div = dbg_get_internal_var(exp->un.intvar.name)))
RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL); RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL);
rtn.cookie = DLV_HOST; rtn.type.id = div->typeid;
rtn.typeid = div->typeid; rtn.type.module = 0;
rtn.addr.Offset = (unsigned int)div->pval; rtn.addr.Offset = (unsigned int)div->pval;
break; break;
case EXPR_TYPE_BINOP: case EXPR_TYPE_BINOP:
rtn.cookie = DLV_HOST;
exp1 = expr_eval(exp->un.binop.exp1); exp1 = expr_eval(exp->un.binop.exp1);
exp2 = expr_eval(exp->un.binop.exp2); exp2 = expr_eval(exp->un.binop.exp2);
rtn.cookie = DLV_HOST; if (exp1.type.id == dbg_itype_none || exp2.type.id == dbg_itype_none)
if (exp1.typeid == dbg_itype_none || exp2.typeid == dbg_itype_none)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
linear1 = (DWORD)memory_to_linear_addr(&exp1.addr); rtn.type.id = dbg_itype_signed_int;
linear2 = (DWORD)memory_to_linear_addr(&exp2.addr); rtn.type.module = 0;
rtn.typeid = dbg_itype_signed_int;
rtn.addr.Offset = (unsigned int)&exp->un.binop.result; rtn.addr.Offset = (unsigned int)&exp->un.binop.result;
switch (exp->un.binop.binop_type) switch (exp->un.binop.binop_type)
{ {
case EXP_OP_ADD: case EXP_OP_ADD:
if (!types_get_info(linear1, exp1.typeid, TI_GET_SYMTAG, &tag) || if (!types_get_info(&exp1.type, TI_GET_SYMTAG, &tag) ||
tag != SymTagPointerType || tag != SymTagPointerType ||
!types_get_info(linear1, exp1.typeid, TI_GET_TYPE, &type1)) !types_get_info(&exp1.type, TI_GET_TYPE, &type1))
type1 = dbg_itype_none; type1.id = dbg_itype_none;
if (!types_get_info(linear1, exp2.typeid, TI_GET_SYMTAG, &tag) || if (!types_get_info(&exp2.type, TI_GET_SYMTAG, &tag) ||
tag != SymTagPointerType || tag != SymTagPointerType ||
!types_get_info(linear1, exp2.typeid, TI_GET_TYPE, &type2)) !types_get_info(&exp2.type, TI_GET_TYPE, &type2))
type2 = dbg_itype_none; type2.id = dbg_itype_none;
scale1 = 1; scale1 = 1;
scale2 = 1; scale2 = 1;
if (type1 != dbg_itype_none && type2 != dbg_itype_none) if (type1.id != dbg_itype_none && type2.id != dbg_itype_none)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
if (type1 != dbg_itype_none) if (type1.id != dbg_itype_none)
{ {
types_get_info(linear1, type1, TI_GET_LENGTH, &scale2); types_get_info(&type1, TI_GET_LENGTH, &scale2);
rtn.typeid = exp1.typeid; rtn.type = exp1.type;
} }
else if (type2 != dbg_itype_none) else if (type2.id != dbg_itype_none)
{ {
types_get_info(linear2, type2, TI_GET_LENGTH, &scale1); types_get_info(&type2, TI_GET_LENGTH, &scale1);
rtn.typeid = exp2.typeid; rtn.type = exp2.type;
} }
exp->un.binop.result = (types_extract_as_integer(&exp1) * scale1 + exp->un.binop.result = (types_extract_as_integer(&exp1) * scale1 +
scale2 * types_extract_as_integer(&exp2)); scale2 * types_extract_as_integer(&exp2));
break; break;
case EXP_OP_SUB: case EXP_OP_SUB:
if (!types_get_info(linear1, exp1.typeid, TI_GET_SYMTAG, &tag) || if (!types_get_info(&exp1.type, TI_GET_SYMTAG, &tag) ||
tag != SymTagPointerType || tag != SymTagPointerType ||
!types_get_info(linear1, exp1.typeid, TI_GET_TYPE, &type1)) !types_get_info(&exp1.type, TI_GET_TYPE, &type1))
type1 = dbg_itype_none; type1.id = dbg_itype_none;
if (!types_get_info(linear2, exp2.typeid, TI_GET_SYMTAG, &tag) || if (!types_get_info(&exp2.type, TI_GET_SYMTAG, &tag) ||
tag != SymTagPointerType || tag != SymTagPointerType ||
!types_get_info(linear2, exp2.typeid, TI_GET_TYPE, &type2)) !types_get_info(&exp2.type, TI_GET_TYPE, &type2))
type2 = dbg_itype_none; type2.id = dbg_itype_none;
scale1 = 1; scale1 = 1;
scale2 = 1; scale2 = 1;
scale3 = 1; scale3 = 1;
if (type1 != dbg_itype_none && type2 != dbg_itype_none) if (type1.id != dbg_itype_none && type2.id != dbg_itype_none)
{ {
if (type1 != type2) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); WINE_FIXME("This may fail (if module base address are wrongly calculated)\n");
types_get_info(linear1, type1, TI_GET_LENGTH, &scale3); if (memcmp(&type1, &type2, sizeof(struct dbg_type)))
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
types_get_info(&type1, TI_GET_LENGTH, &scale3);
} }
else if (type1 != dbg_itype_none) else if (type1.id != dbg_itype_none)
{ {
types_get_info(linear1, type1, TI_GET_LENGTH, &scale2); types_get_info(&type1, TI_GET_LENGTH, &scale2);
rtn.typeid = exp1.typeid; rtn.type = exp1.type;
} }
else if (type2 != dbg_itype_none) else if (type2.id != dbg_itype_none)
{ {
types_get_info(linear2, type2, TI_GET_LENGTH, &scale1); types_get_info(&type2, TI_GET_LENGTH, &scale1);
rtn.typeid = exp2.typeid; rtn.type = exp2.type;
} }
exp->un.binop.result = (types_extract_as_integer(&exp1) * scale1 - exp->un.binop.result = (types_extract_as_integer(&exp1) * scale1 -
types_extract_as_integer(&exp2) * scale2) / scale3; types_extract_as_integer(&exp2) * scale2) / scale3;
break; break;
case EXP_OP_SEG: case EXP_OP_SEG:
rtn.cookie = DLV_TARGET; rtn.type.id = dbg_itype_none;
rtn.typeid = dbg_itype_none; rtn.type.module = 0;
rtn.addr.Mode = AddrMode1632; rtn.addr.Mode = AddrMode1632;
rtn.addr.Segment = types_extract_as_integer(&exp1); rtn.addr.Segment = types_extract_as_integer(&exp1);
rtn.addr.Offset = types_extract_as_integer(&exp2); rtn.addr.Offset = types_extract_as_integer(&exp2);
@ -607,11 +611,12 @@ struct dbg_lvalue expr_eval(struct expr* exp)
} }
break; break;
case EXPR_TYPE_UNOP: case EXPR_TYPE_UNOP:
exp1 = expr_eval(exp->un.unop.exp1);
if (exp1.typeid == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
rtn.cookie = DLV_HOST; rtn.cookie = DLV_HOST;
exp1 = expr_eval(exp->un.unop.exp1);
if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
rtn.addr.Offset = (unsigned int)&exp->un.unop.result; rtn.addr.Offset = (unsigned int)&exp->un.unop.result;
rtn.typeid = dbg_itype_signed_int; rtn.type.id = dbg_itype_signed_int;
rtn.type.module = 0;
switch (exp->un.unop.unop_type) switch (exp->un.unop.unop_type)
{ {
case EXP_OP_NEG: case EXP_OP_NEG:
@ -624,19 +629,6 @@ struct dbg_lvalue expr_eval(struct expr* exp)
exp->un.unop.result = ~types_extract_as_integer(&exp1); exp->un.unop.result = ~types_extract_as_integer(&exp1);
break; break;
case EXP_OP_DEREF: case EXP_OP_DEREF:
/* FIXME: this is currently buggy.
* there is no way to tell were the deref:ed value is...
* for example:
* x is a pointer to struct s, x being on the stack
* => exp1 is target, result is target
* x is a pointer to struct s, x being optimized into a reg
* => exp1 is host, result is target
* x is a pointer to internal variable x
* => exp1 is host, result is host
* so we force DLV_TARGET, because dereferencing pointers to
* internal variables is very unlikely. a correct fix would be
* rather large.
*/
if (!types_deref(&exp1, &rtn)) if (!types_deref(&exp1, &rtn))
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
break; break;
@ -650,7 +642,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
if (exp1.addr.Mode != AddrModeFlat) if (exp1.addr.Mode != AddrModeFlat)
RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL); RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL);
exp->un.unop.result = (unsigned int)memory_to_linear_addr(&exp1.addr); exp->un.unop.result = (unsigned int)memory_to_linear_addr(&exp1.addr);
rtn.typeid = types_find_pointer(exp->un.unop.result, exp1.typeid); rtn.type = types_find_pointer(&exp1.type);
break; break;
default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
} }
@ -661,14 +653,13 @@ struct dbg_lvalue expr_eval(struct expr* exp)
break; break;
} }
assert(rtn.cookie == DLV_TARGET || rtn.cookie == DLV_HOST);
return rtn; return rtn;
} }
int expr_print(const struct expr* exp) int expr_print(const struct expr* exp)
{ {
int i; int i;
struct dbg_type type;
switch (exp->type) switch (exp->type)
{ {
@ -678,7 +669,9 @@ int expr_print(const struct expr* exp)
switch (exp->un.cast.cast_to.type) switch (exp->un.cast.cast_to.type)
{ {
case type_expr_type_id: case type_expr_type_id:
types_print_type(0, exp->un.cast.cast_to.type, FALSE); break; type.module = 0;
type.id = exp->un.cast.cast_to.type;
types_print_type(&type, FALSE); break;
case type_expr_udt_class: case type_expr_udt_class:
dbg_printf("class %s", exp->un.cast.cast_to.u.name); break; dbg_printf("class %s", exp->un.cast.cast_to.u.name); break;
case type_expr_udt_struct: case type_expr_udt_struct:

View file

@ -468,7 +468,7 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
case OUTPUT_DEBUG_STRING_EVENT: case OUTPUT_DEBUG_STRING_EVENT:
assert(dbg_curr_thread); assert(dbg_curr_thread);
memory_get_string(gdbctx->process->handle, memory_get_string(gdbctx->process->handle,
de->u.DebugString.lpDebugStringData, DLV_TARGET, de->u.DebugString.lpDebugStringData, TRUE,
de->u.DebugString.fUnicode, buffer, sizeof(buffer)); de->u.DebugString.fUnicode, buffer, sizeof(buffer));
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n", fprintf(stderr, "%08lx:%08lx: output debug string (%s)\n",

View file

@ -99,7 +99,6 @@ BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result
} }
else else
{ {
assert(lvalue->addr.Mode == AddrModeFlat);
if (!lvalue->addr.Offset) return FALSE; if (!lvalue->addr.Offset) return FALSE;
memcpy(result, (void*)lvalue->addr.Offset, size); memcpy(result, (void*)lvalue->addr.Offset, size);
} }
@ -118,7 +117,7 @@ BOOL memory_write_value(const struct dbg_lvalue* lvalue, DWORD size, void* value
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr); DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
os = ~size; os = ~size;
types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &os); types_get_info(&lvalue->type, TI_GET_LENGTH, &os);
assert(size == os); assert(size == os);
/* FIXME: only works on little endian systems */ /* FIXME: only works on little endian systems */
@ -128,7 +127,6 @@ BOOL memory_write_value(const struct dbg_lvalue* lvalue, DWORD size, void* value
} }
else else
{ {
assert(lvalue->addr.Mode == AddrModeFlat);
memcpy((void*)lvalue->addr.Offset, value, size); memcpy((void*)lvalue->addr.Offset, value, size);
} }
return ret; return ret;
@ -139,17 +137,18 @@ BOOL memory_write_value(const struct dbg_lvalue* lvalue, DWORD size, void* value
* *
* Implementation of the 'x' command. * Implementation of the 'x' command.
*/ */
void memory_examine(const struct dbg_lvalue* lvalue, int count, char format) void memory_examine(void* linear, int count, char format)
{ {
int i; int i;
ADDRESS x;
char buffer[256]; char buffer[256];
ADDRESS addr;
addr.Mode = AddrModeFlat;
addr.Offset = (unsigned long)linear;
x.Mode = AddrModeFlat;
x.Offset = types_extract_as_integer(lvalue);
if (format != 'i' && count > 1) if (format != 'i' && count > 1)
{ {
print_address(&x, FALSE); print_address(&addr, FALSE);
dbg_printf(": "); dbg_printf(": ");
} }
@ -157,32 +156,33 @@ void memory_examine(const struct dbg_lvalue* lvalue, int count, char format)
{ {
case 'u': case 'u':
if (count == 1) count = 256; if (count == 1) count = 256;
memory_get_string(dbg_curr_thread->handle, (void*)x.Offset, lvalue->cookie, memory_get_string(dbg_curr_process->handle, linear,
TRUE, buffer, min(count, sizeof(buffer))); TRUE, TRUE, buffer, min(count, sizeof(buffer)));
dbg_printf("%s\n", buffer); dbg_printf("%s\n", buffer);
return; return;
case 's': case 's':
if (count == 1) count = 256; if (count == 1) count = 256;
memory_get_string(dbg_curr_thread->handle, (void*)x.Offset, lvalue->cookie, memory_get_string(dbg_curr_process->handle, linear,
FALSE, buffer, min(count, sizeof(buffer))); TRUE, FALSE, buffer, min(count, sizeof(buffer)));
dbg_printf("%s\n", buffer); dbg_printf("%s\n", buffer);
return; return;
case 'i': case 'i':
while (count-- && memory_disasm_one_insn(&x)); while (count-- && memory_disasm_one_insn(&addr));
return; return;
case 'g': case 'g':
while (count--) while (count--)
{ {
GUID guid; GUID guid;
if (!dbg_read_memory_verbose((void*)x.Offset, &guid, sizeof(guid))) break; if (!dbg_read_memory_verbose(linear, &guid, sizeof(guid))) break;
dbg_printf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", dbg_printf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
guid.Data1, guid.Data2, guid.Data3, guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
x.Offset += sizeof(guid); linear = (char*)linear + sizeof(guid);
addr.Offset += sizeof(guid);
if (count) if (count)
{ {
print_address(&x, FALSE); print_address(&addr, FALSE);
dbg_printf(": "); dbg_printf(": ");
} }
} }
@ -191,13 +191,15 @@ void memory_examine(const struct dbg_lvalue* lvalue, int count, char format)
#define DO_DUMP2(_t,_l,_f,_vv) { \ #define DO_DUMP2(_t,_l,_f,_vv) { \
_t _v; \ _t _v; \
for (i = 0; i < count; i++) { \ for (i = 0; i < count; i++) { \
if (!dbg_read_memory_verbose((void*)x.Offset, &_v, \ if (!dbg_read_memory_verbose(linear, &_v, \
sizeof(_t))) break; \ sizeof(_t))) break; \
dbg_printf(_f, (_vv)); \ dbg_printf(_f, (_vv)); \
x.Offset += sizeof(_t); \ addr.Offset += sizeof(_t); \
if ((i % (_l)) == (_l) - 1) { \ linear = (char*)linear + sizeof(_t); \
if ((i % (_l)) == (_l) - 1 && i != count - 1) \
{ \
dbg_printf("\n"); \ dbg_printf("\n"); \
print_address(&x, FALSE); \ print_address(&addr, FALSE); \
dbg_printf(": "); \ dbg_printf(": "); \
} \ } \
} \ } \
@ -214,7 +216,7 @@ void memory_examine(const struct dbg_lvalue* lvalue, int count, char format)
} }
} }
BOOL memory_get_string(HANDLE hp, void* addr, unsigned cookie, BOOL unicode, BOOL memory_get_string(HANDLE hp, void* addr, BOOL in_debuggee, BOOL unicode,
char* buffer, int size) char* buffer, int size)
{ {
DWORD sz; DWORD sz;
@ -222,9 +224,8 @@ BOOL memory_get_string(HANDLE hp, void* addr, unsigned cookie, BOOL unicode,
buffer[0] = 0; buffer[0] = 0;
if (!addr) return FALSE; if (!addr) return FALSE;
switch (cookie) if (in_debuggee)
{ {
case DLV_TARGET:
if (!unicode) return ReadProcessMemory(hp, addr, buffer, size, &sz); if (!unicode) return ReadProcessMemory(hp, addr, buffer, size, &sz);
buffW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); buffW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
@ -232,13 +233,13 @@ BOOL memory_get_string(HANDLE hp, void* addr, unsigned cookie, BOOL unicode,
WideCharToMultiByte(CP_ACP, 0, buffW, sz / sizeof(WCHAR), buffer, size, WideCharToMultiByte(CP_ACP, 0, buffW, sz / sizeof(WCHAR), buffer, size,
NULL, NULL); NULL, NULL);
HeapFree(GetProcessHeap(), 0, buffW); HeapFree(GetProcessHeap(), 0, buffW);
return TRUE; }
case DLV_HOST: else
{
strncpy(buffer, addr, size); strncpy(buffer, addr, size);
buffer[size - 1] = 0; buffer[size - 1] = 0;
return TRUE;
} }
return FALSE; return TRUE;
} }
BOOL memory_get_string_indirect(HANDLE hp, void* addr, BOOL unicode, char* buffer, int size) BOOL memory_get_string_indirect(HANDLE hp, void* addr, BOOL unicode, char* buffer, int size)
@ -250,7 +251,7 @@ BOOL memory_get_string_indirect(HANDLE hp, void* addr, BOOL unicode, char* buffe
if (addr && if (addr &&
ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz) && sz == sizeof(ad) && ad) ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz) && sz == sizeof(ad) && ad)
{ {
return memory_get_string(hp, ad, DLV_TARGET, unicode, buffer, size); return memory_get_string(hp, ad, TRUE, unicode, buffer, size);
} }
return FALSE; return FALSE;
} }
@ -260,20 +261,19 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue)
long long int val_int; long long int val_int;
void* val_ptr; void* val_ptr;
long double val_real; long double val_real;
DWORD tag, size, count, bt, rtype; DWORD tag, size, count, bt;
struct dbg_type rtype;
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr); DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (lvalue->type.id == dbg_itype_none ||
!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
if (lvalue->typeid == dbg_itype_none ||
!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag))
return; return;
switch (tag) switch (tag)
{ {
case SymTagBaseType: case SymTagBaseType:
if (!types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &size) || if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size) ||
!types_get_info(linear, lvalue->typeid, TI_GET_BASETYPE, &bt)) !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt))
{ {
WINE_ERR("Couldn't get information\n"); WINE_ERR("Couldn't get information\n");
RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
@ -309,20 +309,21 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue)
case SymTagPointerType: case SymTagPointerType:
if (!memory_read_value(lvalue, sizeof(void*), &val_ptr)) return; if (!memory_read_value(lvalue, sizeof(void*), &val_ptr)) return;
if (!types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &rtype) || if (!types_get_info(&lvalue->type, TI_GET_TYPE, &rtype.id) ||
rtype == dbg_itype_none) rtype.id == dbg_itype_none)
{ {
dbg_printf("Internal symbol error: unable to access memory location %p", val_ptr); dbg_printf("Internal symbol error: unable to access memory location %p", val_ptr);
break; break;
} }
rtype.module = lvalue->type.module;
if (types_get_info(linear, rtype, TI_GET_SYMTAG, &tag) && tag == SymTagBaseType && if (types_get_info(&rtype, TI_GET_SYMTAG, &tag) && tag == SymTagBaseType &&
types_get_info(linear, rtype, TI_GET_BASETYPE, &bt) && bt == btChar && types_get_info(&rtype, TI_GET_BASETYPE, &bt) && bt == btChar &&
types_get_info(linear, rtype, TI_GET_LENGTH, &size)) types_get_info(&rtype, TI_GET_LENGTH, &size))
{ {
char buffer[1024]; char buffer[1024];
memory_get_string(dbg_curr_thread->handle, (void*)val_ptr, lvalue->cookie, memory_get_string(dbg_curr_process->handle, val_ptr,
lvalue->cookie == DLV_TARGET,
size == 2, buffer, sizeof(buffer)); size == 2, buffer, sizeof(buffer));
dbg_printf("\"%s\"", buffer); dbg_printf("\"%s\"", buffer);
} }
@ -345,24 +346,27 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue)
*/ */
if (!be_cpu->fetch_integer(lvalue, 4, TRUE, &val_int)) return; if (!be_cpu->fetch_integer(lvalue, 4, TRUE, &val_int)) return;
if (types_get_info(linear, lvalue->typeid, TI_GET_CHILDRENCOUNT, &count)) if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
{ {
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;
char tmp[256]; char tmp[256];
VARIANT variant; VARIANT variant;
int i; int i;
struct dbg_type type;
fcp->Start = 0; fcp->Start = 0;
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(linear, lvalue->typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
{ {
type.module = linear;
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
if (!types_get_info(linear, fcp->ChildId[i], TI_GET_VALUE, &variant)) type.id = fcp->ChildId[i];
if (!types_get_info(&type, TI_GET_VALUE, &variant))
continue; continue;
switch (variant.n1.n2.vt) switch (variant.n1.n2.vt)
{ {
@ -372,7 +376,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue)
if (ok) if (ok)
{ {
ptr = NULL; ptr = NULL;
types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr); types_get_info(&type, TI_GET_SYMNAME, &ptr);
if (!ptr) continue; if (!ptr) continue;
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);
@ -404,8 +408,7 @@ void print_basic(const struct dbg_lvalue* lvalue, int count, char format)
{ {
long int res; long int res;
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (lvalue->type.id == dbg_itype_none)
if (lvalue->typeid == dbg_itype_none)
{ {
dbg_printf("Unable to evaluate expression\n"); dbg_printf("Unable to evaluate expression\n");
return; return;
@ -465,6 +468,9 @@ void print_bare_address(const ADDRESS* addr)
case AddrMode1632: case AddrMode1632:
dbg_printf("0x%04x:0x%08lx", addr->Segment, addr->Offset); dbg_printf("0x%04x:0x%08lx", addr->Segment, addr->Offset);
break; break;
default:
dbg_printf("Unknown mode %x\n", addr->Mode);
break;
} }
} }
@ -499,7 +505,7 @@ void print_address(const ADDRESS* addr, BOOLEAN with_line)
} }
} }
struct foo struct sym_enum
{ {
char* tmp; char* tmp;
DWORD frame; DWORD frame;
@ -507,19 +513,23 @@ struct foo
static BOOL WINAPI sym_enum_cb(SYMBOL_INFO* sym_info, ULONG size, void* user) static BOOL WINAPI sym_enum_cb(SYMBOL_INFO* sym_info, ULONG size, void* user)
{ {
struct foo* foo = (struct foo*)user; struct sym_enum* se = (struct sym_enum*)user;
DWORD addr; DWORD addr;
unsigned val; unsigned val;
long offset; long offset;
if ((sym_info->Flags & (SYMFLAG_PARAMETER|SYMFLAG_FRAMEREL)) == (SYMFLAG_PARAMETER|SYMFLAG_FRAMEREL)) if ((sym_info->Flags & (SYMFLAG_PARAMETER|SYMFLAG_FRAMEREL)) == (SYMFLAG_PARAMETER|SYMFLAG_FRAMEREL))
{ {
if (foo->tmp[0]) strcat(foo->tmp, ", "); struct dbg_type type;
addr = foo->frame;
types_get_info(sym_info->ModBase, sym_info->TypeIndex, TI_GET_OFFSET, &offset); if (se->tmp[0]) strcat(se->tmp, ", ");
addr = se->frame;
type.module = sym_info->ModBase;
type.id = sym_info->TypeIndex;
types_get_info(&type, TI_GET_OFFSET, &offset);
addr += offset; addr += offset;
dbg_read_memory_verbose((char*)addr, &val, sizeof(val)); dbg_read_memory_verbose((char*)addr, &val, sizeof(val));
sprintf(foo->tmp + strlen(foo->tmp), "%s=0x%x", sym_info->Name, val); sprintf(se->tmp + strlen(se->tmp), "%s=0x%x", sym_info->Name, val);
} }
return TRUE; return TRUE;
} }
@ -531,7 +541,7 @@ void print_addr_and_args(const ADDRESS* pc, const ADDRESS* frame)
IMAGEHLP_STACK_FRAME isf; IMAGEHLP_STACK_FRAME isf;
IMAGEHLP_LINE il; IMAGEHLP_LINE il;
IMAGEHLP_MODULE im; IMAGEHLP_MODULE im;
struct foo foo; struct sym_enum se;
char tmp[1024]; char tmp[1024];
DWORD disp; DWORD disp;
@ -552,10 +562,10 @@ void print_addr_and_args(const ADDRESS* pc, const ADDRESS* frame)
if (disp) dbg_printf("+0x%lx", disp); if (disp) dbg_printf("+0x%lx", disp);
SymSetContext(dbg_curr_process->handle, &isf, NULL); SymSetContext(dbg_curr_process->handle, &isf, NULL);
foo.tmp = tmp; se.tmp = tmp;
foo.frame = isf.FrameOffset; se.frame = isf.FrameOffset;
tmp[0] = '\0'; tmp[0] = '\0';
SymEnumSymbols(dbg_curr_process->handle, 0, NULL, sym_enum_cb, &foo); SymEnumSymbols(dbg_curr_process->handle, 0, NULL, sym_enum_cb, &se);
if (tmp[0]) dbg_printf("(%s)", tmp); if (tmp[0]) dbg_printf("(%s)", tmp);
il.SizeOfStruct = sizeof(il); il.SizeOfStruct = sizeof(il);

View file

@ -42,27 +42,24 @@ static IMAGEHLP_STACK_FRAME* frames = NULL;
*/ */
void stack_info(void) void stack_info(void)
{ {
struct dbg_lvalue lvalue; ADDRESS addr;
lvalue.typeid = dbg_itype_none;
lvalue.cookie = DLV_TARGET;
/* FIXME: we assume stack grows the same way as on i386 */ /* FIXME: we assume stack grows the same way as on i386 */
if (!memory_get_current_stack(&lvalue.addr)) if (!memory_get_current_stack(&addr))
dbg_printf("Bad segment (%d)\n", lvalue.addr.Segment); dbg_printf("Bad segment (%d)\n", addr.Segment);
dbg_printf("Stack dump:\n"); dbg_printf("Stack dump:\n");
switch (lvalue.addr.Mode) switch (addr.Mode)
{ {
case AddrModeFlat: /* 32-bit mode */ case AddrModeFlat: /* 32-bit mode */
case AddrMode1632: /* 32-bit mode */ case AddrMode1632: /* 32-bit mode */
memory_examine(&lvalue, 24, 'x'); memory_examine(memory_to_linear_addr(&addr), 24, 'x');
break; break;
case AddrModeReal: /* 16-bit mode */ case AddrModeReal: /* 16-bit mode */
case AddrMode1616: case AddrMode1616:
memory_examine(&lvalue, 24, 'w'); memory_examine(memory_to_linear_addr(&addr), 24, 'w');
break; break;
} }
dbg_printf("\n");
} }
int stack_set_frame(int newframe) int stack_set_frame(int newframe)

View file

@ -38,19 +38,24 @@ static BOOL symbol_get_debug_start(DWORD mod_base, DWORD typeid, DWORD* start)
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;
int i; int i;
struct dbg_type type;
if (!types_get_info(mod_base, typeid, TI_GET_CHILDRENCOUNT, &count)) return FALSE; type.module = mod_base;
type.id = typeid;
if (!types_get_info(&type, TI_GET_CHILDRENCOUNT, &count)) return FALSE;
fcp->Start = 0; fcp->Start = 0;
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(mod_base, typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(&type, TI_FINDCHILDREN, fcp))
{ {
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
types_get_info(mod_base, fcp->ChildId[i], TI_GET_SYMTAG, &tag); type.id = fcp->ChildId[i];
types_get_info(&type, TI_GET_SYMTAG, &tag);
if (tag != SymTagFuncDebugStart) continue; if (tag != SymTagFuncDebugStart) continue;
return types_get_info(mod_base, fcp->ChildId[i], TI_GET_ADDRESS, start); return types_get_info(&type, TI_GET_ADDRESS, start);
} }
count -= min(count, 256); count -= min(count, 256);
fcp->Start += 256; fcp->Start += 256;
@ -107,7 +112,11 @@ static BOOL CALLBACK sgv_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
else if (sym->Flags & SYMFLAG_FRAMEREL) else if (sym->Flags & SYMFLAG_FRAMEREL)
{ {
ULONG offset; ULONG offset;
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_OFFSET, &offset); struct dbg_type type;
type.module = sym->ModBase;
type.id = sym->TypeIndex;
types_get_info(&type, TI_GET_OFFSET, &offset);
addr = sgv->ihsf.FrameOffset + offset; addr = sgv->ihsf.FrameOffset + offset;
} }
else if (sym->Flags & SYMFLAG_THUNK) else if (sym->Flags & SYMFLAG_THUNK)
@ -175,11 +184,13 @@ static BOOL CALLBACK sgv_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
memmove(&sgv->syms[insp + 1], &sgv->syms[insp], memmove(&sgv->syms[insp + 1], &sgv->syms[insp],
sizeof(sgv->syms[0]) * sgv->num_thunks); sizeof(sgv->syms[0]) * sgv->num_thunks);
} }
sgv->syms[insp].lvalue.cookie = cookie;
sgv->syms[insp].lvalue.addr.Mode = AddrModeFlat; sgv->syms[insp].lvalue.addr.Mode = AddrModeFlat;
sgv->syms[insp].lvalue.addr.Offset = addr; sgv->syms[insp].lvalue.addr.Offset = addr;
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, sgv->syms[insp].lvalue.type.module = sym->ModBase;
&sgv->syms[insp].lvalue.typeid); sgv->syms[insp].lvalue.type.id = sym->TypeIndex;
sgv->syms[insp].lvalue.cookie = cookie; types_get_info(&sgv->syms[insp].lvalue.type, TI_GET_TYPE,
&sgv->syms[insp].lvalue.type.id);
sgv->syms[insp].flags = sym->Flags; sgv->syms[insp].flags = sym->Flags;
sgv->num++; sgv->num++;
@ -314,8 +325,9 @@ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno,
} }
else else
{ {
dbg_printf("More than one symbol named %s, picking the first one\n", name); /* FIXME: could display the list of non-picked up symbols */
i = 0; if (sgv.num > 1)
dbg_printf("More than one symbol named %s, picking the first one\n", name);
} }
*rtn = sgv.syms[i].lvalue; *rtn = sgv.syms[i].lvalue;
return sglv_found; return sglv_found;
@ -390,6 +402,7 @@ enum dbg_line_status symbol_get_function_line_status(const ADDRESS* addr)
DWORD lin = (DWORD)memory_to_linear_addr(addr); DWORD lin = (DWORD)memory_to_linear_addr(addr);
char buffer[sizeof(SYMBOL_INFO) + 256]; char buffer[sizeof(SYMBOL_INFO) + 256];
SYMBOL_INFO* sym = (SYMBOL_INFO*)buffer; SYMBOL_INFO* sym = (SYMBOL_INFO*)buffer;
struct dbg_type type;
il.SizeOfStruct = sizeof(il); il.SizeOfStruct = sizeof(il);
sym->SizeOfStruct = sizeof(SYMBOL_INFO); sym->SizeOfStruct = sizeof(SYMBOL_INFO);
@ -419,7 +432,9 @@ enum dbg_line_status symbol_get_function_line_status(const ADDRESS* addr)
if (symbol_get_debug_start(sym->ModBase, sym->TypeIndex, &start) && lin < start) if (symbol_get_debug_start(sym->ModBase, sym->TypeIndex, &start) && lin < start)
return dbg_not_on_a_line_number; return dbg_not_on_a_line_number;
if (!types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_LENGTH, &size) || size == 0) type.module = sym->ModBase;
type.id = sym->TypeIndex;
if (!types_get_info(&type, TI_GET_LENGTH, &size) || size == 0)
size = 0x100000; size = 0x100000;
if (il.FileName && il.FileName[0] && disp < size) if (il.FileName && il.FileName[0] && disp < size)
return (disp == 0) ? dbg_on_a_line_number : dbg_not_on_a_line_number; return (disp == 0) ? dbg_on_a_line_number : dbg_not_on_a_line_number;
@ -492,14 +507,16 @@ BOOL symbol_get_line(const char* filename, const char* name, IMAGEHLP_LINE* line
static BOOL CALLBACK info_locals_cb(SYMBOL_INFO* sym, ULONG size, void* ctx) static BOOL CALLBACK info_locals_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
{ {
DWORD tid; ULONG v, val;
ULONG v, val; const char* explain = NULL;
const char* explain = NULL; char buf[128];
char buf[128]; struct dbg_type type;
dbg_printf("\t"); dbg_printf("\t");
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &tid); type.module = sym->ModBase;
types_print_type(sym->ModBase, tid, FALSE); type.id = sym->TypeIndex;
types_get_info(&type, TI_GET_TYPE, &type.id);
types_print_type(&type, FALSE);
if (sym->Flags & SYMFLAG_LOCAL) explain = "local"; if (sym->Flags & SYMFLAG_LOCAL) explain = "local";
else if (sym->Flags & SYMFLAG_PARAMETER) explain = "parameter"; else if (sym->Flags & SYMFLAG_PARAMETER) explain = "parameter";
@ -527,7 +544,8 @@ static BOOL CALLBACK info_locals_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
} }
else if (sym->Flags & SYMFLAG_FRAMEREL) else if (sym->Flags & SYMFLAG_FRAMEREL)
{ {
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_OFFSET, &v); type.id = sym->TypeIndex;
types_get_info(&type, TI_GET_OFFSET, &v);
v += ((IMAGEHLP_STACK_FRAME*)ctx)->FrameOffset; v += ((IMAGEHLP_STACK_FRAME*)ctx)->FrameOffset;
dbg_read_memory_verbose((void*)v, &val, sizeof(val)); dbg_read_memory_verbose((void*)v, &val, sizeof(val));
@ -556,13 +574,13 @@ int symbol_info_locals(void)
static BOOL CALLBACK symbols_info_cb(SYMBOL_INFO* sym, ULONG size, void* ctx) static BOOL CALLBACK symbols_info_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
{ {
DWORD type; struct dbg_type type;
dbg_printf("%08lx: %s (", sym->Address, sym->Name); dbg_printf("%08lx: %s (", sym->Address, sym->Name);
if (sym->TypeIndex != dbg_itype_none && sym->TypeIndex != 0 && if (sym->TypeIndex != dbg_itype_none && sym->TypeIndex != 0 &&
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &type)) types_get_info(&type, TI_GET_TYPE, &type.id))
{ {
types_print_type(sym->ModBase, type, FALSE); types_print_type(&type, FALSE);
} }
dbg_printf(")\n"); dbg_printf(")\n");
return TRUE; return TRUE;

View file

@ -39,19 +39,16 @@ long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
{ {
long int rtn = 0; long int rtn = 0;
DWORD tag, size, bt; DWORD tag, size, bt;
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (lvalue->type.id == dbg_itype_none ||
!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
if (lvalue->typeid == dbg_itype_none ||
!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag))
return 0; return 0;
switch (tag) switch (tag)
{ {
case SymTagBaseType: case SymTagBaseType:
if (!types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &size) || if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size) ||
!types_get_info(linear, lvalue->typeid, TI_GET_BASETYPE, &bt)) !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt))
{ {
WINE_ERR("Couldn't get information\n"); WINE_ERR("Couldn't get information\n");
RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
@ -107,23 +104,34 @@ long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result) BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
{ {
DWORD tag; DWORD tag;
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST);
memset(result, 0, sizeof(*result)); memset(result, 0, sizeof(*result));
result->typeid = dbg_itype_none; result->type.id = dbg_itype_none;
result->type.module = 0;
/* /*
* Make sure that this really makes sense. * Make sure that this really makes sense.
*/ */
if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag) || if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
tag != SymTagPointerType || tag != SymTagPointerType ||
memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) || memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
!types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &result->typeid)) !types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id))
return FALSE; return FALSE;
result->type.module = lvalue->type.module;
result->cookie = DLV_TARGET; /* see comment on DEREF below */ result->cookie = DLV_TARGET;
/* FIXME: this is currently buggy.
* there is no way to tell were the deref:ed value is...
* for example:
* x is a pointer to struct s, x being on the stack
* => lvalue is in debuggee, result is in debugger
* x is a pointer to struct s, x being optimized into a reg
* => lvalue is debugger, result is debuggee
* x is a pointer to internal variable x
* => lvalue is debugger, result is debuggee
* so we force debuggee address space, because dereferencing pointers to
* internal variables is very unlikely. A correct fix would be
* rather large.
*/
result->addr.Mode = AddrModeFlat; result->addr.Mode = AddrModeFlat;
return TRUE; return TRUE;
} }
@ -133,19 +141,20 @@ BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
* *
* Implement a structure derefencement * Implement a structure derefencement
*/ */
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, DWORD linear, static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue,
DWORD typeid, long int* tmpbuf) const struct dbg_type* type, long int* tmpbuf)
{ {
DWORD offset, length, bitoffset; DWORD offset, length, bitoffset;
DWORD bt; DWORD bt;
unsigned mask; unsigned mask;
types_get_info(linear, typeid, TI_GET_TYPE, &lvalue->typeid); types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
types_get_info(linear, typeid, TI_GET_OFFSET, &offset); lvalue->type.module = type->module;
types_get_info(type, TI_GET_OFFSET, &offset);
if (types_get_info(linear, typeid, TI_GET_BITPOSITION, &bitoffset)) if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
{ {
types_get_info(linear, typeid, TI_GET_LENGTH, &length); types_get_info(type, TI_GET_LENGTH, &length);
if (length > sizeof(*tmpbuf)) return FALSE; if (length > sizeof(*tmpbuf)) return FALSE;
/* /*
* Bitfield operation. We have to extract the field and store * Bitfield operation. We have to extract the field and store
@ -157,8 +166,7 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, DWORD linear
*tmpbuf >>= bitoffset & 7; *tmpbuf >>= bitoffset & 7;
*tmpbuf &= ~mask; *tmpbuf &= ~mask;
lvalue->cookie = DLV_HOST; lvalue->cookie = DLV_HOST;
lvalue->addr.Mode = AddrModeFlat;
lvalue->addr.Offset = (DWORD)tmpbuf; lvalue->addr.Offset = (DWORD)tmpbuf;
/* /*
@ -166,14 +174,14 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, DWORD linear
* Check to see whether the basic type is signed or not, and if so, * Check to see whether the basic type is signed or not, and if so,
* we need to sign extend the number. * we need to sign extend the number.
*/ */
if (types_get_info(linear, lvalue->typeid, TI_GET_BASETYPE, &bt) && if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) &&
bt == btInt && (*tmpbuf & (1 << (length - 1)))) bt == btInt && (*tmpbuf & (1 << (length - 1))))
{ {
*tmpbuf |= mask; *tmpbuf |= mask;
} }
return TRUE; return TRUE;
} }
if (types_get_info(linear, typeid, TI_GET_OFFSET, &offset)) if (types_get_info(type, TI_GET_OFFSET, &offset))
{ {
lvalue->addr.Offset += offset; lvalue->addr.Offset += offset;
return TRUE; return TRUE;
@ -187,39 +195,38 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, DWORD linear
*/ */
BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf) BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf)
{ {
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
DWORD tag, count; DWORD tag, count;
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;
char tmp[256]; char tmp[256];
int i; int i;
struct dbg_type type;
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag) ||
tag != SymTagUDT) tag != SymTagUDT)
return FALSE; return FALSE;
if (types_get_info(linear, lvalue->typeid, TI_GET_CHILDRENCOUNT, &count)) if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
{ {
fcp->Start = 0; fcp->Start = 0;
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(linear, lvalue->typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
{ {
type.module = lvalue->type.module;
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
ptr = NULL; ptr = NULL;
types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr); type.id = fcp->ChildId[i];
types_get_info(&type, TI_GET_SYMNAME, &ptr);
if (!ptr) continue; if (!ptr) continue;
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)) continue; if (strcmp(tmp, name)) continue;
return types_get_udt_element_lvalue(lvalue, linear, return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
fcp->ChildId[i], tmpbuf);
} }
} }
count -= min(count, 256); count -= min(count, 256);
@ -238,26 +245,23 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index,
struct dbg_lvalue* result) struct dbg_lvalue* result)
{ {
DWORD tag, length, count; DWORD tag, length, count;
DWORD linear = (DWORD)memory_to_linear_addr(&lvalue->addr);
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
if (!types_get_info(0, lvalue->typeid, TI_GET_SYMTAG, &tag))
return FALSE; return FALSE;
switch (tag) switch (tag)
{ {
case SymTagArrayType: case SymTagArrayType:
types_get_info(linear, lvalue->typeid, TI_GET_COUNT, &count); types_get_info(&lvalue->type, TI_GET_COUNT, &count);
if (index < 0 || index >= count) return FALSE; if (index < 0 || index >= count) return FALSE;
/* fall through */ /* fall through */
case SymTagPointerType: case SymTagPointerType:
/* /*
* Get the base type, so we know how much to index by. * Get the base type, so we know how much to index by.
*/ */
types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &result->typeid); types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id);
types_get_info(linear, result->typeid, TI_GET_LENGTH, &length); result->type.module = lvalue->type.module;
types_get_info(&result->type, TI_GET_LENGTH, &length);
/* Contents of array must be on same target */ /* Contents of array must be on same target */
result->cookie = lvalue->cookie;
result->addr.Mode = lvalue->addr.Mode; result->addr.Mode = lvalue->addr.Mode;
memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset); memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
result->addr.Offset += index * length; result->addr.Offset += index * length;
@ -283,7 +287,7 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
{ {
struct type_find_t* user = (struct type_find_t*)_user; struct type_find_t* user = (struct type_find_t*)_user;
BOOL ret = TRUE; BOOL ret = TRUE;
DWORD typeid; struct dbg_type type;
if (sym->Tag == user->tag) if (sym->Tag == user->tag)
{ {
@ -297,9 +301,9 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
} }
break; break;
case SymTagPointerType: case SymTagPointerType:
types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &typeid); type.module = sym->ModBase;
if (types_get_info(sym->ModBase, sym->TypeIndex, TI_GET_TYPE, &typeid) && type.id = sym->TypeIndex;
typeid == user->u.typeid) if (types_get_info(&type, TI_GET_TYPE, &type.id) && type.id == user->u.typeid)
{ {
user->result = sym->TypeIndex; user->result = sym->TypeIndex;
ret = FALSE; ret = FALSE;
@ -316,14 +320,18 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
* Should look up in module based at linear whether (typeid*) exists * Should look up in module based at linear whether (typeid*) exists
* Otherwise, we could create it locally * Otherwise, we could create it locally
*/ */
unsigned long types_find_pointer(unsigned long linear, unsigned long typeid) struct dbg_type types_find_pointer(const struct dbg_type* type)
{ {
struct type_find_t f; struct type_find_t f;
struct dbg_type ret;
f.result = dbg_itype_none; f.result = dbg_itype_none;
f.tag = SymTagPointerType; f.tag = SymTagPointerType;
f.u.typeid = typeid; f.u.typeid = type->id;
SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f); SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
return f.result; ret.module = type->module;
ret.id = f.result;
return ret;
} }
/****************************************************************** /******************************************************************
@ -332,15 +340,19 @@ unsigned long types_find_pointer(unsigned long linear, unsigned long typeid)
* Should look up in the module based at linear address whether a type * Should look up in the module based at linear address whether a type
* named 'name' and with the correct tag exists * named 'name' and with the correct tag exists
*/ */
unsigned long types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag) struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
{ {
struct type_find_t f; struct type_find_t f;
struct dbg_type ret;
f.result = dbg_itype_none; f.result = dbg_itype_none;
f.tag = tag; f.tag = tag;
f.u.name = name; f.u.name = name;
SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f); SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
return f.result; ret.module = linear;
ret.id = f.result;
return ret;
} }
/*********************************************************************** /***********************************************************************
@ -352,15 +364,11 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
{ {
struct dbg_lvalue lvalue_field; struct dbg_lvalue lvalue_field;
int i; int i;
unsigned long linear;
DWORD tag; DWORD tag;
DWORD count; DWORD count;
DWORD size; DWORD size;
assert(lvalue->cookie == DLV_TARGET || lvalue->cookie == DLV_HOST); if (lvalue->type.id == dbg_itype_none)
linear = (unsigned long)memory_to_linear_addr(&lvalue->addr);
if (lvalue->typeid == dbg_itype_none)
{ {
/* No type, just print the addr value */ /* No type, just print the addr value */
print_bare_address(&lvalue->addr); print_bare_address(&lvalue->addr);
@ -373,7 +381,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
format = '\0'; format = '\0';
} }
if (!types_get_info(linear, lvalue->typeid, TI_GET_SYMTAG, &tag)) if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
{ {
WINE_FIXME("---error\n"); WINE_FIXME("---error\n");
return; return;
@ -386,32 +394,34 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
print_basic(lvalue, 1, format); print_basic(lvalue, 1, format);
break; break;
case SymTagUDT: case SymTagUDT:
if (types_get_info(linear, lvalue->typeid, TI_GET_CHILDRENCOUNT, &count)) if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
{ {
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;
char tmp[256]; char tmp[256];
long int tmpbuf; long int tmpbuf;
struct dbg_type type;
dbg_printf("{"); dbg_printf("{");
fcp->Start = 0; fcp->Start = 0;
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(linear, lvalue->typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
{ {
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
ptr = NULL; ptr = NULL;
types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr); type.module = (unsigned long)memory_to_linear_addr(&lvalue->addr);
type.id = fcp->ChildId[i];
types_get_info(&type, TI_GET_SYMNAME, &ptr);
if (!ptr) continue; if (!ptr) continue;
WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL); WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
dbg_printf("%s=", tmp); dbg_printf("%s=", tmp);
HeapFree(GetProcessHeap(), 0, ptr); HeapFree(GetProcessHeap(), 0, ptr);
lvalue_field = *lvalue; lvalue_field = *lvalue;
if (types_get_udt_element_lvalue(&lvalue_field, linear, if (types_get_udt_element_lvalue(&lvalue_field, &type, &tmpbuf))
fcp->ChildId[i], &tmpbuf))
{ {
print_value(&lvalue_field, format, level + 1); print_value(&lvalue_field, format, level + 1);
} }
@ -429,8 +439,8 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
* Loop over all of the entries, printing stuff as we go. * Loop over all of the entries, printing stuff as we go.
*/ */
count = 1; size = 1; count = 1; size = 1;
types_get_info(linear, lvalue->typeid, TI_GET_COUNT, &count); types_get_info(&lvalue->type, TI_GET_COUNT, &count);
types_get_info(linear, lvalue->typeid, TI_GET_LENGTH, &size); types_get_info(&lvalue->type, TI_GET_LENGTH, &size);
if (size == count) if (size == count)
{ {
@ -441,14 +451,14 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
*/ */
/* FIXME should check basic type here (should be a char!!!!)... */ /* FIXME should check basic type here (should be a char!!!!)... */
len = min(count, sizeof(buffer)); len = min(count, sizeof(buffer));
memory_get_string(dbg_curr_thread->handle, memory_get_string(dbg_curr_process->handle,
memory_to_linear_addr(&lvalue->addr), memory_to_linear_addr(&lvalue->addr),
lvalue->cookie, TRUE, buffer, len); lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : ""); dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
break; break;
} }
lvalue_field = *lvalue; lvalue_field = *lvalue;
types_get_info(linear, lvalue->typeid, TI_GET_TYPE, &lvalue_field.typeid); types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
dbg_printf("{"); dbg_printf("{");
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
@ -461,7 +471,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level)
dbg_printf("Function "); dbg_printf("Function ");
print_bare_address(&lvalue->addr); print_bare_address(&lvalue->addr);
dbg_printf(": "); dbg_printf(": ");
types_print_type(linear, lvalue->typeid, FALSE); types_print_type(&lvalue->type, FALSE);
break; break;
default: default:
WINE_FIXME("Unknown tag (%lu)\n", tag); WINE_FIXME("Unknown tag (%lu)\n", tag);
@ -476,7 +486,11 @@ leave:
static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx) static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
{ {
types_print_type(sym->ModBase, sym->TypeIndex, TRUE); struct dbg_type type;
type.module = sym->ModBase;
type.id = sym->TypeIndex;
dbg_printf("Mod: %08lx ID: %08lx \n", type.module, type.id);
types_print_type(&type, TRUE);
dbg_printf("\n"); dbg_printf("\n");
return TRUE; return TRUE;
} }
@ -492,20 +506,21 @@ int print_types(void)
return 0; return 0;
} }
int types_print_type(DWORD linear, DWORD typeid, BOOL details) int types_print_type(const struct dbg_type* type, BOOL details)
{ {
WCHAR* ptr; WCHAR* ptr;
char tmp[256]; char tmp[256];
const char* name; const char* name;
DWORD tag, subtype, count; DWORD tag, udt, count;
struct dbg_type subtype;
if (typeid == dbg_itype_none || !types_get_info(linear, typeid, TI_GET_SYMTAG, &tag)) if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
{ {
dbg_printf("--invalid--<%lxh>--", typeid); dbg_printf("--invalid--<%lxh>--", type->id);
return FALSE; return FALSE;
} }
if (types_get_info(linear, typeid, TI_GET_SYMNAME, &ptr) && ptr) if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
{ {
WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL); WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
name = tmp; name = tmp;
@ -519,47 +534,50 @@ int types_print_type(DWORD linear, DWORD typeid, BOOL details)
if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name); if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
break; break;
case SymTagPointerType: case SymTagPointerType:
types_get_info(linear, typeid, TI_GET_TYPE, &subtype); types_get_info(type, TI_GET_TYPE, &subtype.id);
types_print_type(linear, subtype, details); subtype.module = type->module;
types_print_type(&subtype, FALSE);
dbg_printf("*"); dbg_printf("*");
break; break;
case SymTagUDT: case SymTagUDT:
types_get_info(linear, typeid, TI_GET_UDTKIND, &subtype); types_get_info(type, TI_GET_UDTKIND, &udt);
switch (subtype) switch (udt)
{ {
case UdtStruct: dbg_printf("struct %s", name); break; case UdtStruct: dbg_printf("struct %s", name); break;
case UdtUnion: dbg_printf("union %s", name); break; case UdtUnion: dbg_printf("union %s", name); break;
case UdtClass: dbg_printf("class %s", name); break; case UdtClass: dbg_printf("class %s", name); break;
} }
if (details && if (details &&
types_get_info(linear, typeid, TI_GET_CHILDRENCOUNT, &count)) types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
{ {
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;
char tmp[256]; char tmp[256];
int i; int i;
struct dbg_type type_elt;
dbg_printf(" {"); dbg_printf(" {");
fcp->Start = 0; fcp->Start = 0;
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(linear, typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(type, TI_FINDCHILDREN, fcp))
{ {
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
ptr = NULL; ptr = NULL;
types_get_info(linear, fcp->ChildId[i], TI_GET_SYMNAME, &ptr); type_elt.module = type->module;
type_elt.id = fcp->ChildId[i];
types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
if (!ptr) continue; if (!ptr) continue;
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);
dbg_printf("%s", tmp); dbg_printf("%s", tmp);
if (types_get_info(linear, fcp->ChildId[i], TI_GET_TYPE, &subtype)) if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
{ {
dbg_printf(":"); dbg_printf(":");
types_print_type(linear, subtype, details); types_print_type(&type_elt, details);
} }
if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", "); if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
} }
@ -571,18 +589,20 @@ int types_print_type(DWORD linear, DWORD typeid, BOOL details)
} }
break; break;
case SymTagArrayType: case SymTagArrayType:
types_get_info(linear, typeid, TI_GET_TYPE, &subtype); types_get_info(type, TI_GET_TYPE, &subtype.id);
types_print_type(linear, subtype, details); subtype.module = type->module;
types_print_type(&subtype, details);
dbg_printf(" %s[]", name); dbg_printf(" %s[]", name);
break; break;
case SymTagEnum: case SymTagEnum:
dbg_printf("enum %s", name); dbg_printf("enum %s", name);
break; break;
case SymTagFunctionType: case SymTagFunctionType:
types_get_info(linear, typeid, TI_GET_TYPE, &subtype); types_get_info(type, TI_GET_TYPE, &subtype.id);
types_print_type(linear, subtype, FALSE); subtype.module = type->module;
types_print_type(&subtype, FALSE);
dbg_printf(" (*%s)(", name); dbg_printf(" (*%s)(", name);
if (types_get_info(linear, typeid, TI_GET_CHILDRENCOUNT, &count)) if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
{ {
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;
@ -592,11 +612,12 @@ int types_print_type(DWORD linear, DWORD typeid, BOOL details)
while (count) while (count)
{ {
fcp->Count = min(count, 256); fcp->Count = min(count, 256);
if (types_get_info(linear, typeid, TI_FINDCHILDREN, fcp)) if (types_get_info(type, TI_FINDCHILDREN, fcp))
{ {
for (i = 0; i < min(fcp->Count, count); i++) for (i = 0; i < min(fcp->Count, count); i++)
{ {
types_print_type(linear, fcp->ChildId[i], FALSE); subtype.id = fcp->ChildId[i];
types_print_type(&subtype, FALSE);
if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", "); if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
} }
} }
@ -614,31 +635,17 @@ int types_print_type(DWORD linear, DWORD typeid, BOOL details)
return TRUE; return TRUE;
} }
BOOL types_get_info(unsigned long modbase, unsigned long typeid, BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
{ {
if (typeid == dbg_itype_none) return FALSE; if (type->id == dbg_itype_none) return FALSE;
if (typeid < dbg_itype_first) if (type->module != 0)
{ return SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
BOOL ret;
DWORD tag;
ret = SymGetTypeInfo(dbg_curr_process->handle, modbase, typeid, ti, pInfo);
if (!ret && ti == TI_GET_LENGTH &&
(!SymGetTypeInfo(dbg_curr_process->handle, modbase, typeid,
TI_GET_SYMTAG, &tag) || tag == SymTagData))
{
WINE_FIXME("get length on symtag data is no longer supported\n");
assert(0);
}
return ret;
}
assert(modbase);
assert(type->id >= dbg_itype_first);
/* helper to typecast pInfo to its expected type (_t) */ /* helper to typecast pInfo to its expected type (_t) */
#define X(_t) (*((_t*)pInfo)) #define X(_t) (*((_t*)pInfo))
switch (typeid) switch (type->id)
{ {
case dbg_itype_unsigned_int: case dbg_itype_unsigned_int:
switch (ti) switch (ti)
@ -712,7 +719,7 @@ BOOL types_get_info(unsigned long modbase, unsigned long typeid,
default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE; default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
} }
break; break;
default: WINE_FIXME("unsupported typeid 0x%lx\n", typeid); default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
} }
#undef X #undef X

View file

@ -45,6 +45,9 @@
* + make the output as close as possible to what gdb does * + make the output as close as possible to what gdb does
* - symbol management: * - symbol management:
* + symbol table loading is broken * + symbol table loading is broken
* + in symbol_get_lvalue, we don't do any scoping (as C does) between local and
* global vars (we may need this to force some display for example). A solution
* would be always to return arrays with: local vars, global vars, thunks
* - 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)
@ -55,7 +58,10 @@
* o bitfield size is on a 4-bytes * o bitfield size is on a 4-bytes
* + 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)
* - execution * - execution:
* + display: we shouldn't need to tell whether a display is local or not. This
* should be automatically guessed by checking whether the variables that are
* references are local or not
* + 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
* + trampoline management is broken when getting 16 <=> 32 thunk destination * + trampoline management is broken when getting 16 <=> 32 thunk destination
@ -339,6 +345,8 @@ struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid,
t->wait_for_first_exception = 0; t->wait_for_first_exception = 0;
t->exec_mode = dbg_exec_cont; t->exec_mode = dbg_exec_cont;
t->exec_count = 0; t->exec_count = 0;
t->step_over_bp.enabled = FALSE;
t->step_over_bp.refcount = 0;
snprintf(t->name, sizeof(t->name), "0x%08lx", tid); snprintf(t->name, sizeof(t->name), "0x%08lx", tid);
@ -354,8 +362,8 @@ static void dbg_init_current_thread(void* start)
{ {
if (start) if (start)
{ {
if (dbg_curr_thread->process->threads && if (dbg_curr_process->threads &&
!dbg_curr_thread->process->threads->next && /* first thread ? */ !dbg_curr_process->threads->next && /* first thread ? */
DBG_IVAR(BreakAllThreadsStartup)) DBG_IVAR(BreakAllThreadsStartup))
{ {
ADDRESS addr; ADDRESS addr;
@ -562,8 +570,7 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance,
else else
pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID); pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
if (ReadProcessMemory(dbg_curr_thread->process->handle, pThreadName->szName, if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
pThread->name, 9, NULL))
dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n", dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
pThread->tid, pThread->name); pThread->tid, pThread->name);
return DBG_CONTINUE; return DBG_CONTINUE;
@ -636,11 +643,11 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance,
case EXCEPTION_WINE_STUB: case EXCEPTION_WINE_STUB:
{ {
char dll[32], name[64]; char dll[32], name[64];
memory_get_string(dbg_curr_thread->process->handle, memory_get_string(dbg_curr_process->handle,
(void*)rec->ExceptionInformation[0], DLV_TARGET, FALSE, (void*)rec->ExceptionInformation[0], TRUE, FALSE,
dll, sizeof(dll)); dll, sizeof(dll));
memory_get_string(dbg_curr_thread->process->handle, memory_get_string(dbg_curr_process->handle,
(void*)rec->ExceptionInformation[1], DLV_TARGET, FALSE, (void*)rec->ExceptionInformation[1], TRUE, FALSE,
name, sizeof(name)); name, sizeof(name));
dbg_printf("unimplemented function %s.%s called", dll, name); dbg_printf("unimplemented function %s.%s called", dll, name);
} }
@ -854,7 +861,7 @@ static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
WINE_ERR("Unknown thread\n"); WINE_ERR("Unknown thread\n");
break; break;
} }
memory_get_string_indirect(dbg_curr_thread->process->handle, memory_get_string_indirect(dbg_curr_process->handle,
de->u.LoadDll.lpImageName, de->u.LoadDll.lpImageName,
de->u.LoadDll.fUnicode, de->u.LoadDll.fUnicode,
buffer, sizeof(buffer)); buffer, sizeof(buffer));
@ -894,8 +901,8 @@ static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
break; break;
} }
memory_get_string(dbg_curr_thread->process->handle, memory_get_string(dbg_curr_process->handle,
de->u.DebugString.lpDebugStringData, DLV_TARGET, de->u.DebugString.lpDebugStringData, TRUE,
de->u.DebugString.fUnicode, buffer, sizeof(buffer)); de->u.DebugString.fUnicode, buffer, sizeof(buffer));
WINE_TRACE("%08lx:%08lx: output debug string (%s)\n", WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
de->dwProcessId, de->dwThreadId, buffer); de->dwProcessId, de->dwThreadId, buffer);