- removed file extension from module (and suffixed ELF modules with
  <elf>)
- added generic thunk support for builtin modules (with the help of
  winebuild's new markers for thunks)
- for ELF modules, no longer generating SymTagPublicSymbols objects
  from ELF public symbol table
- because of last point, rewrote stabs symbols' address and size
  management by parsing directly the symtab instead of using
  SymTagPublicSymbols objects
- cleaned up SymTagPublicSymbols object names for native modules
- fixed off by one errors in array management
- SymLoadModule(hProc,0,0,0,0) (wine extension) will force the
  resynchronization of internal ELF modules list)
- new option (0x40000000) for Sym{Get|Set}Option to report ELF modules
  in SymEnumModules (as well as loader with <wine-loader>)
- some minor internal clean-ups
- enhanced const correctness

diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c
index 3ee317b..c7f326e 100644
--- a/dlls/dbghelp/dbghelp.c
+++ b/dlls/dbghelp/dbghelp.c
@@ -42,9 +42,9 @@
  *      + 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)
+ *      + support the PUBLICS_ONLY, NO_PUBLICS and AUTO_PUBLICS options
  *      + C++ management
  *  - stabs: 
- *      + should identify the relay code in Wine and mark it as thunk type
  *      + C++ management
  *  - implement the callback notification mechanism
  */
@@ -122,7 +122,7 @@
 static BOOL process_invade(HANDLE hProcess)
 {
     HMODULE     hMods[256];
-    char        img[256], mod[256];
+    char        img[256];
     DWORD       i, sz;
     MODULEINFO  mi;
 
@@ -133,8 +133,7 @@
     {
         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
             !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
-            !GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)) ||
-            !SymLoadModule(hProcess, 0, img, mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
+            !SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
             return FALSE;
     }
 
@@ -218,8 +217,7 @@
 
     if (fInvadeProcess)
     {
-        pcs->dbg_hdr_addr = elf_read_wine_loader_dbg_info(pcs);
-        if (pcs->dbg_hdr_addr == 0)
+        if (!elf_read_wine_loader_dbg_info(pcs))
         {
             SymCleanup(hProcess);
             return FALSE;
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index 5cd9c5b..8c7f644 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -149,7 +149,7 @@
 {
     struct symt                 symt;
     struct hash_table_elt       hash_elt;       /* if global symbol */
-    unsigned long               addr;
+    unsigned long               address;
     struct symt*                container;      /* compiland */
     struct symt*                type;           /* points to function_signature */
     unsigned long               size;
@@ -176,6 +176,16 @@
                                 is_function : 1;
 };
 
+struct symt_thunk
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;
+    struct symt*                container;      /* compiland */
+    unsigned long               address;
+    unsigned long               size;
+    THUNK_ORDINAL               ordinal;        /* FIXME: doesn't seem to be accessible */
+};
+
 /* class tree */
 struct symt_array
 {
@@ -229,15 +239,19 @@
     struct vector               vchildren;
 };
 
-enum DbgModuleType {DMT_UNKNOWN, DMT_ELF, DMT_NE, DMT_PE};
+enum module_type
+{
+    DMT_UNKNOWN,        /* for lookup, not actually used for a module */
+    DMT_ELF,            /* a real ELF shared module */
+    DMT_PE,             /* a native or builtin PE module */
+};
 
 struct module
 {
     IMAGEHLP_MODULE             module;
     struct module*              next;
-    enum DbgModuleType		type;
-    unsigned short		elf_mark : 1;
-    struct tagELF_DBG_INFO*	elf_dbg_info;
+    enum module_type		type;
+    struct elf_module_info*	elf_info;
     
     /* memory allocation pool */
     struct pool                 pool;
@@ -275,8 +289,7 @@
 extern SYM_TYPE     elf_load_debug_info(struct module* module);
 extern struct module*
                     elf_load_module(struct process* pcs, const char* name);
-extern unsigned long
-                    elf_read_wine_loader_dbg_info(struct process* pcs);
+extern BOOL         elf_read_wine_loader_dbg_info(struct process* pcs);
 extern BOOL         elf_synchronize_module_list(struct process* pcs);
 
 /* memory.c */
@@ -294,15 +307,15 @@
 /* module.c */
 extern struct module*
                     module_find_by_addr(const struct process* pcs, unsigned long addr,
-                                        enum DbgModuleType type);
+                                        enum module_type type);
 extern struct module*
                     module_find_by_name(const struct process* pcs, 
-                                        const char* name, enum DbgModuleType type);
+                                        const char* name, enum module_type type);
 extern struct module*
                     module_get_debug(const struct process* pcs, struct module*);
 extern struct module*
                     module_new(struct process* pcs, const char* name, 
-                               enum DbgModuleType type, unsigned long addr, 
+                               enum module_type type, unsigned long addr, 
                                unsigned long size, unsigned long stamp, 
                                unsigned long checksum);
 
@@ -312,7 +325,7 @@
 extern SYM_TYPE     pe_load_debug_directory(const struct process* pcs, 
                                             struct module* module, 
                                             const BYTE* file_map,
-                                            PIMAGE_DEBUG_DIRECTORY dbg, int nDbg);
+                                            const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
 /* pe_module.c */
 extern struct module*
                     pe_load_module(struct process* pcs, char* name,
@@ -335,6 +348,7 @@
 /* symbol.c */
 extern const char*  symt_get_name(const struct symt* sym);
 extern int          symt_cmp_addr(const void* p1, const void* p2);
+extern int          symt_find_nearest(struct module* module, DWORD addr);
 extern struct symt_compiland*
                     symt_new_compiland(struct module* module, 
                                        const char* filename);
@@ -351,10 +365,10 @@
                                              unsigned long addr, unsigned long size, 
                                              struct symt* type);
 extern struct symt_function*
-                    symt_new_function(struct module* module, 
+                    symt_new_function(struct module* module,
                                       struct symt_compiland* parent,
                                       const char* name,
-                                      unsigned long addr, unsigned long size,        
+                                      unsigned long addr, unsigned long size,
                                       struct symt* type);
 extern BOOL         symt_normalize_function(struct module* module, 
                                             struct symt_function* func);
@@ -386,6 +400,11 @@
                                              struct symt_function* func, 
                                              DWORD addr, IMAGEHLP_LINE* line);
 extern BOOL         symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line);
+extern struct symt_thunk*
+                    symt_new_thunk(struct module* module, 
+                                   struct symt_compiland* parent,
+                                   const char* name, THUNK_ORDINAL ord,
+                                   unsigned long addr, unsigned long size);
 
 /* type.c */
 extern void         symt_init_basic(struct module* module);
@@ -424,3 +443,7 @@
 extern struct symt_typedef*
                     symt_new_typedef(struct module* module, struct symt* ref, 
                                      const char* name);
+
+
+/* some more Wine extensions */
+#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c
index 885fe4d..952c988 100644
--- a/dlls/dbghelp/elf_module.c
+++ b/dlls/dbghelp/elf_module.c
@@ -70,10 +70,12 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 
-typedef struct tagELF_DBG_INFO
+struct elf_module_info
 {
-    unsigned long       elf_addr;
-} ELF_DBG_INFO;
+    unsigned long               elf_addr;
+    unsigned short	        elf_mark : 1,
+                                elf_loader : 1;
+};
 
 #ifdef __ELF__
 
@@ -82,43 +84,57 @@
 
 struct elf_info
 {
-    unsigned            flags;          /* IN  one (or several) of the ELF_INFO constants */
-    unsigned long       dbg_hdr_addr;   /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
-    struct module*      module;         /* OUT loaded module (if ELF_INFO_MODULE is set) */
+    unsigned                    flags;          /* IN  one (or several) of the ELF_INFO constants */
+    unsigned long               dbg_hdr_addr;   /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
+    struct module*              module;         /* OUT loaded module (if ELF_INFO_MODULE is set) */
+};
+
+struct symtab_elt
+{
+    struct hash_table_elt       ht_elt;
+    const Elf32_Sym*            symp;
+    const char*                 filename;
+    unsigned                    used;
+};
+
+struct thunk_area
+{
+    const char*                 symname;
+    THUNK_ORDINAL               ordinal;
+    unsigned long               rva_start;
+    unsigned long               rva_end;
 };
 
 /******************************************************************
- *		elf_load_symtab
+ *		elf_hash_symtab
  *
- * Walk through the entire symbol table and add any symbols we find there.
- * This can be used in cases where we have stripped ELF shared libraries,
- * or it can be used in cases where we have data symbols for which the address
- * isn't encoded in the stabs.
- *
- * This is all really quite easy, since we don't have to worry about line
- * numbers or local data variables.
+ * creating an internal hash table to ease use ELF symtab information lookup
  */
-static int elf_load_symtab(struct module* module, const char* addr,
-                           unsigned long load_addr, const Elf32_Shdr* symtab,
-                           const Elf32_Shdr* strtab)
+static void elf_hash_symtab(const struct module* module, struct pool* pool, 
+                            struct hash_table* ht_symtab, const char* map_addr,
+                            const Elf32_Shdr* symtab, const Elf32_Shdr* strtab,
+                            unsigned num_areas, struct thunk_area* thunks)
 {
-    int		                i, nsym;
+    int		                i, j, nsym;
     const char*                 strp;
     const char*                 symname;
+    const char*                 filename = NULL;
     const Elf32_Sym*            symp;
-    struct symt_compiland*      compiland = NULL;
+    struct symtab_elt*          ste;
 
-    symp = (Elf32_Sym*)(addr + symtab->sh_offset);
+    symp = (const Elf32_Sym*)(map_addr + symtab->sh_offset);
     nsym = symtab->sh_size / sizeof(*symp);
-    strp = (char*)(addr + strtab->sh_offset);
+    strp = (const char*)(map_addr + strtab->sh_offset);
+
+    for (j = 0; j < num_areas; j++)
+        thunks[j].rva_start = thunks[j].rva_end = 0;
 
     for (i = 0; i < nsym; i++, symp++)
     {
         /* Ignore certain types of entries which really aren't of that much
          * interest.
          */
-        if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION || 
-            symp->st_shndx == SHN_UNDEF)
+        if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION || symp->st_shndx == SHN_UNDEF)
         {
             continue;
         }
