[DBGHELP] set correct values in symt_fill_sym_info (SYMBOL_INFO).
[reactos.git] / dll / win32 / dbghelp / symbol.c
index 30e33a5..fea06e2 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #define NONAMELESSUNION
-#define NONAMELESSSTRUCT
 
 #include "config.h"
 
 #include <limits.h>
 #include <sys/types.h>
 #include <assert.h>
-
-#include "dbghelp_private.h"
-
 #ifndef DBGHELP_STATIC_LIB
 #include "wine/debug.h"
+#endif
+#include "dbghelp_private.h"
+#ifndef DBGHELP_STATIC_LIB
 #include "winnls.h"
 #endif
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
 
-static WCHAR    starW[] = {'*','\0'};
+static const WCHAR starW[] = {'*','\0'};
 
 static inline int cmp_addr(ULONG64 a1, ULONG64 a2)
 {
@@ -72,16 +71,37 @@ DWORD             symt_ptr2index(struct module* module, const struct symt* sym)
 {
 #ifdef __x86_64__
     const struct symt** c;
-    int                 len = vector_length(&module->vsymt), i;
-
-    /* FIXME: this is inefficient */
-    for (i = 0; i < len; i++)
-    {
-        if (*(struct symt**)vector_at(&module->vsymt, i) == sym)
-            return i + 1;
+    int len = vector_length(&module->vsymt);
+    struct hash_table_iter hti;
+    void *ptr;
+    struct symt_idx_to_ptr *idx_to_ptr;
+    /* place enough storage on the stack to represent a pointer in %p form */
+    char ptrbuf[3 + (sizeof(void *) * 2)];
+
+    /* make a string representation of the pointer to use as a hash key */
+    sprintf(ptrbuf, "%p", sym);
+    hash_table_iter_init(&module->ht_symaddr, &hti, ptrbuf);
+
+    /* try to find the pointer in our ht */
+    while ((ptr = hash_table_iter_up(&hti))) {
+        idx_to_ptr = CONTAINING_RECORD(ptr, struct symt_idx_to_ptr, hash_elt);
+        if (idx_to_ptr->sym == sym)
+            return idx_to_ptr->idx;
     }
+
     /* not found */
+    /* add the symbol to our symbol vector */
     c = vector_add(&module->vsymt, &module->pool);
+
+    /* add an idx to ptr mapping so we can find it again by address */
+    if ((idx_to_ptr = pool_alloc(&module->pool, sizeof(*idx_to_ptr)))) 
+    {
+        idx_to_ptr->hash_elt.name = pool_strdup(&module->pool, ptrbuf);
+        idx_to_ptr->sym = sym;
+        idx_to_ptr->idx = len + 1;
+        hash_table_add(&module->ht_symaddr, &idx_to_ptr->hash_elt);
+    }
+
     if (c) *c = sym;
     return len + 1;
 #else
@@ -206,6 +226,7 @@ struct symt_compiland* symt_new_compiland(struct module* module,
 struct symt_public* symt_new_public(struct module* module, 
                                     struct symt_compiland* compiland,
                                     const char* name,
+                                    BOOL is_function,
                                     unsigned long address, unsigned size)
 {
     struct symt_public* sym;
@@ -221,6 +242,7 @@ struct symt_public* symt_new_public(struct module* module,
         sym->symt.tag      = SymTagPublicSymbol;
         sym->hash_elt.name = pool_strdup(&module->pool, name);
         sym->container     = compiland ? &compiland->symt : NULL;
+        sym->is_function   = is_function;
         sym->address       = address;
         sym->size          = size;
         symt_add_module_ht(module, (struct symt_ht*)sym);
@@ -426,7 +448,7 @@ struct symt_block* symt_close_func_block(struct module* module,
 
     if (pc) block->size = func->address + pc - block->address;
     return (block->container->tag == SymTagBlock) ? 
-        GET_ENTRY(block->container, struct symt_block, symt) : NULL;
+        CONTAINING_RECORD(block->container, struct symt_block, symt) : NULL;
 }
 
 struct symt_hierarchy_point* symt_add_function_point(struct module* module,
@@ -568,7 +590,7 @@ static void symt_fill_sym_info(struct module_pair* pair,
 
     if (!symt_get_info(pair->effective, sym, TI_GET_TYPE, &sym_info->TypeIndex))
         sym_info->TypeIndex = 0;
-    sym_info->info = symt_ptr2index(pair->effective, sym);
+    sym_info->Index = symt_ptr2index(pair->effective, sym);
     sym_info->Reserved[0] = sym_info->Reserved[1] = 0;
     if (!symt_get_info(pair->effective, sym, TI_GET_LENGTH, &size) &&
         (!sym_info->TypeIndex ||
@@ -677,11 +699,16 @@ static void symt_fill_sym_info(struct module_pair* pair,
         }
         break;
     case SymTagPublicSymbol:
-        sym_info->Flags |= SYMFLAG_EXPORT;
-        symt_get_address(sym, &sym_info->Address);
+        {
+            const struct symt_public* pub = (const struct symt_public*)sym;
+            if (pub->is_function)
+                sym_info->Flags |= SYMFLAG_PUBLIC_CODE;
+            else
+                sym_info->Flags |= SYMFLAG_EXPORT;
+            symt_get_address(sym, &sym_info->Address);
+        }
         break;
     case SymTagFunction:
-        sym_info->Flags |= SYMFLAG_FUNCTION;
         symt_get_address(sym, &sym_info->Address);
         break;
     case SymTagThunk:
@@ -699,8 +726,8 @@ static void symt_fill_sym_info(struct module_pair* pair,
     if (sym_info->MaxNameLen)
     {
         if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) ||
-            (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name,
-                                                      sym_info->MaxNameLen, UNDNAME_NAME_ONLY) == 0))
+            ((sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name,
+                                                       sym_info->MaxNameLen, UNDNAME_NAME_ONLY)) == 0))
         {
             sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1);
             memcpy(sym_info->Name, name, sym_info->NameLen);
@@ -727,7 +754,7 @@ static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair,
                         const struct symt_function* func, const struct symt* sym)
 {
     symt_fill_sym_info(pair, func, sym, se->sym_info);
-    if (se->index && se->sym_info->info != se->index) return FALSE;
+    if (se->index && se->sym_info->Index != se->index) return FALSE;
     if (se->tag && se->sym_info->Tag != se->tag) return FALSE;
     if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE;
     return !se->cb(se->sym_info, se->sym_info->Size, se->user);
@@ -745,7 +772,7 @@ static BOOL symt_enum_module(struct module_pair* pair, const WCHAR* match,
     hash_table_iter_init(&pair->effective->ht_symbols, &hti, NULL);
     while ((ptr = hash_table_iter_up(&hti)))
     {
-        sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+        sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
         nameW = symt_get_nameW(&sym->symt);
         ret = SymMatchStringW(nameW, match, FALSE);
         HeapFree(GetProcessHeap(), 0, nameW);
@@ -991,7 +1018,7 @@ void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si)
     siw->TypeIndex = si->TypeIndex; 
     siw->Reserved[0] = si->Reserved[0];
     siw->Reserved[1] = si->Reserved[1];
-    siw->Index = si->info; /* FIXME: see dbghelp.h */
+    siw->Index = si->Index;
     siw->Size = si->Size;
     siw->ModBase = si->ModBase;
     siw->Flags = si->Flags;
@@ -1232,7 +1259,8 @@ BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address,
     if ((sym = symt_find_nearest(pair.effective, Address)) == NULL) return FALSE;
 
     symt_fill_sym_info(&pair, NULL, &sym->symt, Symbol);
-    *Displacement = Address - Symbol->Address;
+    if (Displacement)
+        *Displacement = Address - Symbol->Address;
     return TRUE;
 }
 
@@ -1332,7 +1360,7 @@ static BOOL find_name(struct process* pcs, struct module* module, const char* na
     hash_table_iter_init(&pair.effective->ht_symbols, &hti, name);
     while ((ptr = hash_table_iter_up(&hti)))
     {
-        sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+        sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
 
         if (!strcmp(sym->hash_elt.name, name))
         {
@@ -1755,31 +1783,69 @@ BOOL WINAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym, PSTR UnDecName, DWORD UnDecName
 static void * CDECL und_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); }
 static void   CDECL und_free (void* ptr)  { HeapFree(GetProcessHeap(), 0, ptr); }
 
-/***********************************************************************
- *             UnDecorateSymbolName (DBGHELP.@)
- */
-DWORD WINAPI UnDecorateSymbolName(PCSTR DecoratedName, PSTR UnDecoratedName,
-                                  DWORD UndecoratedLength, DWORD Flags)
+static char *und_name(char *buffer, const char *mangled, int buflen, unsigned short flags)
 {
     /* undocumented from msvcrt */
+    static HANDLE hMsvcrt;
     static char* (CDECL *p_undname)(char*, const char*, int, void* (CDECL*)(size_t), void (CDECL*)(void*), unsigned short);
     static const WCHAR szMsvcrt[] = {'m','s','v','c','r','t','.','d','l','l',0};
 
-    TRACE("(%s, %p, %d, 0x%08x)\n",
-          debugstr_a(DecoratedName), UnDecoratedName, UndecoratedLength, Flags);
-
     if (!p_undname)
     {
         if (!hMsvcrt) hMsvcrt = LoadLibraryW(szMsvcrt);
         if (hMsvcrt) p_undname = (void*)GetProcAddress(hMsvcrt, "__unDName");
-        if (!p_undname) return 0;
+        if (!p_undname) return NULL;
     }
 
-    if (!UnDecoratedName) return 0;
-    if (!p_undname(UnDecoratedName, DecoratedName, UndecoratedLength, 
-                   und_alloc, und_free, Flags))
+    return p_undname(buffer, mangled, buflen, und_alloc, und_free, flags);
+}
+
+/***********************************************************************
+ *             UnDecorateSymbolName (DBGHELP.@)
+ */
+DWORD WINAPI UnDecorateSymbolName(const char *decorated_name, char *undecorated_name,
+                                  DWORD undecorated_length, DWORD flags)
+{
+    TRACE("(%s, %p, %d, 0x%08x)\n",
+          debugstr_a(decorated_name), undecorated_name, undecorated_length, flags);
+
+    if (!undecorated_name || !undecorated_length)
         return 0;
-    return strlen(UnDecoratedName);
+    if (!und_name(undecorated_name, decorated_name, undecorated_length, flags))
+        return 0;
+    return strlen(undecorated_name);
+}
+
+/***********************************************************************
+ *             UnDecorateSymbolNameW (DBGHELP.@)
+ */
+DWORD WINAPI UnDecorateSymbolNameW(const WCHAR *decorated_name, WCHAR *undecorated_name,
+                                   DWORD undecorated_length, DWORD flags)
+{
+    char *buf, *ptr;
+    int len, ret = 0;
+
+    TRACE("(%s, %p, %d, 0x%08x)\n",
+          debugstr_w(decorated_name), undecorated_name, undecorated_length, flags);
+
+    if (!undecorated_name || !undecorated_length)
+        return 0;
+
+    len = WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, NULL, 0, NULL, NULL);
+    if ((buf = HeapAlloc(GetProcessHeap(), 0, len)))
+    {
+        WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, buf, len, NULL, NULL);
+        if ((ptr = und_name(NULL, buf, 0, flags)))
+        {
+            MultiByteToWideChar(CP_ACP, 0, ptr, -1, undecorated_name, undecorated_length);
+            undecorated_name[undecorated_length - 1] = 0;
+            ret = strlenW(undecorated_name);
+            und_free(ptr);
+        }
+        HeapFree(GetProcessHeap(), 0, buf);
+    }
+
+    return ret;
 }
 
 #define WILDCHAR(x)      (-(x))
@@ -2113,7 +2179,7 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
     {
         unsigned int    i;
 
-        sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+        sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
         if (sym->symt.tag != SymTagFunction) continue;
 
         sci.FileName[0] = '\0';
@@ -2199,3 +2265,25 @@ BOOL WINAPI SymFromIndexW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMB
 
     return FALSE;
 }
+
+/******************************************************************
+ *             SymSetHomeDirectory (DBGHELP.@)
+ *
+ */
+PCHAR WINAPI SymSetHomeDirectory(HANDLE hProcess, PCSTR dir)
+{
+    FIXME("(%p, %s): stub\n", hProcess, dir);
+
+    return NULL;
+}
+
+/******************************************************************
+ *             SymSetHomeDirectoryW (DBGHELP.@)
+ *
+ */
+PWSTR WINAPI SymSetHomeDirectoryW(HANDLE hProcess, PCWSTR dir)
+{
+    FIXME("(%p, %s): stub\n", hProcess, debugstr_w(dir));
+
+    return NULL;
+}