- fixed some bugs in StackWalk (claimed for but forgotten in last
patch) - removed location field in symt_data, and reworked the actual location of information based on the 'kind' field - shorten debug channel name - added support for bitfield in struct:s - cleaned up source line information support - now storing constants values as VARIANT
This commit is contained in:
parent
c5524e1e6b
commit
c5e0a696d9
|
@ -132,18 +132,16 @@ struct symt_data
|
|||
enum DataKind kind;
|
||||
struct symt* container;
|
||||
struct symt* type;
|
||||
enum LocationType location;
|
||||
union /* depends on location */
|
||||
union /* depends on kind */
|
||||
{
|
||||
unsigned long address; /* used by Static, Tls, ThisRel */
|
||||
int offset; /* used by RegRel */
|
||||
unsigned reg_id; /* used by Enregistered */
|
||||
unsigned long address; /* DataIs{Global, FileStatic} */
|
||||
struct
|
||||
{
|
||||
unsigned position;
|
||||
unsigned length;
|
||||
} bitfield; /* used by BitField */
|
||||
VARIANT value; /* LocIsConstant */
|
||||
long offset; /* DataIs{Member,Local,Param} in bits*/
|
||||
unsigned long length; /* DataIs{Member} in bits */
|
||||
unsigned long reg_id; /* DataIs{Local} (0 if frame relative) */
|
||||
} s;
|
||||
VARIANT value; /* DataIsConstant */
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
|
@ -70,14 +70,12 @@ static const char* wine_dbgstr_addr(const ADDRESS* addr)
|
|||
* StackWalk (DBGHELP.@)
|
||||
*/
|
||||
BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
||||
LPSTACKFRAME frame, LPVOID _ctx,
|
||||
LPSTACKFRAME frame, LPVOID ctx,
|
||||
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem,
|
||||
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
|
||||
PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
|
||||
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr)
|
||||
{
|
||||
#ifdef __i386__
|
||||
CONTEXT* ctx = (CONTEXT*)_ctx;
|
||||
STACK32FRAME frame32;
|
||||
STACK16FRAME frame16;
|
||||
char ch;
|
||||
|
@ -87,7 +85,7 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
BOOL do_switch;
|
||||
|
||||
TRACE("(%ld, %p, %p, %p, %p, %p, %p, %p, %p)\n",
|
||||
MachineType, hProcess, hThread, frame, _ctx,
|
||||
MachineType, hProcess, hThread, frame, ctx,
|
||||
f_read_mem, FunctionTableAccessRoutine,
|
||||
GetModuleBaseRoutine, f_xlat_adr);
|
||||
|
||||
|
@ -119,13 +117,6 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ?
|
||||
stm_32bit : stm_16bit;
|
||||
|
||||
/* Get the current ESP (don't know if this is valid) */
|
||||
if (ctx)
|
||||
{
|
||||
frame->AddrStack.Segment = 0;
|
||||
frame->AddrStack.Offset = ctx->Esp;
|
||||
frame->AddrStack.Mode = AddrModeFlat;
|
||||
}
|
||||
/* cur_switch holds address of curr_stack's field in TEB in debuggee
|
||||
* address space
|
||||
*/
|
||||
|
@ -155,11 +146,6 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
&ch, sizeof(ch), NULL))
|
||||
curr_switch = 0xFFFFFFFF;
|
||||
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrMode1616;
|
||||
/* "pop up" previous BP value */
|
||||
if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset,
|
||||
&val, sizeof(WORD), NULL))
|
||||
goto done_err;
|
||||
frame->AddrFrame.Offset = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -177,11 +163,10 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
if (!f_read_mem(hProcess, (void*)curr_switch, &ch, sizeof(ch), NULL))
|
||||
curr_switch = 0xFFFFFFFF;
|
||||
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
|
||||
/* "pop up" previous EBP value */
|
||||
if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset,
|
||||
&frame->AddrFrame.Offset, sizeof(DWORD), NULL))
|
||||
goto done_err;
|
||||
}
|
||||
/* don't set up AddrStack on first call. Either the caller has set it up, or
|
||||
* we will get it in the next frame
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -393,11 +378,4 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
done_err:
|
||||
curr_mode = stm_done;
|
||||
return FALSE;
|
||||
#else /* __i386__ */
|
||||
FIXME("(%ld, %p, %p, %p, %p, %p, %p, %p, %p): stub\n",
|
||||
MachineType, hProcess, hThread, frame, _ctx,
|
||||
f_read_mem, FunctionTableAccessRoutine,
|
||||
GetModuleBaseRoutine, f_xlat_adr);
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -35,21 +35,18 @@
|
|||
#include "dbghelp_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symtype);
|
||||
|
||||
#define DLIT_OFFSET 0x00
|
||||
#define DLIT_FIRST 0x01
|
||||
#define DLIT_LAST 0x02
|
||||
#define DLIT_SOURCEFILE 0x04
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
|
||||
|
||||
struct line_info
|
||||
{
|
||||
unsigned long cookie : 3,
|
||||
unsigned long is_first : 1,
|
||||
is_last : 1,
|
||||
is_source_file : 1,
|
||||
line_number;
|
||||
union
|
||||
{
|
||||
unsigned long pc_offset;
|
||||
unsigned source_file;
|
||||
unsigned long pc_offset; /* if is_source_file isn't set */
|
||||
unsigned source_file; /* if is_source_file is set */
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -138,7 +135,7 @@ struct symt_compiland* symt_new_compiland(struct module* module, const char* nam
|
|||
{
|
||||
struct symt_compiland* sym;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding compiland symbol %s:%s\n",
|
||||
TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n",
|
||||
module->module.ModuleName, name);
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
|
@ -158,7 +155,7 @@ struct symt_public* symt_new_public(struct module* module,
|
|||
struct symt_public* sym;
|
||||
struct symt** p;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding public symbol %s:%s @%lx\n",
|
||||
TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%lx\n",
|
||||
module->module.ModuleName, name, address);
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
|
@ -189,7 +186,7 @@ struct symt_data* symt_new_global_variable(struct module* module,
|
|||
struct symt_data* sym;
|
||||
struct symt** p;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding global symbol %s:%s @%lx %p\n",
|
||||
TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n",
|
||||
module->module.ModuleName, name, addr, type);
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
|
@ -200,7 +197,6 @@ struct symt_data* symt_new_global_variable(struct module* module,
|
|||
sym->kind = is_static ? DataIsFileStatic : DataIsGlobal;
|
||||
sym->container = compiland ? &compiland->symt : NULL;
|
||||
sym->type = type;
|
||||
sym->location = LocIsStatic; /* FIXME */
|
||||
sym->u.address = addr;
|
||||
if (compiland)
|
||||
{
|
||||
|
@ -220,7 +216,7 @@ struct symt_function* symt_new_function(struct module* module,
|
|||
struct symt_function* sym;
|
||||
struct symt** p;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding global function %s:%s @%lx-%lx\n",
|
||||
TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n",
|
||||
module->module.ModuleName, name, addr, addr + size - 1);
|
||||
|
||||
assert(!sig_type || sig_type->tag == SymTagFunctionType);
|
||||
|
@ -254,7 +250,7 @@ void symt_add_func_line(struct module* module, struct symt_function* func,
|
|||
|
||||
if (func == NULL || !(dbghelp_options & SYMOPT_LOAD_LINES)) return;
|
||||
|
||||
TRACE_(dbghelp_symtype)("(%p)%s:%lx %s:%u\n",
|
||||
TRACE_(dbghelp_symt)("(%p)%s:%lx %s:%u\n",
|
||||
func, func->hash_elt.name, offset,
|
||||
source_get(module, source_idx), line_num);
|
||||
|
||||
|
@ -263,7 +259,7 @@ void symt_add_func_line(struct module* module, struct symt_function* func,
|
|||
dli = NULL;
|
||||
while ((dli = vector_iter_down(&func->vlines, dli)))
|
||||
{
|
||||
if (dli->cookie & DLIT_SOURCEFILE)
|
||||
if (dli->is_source_file)
|
||||
{
|
||||
last_matches = (source_idx == dli->u.source_file);
|
||||
break;
|
||||
|
@ -274,12 +270,14 @@ void symt_add_func_line(struct module* module, struct symt_function* func,
|
|||
{
|
||||
/* we shouldn't have line changes on first line of function */
|
||||
dli = vector_add(&func->vlines, &module->pool);
|
||||
dli->cookie = DLIT_SOURCEFILE;
|
||||
dli->is_source_file = 1;
|
||||
dli->is_first = dli->is_last = 0;
|
||||
dli->line_number = 0;
|
||||
dli->u.source_file = source_idx;
|
||||
}
|
||||
dli = vector_add(&func->vlines, &module->pool);
|
||||
dli->cookie = DLIT_OFFSET;
|
||||
dli->is_source_file = 0;
|
||||
dli->is_first = dli->is_last = 0;
|
||||
dli->line_number = line_num;
|
||||
dli->u.pc_offset = func->addr + offset;
|
||||
}
|
||||
|
@ -296,7 +294,7 @@ struct symt_data* symt_add_func_local(struct module* module,
|
|||
assert(func);
|
||||
assert(func->symt.tag == SymTagFunction);
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding local symbol (%s:%s): %s %p\n",
|
||||
TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %p\n",
|
||||
module->module.ModuleName, func->hash_elt.name,
|
||||
name, type);
|
||||
locsym = pool_alloc(&module->pool, sizeof(*locsym));
|
||||
|
@ -308,14 +306,15 @@ struct symt_data* symt_add_func_local(struct module* module,
|
|||
locsym->type = type;
|
||||
if (regno)
|
||||
{
|
||||
locsym->location = LocIsEnregistered;
|
||||
locsym->u.reg_id = regno;
|
||||
locsym->u.s.reg_id = regno;
|
||||
locsym->u.s.offset = 0;
|
||||
locsym->u.s.length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
locsym->location = LocIsRegRel;
|
||||
locsym->u.reg_id = CV_REG_EBP;
|
||||
locsym->u.offset = offset;
|
||||
locsym->u.s.reg_id = 0;
|
||||
locsym->u.s.offset = offset * 8;
|
||||
locsym->u.s.length = 0;
|
||||
}
|
||||
if (block)
|
||||
p = vector_add(&block->vchildren, &module->pool);
|
||||
|
@ -400,8 +399,8 @@ BOOL symt_normalize_function(struct module* module, struct symt_function* func)
|
|||
len = vector_length(&func->vlines);
|
||||
if (len--)
|
||||
{
|
||||
dli = vector_at(&func->vlines, 0); dli->cookie |= DLIT_FIRST;
|
||||
dli = vector_at(&func->vlines, len); dli->cookie |= DLIT_LAST;
|
||||
dli = vector_at(&func->vlines, 0); dli->is_first = 1;
|
||||
dli = vector_at(&func->vlines, len); dli->is_last = 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -422,25 +421,32 @@ static void symt_fill_sym_info(const struct module* module,
|
|||
case SymTagData:
|
||||
{
|
||||
struct symt_data* data = (struct symt_data*)sym;
|
||||
switch (data->location)
|
||||
switch (data->kind)
|
||||
{
|
||||
case DataIsLocal:
|
||||
case DataIsParam:
|
||||
if (data->u.s.reg_id)
|
||||
{
|
||||
case LocIsEnregistered:
|
||||
sym_info->Flags |= SYMFLAG_REGISTER;
|
||||
sym_info->Register = data->u.reg_id;
|
||||
sym_info->Register = data->u.s.reg_id;
|
||||
sym_info->Address = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data->u.s.offset < 0)
|
||||
sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_FRAMEREL;
|
||||
else
|
||||
sym_info->Flags |= SYMFLAG_PARAMETER | SYMFLAG_FRAMEREL;
|
||||
sym_info->Register = CV_REG_EBP; /* FIXME: needed ? */
|
||||
sym_info->Address = data->u.s.offset;
|
||||
}
|
||||
break;
|
||||
case LocIsRegRel:
|
||||
sym_info->Flags |=
|
||||
((data->u.offset < 0) ? SYMFLAG_LOCAL : SYMFLAG_PARAMETER) |
|
||||
SYMFLAG_FRAMEREL;
|
||||
sym_info->Register = data->u.reg_id;
|
||||
sym_info->Address = data->u.offset;
|
||||
break;
|
||||
case LocIsStatic:
|
||||
case DataIsGlobal:
|
||||
case DataIsFileStatic:
|
||||
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
||||
sym_info->Register = 0;
|
||||
break;
|
||||
case LocIsConstant:
|
||||
case DataIsConstant:
|
||||
sym_info->Flags |= SYMFLAG_VALUEPRESENT;
|
||||
switch (data->u.value.n1.n2.vt)
|
||||
{
|
||||
|
@ -455,7 +461,7 @@ static void symt_fill_sym_info(const struct module* module,
|
|||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("Unhandled loc (%u) in sym data\n", data->location);
|
||||
FIXME("Unhandled kind (%u) in sym data\n", data->kind);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -481,7 +487,7 @@ static void symt_fill_sym_info(const struct module* module,
|
|||
strncpy(sym_info->Name, name, min(sym_info->NameLen, sym_info->MaxNameLen));
|
||||
sym_info->Name[sym_info->MaxNameLen - 1] = '\0';
|
||||
}
|
||||
TRACE_(dbghelp_symtype)("%p => %s %lu %lx\n",
|
||||
TRACE_(dbghelp_symt)("%p => %s %lu %lx\n",
|
||||
sym, sym_info->Name, sym_info->Size, sym_info->Address);
|
||||
}
|
||||
|
||||
|
@ -899,7 +905,7 @@ BOOL symt_fill_func_line_info(struct module* module, struct symt_function* func,
|
|||
|
||||
while ((dli = vector_iter_down(&func->vlines, dli)))
|
||||
{
|
||||
if (!(dli->cookie & DLIT_SOURCEFILE))
|
||||
if (!dli->is_source_file)
|
||||
{
|
||||
if (found || dli->u.pc_offset > addr) continue;
|
||||
line->LineNumber = dli->line_number;
|
||||
|
@ -998,10 +1004,10 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
|
|||
* source file name for the DLIT_OFFSET element just before
|
||||
* the first DLIT_SOURCEFILE
|
||||
*/
|
||||
while (!(li->cookie & DLIT_FIRST))
|
||||
while (!li->is_first)
|
||||
{
|
||||
li--;
|
||||
if (!(li->cookie & DLIT_SOURCEFILE))
|
||||
if (!li->is_source_file)
|
||||
{
|
||||
Line->LineNumber = li->line_number;
|
||||
Line->Address = li->u.pc_offset;
|
||||
|
@ -1028,10 +1034,10 @@ BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line)
|
|||
|
||||
if (line->Key == 0) return FALSE;
|
||||
li = (struct line_info*)line->Key;
|
||||
while (!(li->cookie & DLIT_LAST))
|
||||
while (!li->is_last)
|
||||
{
|
||||
li++;
|
||||
if (!(li->cookie & DLIT_SOURCEFILE))
|
||||
if (!li->is_source_file)
|
||||
{
|
||||
line->LineNumber = li->line_number;
|
||||
line->Address = li->u.pc_offset;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "dbghelp_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symtype);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
|
||||
|
||||
static const char* symt_get_tag_str(DWORD tag)
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ struct symt_udt* symt_new_udt(struct module* module, const char* typename,
|
|||
{
|
||||
struct symt_udt* sym;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding udt %s:%s\n", module->module.ModuleName, typename);
|
||||
TRACE_(dbghelp_symt)("Adding udt %s:%s\n", module->module.ModuleName, typename);
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
sym->symt.tag = SymTagUDT;
|
||||
|
@ -176,7 +176,7 @@ BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned siz
|
|||
if (vector_length(&udt->vchildren) != 0)
|
||||
{
|
||||
if (udt->size != size)
|
||||
FIXME_(dbghelp_symtype)("Changing size for %s from %u to %u\n",
|
||||
FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n",
|
||||
udt->hash_elt.name, udt->size, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
|
|||
|
||||
assert(udt_type->symt.tag == SymTagUDT);
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
|
||||
TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
|
||||
p = NULL;
|
||||
while ((p = vector_iter_up(&udt_type->vchildren, p)))
|
||||
{
|
||||
|
@ -221,18 +221,9 @@ BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
|
|||
m->kind = DataIsMember;
|
||||
m->container = &udt_type->symt;
|
||||
m->type = elt_type;
|
||||
if (!(offset & 7) && !(size & 7))
|
||||
{
|
||||
m->location = LocIsThisRel;
|
||||
m->u.offset = offset >> 3;
|
||||
/* we could check that elt_type's size is actually size */
|
||||
}
|
||||
else
|
||||
{
|
||||
m->location = LocIsBitField;
|
||||
m->u.bitfield.position = offset;
|
||||
m->u.bitfield.length = size;
|
||||
}
|
||||
m->u.s.offset = offset;
|
||||
m->u.s.length = ((offset & 7) || (size & 7)) ? size : 0;
|
||||
m->u.s.reg_id = 0;
|
||||
p = vector_add(&udt_type->vchildren, &module->pool);
|
||||
*p = &m->symt;
|
||||
|
||||
|
@ -269,7 +260,6 @@ BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
|
|||
e->container = &enum_type->symt;
|
||||
/* CV defines the underlying type for the enumeration */
|
||||
e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
|
||||
e->location = LocIsConstant;
|
||||
e->u.value.n1.n2.vt = VT_I4;
|
||||
e->u.value.n1.n2.n3.lVal = value;
|
||||
|
||||
|
@ -491,9 +481,11 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
break;
|
||||
|
||||
case TI_GET_BITPOSITION:
|
||||
if (type->tag != SymTagData || ((struct symt_data*)type)->location != LocIsBitField)
|
||||
if (type->tag != SymTagData ||
|
||||
((struct symt_data*)type)->kind != DataIsMember ||
|
||||
((struct symt_data*)type)->u.s.length == 0)
|
||||
return FALSE;
|
||||
X(DWORD) = ((struct symt_data*)type)->u.bitfield.position;
|
||||
X(DWORD) = ((struct symt_data*)type)->u.s.offset & 7;
|
||||
break;
|
||||
|
||||
case TI_GET_CHILDRENCOUNT:
|
||||
|
@ -560,10 +552,10 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
|
||||
break;
|
||||
case SymTagData:
|
||||
if (((struct symt_data*)type)->location == LocIsBitField)
|
||||
X(DWORD) = ((struct symt_data*)type)->u.bitfield.length;
|
||||
else
|
||||
if (((struct symt_data*)type)->kind != DataIsMember ||
|
||||
!((struct symt_data*)type)->u.s.length)
|
||||
return FALSE;
|
||||
X(DWORD) = ((struct symt_data*)type)->u.s.length;
|
||||
break;
|
||||
case SymTagArrayType:
|
||||
if (!symt_get_info(((struct symt_array*)type)->basetype,
|
||||
|
@ -622,7 +614,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
case DataIsParam:
|
||||
case DataIsLocal:
|
||||
case DataIsMember:
|
||||
X(ULONG) = ((struct symt_data*)type)->u.offset;
|
||||
X(ULONG) = ((struct symt_data*)type)->u.s.offset >> 3;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown kind (%u) for get-offset\n",
|
||||
|
|
Loading…
Reference in New Issue