@@ -127,14 +143,252 @@
 
         if (ELF32_ST_TYPE(symp->st_info) == STT_FILE)
         {
-            compiland = symt_new_compiland(module, symname);
+            filename = symname;
             continue;
         }
-        symt_new_public(module, compiland, symname,
-                        load_addr + symp->st_value, symp->st_size,
-                        TRUE /* FIXME */, ELF32_ST_TYPE(symp->st_info) == STT_FUNC);
+        for (j = 0; j < num_areas; j++)
+        {
+            if (!strcmp(symname, thunks[j].symname))
+            {
+                thunks[j].rva_start = symp->st_value;
+                thunks[j].rva_end   = symp->st_value + symp->st_size;
+                break;
+            }
+        }
+        if (j < num_areas) continue;
+        ste = pool_alloc(pool, sizeof(*ste));
+        ste->ht_elt.name = symname;
+        ste->symp        = symp;
+        ste->filename    = filename;
+        ste->used        = 0;
+        hash_table_add(ht_symtab, &ste->ht_elt);
     }
+}
 
+/******************************************************************
+ *		elf_lookup_symtab
+ *
+ * lookup a symbol by name in our internal hash table for the symtab
+ */
+static const Elf32_Sym* elf_lookup_symtab(const struct module* module,        
+                                          const struct hash_table* ht_symtab,
+                                          const char* name, struct symt* compiland)
+{
+    struct symtab_elt*          weak_result = NULL; /* without compiland name */
+    struct symtab_elt*          result = NULL;
+    struct hash_table_iter      hti;
+    struct symtab_elt*          ste;
+    const char*                 compiland_name;
+    const char*                 compiland_basename;
+    const char*                 base;
+
+    /* we need weak match up (at least) when symbols of same name, 
+     * defined several times in different compilation units,
+     * are merged in a single one (hence a different filename for c.u.)
+     */
+    if (compiland)
+    {
+        compiland_name = source_get(module,
+                                    ((struct symt_compiland*)compiland)->source);
+        compiland_basename = strrchr(compiland_name, '/');
+        if (!compiland_basename++) compiland_basename = compiland_name;
+    }
+    else compiland_name = compiland_basename = NULL;
+    
+    hash_table_iter_init(ht_symtab, &hti, name);
+    while ((ste = hash_table_iter_up(&hti)))
+    {
+        if (ste->used || strcmp(ste->ht_elt.name, name)) continue;
+
+        weak_result = ste;
+        if ((ste->filename && !compiland_name) || (!ste->filename && compiland_name))
+            continue;
+        if (ste->filename && compiland_name)
+        {
+            if (strcmp(ste->filename, compiland_name))
+            {
+                base = strrchr(ste->filename, '/');
+                if (!base++) base = ste->filename;
+                if (strcmp(base, compiland_basename)) continue;
+            }
+        }
+        if (result)
+        {
+            FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n", 
+                  name, compiland_name, result->filename, result->symp->st_value,
+                  ste->filename, ste->symp->st_value);
+        }
+        else
+        {
+            result = ste;
+            ste->used = 1;
+        }
+    }
+    if (!result && !(result = weak_result))
+    {
+        FIXME("Couldn't find symbol %s.%s in symtab\n", 
+              module->module.ModuleName, name);
+        return NULL;
+    }
+    return result->symp;
+}
+
+/******************************************************************
+ *		elf_finish_stabs_info
+ *
+ * - get any relevant information (address & size) from the bits we got from the
+ *   stabs debugging information
+ */
+static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
+{
+    struct hash_table_iter      hti;
+    void*                       ptr;
+    struct symt_ht*             sym;
+    const Elf32_Sym*            symp;
+
+    hash_table_iter_init(&module->ht_symbols, &hti, NULL);
+    while ((ptr = hash_table_iter_up(&hti)))
+    {
+        sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+        switch (sym->symt.tag)
+        {
+        case SymTagFunction:
+            if (((struct symt_function*)sym)->address != module->elf_info->elf_addr)
+                break;
+            symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
+                                     ((struct symt_function*)sym)->container);
+            if (symp)
+            {
+                ((struct symt_function*)sym)->address = module->elf_info->elf_addr +
+                                                        symp->st_value;
+                ((struct symt_function*)sym)->size    = symp->st_size;
+            }
+            break;
+        case SymTagData:
+            switch (((struct symt_data*)sym)->kind)
+            {
+            case DataIsGlobal:
+            case DataIsFileStatic:
+                if (((struct symt_data*)sym)->u.address != module->elf_info->elf_addr)
+                    break;
+                symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
+                                         ((struct symt_data*)sym)->container);
+                if (symp)
+                    ((struct symt_data*)sym)->u.address = module->elf_info->elf_addr +
+                                                          symp->st_value;
+                break;
+            default:;
+            }
+            break;
+        default:
+            FIXME("Unsupported tag %u\n", sym->symt.tag);
+            break;
+        }
+    }
+}
+
+/******************************************************************
+ *		elf_load_wine_thunks
+ *
+ * creating the thunk objects for a wine native DLL
+ */
+static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
+                               unsigned num_areas, struct thunk_area* thunks)
+{
+    int		                j;
+    struct symt_compiland*      compiland = NULL;
+    const char*                 compiland_name = NULL;
+    struct hash_table_iter      hti;
+    struct symtab_elt*          ste;
+    DWORD                       addr;
+
+    hash_table_iter_init(ht_symtab, &hti, NULL);
+    while ((ste = hash_table_iter_up(&hti)))
+    {
+        if (ste->used) continue;
+
+        /* FIXME: this is not a good idea anyway... we are creating several
+         * compiland objects for a same compilation unit
+         * We try to cache the last compiland used, but it's not enough
+         * (we should here only create compilands if they are not yet 
+         *  defined)
+         */
+        if (!compiland_name || compiland_name != ste->filename)
+            compiland = symt_new_compiland(module, 
+                                           compiland_name = ste->filename);
+
+        addr = module->elf_info->elf_addr + ste->symp->st_value;
+
+        for (j = 0; j < num_areas; j++)
+        {
+            if (ste->symp->st_value >= thunks[j].rva_start && 
+                ste->symp->st_value < thunks[j].rva_end)
+                break;
+        }
+        if (j < num_areas) /* thunk found */
+        {
+            symt_new_thunk(module, compiland, ste->ht_elt.name, thunks[j].ordinal,
+                           addr, ste->symp->st_size);
+        }
+        else if (symt_find_nearest(module, addr) == -1)
+        {
+            /* creating public symbols for all the ELF symbols which haven't been
+             * used yet (ie we have no debug information on them)
+             * That's the case, for example, of the .spec.c files
+             */
+            if (ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC)
+            {
+                symt_new_function(module, compiland, ste->ht_elt.name,
+                                  addr, ste->symp->st_size, NULL);
+            }
+            else
+            {
+                symt_new_global_variable(module, compiland, ste->ht_elt.name,
+                                         FALSE /* FIXME */,
+                                         addr, ste->symp->st_size, NULL);
+            }
+        }
+    }
+    return TRUE;
+}
+
+/******************************************************************
+ *		elf_new_public_symbols
+ *
+ * Creates a set of public symbols from an ELF symtab
+ */
+static int elf_new_public_symbols(struct module* module, struct hash_table* symtab,
+                                  BOOL dont_check)
+{
+    struct symt_compiland*      compiland = NULL;
+    const char*                 compiland_name = NULL;
+    struct hash_table_iter      hti;
+    struct symtab_elt*          ste;
+
+    if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) return TRUE;
+
+    hash_table_iter_init(symtab, &hti, NULL);
+    while ((ste = hash_table_iter_up(&hti)))
+    {
+        /* FIXME: this is not a good idea anyway... we are creating several
+         * compiland objects for a same compilation unit
+         * We try to cache the last compiland used, but it's not enough
+         * (we should here only create compilands if they are not yet 
+         *  defined)
+         */
+        if (!compiland_name || compiland_name != ste->filename)
+            compiland = symt_new_compiland(module, 
+                                           compiland_name = ste->filename);
+
+        if (dont_check || !(dbghelp_options & SYMOPT_AUTO_PUBLICS) ||
+            symt_find_nearest(module, module->elf_info->elf_addr + ste->symp->st_value) == -1)
+        {
+            symt_new_public(module, compiland, ste->ht_elt.name,
+                            module->elf_info->elf_addr + ste->symp->st_value,
+                            ste->symp->st_size, TRUE /* FIXME */, 
+                            ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
+        }
+    }
     return TRUE;
 }
 
@@ -160,10 +414,22 @@
     const Elf32_Shdr*   spnt;
     const char*	        shstrtab;
     int	       	        i;
