- 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)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c
index ca90828..3ee317b 100644
--- a/dlls/dbghelp/dbghelp.c
+++ b/dlls/dbghelp/dbghelp.c
@@ -29,22 +29,21 @@
/* 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
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index ebf5988..d5f3710 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -26,6 +26,7 @@
#include "winbase.h"
#include "winver.h"
#include "dbghelp.h"
+#include "oaidl.h"
#include "cvconst.h"
@@ -142,11 +143,7 @@
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* 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 symt;
struct symt* rettype;
+ struct vector vchildren;
};
struct symt_pointer
@@ -367,11 +373,21 @@
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 @@
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);
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 1f3b394..e1d719e 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -1068,7 +1068,7 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
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
diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c
index 76c5dda..e08a86c 100644
--- a/dlls/dbghelp/stabs.c
+++ b/dlls/dbghelp/stabs.c
@@ -1112,6 +1112,30 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
{
/* 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 @@
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:
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index 21d562e..4e78a66 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -20,6 +20,8 @@
*/
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
@@ -77,6 +79,61 @@
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_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 @@
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 @@
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_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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
/******************************************************************
- * 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 @@
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 @@
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 @@
{
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 @@
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;
}
diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c
index 79e444e..8089dbc 100644
--- a/dlls/dbghelp/type.c
+++ b/dlls/dbghelp/type.c
@@ -84,6 +84,7 @@
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 @@
}
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 @@
/* 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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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: