- implemented support for function debug start/stop and labels (msc.c
and stabs.c) - started implementing typedef support - functions now have a real function signature (only in stabs.c, still to be done in msc.c) - small enhancements to TI_GET_TYPE for functions - added support for functions' block and local variables in registers (msc.c) - fixed some bugs in StackWalk - constants are now stored as variants (instead of unsigned ints) - fixed regular expression management (dbghelp's RE are not the same as POSIX ones)
This commit is contained in:
parent
9509912e41
commit
eb80f29350
|
@ -29,22 +29,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
|||
|
||||
/* TODO
|
||||
* - support for symbols' types is still partly missing
|
||||
* + debug start/stop in functions
|
||||
* + parameters in function prototype...
|
||||
* + C++ support
|
||||
* + funcargtype:s are (partly) wrong: they should be a specific struct (like
|
||||
* typedef) pointing to the actual type (and not a direct access)
|
||||
* + we should store the underlying type for an enum in the symt_enum struct
|
||||
* - most options (dbghelp_options) are not used (loading lines, decoration,
|
||||
* deferring reading of module symbols, public symbols...)
|
||||
* - (un)decoration is not handled (should make winedump's code a (.a) library
|
||||
* and link it to winedump, and potentially to msvcrt and dbghelp (check best
|
||||
* way not to duplicate code in msvcrt & dbghelp)
|
||||
* - msc:
|
||||
* + handle the debug_start & debug_end information block
|
||||
* + we should add parameters' types to the function's signature
|
||||
* while processing a function's parameters
|
||||
* + get rid of MSC reading FIXME:s (lots of types are not defined)
|
||||
* + C++ management
|
||||
* - stabs:
|
||||
* + we should add parameters' types to the function's signature
|
||||
* while processing a function's parameters
|
||||
* + should generate the func debug_{start,end} statements (black magic ?)
|
||||
* + should identify the relay code in Wine and mark it as thunk type
|
||||
* + C++ management
|
||||
* - implement the callback notification mechanism
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winver.h"
|
||||
#include "dbghelp.h"
|
||||
#include "oaidl.h"
|
||||
|
||||
#include "cvconst.h"
|
||||
|
||||
|
@ -142,11 +143,7 @@ struct symt_data
|
|||
unsigned position;
|
||||
unsigned length;
|
||||
} bitfield; /* used by BitField */
|
||||
#if 1
|
||||
unsigned value; /* LocIsConstant */
|
||||
#else
|
||||
VARIANT value; /* LocIsConstant */
|
||||
#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -159,7 +156,15 @@ struct symt_function
|
|||
struct symt* type; /* points to function_signature */
|
||||
unsigned long size;
|
||||
struct vector vlines;
|
||||
struct vector vchildren; /* locals, params, blocks */
|
||||
struct vector vchildren; /* locals, params, blocks, start/end, labels */
|
||||
};
|
||||
|
||||
struct symt_function_point
|
||||
{
|
||||
struct symt symt; /* either SymTagFunctionDebugStart, SymTagFunctionDebugEnd, SymTagLabel */
|
||||
struct symt_function* parent;
|
||||
unsigned long offset;
|
||||
const char* name; /* for labels */
|
||||
};
|
||||
|
||||
struct symt_public
|
||||
|
@ -201,6 +206,7 @@ struct symt_function_signature
|
|||
{
|
||||
struct symt symt;
|
||||
struct symt* rettype;
|
||||
struct vector vchildren;
|
||||
};
|
||||
|
||||
struct symt_pointer
|
||||
|
@ -367,11 +373,21 @@ extern struct symt_data*
|
|||
extern struct symt_block*
|
||||
symt_open_func_block(struct module* module,
|
||||
struct symt_function* func,
|
||||
struct symt_block* block, unsigned pc);
|
||||
struct symt_block* block,
|
||||
unsigned pc, unsigned len);
|
||||
extern struct symt_block*
|
||||
symt_close_func_block(struct module* module,
|
||||
struct symt_function* func,
|
||||
struct symt_block* block, unsigned pc);
|
||||
extern struct symt_function_point*
|
||||
symt_add_function_point(struct module* module,
|
||||
struct symt_function* func,
|
||||
enum SymTagEnum point,
|
||||
unsigned offset, const char* name);
|
||||
extern BOOL symt_fill_func_line_info(struct module* module,
|
||||
struct symt_function* func,
|
||||
DWORD addr, IMAGEHLP_LINE* line);
|
||||
extern BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line);
|
||||
|
||||
/* type.c */
|
||||
extern void symt_init_basic(struct module* module);
|
||||
|
@ -394,13 +410,19 @@ extern struct symt_enum*
|
|||
symt_new_enum(struct module* module, const char* typename);
|
||||
extern BOOL symt_add_enum_element(struct module* module,
|
||||
struct symt_enum* enum_type,
|
||||
const char* name, unsigned value);
|
||||
const char* name, int value);
|
||||
extern struct symt_array*
|
||||
symt_new_array(struct module* module, int min, int max,
|
||||
struct symt* base);
|
||||
extern struct symt_function_signature*
|
||||
symt_new_function_signature(struct module* module,
|
||||
struct symt* ret_type);
|
||||
extern BOOL symt_add_function_signature_parameter(struct module* module,
|
||||
struct symt_function_signature* sig,
|
||||
struct symt* param);
|
||||
extern struct symt_pointer*
|
||||
symt_new_pointer(struct module* module,
|
||||
struct symt* ref_type);
|
||||
extern struct symt_typedef*
|
||||
symt_new_typedef(struct module* module, struct symt* ref,
|
||||
const char* name);
|
||||
|
|
|
@ -1068,7 +1068,7 @@ static void codeview_init_basic_types(struct module* module)
|
|||
cv_basic_types[T_SHORT] = &symt_new_basic(module, btInt, "short int", 2)->symt;
|
||||
cv_basic_types[T_LONG] = &symt_new_basic(module, btInt, "long int", 4)->symt;
|
||||
cv_basic_types[T_QUAD] = &symt_new_basic(module, btInt, "long long int", 8)->symt;
|
||||
cv_basic_types[T_UCHAR] = &symt_new_basic(module, btUInt, "unsignd char", 1)->symt;
|
||||
cv_basic_types[T_UCHAR] = &symt_new_basic(module, btUInt, "unsigned char", 1)->symt;
|
||||
cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt, "unsigned short", 2)->symt;
|
||||
cv_basic_types[T_ULONG] = &symt_new_basic(module, btUInt, "unsigned long", 4)->symt;
|
||||
cv_basic_types[T_UQUAD] = &symt_new_basic(module, btUInt, "unsigned long long", 8)->symt;
|
||||
|
@ -1937,9 +1937,9 @@ union codeview_symbol
|
|||
|
||||
struct
|
||||
{
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_BPREL32 */
|
||||
unsigned int offset; /* Stack offset relative to BP */
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_BPREL */
|
||||
unsigned int offset; /* Stack offset relative to BP */
|
||||
unsigned short symtype;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
|
@ -1947,13 +1947,101 @@ union codeview_symbol
|
|||
|
||||
struct
|
||||
{
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_BPREL32 */
|
||||
unsigned int offset; /* Stack offset relative to BP */
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_BPREL_32 */
|
||||
unsigned int offset; /* Stack offset relative to EBP */
|
||||
unsigned int symtype;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
} stack32;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_REGISTER */
|
||||
unsigned short type;
|
||||
unsigned short reg;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
/* don't handle register tracking */
|
||||
} s_register;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len; /* Total length of this entry */
|
||||
short int id; /* Always S_REGISTER_32 */
|
||||
unsigned int type; /* check whether type & reg are correct */
|
||||
unsigned int reg;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
/* don't handle register tracking */
|
||||
} s_register32;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned int parent;
|
||||
unsigned int end;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
unsigned short segment;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
} block;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned int offset;
|
||||
unsigned short segment;
|
||||
unsigned char flags;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
} label;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned short type;
|
||||
unsigned short arrlen; /* numeric leaf */
|
||||
#if 0
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
#endif
|
||||
} constant;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned type;
|
||||
unsigned short arrlen; /* numeric leaf */
|
||||
#if 0
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
#endif
|
||||
} constant32;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned short type;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
} udt;
|
||||
|
||||
struct
|
||||
{
|
||||
short int len;
|
||||
short int id;
|
||||
unsigned type;
|
||||
unsigned char namelen;
|
||||
unsigned char name[1];
|
||||
} udt32;
|
||||
};
|
||||
|
||||
#define S_COMPILE 0x0001
|
||||
|
@ -1997,7 +2085,6 @@ union codeview_symbol
|
|||
#define S_UDT_32 0x1003
|
||||
#define S_COBOLUDT_32 0x1004
|
||||
#define S_MANYREG_32 0x1005
|
||||
|
||||
#define S_BPREL_32 0x1006
|
||||
#define S_LDATA_32 0x1007
|
||||
#define S_GDATA_32 0x1008
|
||||
|
@ -2081,6 +2168,8 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
int i, length;
|
||||
char symname[PATH_MAX];
|
||||
const struct codeview_linetab* flt;
|
||||
struct symt_block* block = NULL;
|
||||
struct symt* symt;
|
||||
|
||||
/*
|
||||
* Loop over the different types of records and whenever we
|
||||
|
@ -2102,13 +2191,9 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
memcpy(symname, sym->data.name, sym->data.namelen);
|
||||
symname[sym->data.namelen] = '\0';
|
||||
flt = codeview_get_linetab(linetab, sym->data.seg, sym->data.offset);
|
||||
/* global data should be the only one of type global var...
|
||||
* the other ones sound different
|
||||
* FIXME
|
||||
*/
|
||||
symt_new_global_variable(msc_dbg->module,
|
||||
flt ? flt->compiland : NULL,
|
||||
symname, sym->generic.id == S_GDATA,
|
||||
symname, sym->generic.id == S_LDATA,
|
||||
codeview_get_address(msc_dbg, sym->data.seg, sym->data.offset),
|
||||
0,
|
||||
codeview_get_type(sym->data.symtype, FALSE));
|
||||
|
@ -2119,12 +2204,8 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
memcpy(symname, sym->data32.name, sym->data32.namelen);
|
||||
symname[sym->data32.namelen] = '\0';
|
||||
flt = codeview_get_linetab(linetab, sym->data32.seg, sym->data32.offset);
|
||||
/* global data should be the only one of type global var...
|
||||
* the other ones sound different
|
||||
* FIXME
|
||||
*/
|
||||
symt_new_global_variable(msc_dbg->module, flt ? flt->compiland : NULL,
|
||||
symname, sym->generic.id == S_GDATA_32,
|
||||
symname, sym->generic.id == S_LDATA_32,
|
||||
codeview_get_address(msc_dbg, sym->data32.seg, sym->data32.offset),
|
||||
0,
|
||||
codeview_get_type(sym->data32.symtype, FALSE));
|
||||
|
@ -2171,8 +2252,6 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
*/
|
||||
case S_GPROC:
|
||||
case S_LPROC:
|
||||
if (curr_func) symt_normalize_function(msc_dbg->module, curr_func);
|
||||
|
||||
memcpy(symname, sym->proc.name, sym->proc.namelen);
|
||||
symname[sym->proc.namelen] = '\0';
|
||||
flt = codeview_get_linetab(linetab, sym->proc.segment, sym->proc.offset);
|
||||
|
@ -2181,15 +2260,13 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
codeview_get_address(msc_dbg, sym->proc.segment, sym->proc.offset),
|
||||
sym->proc.proc_len,
|
||||
codeview_get_type(sym->proc.proctype, FALSE));
|
||||
|
||||
codeview_add_func_linenum(msc_dbg->module, curr_func, flt,
|
||||
sym->proc.offset, sym->proc.proc_len);
|
||||
/* DEBUG_SetSymbolBPOff(curr_func, sym->proc.debug_start); */
|
||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc.debug_start, NULL);
|
||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc.debug_end, NULL);
|
||||
break;
|
||||
case S_GPROC_32:
|
||||
case S_LPROC_32:
|
||||
if (curr_func) symt_normalize_function(msc_dbg->module, curr_func);
|
||||
|
||||
memcpy(symname, sym->proc32.name, sym->proc32.namelen);
|
||||
symname[sym->proc32.namelen] = '\0';
|
||||
flt = codeview_get_linetab(linetab, sym->proc32.segment, sym->proc32.offset);
|
||||
|
@ -2198,10 +2275,10 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
codeview_get_address(msc_dbg, sym->proc32.segment, sym->proc32.offset),
|
||||
sym->proc32.proc_len,
|
||||
codeview_get_type(sym->proc32.proctype, FALSE));
|
||||
|
||||
codeview_add_func_linenum(msc_dbg->module, curr_func, flt,
|
||||
sym->proc32.offset, sym->proc32.proc_len);
|
||||
/* DEBUG_SetSymbolBPOff(curr_func, sym->proc32.debug_start); */
|
||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc32.debug_start, NULL);
|
||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc32.debug_end, NULL);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -2211,17 +2288,116 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
|||
memcpy(symname, sym->stack.name, sym->stack.namelen);
|
||||
symname[sym->stack.namelen] = '\0';
|
||||
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack.offset,
|
||||
NULL, codeview_get_type(sym->stack.symtype, FALSE),
|
||||
block, codeview_get_type(sym->stack.symtype, FALSE),
|
||||
symname);
|
||||
break;
|
||||
case S_BPREL_32:
|
||||
memcpy(symname, sym->stack32.name, sym->stack32.namelen);
|
||||
symname[sym->stack32.namelen] = '\0';
|
||||
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack32.offset,
|
||||
NULL, codeview_get_type(sym->stack32.symtype, FALSE),
|
||||
block, codeview_get_type(sym->stack32.symtype, FALSE),
|
||||
symname);
|
||||
break;
|
||||
|
||||
case S_REGISTER:
|
||||
memcpy(symname, sym->s_register.name, sym->s_register.namelen);
|
||||
symname[sym->s_register.namelen] = '\0';
|
||||
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->s_register.reg,
|
||||
block, codeview_get_type(sym->s_register.type, FALSE),
|
||||
symname);
|
||||
break;
|
||||
|
||||
case S_REGISTER_32:
|
||||
memcpy(symname, sym->s_register32.name, sym->s_register32.namelen);
|
||||
symname[sym->s_register32.namelen] = '\0';
|
||||
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->s_register32.reg,
|
||||
block, codeview_get_type(sym->s_register32.type, FALSE),
|
||||
symname);
|
||||
break;
|
||||
|
||||
case S_BLOCK:
|
||||
block = symt_open_func_block(msc_dbg->module, curr_func, block,
|
||||
codeview_get_address(msc_dbg, sym->block.segment, sym->block.offset),
|
||||
sym->block.length);
|
||||
break;
|
||||
|
||||
case S_END:
|
||||
if (block)
|
||||
{
|
||||
block = symt_close_func_block(msc_dbg->module, curr_func, block, 0);
|
||||
}
|
||||
else if (curr_func)
|
||||
{
|
||||
symt_normalize_function(msc_dbg->module, curr_func);
|
||||
curr_func = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case S_COMPILE:
|
||||
TRACE("S-Compile %x %.*s\n", ((LPBYTE)sym)[4], ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
|
||||
break;
|
||||
|
||||
case S_OBJNAME:
|
||||
TRACE("S-ObjName %.*s\n", ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
|
||||
break;
|
||||
|
||||
case S_LABEL:
|
||||
memcpy(symname, sym->label.name, sym->label.namelen);
|
||||
symname[sym->label.namelen] = '\0';
|
||||
if (curr_func)
|
||||
{
|
||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel,
|
||||
codeview_get_address(msc_dbg, sym->label.segment, sym->label.offset) - curr_func->addr,
|
||||
symname);
|
||||
}
|
||||
else FIXME("No current function for label %s\n", symname);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case S_CONSTANT_32:
|
||||
{
|
||||
int val, vlen;
|
||||
char* ptr;
|
||||
const char* x;
|
||||
struct symt* se;
|
||||
|
||||
vlen = numeric_leaf(&val, &sym->constant32.arrlen);
|
||||
ptr = (char*)&sym->constant32.arrlen + vlen;
|
||||
se = codeview_get_type(sym->constant32.type, FALSE);
|
||||
if (!se) x = "---";
|
||||
else if (se->tag == SymTagEnum) x = ((struct symt_enum*)se)->name;
|
||||
else x = "###";
|
||||
|
||||
FIXME("S-Constant %u %.*s %x (%s)\n",
|
||||
val, ptr[0], ptr + 1, sym->constant32.type, x);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case S_UDT:
|
||||
symt = codeview_get_type(sym->udt.type, FALSE);
|
||||
if (symt)
|
||||
{
|
||||
memcpy(symname, sym->udt.name, sym->udt.namelen);
|
||||
symname[sym->udt.namelen] = '\0';
|
||||
symt_new_typedef(msc_dbg->module, symt, symname);
|
||||
}
|
||||
else FIXME("S-Udt %.*s: couldn't find type 0x%x\n",
|
||||
sym->udt.namelen, sym->udt.name, sym->udt.type);
|
||||
break;
|
||||
|
||||
case S_UDT_32:
|
||||
symt = codeview_get_type(sym->udt32.type, FALSE);
|
||||
if (symt)
|
||||
{
|
||||
memcpy(symname, sym->udt32.name, sym->udt32.namelen);
|
||||
symname[sym->udt32.namelen] = '\0';
|
||||
symt_new_typedef(msc_dbg->module, symt, symname);
|
||||
}
|
||||
else FIXME("S-Udt %.*s: couldn't find type 0x%x\n",
|
||||
sym->udt32.namelen, sym->udt32.name, sym->udt32.type);
|
||||
break;
|
||||
|
||||
/*
|
||||
* These are special, in that they are always followed by an
|
||||
* additional length-prefixed string which is *not* included
|
||||
|
|
|
@ -1112,6 +1112,30 @@ struct symt_public* lookup_public(const struct module* module,
|
|||
return found;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* stabs_finalize_function
|
||||
*
|
||||
* Ends function creation: mainly:
|
||||
* - cleans up line number information
|
||||
* - tries to set up a debug-start tag (FIXME: heuristic to be enhanced)
|
||||
*/
|
||||
static void stabs_finalize_function(struct module* module, struct symt_function* func)
|
||||
{
|
||||
IMAGEHLP_LINE il;
|
||||
|
||||
if (!func) return;
|
||||
symt_normalize_function(module, func);
|
||||
/* To define the debug-start of the function, we use the second line number.
|
||||
* Not 100% bullet proof, but better than nothing
|
||||
*/
|
||||
if (symt_fill_func_line_info(module, func, func->addr, &il) &&
|
||||
symt_get_func_line_next(module, &il))
|
||||
{
|
||||
symt_add_function_point(module, func, SymTagFuncDebugStart,
|
||||
il.Address - func->addr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
||||
unsigned long load_offset, unsigned int staboff, int stablen,
|
||||
unsigned int strtaboff, int strtablen)
|
||||
|
@ -1267,7 +1291,7 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
break;
|
||||
case N_LBRAC:
|
||||
block = symt_open_func_block(module, curr_func, block,
|
||||
stab_ptr->n_value);
|
||||
stab_ptr->n_value, 0);
|
||||
for (j = 0; j < num_pending_vars; j++)
|
||||
{
|
||||
symt_add_func_local(module, curr_func, pending_vars[j].regno,
|
||||
|
@ -1284,9 +1308,13 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
/* These are function parameters. */
|
||||
if (curr_func != NULL)
|
||||
{
|
||||
struct symt* param_type = stabs_parse_type(ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
symt_add_func_local(module, curr_func, 0, stab_ptr->n_value,
|
||||
NULL, stabs_parse_type(ptr), symname);
|
||||
NULL, param_type, symname);
|
||||
symt_add_function_signature_parameter(module,
|
||||
(struct symt_function_signature*)curr_func->type,
|
||||
param_type);
|
||||
}
|
||||
break;
|
||||
case N_RSYM:
|
||||
|
@ -1385,7 +1413,7 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
break;
|
||||
case N_FUN:
|
||||
/* First, clean up the previous function we were working on. */
|
||||
symt_normalize_function(module, curr_func);
|
||||
stabs_finalize_function(module, curr_func);
|
||||
|
||||
/*
|
||||
* For now, just declare the various functions. Later
|
||||
|
@ -1402,18 +1430,18 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
if (*symname)
|
||||
{
|
||||
struct symt_function_signature* func_type;
|
||||
struct symt_function_signature* func_type;
|
||||
func_type = symt_new_function_signature(module,
|
||||
stabs_parse_type(ptr));
|
||||
#ifdef __ELF__
|
||||
if ((public = lookup_public(module, compiland, symname)))
|
||||
curr_func = symt_new_function(module, compiland, symname,
|
||||
public->address, public->size,
|
||||
stabs_parse_type(ptr));
|
||||
curr_func = symt_new_function(module, compiland, symname,
|
||||
public->address, public->size,
|
||||
&func_type->symt);
|
||||
#else
|
||||
curr_func = symt_new_function(module, compiland, symname,
|
||||
load_offset + stab_ptr->n_value, 0,
|
||||
stabs_parse_type(ptr));
|
||||
&func_type->symt);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -1431,7 +1459,7 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
{
|
||||
/* Nuke old path. */
|
||||
currpath[0] = '\0';
|
||||
symt_normalize_function(module, curr_func);
|
||||
stabs_finalize_function(module, curr_func);
|
||||
curr_func = NULL;
|
||||
source_idx = -1;
|
||||
incl_stk = -1;
|
||||
|
@ -1456,7 +1484,7 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
|||
case N_UNDF:
|
||||
strs += strtabinc;
|
||||
strtabinc = stab_ptr->n_value;
|
||||
symt_normalize_function(module, curr_func);
|
||||
stabs_finalize_function(module, curr_func);
|
||||
curr_func = NULL;
|
||||
break;
|
||||
case N_OPT:
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -77,6 +79,61 @@ int symt_cmp_addr(const void* p1, const void* p2)
|
|||
return cmp_addr(a1, a2);
|
||||
}
|
||||
|
||||
static inline void re_append(char** mask, unsigned* len, char ch)
|
||||
{
|
||||
*mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
|
||||
(*mask)[*len - 2] = ch;
|
||||
}
|
||||
|
||||
/* transforms a dbghelp's regular expression into a POSIX one
|
||||
* Here are the valid dbghelp reg ex characters:
|
||||
* * 0 or more characters
|
||||
* ? a single character
|
||||
* [] list
|
||||
* # 0 or more of preceding char
|
||||
* + 1 or more of preceding char
|
||||
* escapes \ on #, ?, [, ], *, +. don't work on -
|
||||
*/
|
||||
static void compile_regex(const char* str, regex_t* re)
|
||||
{
|
||||
char* mask = HeapAlloc(GetProcessHeap(), 0, 1);
|
||||
unsigned len = 1;
|
||||
BOOL in_escape = FALSE;
|
||||
|
||||
re_append(&mask, &len, '^');
|
||||
while (*str)
|
||||
{
|
||||
/* FIXME: this shouldn't be valid on '-' */
|
||||
if (in_escape)
|
||||
{
|
||||
re_append(&mask, &len, '\\');
|
||||
re_append(&mask, &len, *str);
|
||||
in_escape = FALSE;
|
||||
}
|
||||
else switch (*str)
|
||||
{
|
||||
case '\\': in_escape = TRUE; break;
|
||||
case '*': re_append(&mask, &len, '.'); re_append(&mask, &len, '*'); break;
|
||||
case '?': re_append(&mask, &len, '.'); break;
|
||||
case '#': re_append(&mask, &len, '*'); break;
|
||||
/* escape some valid characters in dbghelp reg exp:s */
|
||||
case '$': re_append(&mask, &len, '\\'); re_append(&mask, &len, '$'); break;
|
||||
/* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
|
||||
default: re_append(&mask, &len, *str); break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
if (in_escape)
|
||||
{
|
||||
re_append(&mask, &len, '\\');
|
||||
re_append(&mask, &len, '\\');
|
||||
}
|
||||
re_append(&mask, &len, '$');
|
||||
mask[len - 1] = '\0';
|
||||
regcomp(re, mask, REG_NOSUB);
|
||||
HeapFree(GetProcessHeap(), 0, mask);
|
||||
}
|
||||
|
||||
struct symt_compiland* symt_new_compiland(struct module* module, const char* name)
|
||||
{
|
||||
struct symt_compiland* sym;
|
||||
|
@ -158,13 +215,15 @@ struct symt_function* symt_new_function(struct module* module,
|
|||
struct symt_compiland* compiland,
|
||||
const char* name,
|
||||
unsigned long addr, unsigned long size,
|
||||
struct symt* type)
|
||||
struct symt* sig_type)
|
||||
{
|
||||
struct symt_function* sym;
|
||||
struct symt** p;
|
||||
|
||||
TRACE_(dbghelp_symtype)("Adding global function %s:%s @%lx-%lx\n",
|
||||
module->module.ModuleName, name, addr, addr + size - 1);
|
||||
|
||||
assert(!sig_type || sig_type->tag == SymTagFunctionType);
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
sym->symt.tag = SymTagFunction;
|
||||
|
@ -173,7 +232,7 @@ struct symt_function* symt_new_function(struct module* module,
|
|||
module->sortlist_valid = FALSE;
|
||||
sym->container = &compiland->symt;
|
||||
sym->addr = addr;
|
||||
sym->type = type;
|
||||
sym->type = sig_type;
|
||||
sym->size = size;
|
||||
sym->addr = addr;
|
||||
vector_init(&sym->vlines, sizeof(struct line_info), 64);
|
||||
|
@ -244,7 +303,7 @@ struct symt_data* symt_add_func_local(struct module* module,
|
|||
locsym->symt.tag = SymTagData;
|
||||
locsym->hash_elt.name = pool_strdup(&module->pool, name);
|
||||
locsym->hash_elt.next = NULL;
|
||||
locsym->kind = DataIsLocal;
|
||||
locsym->kind = (offset < 0) ? DataIsParam : DataIsLocal;
|
||||
locsym->container = &block->symt;
|
||||
locsym->type = type;
|
||||
if (regno)
|
||||
|
@ -269,7 +328,7 @@ struct symt_data* symt_add_func_local(struct module* module,
|
|||
struct symt_block* symt_open_func_block(struct module* module,
|
||||
struct symt_function* func,
|
||||
struct symt_block* parent_block,
|
||||
unsigned pc)
|
||||
unsigned pc, unsigned len)
|
||||
{
|
||||
struct symt_block* block;
|
||||
struct symt** p;
|
||||
|
@ -279,9 +338,9 @@ struct symt_block* symt_open_func_block(struct module* module,
|
|||
|
||||
assert(!parent_block || parent_block->symt.tag == SymTagBlock);
|
||||
block = pool_alloc(&module->pool, sizeof(*block));
|
||||
block->symt.tag = SymTagBlock;
|
||||
block->address = func->addr + pc;
|
||||
block->size = 0;
|
||||
block->symt.tag = SymTagBlock;
|
||||
block->address = func->addr + pc;
|
||||
block->size = len;
|
||||
block->container = parent_block ? &parent_block->symt : &func->symt;
|
||||
vector_init(&block->vchildren, sizeof(struct symt*), 4);
|
||||
if (parent_block)
|
||||
|
@ -299,17 +358,37 @@ struct symt_block* symt_close_func_block(struct module* module,
|
|||
{
|
||||
assert(func->symt.tag == SymTagFunction);
|
||||
|
||||
block->size = func->addr + pc - block->address;
|
||||
if (pc) block->size = func->addr + pc - block->address;
|
||||
return (block->container->tag == SymTagBlock) ?
|
||||
GET_ENTRY(block->container, struct symt_block, symt) : NULL;
|
||||
}
|
||||
|
||||
struct symt_function_point* symt_add_function_point(struct module* module,
|
||||
struct symt_function* func,
|
||||
enum SymTagEnum point,
|
||||
unsigned offset, const char* name)
|
||||
{
|
||||
struct symt_function_point* sym;
|
||||
struct symt** p;
|
||||
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
sym->symt.tag = point;
|
||||
sym->parent = func;
|
||||
sym->offset = offset;
|
||||
sym->name = name ? pool_strdup(&module->pool, name) : NULL;
|
||||
p = vector_add(&func->vchildren, &module->pool);
|
||||
*p = &sym->symt;
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
BOOL symt_normalize_function(struct module* module, struct symt_function* func)
|
||||
{
|
||||
unsigned len;
|
||||
struct line_info* dli;
|
||||
|
||||
if (!func) return TRUE;
|
||||
assert(func);
|
||||
/* We aren't adding any more locals or line numbers to this function.
|
||||
* Free any spare memory that we might have allocated.
|
||||
*/
|
||||
|
@ -363,7 +442,17 @@ static void symt_fill_sym_info(const struct module* module,
|
|||
break;
|
||||
case LocIsConstant:
|
||||
sym_info->Flags |= SYMFLAG_VALUEPRESENT;
|
||||
sym_info->Value = data->u.value;
|
||||
switch (data->u.value.n1.n2.vt)
|
||||
{
|
||||
case VT_I4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
|
||||
case VT_I2: sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
|
||||
case VT_I1: sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
|
||||
case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
|
||||
case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
|
||||
case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
|
||||
default:
|
||||
FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("Unhandled loc (%u) in sym data\n", data->location);
|
||||
|
@ -408,7 +497,7 @@ static BOOL symt_enum_module(struct module* module, const char* mask,
|
|||
|
||||
assert(mask);
|
||||
assert(mask[0] != '!');
|
||||
regcomp(&preg, mask, REG_NOSUB);
|
||||
compile_regex(mask, &preg);
|
||||
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
|
||||
while ((ptr = hash_table_iter_up(&hti)))
|
||||
{
|
||||
|
@ -550,6 +639,10 @@ static BOOL symt_enum_locals_helper(struct process* pcs, struct module* module,
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SymTagLabel:
|
||||
case SymTagFuncDebugStart:
|
||||
case SymTagFuncDebugEnd:
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
|
||||
assert(0);
|
||||
|
@ -582,7 +675,7 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
|
|||
BOOL ret;
|
||||
regex_t preg;
|
||||
|
||||
regcomp(&preg, mask ? mask : ".*", REG_NOSUB);
|
||||
compile_regex(mask ? mask : "*", &preg);
|
||||
ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback,
|
||||
UserContext, sym_info,
|
||||
&((struct symt_function*)sym)->vchildren);
|
||||
|
@ -620,7 +713,7 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
|
|||
for (module = pcs->lmodules; module; module = module->next)
|
||||
{
|
||||
if (module->module.SymType != SymNone &&
|
||||
!symt_enum_module(module, ".*", EnumSymbolsCallback, UserContext))
|
||||
!symt_enum_module(module, "*", EnumSymbolsCallback, UserContext))
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -641,9 +734,9 @@ BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
|
|||
FIXME("Strange call mode\n");
|
||||
return FALSE;
|
||||
}
|
||||
Mask = ".*";
|
||||
Mask = "*";
|
||||
}
|
||||
else if (!Mask) Mask = ".*";
|
||||
else if (!Mask) Mask = "*";
|
||||
}
|
||||
if ((module = module_get_debug(pcs, module)))
|
||||
symt_enum_module(module, Mask, EnumSymbolsCallback, UserContext);
|
||||
|
@ -792,12 +885,12 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, LPSTR Name, PIMAGEHLP_SYMBOL Symb
|
|||
}
|
||||
|
||||
/******************************************************************
|
||||
* fill_line_info
|
||||
* sym_fill_func_line_info
|
||||
*
|
||||
* fills information about a file
|
||||
*/
|
||||
static BOOL fill_line_info(struct module* module, struct symt_function* func,
|
||||
DWORD addr, IMAGEHLP_LINE* line)
|
||||
BOOL symt_fill_func_line_info(struct module* module, struct symt_function* func,
|
||||
DWORD addr, IMAGEHLP_LINE* line)
|
||||
{
|
||||
struct line_info* dli = NULL;
|
||||
BOOL found = FALSE;
|
||||
|
@ -872,9 +965,9 @@ BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr,
|
|||
if ((idx = symt_find_nearest(module, dwAddr)) == -1) return FALSE;
|
||||
|
||||
if (module->addr_sorttab[idx]->symt.tag != SymTagFunction) return FALSE;
|
||||
if (!fill_line_info(module,
|
||||
(struct symt_function*)module->addr_sorttab[idx],
|
||||
dwAddr, Line)) return FALSE;
|
||||
if (!symt_fill_func_line_info(module,
|
||||
(struct symt_function*)module->addr_sorttab[idx],
|
||||
dwAddr, Line)) return FALSE;
|
||||
if (pdwDisplacement) *pdwDisplacement = dwAddr - Line->Address;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -929,6 +1022,27 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line)
|
||||
{
|
||||
struct line_info* li;
|
||||
|
||||
if (line->Key == 0) return FALSE;
|
||||
li = (struct line_info*)line->Key;
|
||||
while (!(li->cookie & DLIT_LAST))
|
||||
{
|
||||
li++;
|
||||
if (!(li->cookie & DLIT_SOURCEFILE))
|
||||
{
|
||||
line->LineNumber = li->line_number;
|
||||
line->Address = li->u.pc_offset;
|
||||
line->Key = li;
|
||||
return TRUE;
|
||||
}
|
||||
line->FileName = (char*)source_get(module, li->u.source_file);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* SymGetLineNext (DBGHELP.@)
|
||||
*
|
||||
|
@ -937,7 +1051,6 @@ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
|
|||
{
|
||||
struct process* pcs = process_find_by_handle(hProcess);
|
||||
struct module* module;
|
||||
struct line_info* li;
|
||||
|
||||
TRACE("(%p %p)\n", hProcess, Line);
|
||||
|
||||
|
@ -946,20 +1059,7 @@ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
|
|||
module = module_find_by_addr(pcs, Line->Address, DMT_UNKNOWN);
|
||||
if (!(module = module_get_debug(pcs, module))) return FALSE;
|
||||
|
||||
if (Line->Key == 0) return FALSE;
|
||||
li = (struct line_info*)Line->Key;
|
||||
while (!(li->cookie & DLIT_LAST))
|
||||
{
|
||||
li++;
|
||||
if (!(li->cookie & DLIT_SOURCEFILE))
|
||||
{
|
||||
Line->LineNumber = li->line_number;
|
||||
Line->Address = li->u.pc_offset;
|
||||
Line->Key = li;
|
||||
return TRUE;
|
||||
}
|
||||
Line->FileName = (char*)source_get(module, li->u.source_file);
|
||||
}
|
||||
if (symt_get_func_line_next(module, Line)) return TRUE;
|
||||
SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ const char* symt_get_name(const struct symt* sym)
|
|||
case SymTagFunction: return ((struct symt_function*)sym)->hash_elt.name;
|
||||
case SymTagPublicSymbol: return ((struct symt_public*)sym)->hash_elt.name;
|
||||
case SymTagBaseType: return ((struct symt_basic*)sym)->hash_elt.name;
|
||||
case SymTagLabel: return ((struct symt_function_point*)sym)->name;
|
||||
/* hierarchy tree */
|
||||
case SymTagEnum: return ((struct symt_enum*)sym)->name;
|
||||
case SymTagTypedef: return ((struct symt_typedef*)sym)->hash_elt.name;
|
||||
|
@ -252,7 +253,7 @@ struct symt_enum* symt_new_enum(struct module* module, const char* typename)
|
|||
}
|
||||
|
||||
BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
|
||||
const char* name, unsigned value)
|
||||
const char* name, int value)
|
||||
{
|
||||
struct symt_data* e;
|
||||
struct symt** p;
|
||||
|
@ -269,7 +270,8 @@ BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
|
|||
/* CV defines the underlying type for the enumeration */
|
||||
e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
|
||||
e->location = LocIsConstant;
|
||||
e->u.value = value; /* FIXME: use variant */
|
||||
e->u.value.n1.n2.vt = VT_I4;
|
||||
e->u.value.n1.n2.n3.lVal = value;
|
||||
|
||||
p = vector_add(&enum_type->vchildren, &module->pool);
|
||||
if (!p) return FALSE; /* FIXME we leak e */
|
||||
|
@ -296,16 +298,31 @@ struct symt_array* symt_new_array(struct module* module, int min, int max,
|
|||
struct symt_function_signature* symt_new_function_signature(struct module* module,
|
||||
struct symt* ret_type)
|
||||
{
|
||||
struct symt_function_signature* sym;
|
||||
struct symt_function_signature* sym;
|
||||
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
sym->symt.tag = SymTagFunctionType;
|
||||
sym->rettype = ret_type;
|
||||
vector_init(&sym->vchildren, sizeof(struct symt*), 4);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
BOOL symt_add_function_signature_parameter(struct module* module,
|
||||
struct symt_function_signature* sig_type,
|
||||
struct symt* param)
|
||||
{
|
||||
struct symt** p;
|
||||
|
||||
assert(sig_type->symt.tag == SymTagFunctionType);
|
||||
p = vector_add(&sig_type->vchildren, &module->pool);
|
||||
if (!p) return FALSE; /* FIXME we leak e */
|
||||
*p = param;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
|
||||
{
|
||||
struct symt_pointer* sym;
|
||||
|
@ -318,6 +335,21 @@ struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_ty
|
|||
return sym;
|
||||
}
|
||||
|
||||
struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref,
|
||||
const char* name)
|
||||
{
|
||||
struct symt_typedef* sym;
|
||||
|
||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||
{
|
||||
sym->symt.tag = SymTagTypedef;
|
||||
sym->type = ref;
|
||||
sym->hash_elt.name = pool_strdup(&module->pool, name);
|
||||
hash_table_add(&module->ht_types, &sym->hash_elt);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* SymEnumTypes (DBGHELP.@)
|
||||
*
|
||||
|
@ -395,10 +427,13 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
|
||||
switch (type->tag)
|
||||
{
|
||||
case SymTagUDT: v = &((struct symt_udt*)type)->vchildren; break;
|
||||
case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
|
||||
case SymTagUDT: v = &((struct symt_udt*)type)->vchildren; break;
|
||||
case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
|
||||
case SymTagFunctionType: v = &((struct symt_function_signature*)type)->vchildren; break;
|
||||
case SymTagFunction: v = &((struct symt_function*)type)->vchildren; break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for find-children\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for find-children\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < tifp->Count; i++)
|
||||
|
@ -428,25 +463,31 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
case SymTagPublicSymbol:
|
||||
X(DWORD) = ((struct symt_public*)type)->address;
|
||||
break;
|
||||
case SymTagFuncDebugStart:
|
||||
case SymTagFuncDebugEnd:
|
||||
case SymTagLabel:
|
||||
X(DWORD) = ((struct symt_function_point*)type)->parent->addr +
|
||||
((struct symt_function_point*)type)->offset;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-address\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
/* this is wrong, we should return the type of the index, not the
|
||||
* type of the array[0]
|
||||
*/
|
||||
case TI_GET_ARRAYINDEXTYPEID:
|
||||
if (type->tag != SymTagArrayType) return FALSE;
|
||||
X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TI_GET_BASETYPE:
|
||||
if (type->tag != SymTagBaseType) return FALSE;
|
||||
X(DWORD) = ((struct symt_basic*)type)->bt;
|
||||
switch (type->tag)
|
||||
{
|
||||
case SymTagBaseType:
|
||||
X(DWORD) = ((struct symt_basic*)type)->bt;
|
||||
break;
|
||||
case SymTagEnum:
|
||||
X(DWORD) = btInt;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TI_GET_BITPOSITION:
|
||||
|
@ -464,17 +505,32 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
case SymTagEnum:
|
||||
X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
|
||||
break;
|
||||
case SymTagFunctionType:
|
||||
X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
|
||||
break;
|
||||
case SymTagFunction:
|
||||
X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
|
||||
break;
|
||||
case SymTagPointerType: /* MS does it that way */
|
||||
case SymTagArrayType: /* MS does it that way */
|
||||
X(DWORD) = 0;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-children-count\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-children-count\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
/* fall through */
|
||||
case SymTagData:
|
||||
case SymTagPublicSymbol:
|
||||
case SymTagPointerType:
|
||||
case SymTagBaseType:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TI_GET_COUNT:
|
||||
/* it seems that FunctionType also react to GET_COUNT (same value as
|
||||
* GET_CHILDREN_COUNT ?, except for C++ methods, where it seems to
|
||||
* also include 'this' (GET_CHILDREN_COUNT+1)
|
||||
*/
|
||||
if (type->tag != SymTagArrayType) return FALSE;
|
||||
X(DWORD) = ((struct symt_array*)type)->end -
|
||||
((struct symt_array*)type)->start;
|
||||
|
@ -501,14 +557,13 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
X(DWORD) = ((struct symt_udt*)type)->size;
|
||||
break;
|
||||
case SymTagEnum:
|
||||
X(DWORD) = sizeof(int);
|
||||
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
|
||||
return symt_get_info(((struct symt_data*)type)->type,
|
||||
TI_GET_LENGTH, pInfo);
|
||||
return FALSE;
|
||||
break;
|
||||
case SymTagArrayType:
|
||||
if (!symt_get_info(((struct symt_array*)type)->basetype,
|
||||
|
@ -520,8 +575,12 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
case SymTagPublicSymbol:
|
||||
X(DWORD) = ((struct symt_public*)type)->size;
|
||||
break;
|
||||
case SymTagTypedef:
|
||||
return symt_get_info(((struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-size\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-length\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
@ -536,7 +595,20 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
X(DWORD) = (DWORD)((struct symt_data*)type)->container;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-lexical-parent\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TI_GET_NESTED:
|
||||
switch (type->tag)
|
||||
{
|
||||
case SymTagUDT:
|
||||
case SymTagEnum:
|
||||
X(DWORD) = 0;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -545,23 +617,22 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
switch (type->tag)
|
||||
{
|
||||
case SymTagData:
|
||||
switch (((struct symt_data*)type)->location)
|
||||
switch (((struct symt_data*)type)->kind)
|
||||
{
|
||||
case LocIsRegRel:
|
||||
case LocIsThisRel:
|
||||
case DataIsParam:
|
||||
case DataIsLocal:
|
||||
case DataIsMember:
|
||||
X(ULONG) = ((struct symt_data*)type)->u.offset;
|
||||
break;
|
||||
case LocIsConstant:
|
||||
X(ULONG) = 0; /* FIXME ???? */
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown location (%u) for get-offset\n",
|
||||
((struct symt_data*)type)->location);
|
||||
break;
|
||||
FIXME("Unknown kind (%u) for get-offset\n",
|
||||
((struct symt_data*)type)->kind);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-offset\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-offset\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -582,8 +653,10 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
break;
|
||||
|
||||
case TI_GET_TYPE:
|
||||
case TI_GET_TYPEID:
|
||||
switch (type->tag)
|
||||
{
|
||||
/* hierarchical => hierarchical */
|
||||
case SymTagArrayType:
|
||||
X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
|
||||
break;
|
||||
|
@ -593,34 +666,43 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
|||
case SymTagFunctionType:
|
||||
X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
|
||||
break;
|
||||
case SymTagTypedef:
|
||||
X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
|
||||
break;
|
||||
/* lexical => hierarchical */
|
||||
case SymTagData:
|
||||
X(DWORD) = (DWORD)((struct symt_data*)type)->type;
|
||||
break;
|
||||
case SymTagFunction:
|
||||
X(DWORD) = (DWORD)((struct symt_function*)type)->type;
|
||||
break;
|
||||
/* FIXME: should also work for enums and FunctionArgType */
|
||||
default:
|
||||
FIXME("Unsupported sym-tag %s for get-type\n", symt_get_tag_str(type->tag));
|
||||
FIXME("Unsupported sym-tag %s for get-type\n",
|
||||
symt_get_tag_str(type->tag));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TI_GET_TYPEID:
|
||||
X(DWORD) = (DWORD)type;
|
||||
break;
|
||||
|
||||
case TI_GET_UDTKIND:
|
||||
if (type->tag != SymTagUDT) return FALSE;
|
||||
X(DWORD) = ((struct symt_udt*)type)->kind;
|
||||
break;
|
||||
|
||||
case TI_GET_VALUE:
|
||||
if (type->tag != SymTagData || ((struct symt_data*)type)->kind != DataIsConstant)
|
||||
return FALSE;
|
||||
X(VARIANT) = ((struct symt_data*)type)->u.value;
|
||||
break;
|
||||
|
||||
#undef X
|
||||
|
||||
case TI_GET_ADDRESSOFFSET:
|
||||
case TI_GET_ARRAYINDEXTYPEID:
|
||||
case TI_GET_CALLING_CONVENTION:
|
||||
case TI_GET_CLASSPARENTID:
|
||||
case TI_GET_NESTED:
|
||||
case TI_GET_SYMINDEX:
|
||||
case TI_GET_THISADJUST:
|
||||
case TI_GET_VALUE:
|
||||
case TI_GET_VIRTUALBASECLASS:
|
||||
case TI_GET_VIRTUALBASEPOINTEROFFSET:
|
||||
case TI_GET_VIRTUALTABLESHAPEID:
|
||||
|
|
Loading…
Reference in New Issue