-    int		        stabsect, stabstrsect, debugsect;
-    int                 symsect, dynsect;
+    int                 symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect;
+    struct pool         pool;
+    struct hash_table   ht_symtab;
+    struct thunk_area   thunks[] = 
+    {
+        {"__wine_spec_import_thunks",           THUNK_ORDINAL_NOTYPE, 0, 0},    /* inter DLL calls */
+        {"__wine_spec_delayed_import_loaders",  THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
+        {"__wine_spec_delayed_import_thunks",   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
+        {"__wine_delay_load",                   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
+        {"__wine_spec_thunk_text_16",           -16,                  0, 0},    /* 16 => 32 thunks */
+        {"__wine_spec_thunk_data_16",           -16,                  0, 0},    /* 16 => 32 thunks */
+        {"__wine_spec_thunk_text_32",           -32,                  0, 0},    /* 32 => 16 thunks */
+        {"__wine_spec_thunk_data_32",           -32,                  0, 0},    /* 32 => 16 thunks */
+    };
 
-    if (module->type != DMT_ELF || !module->elf_dbg_info)
+    if (module->type != DMT_ELF || !module->elf_info)
     {
 	ERR("Bad elf module '%s'\n", module->module.LoadedImageName);
 	return sym_type;
@@ -195,55 +461,86 @@
     spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
     shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
 
-    symsect = dynsect = stabsect = stabstrsect = debugsect = -1;
+    symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = -1;
 
     for (i = 0; i < ehptr->e_shnum; i++)
     {
 	if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
-	    stabsect = i;
+	    stab_sect = i;
 	if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
-	    stabstrsect = i;
+	    stabstr_sect = i;
 	if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
-	    debugsect = i;
+	    debug_sect = i;
 	if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
 	    (spnt[i].sh_type == SHT_SYMTAB))
-            symsect = i;
-	if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
-	    (spnt[i].sh_type == SHT_DYNSYM))
-            dynsect = i;
+            symtab_sect = i;
+        if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
+            (spnt[i].sh_type == SHT_DYNSYM))
+            dynsym_sect = i;
     }
-    /* start loading dynamic symbol info (so that we can get the correct address) */
-    if (symsect != -1)
-        elf_load_symtab(module, addr, module->elf_dbg_info->elf_addr,
-                        spnt + symsect, spnt + spnt[symsect].sh_link);
-    else if (dynsect != -1)
-        elf_load_symtab(module, addr, module->elf_dbg_info->elf_addr,
-                        spnt + dynsect, spnt + spnt[dynsect].sh_link);
+
     sym_type = SymExport;
 
-    if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+    if (symtab_sect == -1)
     {
-        if (stabsect != -1 && stabstrsect != -1)
-        {
-            /* OK, now just parse all of the stabs. */
-            sym_type = stabs_parse(module, addr, module->elf_dbg_info->elf_addr,
-                                   spnt[stabsect].sh_offset, spnt[stabsect].sh_size,
-                                   spnt[stabstrsect].sh_offset,
-                                   spnt[stabstrsect].sh_size);
-            if (sym_type == -1)
-            {
-                WARN("Couldn't read correctly read stabs\n");
-                goto leave;
-            }
-        }
-        else if (debugsect != -1)
-        {
-            /* Dwarf 2 debug information */
-            FIXME("Unsupported Dwarf2 information\n");
-            sym_type = SymNone;
-        }
+        /* if we don't have a symtab but a dynsym, process the dynsym
+         * section instead. It'll contain less (relevant) information, 
+         * but it'll be better than nothing
+         */
+        if (dynsym_sect == -1) goto leave;
+        symtab_sect = dynsym_sect;
     }
 
+    /* FIXME: guess a better size from ELF info */
+    pool_init(&pool, 65536);
+    hash_table_init(&pool, &ht_symtab, 256);
+
+    /* create a hash table for the symtab */
+    elf_hash_symtab(module, &pool, &ht_symtab, addr, 
+                    spnt + symtab_sect, spnt + spnt[symtab_sect].sh_link,
+                    sizeof(thunks) / sizeof(thunks[0]), thunks);
+
+    if (stab_sect != -1 && stabstr_sect != -1 && 
+        !(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+    {
+        /* OK, now just parse all of the stabs. */
+        sym_type = stabs_parse(module, addr, module->elf_info->elf_addr,
+                               spnt[stab_sect].sh_offset, spnt[stab_sect].sh_size,
+                               spnt[stabstr_sect].sh_offset,
+                               spnt[stabstr_sect].sh_size);
+        if (sym_type == -1)
+        {
+            WARN("Couldn't read correctly read stabs\n");
+            goto leave;
+        }
+        /* and fill in the missing information for stabs */
+        elf_finish_stabs_info(module, &ht_symtab);
+    }
+    else if (debug_sect != -1)
+    {
+        /* Dwarf 2 debug information */
+        FIXME("Unsupported Dwarf2 information\n");
+        sym_type = SymNone;
+    }
+    if (strstr(module->module.ModuleName, "<elf>"))
+    {
+        /* add the thunks for native libraries */
+        if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+            elf_new_wine_thunks(module, &ht_symtab, 
+                                sizeof(thunks) / sizeof(thunks[0]), thunks);
+        /* add the public symbols from symtab
+        * (only if they haven't been defined yet)
+        */
+        elf_new_public_symbols(module, &ht_symtab, FALSE);
+    }
+    else
+    {
+        /* add all the public symbols from symtab */
+        elf_new_public_symbols(module, &ht_symtab, TRUE);
+    }
+
+    pool_destroy(&pool);
+
 leave:
     if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
     if (fd != -1) close(fd);
@@ -298,6 +595,7 @@
     const char*         shstrtab;
     int	       	        i;
     DWORD	        delta, size;
+    unsigned            tmp, page_mask = getpagesize() - 1;
 
     TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset);
 
@@ -317,10 +615,10 @@
      * this thing.  We need the main executable header, and the section
      * table.
      */
-    ehptr = (Elf32_Ehdr*)addr;
+    ehptr = (const Elf32_Ehdr*)addr;
     if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
 
-    spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
+    spnt = (const Elf32_Shdr*)(addr + ehptr->e_shoff);
     shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
 
     /* if non relocatable ELF, then remove fixed address from computation
@@ -329,14 +627,14 @@
     delta = (load_offset == 0) ? ehptr->e_entry : 0;
 
     /* grab size of module once loaded in memory */
-    ppnt = (Elf32_Phdr*)(addr + ehptr->e_phoff);
+    ppnt = (const Elf32_Phdr*)(addr + ehptr->e_phoff);
     size = 0;
     for (i = 0; i < ehptr->e_phnum; i++)
     {
-	if (ppnt[i].p_type == PT_LOAD)
+        if (ppnt[i].p_type == PT_LOAD)
         {
-            size += (ppnt[i].p_align <= 1) ? ppnt[i].p_memsz :
-                (ppnt[i].p_memsz + ppnt[i].p_align - 1) & ~(ppnt[i].p_align - 1);
+            tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask;
+            if (size < tmp) size = tmp;
         }
     }
 
@@ -375,16 +673,19 @@
                                       size, 0, 0);
         if (elf_info->module)
         {
-            if ((elf_info->module->elf_dbg_info = HeapAlloc(GetProcessHeap(), 0, sizeof(ELF_DBG_INFO))) == NULL) 
+            elf_info->module->elf_info = HeapAlloc(GetProcessHeap(), 
+                                                   0, sizeof(struct elf_module_info));
+            if (elf_info->module->elf_info == NULL) 
             {
                 ERR("OOM\n");
                 exit(0); /* FIXME */
             }
-            elf_info->module->elf_dbg_info->elf_addr = load_offset;
+            elf_info->module->elf_info->elf_addr = load_offset;
             elf_info->module->module.SymType = sym_type = 
                 (dbghelp_options & SYMOPT_DEFERRED_LOADS) ? SymDeferred : 
                 elf_load_debug_info(elf_info->module);
-            elf_info->module->elf_mark = 1;
+            elf_info->module->elf_info->elf_mark = 1;
+            elf_info->module->elf_info->elf_loader = 0;
         }
         else sym_type = -1;
     }
@@ -447,7 +748,7 @@
     if ((module = module_find_by_name(pcs, filename, DMT_ELF)))
     {
         elf_info->module = module;
-        module->elf_mark = 1;
+        module->elf_info->elf_mark = 1;
         return module->module.SymType;
     }
 
@@ -493,7 +794,7 @@
 
     for (module = pcs->lmodules; module; module = module->next)
     {
-        if (module->type == DMT_ELF) module->elf_mark = 0;
+        if (module->type == DMT_ELF) module->elf_info->elf_mark = 0;
     }
 
     elf_info.flags = ELF_INFO_MODULE;
@@ -519,7 +820,8 @@
 
     for (module = pcs->lmodules; module; module = module->next)
     {
-        if (module->type == DMT_ELF && !module->elf_mark)
+        if (module->type == DMT_ELF && !module->elf_info->elf_mark && 
+            !module->elf_info->elf_loader)
         {
             module_remove(pcs, module);
             /* restart all over */
@@ -532,15 +834,15 @@
 /******************************************************************
  *		elf_read_wine_loader_dbg_info
  *
- * Try to find a decent wine executable which could have loader the debuggee
+ * Try to find a decent wine executable which could have loaded the debuggee
  */
-unsigned long        elf_read_wine_loader_dbg_info(struct process* pcs)
+BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
 {
     const char*         ptr;
     SYM_TYPE            sym_type;
     struct elf_info     elf_info;
 
-    elf_info.flags = ELF_INFO_DEBUG_HEADER;
+    elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
     /* All binaries are loaded with WINELOADER (if run from tree) or by the
      * main executable (either wine-kthread or wine-pthread)
      * Note: the heuristic use to know whether we need to load wine-pthread or
@@ -553,7 +855,10 @@
         if ((sym_type = elf_search_and_load_file(pcs, "wine-kthread", 0, &elf_info)) == -1)
             sym_type = elf_search_and_load_file(pcs, "wine-pthread", 0, &elf_info);
     }
-    return (sym_type < 0) ? 0 : elf_info.dbg_hdr_addr;
+    if (sym_type < 0) return FALSE;
+    elf_info.module->elf_info->elf_loader = 1;
+    strcpy(elf_info.module->module.ModuleName, "<wine-loader>");
+    return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
 }
 
 /******************************************************************
diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c
index 03ce14e..74f37db 100644
--- a/dlls/dbghelp/module.c
+++ b/dlls/dbghelp/module.c
@@ -33,16 +33,37 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 
+static void module_fill_module(const char* in, char* out, unsigned size)
+{
+    const char*         ptr;
+    unsigned            len;
+
+    for (ptr = in + strlen(in) - 1; 
+         *ptr != '/' && *ptr != '\\' && ptr >= in; 
+         ptr--);
+    if (ptr < in || *ptr == '/' || *ptr == '\\') ptr++;
+    strncpy(out, ptr, size);
+    out[size - 1] = '\0';
+    len = strlen(out);
+    if (len > 4 && 
+        (!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe")))
+        out[len - 4] = '\0';
+    else 
+        if (len > 7 && 
+            (!strcasecmp(&out[len - 7], ".dll.so") || !strcasecmp(&out[len - 7], ".exe.so")))
+            strcpy(&out[len - 7], "<elf>");
+    while ((*out = tolower(*out))) out++;
+}
+
 /***********************************************************************
  * Creates and links a new module to a process 
  */
 struct module* module_new(struct process* pcs, const char* name, 
-                          enum DbgModuleType type, 
+                          enum module_type type, 
                           unsigned long mod_addr, unsigned long size,
                           unsigned long stamp, unsigned long checksum) 
 {
     struct module*      module;
-    const char*         ptr;
 
     if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
 	return NULL;
@@ -61,12 +82,7 @@
     module->module.SizeOfStruct = sizeof(module->module);
     module->module.BaseOfImage = mod_addr;
     module->module.ImageSize = size;
-    for (ptr = name + strlen(name) - 1; 
-         *ptr != '/' && *ptr != '\\' && ptr >= name; 
-         ptr--);
-    if (ptr < name || *ptr == '/' || *ptr == '\\') ptr++;
-    strncpy(module->module.ModuleName, ptr, sizeof(module->module.ModuleName));
-    module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
+    module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
     module->module.ImageName[0] = '\0';
     strncpy(module->module.LoadedImageName, name, 
             sizeof(module->module.LoadedImageName));
@@ -97,7 +113,7 @@
  *
  */
 struct module* module_find_by_name(const struct process* pcs, 
-                                   const char* name, enum DbgModuleType type)
+                                   const char* name, enum module_type type)
 {
     struct module*      module;
 
@@ -188,7 +204,7 @@
  * module
  */
 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
-                                   enum DbgModuleType type)
+                                   enum module_type type)
 {
     struct module*      module;
     
@@ -227,6 +243,13 @@
     pcs = process_find_by_handle(hProcess);
     if (!pcs) return FALSE;
 
+    /* this is a Wine extension to the API */
+    if (!ImageName && !hFile)
+    {
+        elf_synchronize_module_list(pcs);
+        return 0;
+    }
+
     if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
     {
         unsigned        len = strlen(ImageName);
@@ -316,7 +339,8 @@
     
     for (module = pcs->lmodules; module; module = module->next)
     {
-        if (module->type != DMT_PE) continue;
+        if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type != DMT_PE)
+            continue;
         if (!EnumModulesCallback(module->module.ModuleName, 
                                  module->module.BaseOfImage, UserContext))
             break;
@@ -333,7 +357,7 @@
                                     PVOID UserContext)
 {
     HMODULE*    hMods;
-    char        img[256], mod[256];
+    char        base[256], mod[256];
     DWORD       i, sz;
     MODULEINFO  mi;
 
@@ -351,9 +375,10 @@
     for (i = 0; i < sz; i++)
     {
         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
-            !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
-            !GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
-            break;
+            !GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
+            continue;
+        module_fill_module(base, mod, sizeof(mod));
+
         EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage, 
                                   UserContext);
     }
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index e1d719e..91e79b5 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -70,9 +70,9 @@
 {
     struct module*              module;
     int			        nsect;
-    PIMAGE_SECTION_HEADER       sectp;
+    const IMAGE_SECTION_HEADER* sectp;
     int			        nomap;
-    OMAP_DATA*                  omapp;
+    const OMAP_DATA*            omapp;
     const BYTE*                 root;
 };
 
@@ -218,8 +218,8 @@
         if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE)
 	{
             curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, 
-                                          (char*)(coff_sym + 1));
-            TRACE("New file %s\n", (char*)(coff_sym + 1));
+                                          (const char*)(coff_sym + 1));
+            TRACE("New file %s\n", (const char*)(coff_sym + 1));
             i += naux;
             continue;
 	}
@@ -1111,27 +1111,27 @@
         {
         case LF_CHAR:
             length += 1;
-            *value = *(char*)leaf;
+            *value = *(const char*)leaf;
             break;
 
         case LF_SHORT:
             length += 2;
-            *value = *(short*)leaf;
+            *value = *(const short*)leaf;
             break;
 
         case LF_USHORT:
             length += 2;
-            *value = *(unsigned short*)leaf;
+            *value = *(const unsigned short*)leaf;
             break;
 
         case LF_LONG:
             length += 4;
-            *value = *(int*)leaf;
+            *value = *(const int*)leaf;
             break;
 
         case LF_ULONG:
             length += 4;
-            *value = *(unsigned int*)leaf;
+            *value = *(const unsigned int*)leaf;
             break;
 
         case LF_QUADWORD:
@@ -1327,7 +1327,7 @@
     symt = symt_new_enum(module, NULL);
     while (ptr - list < len)
     {
-        union codeview_fieldtype* type = (union codeview_fieldtype*)ptr;
+        const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
 
         if (*ptr >= 0xf0)       /* LF_PAD... */
         {
@@ -1340,7 +1340,7 @@
         case LF_ENUMERATE:
         {
             int value, vlen = numeric_leaf(&value, &type->enumerate.value);
-            unsigned char* name = (unsigned char*)&type->enumerate.value + vlen;
+            const unsigned char* name = (const unsigned char*)&type->enumerate.value + vlen;
 
             symt_add_enum_element(module, symt, terminate_string(name), value);
             ptr += 2 + 2 + vlen + (1 + name[0]);
@@ -1400,7 +1400,7 @@
         case LF_IVBCLASS:
         {
             int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass.vbpoff);
-            const unsigned short int* p_vboff = (const unsigned short int*)((char*)&type->vbclass.vbpoff + vbpoff);
+            const unsigned short int* p_vboff = (const unsigned short int*)((const char*)&type->vbclass.vbpoff + vbpoff);
             int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
 
             /* FIXME: ignored for now */
@@ -1413,7 +1413,7 @@
         case LF_IVBCLASS_32:
         {
             int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass32.vbpoff);
-            const unsigned short int* p_vboff = (const unsigned short int*)((char*)&type->vbclass32.vbpoff + vbpoff);
+            const unsigned short int* p_vboff = (const unsigned short int*)((const char*)&type->vbclass32.vbpoff + vbpoff);
             int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
 
             /* FIXME: ignored for now */
@@ -1759,16 +1759,16 @@
     int				file_segcount;
     char			filename[PATH_MAX];
     const unsigned int*         filetab;
-    char*                       fn;
+    const char*                 fn;
     int				i;
     int				k;
     struct codeview_linetab*    lt_hdr;
-    unsigned int*               lt_ptr;
+    const unsigned int*         lt_ptr;
     int				nfile;
     int				nseg;
     union any_size		pnt;
     union any_size		pnt2;
-    struct startend*            start;
+    const struct startend*      start;
     int				this_seg;
     struct symt_compiland*      compiland;
 
@@ -1820,13 +1820,13 @@
         file_segcount = *pnt2.s;
 
         pnt2.ui++;
-        lt_ptr = (unsigned int*) pnt2.c;
-        start = (struct startend*)(lt_ptr + file_segcount);
+        lt_ptr = (const unsigned int*) pnt2.c;
+        start = (const struct startend*)(lt_ptr + file_segcount);
 
         /*
          * Now snarf the filename for all of the segments for this file.
          */
-        fn = (unsigned char*)(start + file_segcount);
+        fn = (const unsigned char*)(start + file_segcount);
         memset(filename, 0, sizeof(filename));
         memcpy(filename, fn + 1, *fn);
         compiland = symt_new_compiland(module, filename);
@@ -1840,7 +1840,7 @@
             lt_hdr[this_seg].segno      = *pnt2.s++;
             lt_hdr[this_seg].nline      = *pnt2.s++;
             lt_hdr[this_seg].offtab     = pnt2.ui;
-            lt_hdr[this_seg].linetab    = (unsigned short*)(pnt2.ui + lt_hdr[this_seg].nline);
+            lt_hdr[this_seg].linetab    = (const unsigned short*)(pnt2.ui + lt_hdr[this_seg].nline);
 	}
     }
 
@@ -2334,11 +2334,11 @@
             break;
 
         case S_COMPILE:
-            TRACE("S-Compile %x %.*s\n", ((LPBYTE)sym)[4], ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
+            TRACE("S-Compile %x %.*s\n", ((const BYTE*)sym)[4], ((const BYTE*)sym)[8], (const BYTE*)sym + 9);
             break;
 
         case S_OBJNAME:
-            TRACE("S-ObjName %.*s\n", ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
+            TRACE("S-ObjName %.*s\n", ((const BYTE*)sym)[8], (const BYTE*)sym + 9);
             break;
 
         case S_LABEL:
@@ -2347,7 +2347,7 @@
             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,
+                                        codeview_get_address(msc_dbg, sym->label.segment, sym->label.offset) - curr_func->address,
                                         symname);
             }
             else FIXME("No current function for label %s\n", symname);
@@ -2407,7 +2407,7 @@
 	case S_DATAREF:
 	case S_LPROCREF:
             {
-                LPBYTE name = (LPBYTE)sym + length;
+                const BYTE* name = (const BYTE*)sym + length;
                 length += (*name + 1 + 3) & ~3;
             }
             break;
@@ -2629,7 +2629,7 @@
     memset(types, 0, sizeof(PDB_TYPES));
     if (!image) return;
 
-    if (*(DWORD*)image < 19960000)   /* FIXME: correct version? */
+    if (*(const DWORD*)image < 19960000)   /* FIXME: correct version? */
     {
         /* Old version of the types record header */
         const PDB_TYPES_OLD*    old = (const PDB_TYPES_OLD*)image;
@@ -2653,7 +2653,7 @@
     memset(symbols, 0, sizeof(PDB_SYMBOLS));
     if (!image) return;
 
-    if (*(DWORD*)image != 0xffffffff)
+    if (*(const DWORD*)image != 0xffffffff)
     {
         /* Old version of the symbols record header */
         const PDB_SYMBOLS_OLD*  old = (const PDB_SYMBOLS_OLD*)image;
@@ -2686,7 +2686,7 @@
 }
 
 static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
-                            char* filename)
+                            const char* filename)
 {
     HANDLE      h;
     char        dbg_file_path[MAX_PATH];
@@ -2695,7 +2695,7 @@
                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     if (h == INVALID_HANDLE_VALUE)
     {
-        h = FindDebugInfoFile(filename, pcs->search_path, dbg_file_path);
+        h = FindDebugInfoFile((char*)filename, pcs->search_path, dbg_file_path);
         if (h == NULL)
         {
             const char* p;
@@ -2716,7 +2716,7 @@
 
 static SYM_TYPE pdb_process_file(const struct process* pcs, 
                                  const struct msc_debug_info* msc_dbg,
-                                 char* filename, DWORD timestamp)
+                                 const char* filename, DWORD timestamp)
 {
     SYM_TYPE    sym_type = -1;
     HANDLE      hFile, hMap = NULL;
@@ -2982,7 +2982,7 @@
 
     case CODEVIEW_NB10_SIG:
     {
-        PCODEVIEW_PDB_DATA pdb = (PCODEVIEW_PDB_DATA)(cv + 1);
+        const CODEVIEW_PDB_DATA* pdb = (const CODEVIEW_PDB_DATA*)(cv + 1);
 
         codeview_init_basic_types(msc_dbg->module);
         sym_type = pdb_process_file(pcs, msc_dbg, pdb->name, pdb->timestamp);
@@ -3001,17 +3001,17 @@
  * Process debug directory.
  */
 SYM_TYPE pe_load_debug_directory(const struct process* pcs, struct module* module, 
-                                 const BYTE* mapping, PIMAGE_DEBUG_DIRECTORY dbg, 
+                                 const BYTE* mapping, const IMAGE_DEBUG_DIRECTORY* dbg, 
                                  int nDbg)
 {
     SYM_TYPE                    sym_type;
     int                         i;
     struct msc_debug_info       msc_dbg;
-    IMAGE_NT_HEADERS*           nth = RtlImageNtHeader((void*)mapping);
+    const IMAGE_NT_HEADERS*     nth = RtlImageNtHeader((void*)mapping);
 
     msc_dbg.module = module;
     msc_dbg.nsect  = nth->FileHeader.NumberOfSections;
-    msc_dbg.sectp  = (PIMAGE_SECTION_HEADER)((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
+    msc_dbg.sectp  = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
     msc_dbg.nomap  = 0;
     msc_dbg.omapp  = NULL;
 
@@ -3025,7 +3025,7 @@
             if (dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)
             {
                 msc_dbg.nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
-                msc_dbg.omapp = (OMAP_DATA*)(mapping + dbg[i].PointerToRawData);
+                msc_dbg.omapp = (const OMAP_DATA*)(mapping + dbg[i].PointerToRawData);
                 break;
             }
         }
diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c
index 12b20b6..91d706d 100644
--- a/dlls/dbghelp/pe_module.c
+++ b/dlls/dbghelp/pe_module.c
@@ -78,22 +78,22 @@
  * loads a .dbg file
  */
 static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* module,
-                                 char* dbg_name, DWORD timestamp)
+                                 const char* dbg_name, DWORD timestamp)
 {
-    char                        tmp[MAX_PATH];
-    HANDLE                      hFile, hMap = 0;
-    const BYTE*                 dbg_mapping = NULL;
-    PIMAGE_SEPARATE_DEBUG_HEADER hdr;
-    PIMAGE_DEBUG_DIRECTORY      dbg;
-    SYM_TYPE                    sym_type = -1;
+    char                                tmp[MAX_PATH];
+    HANDLE                              hFile, hMap = 0;
+    const BYTE*                         dbg_mapping = NULL;
+    const IMAGE_SEPARATE_DEBUG_HEADER*  hdr;
+    const IMAGE_DEBUG_DIRECTORY*        dbg;
+    SYM_TYPE                            sym_type = -1;
 
     WINE_TRACE("Processing DBG file %s\n", dbg_name);
 
-    if ((hFile = FindDebugInfoFile(dbg_name, pcs->search_path, tmp)) != NULL &&
+    if ((hFile = FindDebugInfoFile((char*)dbg_name, pcs->search_path, tmp)) != NULL &&
         ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
         ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
     {
-        hdr = (PIMAGE_SEPARATE_DEBUG_HEADER)dbg_mapping;
+        hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)dbg_mapping;
         if (hdr->TimeDateStamp != timestamp)
         {
             WINE_ERR("Warning - %s has incorrect internal timestamp\n",
@@ -105,7 +105,7 @@
              * which have incorrect timestamps.
              */
         }
-        dbg = (PIMAGE_DEBUG_DIRECTORY) 
+        dbg = (const IMAGE_DEBUG_DIRECTORY*) 
             (dbg_mapping + sizeof(*hdr) + 
              hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
              hdr->ExportedNamesSize);
@@ -133,24 +133,24 @@
                                        struct module* module,
                                        const void* mapping, IMAGE_NT_HEADERS* nth)
 {
-    SYM_TYPE               sym_type = -1;
-    PIMAGE_DATA_DIRECTORY  dir;
-    PIMAGE_DEBUG_DIRECTORY dbg = NULL;
-    int                    nDbg;
+    SYM_TYPE                    sym_type = -1;
+    const IMAGE_DATA_DIRECTORY* dir;
+    const IMAGE_DEBUG_DIRECTORY*dbg = NULL;
+    int                         nDbg;
 
     /* Read in debug directory */
     dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
     nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
     if (!nDbg) return sym_type;
 
-    dbg = (PIMAGE_DEBUG_DIRECTORY)((char*)mapping + dir->VirtualAddress);
+    dbg = (const IMAGE_DEBUG_DIRECTORY*)((const char*)mapping + dir->VirtualAddress);
 
     /* Parse debug directory */
     if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
     {
         /* Debug info is stripped to .DBG file */
-        PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)
-            ((char*)mapping + dbg->PointerToRawData);
+        const IMAGE_DEBUG_MISC* misc = (const IMAGE_DEBUG_MISC*)
+            ((const char*)mapping + dbg->PointerToRawData);
 
         if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
             misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
@@ -179,7 +179,6 @@
                                           struct module* module, 
                                           const void* mapping, IMAGE_NT_HEADERS* nth)
 {
-    char			buffer[512];
     unsigned int 		i;
     IMAGE_DATA_DIRECTORY* 	dir;
     DWORD			base = module->module.BaseOfImage;
@@ -196,21 +195,20 @@
 #endif
     
     /* Add entry point */
-    snprintf(buffer, sizeof(buffer), "%s.EntryPoint", module->module.ModuleName);
-    symt_new_public(module, NULL, buffer, 
+    symt_new_public(module, NULL, "EntryPoint", 
                     base + nth->OptionalHeader.AddressOfEntryPoint, 0,
                     TRUE /* FIXME */, TRUE /* FIXME */);
 
 #if 0
+    /* FIXME: we'd better store addresses linked to sections rather than 
+       absolute values */
     IMAGE_SECTION_HEADER*       section;
     /* Add start of sections */
     section = (IMAGE_SECTION_HEADER*)
         ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
     for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) 
     {
-	snprintf(buffer, sizeof(buffer), "%s.%s", 
-                 module->module.ModuleName, section->Name);
-	symt_new_public(module, NULL, buffer, base + section->VirtualAddress, 0,
+	symt_new_public(module, NULL, section->Name, base + section->VirtualAddress, 0,
                         TRUE /* FIXME */, TRUE /* FIXME */);
     }
 #endif
@@ -219,23 +217,22 @@
     if ((dir = RtlImageDirectoryEntryToData((void*)mapping, TRUE, 
                                             IMAGE_DIRECTORY_ENTRY_EXPORT, NULL)))
     {
-	IMAGE_EXPORT_DIRECTORY* exports;
-	WORD*			ordinals = NULL;
-	void**			functions = NULL;
-	DWORD*			names = NULL;
-	unsigned int		j;
-	
-        exports   = (void*)((char*)mapping + dir->VirtualAddress);
-        functions = (void*)((char*)mapping + exports->AddressOfFunctions);
-        ordinals  = (void*)((char*)mapping + exports->AddressOfNameOrdinals);
-        names     = (void*)((char*)mapping + exports->AddressOfNames);
+	const IMAGE_EXPORT_DIRECTORY*   exports;
+	const WORD*			ordinals = NULL;
+	const void* const*		functions = NULL;
+	const DWORD*			names = NULL;
+	unsigned int		        j;
+	char                            buffer[16];
+
+        exports   = (const void*)((const char*)mapping + dir->VirtualAddress);
+        functions = (const void*)((const char*)mapping + exports->AddressOfFunctions);
+        ordinals  = (const void*)((const char*)mapping + exports->AddressOfNameOrdinals);
+        names     = (const void*)((const char*)mapping + exports->AddressOfNames);
 	    
         for (i = 0; i < exports->NumberOfNames; i++) 
         {
             if (!names[i]) continue;
-            snprintf(buffer, sizeof(buffer), "%s.%s", 
-                     module->module.ModuleName, (char*)base + names[i]);
-            symt_new_public(module, NULL, buffer, 
+            symt_new_public(module, NULL, (const char*)base + names[i], 
                             base + (DWORD)functions[ordinals[i]], 0,
                             TRUE /* FIXME */, TRUE /* FIXME */);
         }
@@ -247,9 +244,8 @@
             for (j = 0; j < exports->NumberOfNames; j++)
                 if ((ordinals[j] == i) && names[j]) break;
             if (j < exports->NumberOfNames) continue;
-            snprintf(buffer, sizeof(buffer), "%s.%ld", 
-                     module->module.ModuleName, i + exports->Base);
-            symt_new_public(module, NULL, buffer,  base + (DWORD)functions[i], 0,
+            snprintf(buffer, sizeof(buffer), "%ld", i + exports->Base);
+            symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
                             TRUE /* FIXME */, TRUE /* FIXME */);
         }
     }
diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c
index e08a86c..7d6913f 100644
--- a/dlls/dbghelp/stabs.c
+++ b/dlls/dbghelp/stabs.c
@@ -57,10 +57,6 @@
 
 #include "dbghelp_private.h"
 
-#if defined(__svr4__) || defined(__sun)
-#define __ELF__
-#endif
-
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
@@ -842,6 +838,9 @@
                             udt, symt_get_name(&udt->symt), udt->symt.tag);
                         return -1;
                     }
+                    if (strcmp(udt->hash_elt.name, typename))
+                        ERR("Forward declaration name mismatch %s <> %s\n",
+                            udt->hash_elt.name, typename);
                     /* should check typename is the same too */
                     new_dt = &udt->symt;
                 }
@@ -1042,76 +1041,6 @@
     unsigned            regno;
 };
 
-static
-struct symt_public* lookup_public(const struct module* module, 
-                                  const struct symt_compiland* compiland,
-                                  const char* name)
-{
-    unsigned                    nfind = 0;
-    struct symt_public*         found = NULL;
-    struct symt_public*         xfound = NULL;
-    struct symt_public*         sym;
-    const char*                 xname;
-    const char*                 tmp;
-    void*                       ptr;
-    struct hash_table_iter      hti;
-    const char*                 in_src;
-    const char*                 out_src;
-
-    if (compiland && compiland->symt.tag == SymTagCompiland)
-        in_src = source_get(module, compiland->source);
-    else in_src = NULL;
-
-    hash_table_iter_init(&module->ht_symbols, &hti, name);
-    while ((ptr = hash_table_iter_up(&hti)))
-    {
-        sym = GET_ENTRY(ptr, struct symt_public, hash_elt);
-        if (sym->symt.tag == SymTagPublicSymbol)
-        {
-            xname = symt_get_name(&sym->symt);
-            if (!xname || strcmp(xname, name)) continue;
-
-            if (sym->container &&
-                sym->container->tag == SymTagCompiland)
-                out_src = source_get(module, ((struct symt_compiland*)sym->container)->source);
-            else out_src = NULL;
-
-            xfound = sym;
-            if ((in_src && !out_src) || (!in_src && out_src)) continue;
-            
-            if (in_src)
-            {
-                if (strcmp(in_src, out_src) || (tmp = strrchr(in_src, '/')) == NULL ||
-                    strcmp(tmp + 1, out_src))
-                    continue;
-            }
-
-            /* we continue once found to insure uniqueness of public symbol's name */
-            if (nfind++)
-            {
-                FIXME("More than one public symbol (%s) in %s: [%u] %p {%lx,%lx} in %s\n", 
-                      name, in_src, nfind, sym, sym->address, sym->size, out_src);
-            }
-            else found = sym;
-        }
-    }
-    if (!nfind)
-    {
-        if (xfound) found = xfound;
-        else FIXME("Couldn't locate %s in public symbols\n", name);
-    }
-    if (found)
-    {
-        if (found->container &&
-            found->container->tag == SymTagCompiland)
-            out_src = source_get(module, ((struct symt_compiland*)found->container)->source);
-        else out_src = NULL;
-        TRACE("Found for %s in %s: %p {%lx,%lx} in %s\n", 
-              name, in_src, found, found->address, found->size, out_src);
-    }
-    return found;
-}
-
 /******************************************************************
  *		stabs_finalize_function
  *
@@ -1128,11 +1057,11 @@
     /* 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) &&
+    if (symt_fill_func_line_info(module, func, func->address, &il) &&
         symt_get_func_line_next(module, &il))
     {
         symt_add_function_point(module, func, SymTagFuncDebugStart, 
-                                il.Address - func->addr, NULL);
+                                il.Address - func->address, NULL);
     }
 }
 
@@ -1142,7 +1071,6 @@
 {
     struct symt_function*       curr_func = NULL;
     struct symt_block*          block = NULL;
-    struct symt_public*         public;
     struct symt_compiland*      compiland = NULL;
     char                        currpath[PATH_MAX];
     int                         i, j;
@@ -1162,8 +1090,8 @@
     unsigned                    num_allocated_pending_vars = 0;
 
     nstab = stablen / sizeof(struct stab_nlist);
-    stab_ptr = (struct stab_nlist*)(addr + staboff);
-    strs = (char*)(addr + strtaboff);
+    stab_ptr = (const struct stab_nlist*)(addr + staboff);
+    strs = (const char*)(addr + strtaboff);
 
     memset(currpath, 0, sizeof(currpath));
     memset(stabs_basic, 0, sizeof(stabs_basic));
@@ -1270,16 +1198,9 @@
              * With a.out or mingw, they actually do make some amount of sense.
              */
             stab_strcpy(symname, sizeof(symname), ptr);
-#ifdef __ELF__
-            if ((public = lookup_public(module, compiland, symname)))
-                symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
-                                         public->address, public->size,
-                                         stabs_parse_type(ptr));
-#else
             symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
                                      load_offset + stab_ptr->n_value, 0,
                                      stabs_parse_type(ptr));
-#endif
             break;
         case N_LCSYM:
         case N_STSYM:
@@ -1396,19 +1317,8 @@
             if (curr_func != NULL)
             {
                 assert(source_idx >= 0);
-#ifdef __ELF__
                 symt_add_func_line(module, curr_func, source_idx, 
                                    stab_ptr->n_desc, stab_ptr->n_value);
-#else
-                /*
-                 * This isn't right.  The order of the stabs is different under
-                 * a.out, and as a result we would end up attaching the line
-                 * number to the wrong function.
-                 */
-                symt_add_func_line(module, curr_func, source_idx,
-                                   stab_ptr->n_desc,
-                                   stab_ptr->n_value - curr_func->addr);
-#endif
             }
             break;
         case N_FUN:
@@ -1433,16 +1343,9 @@
                 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,
-                                                  &func_type->symt);
-#else
                 curr_func = symt_new_function(module, compiland, symname, 
                                               load_offset + stab_ptr->n_value, 0,
                                               &func_type->symt);
-#endif
             }
             else
             {
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index 6d2ad4f..025b9f7 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -288,10 +288,15 @@
 
 void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt)
 {
-    unsigned    hash = hash_table_hash(elt->name, ht->num_buckets);
+    unsigned                    hash = hash_table_hash(elt->name, ht->num_buckets);
+    struct hash_table_elt**     p;
 
-    elt->next = ht->buckets[hash];
-    ht->buckets[hash] = elt;
+    /* in some cases, we need to get back the symbols of same name in the order
+     * in which they've been inserted. So insert new elements at the end of the list.
+     */
+    for (p = &ht->buckets[hash]; *p; p = &((*p)->next));
+    *p = elt;
+    elt->next = NULL;
 }
 
 void* hash_table_find(const struct hash_table* ht, const char* name)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index 56bf671..b43beab 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -70,8 +70,8 @@
 
 int symt_cmp_addr(const void* p1, const void* p2)
 {
-    struct symt*        sym1 = *(struct symt**)p1;
-    struct symt*        sym2 = *(struct symt**)p2;
+    const struct symt*  sym1 = *(const struct symt* const *)p1;
+    const struct symt*  sym2 = *(const struct symt* const *)p2;
     DWORD               a1, a2;
 
     symt_get_info(sym1, TI_GET_ADDRESS, &a1);
@@ -188,6 +188,7 @@
 {
     struct symt_data*   sym;
     struct symt**       p;
+    DWORD               tsz;
 
     TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n", 
                          module->module.ModuleName, name, addr, type);
@@ -201,6 +202,12 @@
         sym->container     = compiland ? &compiland->symt : NULL;
         sym->type          = type;
         sym->u.address     = addr;
+        if (type && size && symt_get_info(type, TI_GET_LENGTH, &tsz))
+        {
+            if (tsz != size)
+                FIXME("Size mismatch for %s.%s between type (%lu) and src (%lu)\n",
+                      module->module.ModuleName, name, tsz, size);
+        }
         if (compiland)
         {
             p = vector_add(&compiland->vchildren, &module->pool);
@@ -230,10 +237,9 @@
         hash_table_add(&module->ht_symbols, &sym->hash_elt);
         module->sortlist_valid = FALSE;
         sym->container = &compiland->symt;
-        sym->addr      = addr;
+        sym->address   = addr;
         sym->type      = sig_type;
         sym->size      = size;
-        sym->addr      = addr;
         vector_init(&sym->vlines,  sizeof(struct line_info), 64);
         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
         if (compiland)
@@ -282,7 +288,7 @@
     dli->is_source_file = 0;
     dli->is_first       = dli->is_last = 0;
     dli->line_number    = line_num;
-    dli->u.pc_offset    = func->addr + offset;
+    dli->u.pc_offset    = func->address + offset;
 }
 
 struct symt_data* symt_add_func_local(struct module* module, 
@@ -341,7 +347,7 @@
     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->address  = func->address + pc;
     block->size     = len;
     block->container = parent_block ? &parent_block->symt : &func->symt;
     vector_init(&block->vchildren, sizeof(struct symt*), 4);
@@ -360,7 +366,7 @@
 {
     assert(func->symt.tag == SymTagFunction);
 
-    if (pc) block->size = func->addr + pc - block->address;
+    if (pc) block->size = func->address + pc - block->address;
     return (block->container->tag == SymTagBlock) ? 
         GET_ENTRY(block->container, struct symt_block, symt) : NULL;
 }
@@ -408,6 +414,37 @@
     return TRUE;
 }
 
+struct symt_thunk* symt_new_thunk(struct module* module, 
+                                  struct symt_compiland* compiland, 
+                                  const char* name, THUNK_ORDINAL ord,
+                                  unsigned long addr, unsigned long size)
+{
+    struct symt_thunk*  sym;
+
+
+    TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n", 
+                         module->module.ModuleName, name, addr, addr + size - 1);
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag  = SymTagThunk;
+        sym->hash_elt.name = pool_strdup(&module->pool, name);
+        hash_table_add(&module->ht_symbols, &sym->hash_elt);
+        module->sortlist_valid = FALSE;
+        sym->container = &compiland->symt;
+        sym->address   = addr;
+        sym->size      = size;
+        sym->ordinal   = ord;
+        if (compiland)
+        {
+            struct symt**       p;
+            p = vector_add(&compiland->vchildren, &module->pool);
+            *p = &sym->symt;
+        }
+    }
+    return sym;
+}
+
 /* expect sym_info->MaxNameLen to be set before being called */
 static void symt_fill_sym_info(const struct module* module, 
                                const struct symt* sym, SYMBOL_INFO* sym_info)
@@ -423,7 +460,7 @@
     {
     case SymTagData:
         {
-            struct symt_data*  data = (struct symt_data*)sym;
+            const struct symt_data*  data = (const struct symt_data*)sym;
             switch (data->kind)
             {
             case DataIsLocal:
@@ -476,6 +513,10 @@
         sym_info->Flags |= SYMFLAG_FUNCTION;
         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
         break;
+    case SymTagThunk:
+        sym_info->Flags |= SYMFLAG_THUNK;
+        symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+        break;
     default:
         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
         sym_info->Register = 0;
@@ -571,9 +612,10 @@
 }
 
 /* assume addr is in module */
-static int symt_find_nearest(struct module* module, DWORD addr)
+int symt_find_nearest(struct module* module, DWORD addr)
 {
     int         mid, high, low;
+    DWORD       ref;
 
     if (!module->sortlist_valid && !resort_symbols(module)) return -1;
 
@@ -582,6 +624,15 @@
      */
     low = 0;
     high = module->module.NumSyms;
+
+    symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref);
+    if (addr < ref) return -1;
+    if (high)
+    {
+        symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref);
+        /* FIXME: use the size of symbol here if known */
+        if (addr > ref + 0x1000) return -1;
+    }
     
     while (high > low + 1)
     {
@@ -600,8 +651,6 @@
      */
     if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
     {   
-        DWORD   ref;
-
         symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref);
         if (low > 0 &&
             module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c
index 15aae51..2be65c3 100644
--- a/dlls/dbghelp/type.c
+++ b/dlls/dbghelp/type.c
@@ -80,15 +80,16 @@
     switch (sym->tag)
     {
     /* lexical tree */
-    case SymTagData:            return ((struct symt_data*)sym)->hash_elt.name;
-    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;
+    case SymTagData:            return ((const struct symt_data*)sym)->hash_elt.name;
+    case SymTagFunction:        return ((const struct symt_function*)sym)->hash_elt.name;
+    case SymTagPublicSymbol:    return ((const struct symt_public*)sym)->hash_elt.name;
+    case SymTagBaseType:        return ((const struct symt_basic*)sym)->hash_elt.name;
+    case SymTagLabel:           return ((const struct symt_function_point*)sym)->name;
+    case SymTagThunk:           return ((const struct symt_thunk*)sym)->hash_elt.name;
     /* hierarchy tree */
-    case SymTagEnum:            return ((struct symt_enum*)sym)->name;
-    case SymTagTypedef:         return ((struct symt_typedef*)sym)->hash_elt.name;
-    case SymTagUDT:             return ((struct symt_udt*)sym)->hash_elt.name;
+    case SymTagEnum:            return ((const struct symt_enum*)sym)->name;
+    case SymTagTypedef:         return ((const struct symt_typedef*)sym)->hash_elt.name;
+    case SymTagUDT:             return ((const struct symt_udt*)sym)->hash_elt.name;
     default:
         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
         /* fall through */
@@ -417,10 +418,10 @@
 
             switch (type->tag)
             {
-            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;
+            case SymTagUDT:          v = &((const struct symt_udt*)type)->vchildren; break;
+            case SymTagEnum:         v = &((const struct symt_enum*)type)->vchildren; break;
+            case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
+            case SymTagFunction:     v = &((const struct symt_function*)type)->vchildren; break;
             default:
                 FIXME("Unsupported sym-tag %s for find-children\n", 
                       symt_get_tag_str(type->tag));
@@ -438,26 +439,29 @@
         switch (type->tag)
         {
         case SymTagData:
-            switch (((struct symt_data*)type)->kind)
+            switch (((const struct symt_data*)type)->kind)
             {
             case DataIsGlobal:
             case DataIsFileStatic:
-                X(DWORD) = ((struct symt_data*)type)->u.address;
+                X(DWORD) = ((const struct symt_data*)type)->u.address;
                 break;
             default: return FALSE;
             }
             break;
         case SymTagFunction:
-            X(DWORD) = ((struct symt_function*)type)->addr;
+            X(DWORD) = ((const struct symt_function*)type)->address;
             break;
         case SymTagPublicSymbol:
-            X(DWORD) = ((struct symt_public*)type)->address;
+            X(DWORD) = ((const 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;
+            X(DWORD) = ((const struct symt_function_point*)type)->parent->address + 
+                ((const struct symt_function_point*)type)->offset;
+            break;
+        case SymTagThunk:
+            X(DWORD) = ((const struct symt_thunk*)type)->address;
             break;
         default:
             FIXME("Unsupported sym-tag %s for get-address\n", 
@@ -470,7 +474,7 @@
         switch (type->tag)
         {
         case SymTagBaseType:
-            X(DWORD) = ((struct symt_basic*)type)->bt;
+            X(DWORD) = ((const struct symt_basic*)type)->bt;
             break;
         case SymTagEnum:
             X(DWORD) = btInt;
@@ -482,29 +486,30 @@
 
     case TI_GET_BITPOSITION:
         if (type->tag != SymTagData || 
-            ((struct symt_data*)type)->kind != DataIsMember ||
-            ((struct symt_data*)type)->u.s.length == 0)
+            ((const struct symt_data*)type)->kind != DataIsMember ||
+            ((const struct symt_data*)type)->u.s.length == 0)
             return FALSE;
-        X(DWORD) = ((struct symt_data*)type)->u.s.offset & 7;
+        X(DWORD) = ((const struct symt_data*)type)->u.s.offset & 7;
         break;
 
     case TI_GET_CHILDRENCOUNT:
         switch (type->tag)
         {
         case SymTagUDT:
-            X(DWORD) = vector_length(&((struct symt_udt*)type)->vchildren);
+            X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
             break;
         case SymTagEnum:
-            X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
+            X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
             break;
         case SymTagFunctionType:
-            X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
+            X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
             break;
         case SymTagFunction:
-            X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
+            X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
             break;
         case SymTagPointerType: /* MS does it that way */
         case SymTagArrayType: /* MS does it that way */
+        case SymTagThunk: /* MS does it that way */
             X(DWORD) = 0;
             break;
         default:
@@ -524,51 +529,54 @@
          * 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;
+        X(DWORD) = ((const struct symt_array*)type)->end - 
+            ((const struct symt_array*)type)->start + 1;
         break;
 
     case TI_GET_DATAKIND:
         if (type->tag != SymTagData) return FALSE;
-        X(DWORD) = ((struct symt_data*)type)->kind;
+        X(DWORD) = ((const struct symt_data*)type)->kind;
         break;
 
     case TI_GET_LENGTH:
         switch (type->tag)
         {
         case SymTagBaseType:
-            X(DWORD) = ((struct symt_basic*)type)->size;
+            X(DWORD) = ((const struct symt_basic*)type)->size;
             break;
         case SymTagFunction:
-            X(DWORD) = ((struct symt_function*)type)->size;
+            X(DWORD) = ((const struct symt_function*)type)->size;
             break;
         case SymTagPointerType:
             X(DWORD) = sizeof(void*);
             break;
         case SymTagUDT:
-            X(DWORD) = ((struct symt_udt*)type)->size;
+            X(DWORD) = ((const struct symt_udt*)type)->size;
             break;
         case SymTagEnum:
             X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
             break;
         case SymTagData:
-            if (((struct symt_data*)type)->kind != DataIsMember ||
-                !((struct symt_data*)type)->u.s.length)
+            if (((const struct symt_data*)type)->kind != DataIsMember ||
+                !((const struct symt_data*)type)->u.s.length)
                 return FALSE;
-            X(DWORD) = ((struct symt_data*)type)->u.s.length;
+            X(DWORD) = ((const struct symt_data*)type)->u.s.length;
             break;
         case SymTagArrayType:   
-            if (!symt_get_info(((struct symt_array*)type)->basetype, 
+            if (!symt_get_info(((const struct symt_array*)type)->basetype, 
                                TI_GET_LENGTH, pInfo))
                 return FALSE;
-            X(DWORD) *= ((struct symt_array*)type)->end - 
-                ((struct symt_array*)type)->start;
+            X(DWORD) *= ((const struct symt_array*)type)->end - 
+                ((const struct symt_array*)type)->start + 1;
             break;
         case SymTagPublicSymbol:
-            X(DWORD) = ((struct symt_public*)type)->size;
+            X(DWORD) = ((const struct symt_public*)type)->size;
             break;
         case SymTagTypedef:
-            return symt_get_info(((struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
+            return symt_get_info(((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
+            break;
+        case SymTagThunk:
+            X(DWORD) = ((const struct symt_thunk*)type)->size;
             break;
         default:
             FIXME("Unsupported sym-tag %s for get-length\n", 
@@ -581,10 +589,16 @@
         switch (type->tag)
         {
         case SymTagBlock:
-            X(DWORD) = (DWORD)((struct symt_block*)type)->container;
+            X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
             break;
         case SymTagData:
-            X(DWORD) = (DWORD)((struct symt_data*)type)->container;
+            X(DWORD) = (DWORD)((const struct symt_data*)type)->container;
+            break;
+        case SymTagFunction:
+            X(DWORD) = (DWORD)((const struct symt_function*)type)->container;
+            break;
+        case SymTagThunk:
+            X(DWORD) = (DWORD)((const struct symt_thunk*)type)->container;
             break;
         default:
             FIXME("Unsupported sym-tag %s for get-lexical-parent\n", 
@@ -609,16 +623,16 @@
         switch (type->tag)
         {
         case SymTagData:
-            switch (((struct symt_data*)type)->kind)
+            switch (((const struct symt_data*)type)->kind)
             {
             case DataIsParam:
             case DataIsLocal:
             case DataIsMember:
-                X(ULONG) = ((struct symt_data*)type)->u.s.offset >> 3; 
+                X(ULONG) = ((const struct symt_data*)type)->u.s.offset >> 3; 
                 break;
             default:
                 FIXME("Unknown kind (%u) for get-offset\n",     
-                      ((struct symt_data*)type)->kind);
+                      ((const struct symt_data*)type)->kind);
                 return FALSE;
             }
             break;
@@ -650,41 +664,42 @@
         {
             /* hierarchical => hierarchical */
         case SymTagArrayType:
-            X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
+            X(DWORD) = (DWORD)((const struct symt_array*)type)->basetype;
             break;
         case SymTagPointerType:
-            X(DWORD) = (DWORD)((struct symt_pointer*)type)->pointsto;
+            X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
             break;
         case SymTagFunctionType:
-            X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
+            X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
             break;
         case SymTagTypedef:
-            X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
+            X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
             break;
             /* lexical => hierarchical */
         case SymTagData:
-            X(DWORD) = (DWORD)((struct symt_data*)type)->type; 
+            X(DWORD) = (DWORD)((const struct symt_data*)type)->type; 
             break;
         case SymTagFunction:
-            X(DWORD) = (DWORD)((struct symt_function*)type)->type;
+            X(DWORD) = (DWORD)((const 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));
+        case SymTagThunk:
             return FALSE;
         }
         break;
 
     case TI_GET_UDTKIND:
         if (type->tag != SymTagUDT) return FALSE;
-        X(DWORD) = ((struct symt_udt*)type)->kind;
+        X(DWORD) = ((const struct symt_udt*)type)->kind;
         break;
 
     case TI_GET_VALUE:
-        if (type->tag != SymTagData || ((struct symt_data*)type)->kind != DataIsConstant)
+        if (type->tag != SymTagData || ((const struct symt_data*)type)->kind != DataIsConstant)
             return FALSE;
-        X(VARIANT) = ((struct symt_data*)type)->u.value;
+        X(VARIANT) = ((const struct symt_data*)type)->u.value;
         break;
 
 #undef X
diff --git a/include/cvconst.h b/include/cvconst.h
index 4f203d2..a63f03b 100644
--- a/include/cvconst.h
+++ b/include/cvconst.h
@@ -421,3 +421,12 @@
     CV_M32R_ACLO        = 33,
     CV_M32R_PC          = 34,
 } CV_HREG_e;
+
+typedef enum
+{
+   THUNK_ORDINAL_NOTYPE,
+   THUNK_ORDINAL_ADJUSTOR,
+   THUNK_ORDINAL_VCALL,
+   THUNK_ORDINAL_PCODE,
+   THUNK_ORDINAL_LOAD 
+} THUNK_ORDINAL;
diff --git a/include/dbghelp.h b/include/dbghelp.h
index 5df1cd7..a5b468f 100644
--- a/include/dbghelp.h
+++ b/include/dbghelp.h
@@ -72,6 +72,9 @@
 #define SYMF_EXPORT           0x00000200
 #define SYMF_FORWARDER        0x00000400
 #define SYMF_FUNCTION         0x00000800
+#define SYMF_VIRTUAL          0x00001000
+#define SYMF_THUNK            0x00002000
+#define SYMF_TLSREL           0x00004000
 
 typedef enum 
 {
@@ -529,6 +532,11 @@
     MINIDUMP_THREAD             Threads[1]; /* FIXME: no support of 0 sized array */
 } MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;
 
+BOOL WINAPI MiniDumpWriteDump(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,const PMINIDUMP_EXCEPTION_INFORMATION,
+                              const PMINIDUMP_USER_STREAM_INFORMATION,const PMINIDUMP_CALLBACK_INFORMATION);
+BOOL WINAPI MiniDumpReadDumpStream(PVOID,ULONG,PMINIDUMP_DIRECTORY*,PVOID*,ULONG*);
+
+
 /*************************
  *    MODULE handling    *
  *************************/
@@ -586,7 +594,7 @@
     ULONG       SizeOfStruct;
     ULONG       TypeIndex;
     ULONG       Reserved[2];
-    ULONG       info;
+    ULONG       info;   /* sdk states info, while MSDN says it's Index... */
     ULONG       Size;
     ULONG       ModBase;
     ULONG       Flags;
@@ -666,8 +674,12 @@
 BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD addr, DWORD* displacement, 
                         SYMBOL_INFO* sym_info);
 BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol);
+BOOL WINAPI SymGetSymFromAddr(HANDLE,DWORD,PDWORD,PIMAGEHLP_SYMBOL);
+BOOL WINAPI SymGetSymFromName(HANDLE,PSTR,PIMAGEHLP_SYMBOL);
 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, DWORD BaseOfDll, LPSTR Name,
                                PSYMBOL_INFO Symbol);
+BOOL WINAPI SymGetSymNext(HANDLE,PIMAGEHLP_SYMBOL);
+BOOL WINAPI SymGetSymPrev(HANDLE,PIMAGEHLP_SYMBOL);
 BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
                            PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
                            PVOID UserContext);
@@ -681,6 +693,7 @@
 BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
                                 PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
                                 PVOID UserContext);
+BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL,PSTR,DWORD);
 DWORD WINAPI UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName,
                                   DWORD UndecoratedLength, DWORD Flags);
 
@@ -731,6 +744,11 @@
                                                PVOID Base, ULONG Rva);
 PVOID WINAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders, PVOID Base,
                           ULONG Rva, OUT PIMAGE_SECTION_HEADER *LastRvaSection);
+BOOL WINAPI SymGetSearchPath(HANDLE,PSTR,DWORD);
+BOOL WINAPI SymSetSearchPath(HANDLE,PSTR);
+DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE);
+BOOL WINAPI MakeSureDirectoryPathExists(PCSTR);
+BOOL WINAPI SearchTreeForFile(PSTR,PSTR,PSTR);
 
 /*************************
  *   Context management  *