Commit in reactos/lib/dbghelp on MAIN
type.c+784added 1.1
symbol.c+1228added 1.1
storage.c+335added 1.1
stack.c+388added 1.1
stabs.c+1480added 1.1
source.c+138added 1.1
pe_module.c+424added 1.1
path.c+272added 1.1
mscvpdb.h+1424added 1.1
msc.c+2332added 1.1
module.c+505added 1.1
minidump.c+266added 1.1
memory.c+61added 1.1
Makefile.ros-template+21added 1.1
Makefile.in+28added 1.1
Makefile+409added 1.1
makefile+9added 1.1
image.c+61added 1.1
elf_module.c+1176added 1.1
dbghelp_private.h+448added 1.1
dbghelp.stubs.c+74added 1.1
dbghelp.spec.def+96added 1.1
dbghelp.spec+99added 1.1
dbghelp.rc+1added 1.1
dbghelp.c+338added 1.1
coff.c+454added 1.1
.cvsignore+26added 1.1
+12877
27 added files
First shot at importing dbghelp. Its broken. Dont enable it
until KJK and Alex have a look.

reactos/lib/dbghelp
type.c added at 1.1
diff -N type.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ type.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,784 @@
+/*
+ * File types.c - management of types (hierarchical tree)
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ *               2004, Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Note: This really doesn't do much at the moment, but it forms the framework
+ * upon which full support for datatype handling will eventually be built.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winnls.h"
+#include "wine/debug.h"
+#include "dbghelp_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
+
+static const char* symt_get_tag_str(DWORD tag)
+{
+    switch (tag)
+    {
+    case SymTagNull:                    return "SymTagNull";
+    case SymTagExe:                     return "SymTagExe";
+    case SymTagCompiland:               return "SymTagCompiland";
+    case SymTagCompilandDetails:        return "SymTagCompilandDetails";
+    case SymTagCompilandEnv:            return "SymTagCompilandEnv";
+    case SymTagFunction:                return "SymTagFunction";
+    case SymTagBlock:                   return "SymTagBlock";
+    case SymTagData:                    return "SymTagData";
+    case SymTagAnnotation:              return "SymTagAnnotation";
+    case SymTagLabel:                   return "SymTagLabel";
+    case SymTagPublicSymbol:            return "SymTagPublicSymbol";
+    case SymTagUDT:                     return "SymTagUDT";
+    case SymTagEnum:                    return "SymTagEnum";
+    case SymTagFunctionType:            return "SymTagFunctionType";
+    case SymTagPointerType:             return "SymTagPointerType";
+    case SymTagArrayType:               return "SymTagArrayType";
+    case SymTagBaseType:                return "SymTagBaseType";
+    case SymTagTypedef:                 return "SymTagTypedef,";
+    case SymTagBaseClass:               return "SymTagBaseClass";
+    case SymTagFriend:                  return "SymTagFriend";
+    case SymTagFunctionArgType:         return "SymTagFunctionArgType,";
+    case SymTagFuncDebugStart:          return "SymTagFuncDebugStart,";
+    case SymTagFuncDebugEnd:            return "SymTagFuncDebugEnd";
+    case SymTagUsingNamespace:          return "SymTagUsingNamespace,";
+    case SymTagVTableShape:             return "SymTagVTableShape";
+    case SymTagVTable:                  return "SymTagVTable";
+    case SymTagCustom:                  return "SymTagCustom";
+    case SymTagThunk:                   return "SymTagThunk";
+    case SymTagCustomType:              return "SymTagCustomType";
+    case SymTagManagedType:             return "SymTagManagedType";
+    case SymTagDimension:               return "SymTagDimension";
+    default:                            return "---";
+    }
+}
+
+const char* symt_get_name(const struct symt* sym)
+{
+    switch (sym->tag)
+    {
+    /* lexical tree */
+    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 ((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 */
+    case SymTagArrayType:
+    case SymTagPointerType:
+    case SymTagFunctionType:
+        return NULL;
+    }
+}
+
+static struct symt* symt_find_type_by_name(struct module* module, 
+                                           enum SymTagEnum sym_tag, 
+                                           const char* typename)
+{
+    void*                       ptr;
+    struct symt_ht*             type;
+    struct hash_table_iter      hti;
+
+    assert(typename);
+    assert(module);
+
+    hash_table_iter_init(&module->ht_types, &hti, typename);
+    while ((ptr = hash_table_iter_up(&hti)))
+    {
+        type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+
+        if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
+            type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
+            return &type->symt;
+    }
+    SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
+    return NULL;
+}
+
+static void symt_add_type(struct module* module, struct symt* symt)
+{
+    struct symt**       p;
+    p = vector_add(&module->vtypes, &module->pool);
+    assert(p);
+    *p = symt;
+}
+
+struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, 
+                                  const char* typename, unsigned size)
+{
+    struct symt_basic*          sym;
+
+    if (typename)
+    {
+        sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
+                                                         typename);
+        if (sym && sym->bt == bt && sym->size == size)
+            return sym;
+    }
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagBaseType;
+        if (typename)
+        {
+            sym->hash_elt.name = pool_strdup(&module->pool, typename);
+            hash_table_add(&module->ht_types, &sym->hash_elt);
+        } else sym->hash_elt.name = NULL;
+        sym->bt = bt;
+        sym->size = size;
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+struct symt_udt* symt_new_udt(struct module* module, const char* typename, 
+                              unsigned size, enum UdtKind kind)
+{
+    struct symt_udt*            sym;
+
+    TRACE_(dbghelp_symt)("Adding udt %s:%s\n", module->module.ModuleName, typename);
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagUDT;
+        sym->kind     = kind;
+        sym->size     = size;
+        if (typename)
+        {
+            sym->hash_elt.name = pool_strdup(&module->pool, typename);
+            hash_table_add(&module->ht_types, &sym->hash_elt);
+        } else sym->hash_elt.name = NULL;
+        vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
+{
+    assert(udt->symt.tag == SymTagUDT);
+    if (vector_length(&udt->vchildren) != 0)
+    {
+        if (udt->size != size)
+            FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n", 
+                                 udt->hash_elt.name, udt->size, size);
+        return TRUE;
+    }
+    udt->size = size;
+    return TRUE;
+}
+
+/******************************************************************
+ *		symt_add_udt_element
+ *
+ * add an element to a udt (struct, class, union)
+ * the size & offset parameters are expressed in bits (not bytes) so that
+ * we can mix in the single call bytes aligned elements (regular fields) and
+ * the others (bit fields)
+ */
+BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
+                          const char* name, struct symt* elt_type,
+                          unsigned offset, unsigned size)
+{
+    struct symt_data*   m;
+    struct symt**       p;
+
+    assert(udt_type->symt.tag == SymTagUDT);
+
+    TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
+    p = NULL;
+    while ((p = vector_iter_up(&udt_type->vchildren, p)))
+    {
+        m = (struct symt_data*)*p;
+        assert(m);
+        assert(m->symt.tag == SymTagData);
+        if (m->hash_elt.name[0] == name[0] && strcmp(m->hash_elt.name, name) == 0)
+            return TRUE;
+    }
+
+    if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
+    memset(m, 0, sizeof(*m));
+    m->symt.tag      = SymTagData;
+    m->hash_elt.name = pool_strdup(&module->pool, name);
+    m->hash_elt.next = NULL;
+
+    m->kind          = DataIsMember;
+    m->container     = &udt_type->symt;
+    m->type          = elt_type;
+    m->u.s.offset    = offset;
+    m->u.s.length    = ((offset & 7) || (size & 7)) ? size : 0;
+    m->u.s.reg_id    = 0;
+    p = vector_add(&udt_type->vchildren, &module->pool);
+    *p = &m->symt;
+
+    return TRUE;
+}
+
+struct symt_enum* symt_new_enum(struct module* module, const char* typename)
+{
+    struct symt_enum*   sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag            = SymTagEnum;
+        sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL;
+        vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+    }
+    return sym;
+}
+
+BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
+                           const char* name, int value)
+{
+    struct symt_data*   e;
+    struct symt**       p;
+
+    assert(enum_type->symt.tag == SymTagEnum);
+    e = pool_alloc(&module->pool, sizeof(*e));
+    if (e == NULL) return FALSE;
+
+    e->symt.tag = SymTagData;
+    e->hash_elt.name = pool_strdup(&module->pool, name);
+    e->hash_elt.next = NULL;
+    e->kind = DataIsConstant;
+    e->container = &enum_type->symt;
+    /* CV defines the underlying type for the enumeration */
+    e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
+    e->u.value.n1.n2.vt = VT_I4;
+    e->u.value.n1.n2.n3.lVal = value;
+
+    p = vector_add(&enum_type->vchildren, &module->pool);
+    if (!p) return FALSE; /* FIXME we leak e */
+    *p = &e->symt;
+
+    return TRUE;
+}
+
+struct symt_array* symt_new_array(struct module* module, int min, int max, 
+                                  struct symt* base)
+{
+    struct symt_array*  sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag  = SymTagArrayType;
+        sym->start     = min;
+        sym->end       = max;
+        sym->basetype  = base;
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+struct symt_function_signature* symt_new_function_signature(struct module* module, 
+                                                            struct symt* ret_type)
+{
+    struct symt_function_signature*     sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagFunctionType;
+        sym->rettype  = ret_type;
+        vector_init(&sym->vchildren, sizeof(struct symt*), 4);
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+BOOL symt_add_function_signature_parameter(struct module* module,
+                                           struct symt_function_signature* sig_type,
+                                           struct symt* param)
+{
+    struct symt**       p;
+
+    assert(sig_type->symt.tag == SymTagFunctionType);
+    p = vector_add(&sig_type->vchildren, &module->pool);
+    if (!p) return FALSE; /* FIXME we leak e */
+    *p = param;
+
+    return TRUE;
+}
+
+struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
+{
+    struct symt_pointer*        sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagPointerType;
+        sym->pointsto = ref_type;
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, 
+                                      const char* name)
+{
+    struct symt_typedef* sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagTypedef;
+        sym->type     = ref;
+        sym->hash_elt.name = pool_strdup(&module->pool, name);
+        hash_table_add(&module->ht_types, &sym->hash_elt);
+        symt_add_type(module, &sym->symt);
+    }
+    return sym;
+}
+
+/******************************************************************
+ *		SymEnumTypes (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
+                         PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
+                         PVOID UserContext)
+{
+    struct process*     pcs;
+    struct module*      module;
+    char                buffer[sizeof(SYMBOL_INFO) + 256];
+    SYMBOL_INFO*        sym_info = (SYMBOL_INFO*)buffer;
+    const char*         tmp;
+    struct symt*        type;
+    void*               pos = NULL;
+    
+    TRACE("(%p %s %p %p)\n",
+          hProcess, wine_dbgstr_longlong(BaseOfDll), EnumSymbolsCallback,
+          UserContext);
+
+    if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
+    module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
+    if (!(module = module_get_debug(pcs, module))) return FALSE;
+
+    sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
+    sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
+
+    while ((pos = vector_iter_up(&module->vtypes, pos)))
+    {
+        type = *(struct symt**)pos;
+        sym_info->TypeIndex = (DWORD)type;
+        sym_info->info = 0; /* FIXME */
+        symt_get_info(type, TI_GET_LENGTH, &sym_info->Size);
+        sym_info->ModBase = module->module.BaseOfImage;
+        sym_info->Flags = 0; /* FIXME */
+        sym_info->Value = 0; /* FIXME */
+        sym_info->Address = 0; /* FIXME */
+        sym_info->Register = 0; /* FIXME */
+        sym_info->Scope = 0; /* FIXME */
+        sym_info->Tag = type->tag;
+        tmp = symt_get_name(type);
+        if (tmp)
+        {
+            sym_info->NameLen = strlen(tmp) + 1;
+            strncpy(sym_info->Name, tmp, min(sym_info->NameLen, sym_info->MaxNameLen));
+            sym_info->Name[sym_info->MaxNameLen - 1] = '\0';
+        }       
+        else sym_info->Name[sym_info->NameLen = 0] = '\0';
+        if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
+    }
+    return TRUE;
+}
+
+/******************************************************************
+ *		symt_get_info
+ *
+ * Retrieves inforamtion about a symt (either symbol or type)
+ */
+BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, 
+                   void* pInfo)
+{
+    unsigned            len;
+
+    if (!type) return FALSE;
+
+/* helper to typecast pInfo to its expected type (_t) */
+#define X(_t) (*((_t*)pInfo))
+
+    switch (req)
+    {
+    case TI_FINDCHILDREN:
+        {
+            const struct vector*        v;
+            struct symt**               pt;
+            unsigned                    i;
+            TI_FINDCHILDREN_PARAMS*     tifp = pInfo;
+
+            switch (type->tag)
+            {
+            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));
+                return FALSE;
+            }
+            for (i = 0; i < tifp->Count; i++)
+            {
+                if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
+                tifp->ChildId[i] = (DWORD)*pt;
+            }
+        }
+        break;
+
+    case TI_GET_ADDRESS:
+        switch (type->tag)
+        {
+        case SymTagData:
+            switch (((const struct symt_data*)type)->kind)
+            {
+            case DataIsGlobal:
+            case DataIsFileStatic:
+                X(ULONG64) = ((const struct symt_data*)type)->u.address;
+                break;
+            default: return FALSE;
+            }
+            break;
+        case SymTagFunction:
+            X(ULONG64) = ((const struct symt_function*)type)->address;
+            break;
+        case SymTagPublicSymbol:
+            X(ULONG64) = ((const struct symt_public*)type)->address;
+            break;
+        case SymTagFuncDebugStart:
+        case SymTagFuncDebugEnd:
+        case SymTagLabel:
+            X(ULONG64) = ((const struct symt_function_point*)type)->parent->address + 
+                ((const struct symt_function_point*)type)->offset;
+            break;
+        case SymTagThunk:
+            X(ULONG64) = ((const struct symt_thunk*)type)->address;
+            break;
+        default:
+            FIXME("Unsupported sym-tag %s for get-address\n", 
+                  symt_get_tag_str(type->tag));
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_BASETYPE:
+        switch (type->tag)
+        {
+        case SymTagBaseType:
+            X(DWORD) = ((const struct symt_basic*)type)->bt;
+            break;
+        case SymTagEnum:
+            X(DWORD) = btInt;
+            break;
+        default:
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_BITPOSITION:
+        if (type->tag != SymTagData || 
+            ((const struct symt_data*)type)->kind != DataIsMember ||
+            ((const struct symt_data*)type)->u.s.length == 0)
+            return FALSE;
+        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(&((const struct symt_udt*)type)->vchildren);
+            break;
+        case SymTagEnum:
+            X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
+            break;
+        case SymTagFunctionType:
+            X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
+            break;
+        case SymTagFunction:
+            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:
+            FIXME("Unsupported sym-tag %s for get-children-count\n", 
+                  symt_get_tag_str(type->tag));
+            /* fall through */
+        case SymTagData:
+        case SymTagPublicSymbol:
+        case SymTagBaseType:
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_COUNT:
+        /* it seems that FunctionType also react to GET_COUNT (same value as
+         * GET_CHILDREN_COUNT ?, except for C++ methods, where it seems to
+         * also include 'this' (GET_CHILDREN_COUNT+1)
+         */
+        if (type->tag != SymTagArrayType) return FALSE;
+        X(DWORD) = ((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) = ((const struct symt_data*)type)->kind;
+        break;
+
+    case TI_GET_LENGTH:
+        switch (type->tag)
+        {
+        case SymTagBaseType:
+            X(DWORD) = ((const struct symt_basic*)type)->size;
+            break;
+        case SymTagFunction:
+            X(DWORD) = ((const struct symt_function*)type)->size;
+            break;
+        case SymTagPointerType:
+            X(DWORD) = sizeof(void*);
+            break;
+        case SymTagUDT:
+            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 (((const struct symt_data*)type)->kind != DataIsMember ||
+                !((const struct symt_data*)type)->u.s.length)
+                return FALSE;
+            X(DWORD) = ((const struct symt_data*)type)->u.s.length;
+            break;
+        case SymTagArrayType:   
+            if (!symt_get_info(((const struct symt_array*)type)->basetype, 
+                               TI_GET_LENGTH, pInfo))
+                return FALSE;
+            X(DWORD) *= ((const struct symt_array*)type)->end - 
+                ((const struct symt_array*)type)->start + 1;
+            break;
+        case SymTagPublicSymbol:
+            X(DWORD) = ((const struct symt_public*)type)->size;
+            break;
+        case SymTagTypedef:
+            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", 
+                  symt_get_tag_str(type->tag));
+            /* fall through */
+        case SymTagFunctionType:
+            return 0;
+        }
+        break;
+
+    case TI_GET_LEXICALPARENT:
+        switch (type->tag)
+        {
+        case SymTagBlock:
+            X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
+            break;
+        case SymTagData:
+            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", 
+                  symt_get_tag_str(type->tag));
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_NESTED:
+        switch (type->tag)
+        {
+        case SymTagUDT:
+        case SymTagEnum:
+            X(DWORD) = 0;
+            break;
+        default:
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_OFFSET:
+        switch (type->tag)
+        {
+        case SymTagData:
+            switch (((const struct symt_data*)type)->kind)
+            {
+            case DataIsParam:
+            case DataIsLocal:
+            case DataIsMember:
+                X(ULONG) = ((const struct symt_data*)type)->u.s.offset >> 3; 
+                break;
+            default:
+                FIXME("Unknown kind (%u) for get-offset\n",     
+                      ((const struct symt_data*)type)->kind);
+                return FALSE;
+            }
+            break;
+        default:
+            FIXME("Unsupported sym-tag %s for get-offset\n", 
+                  symt_get_tag_str(type->tag));
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_SYMNAME:
+        {
+            const char* name = symt_get_name(type);
+            if (!name) return FALSE;
+            len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
+            X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+            if (!X(WCHAR*)) return FALSE;
+            MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
+        }
+        break;
+
+    case TI_GET_SYMTAG:
+        X(DWORD) = type->tag;
+        break;
+
+    case TI_GET_TYPE:
+    case TI_GET_TYPEID:
+        switch (type->tag)
+        {
+            /* hierarchical => hierarchical */
+        case SymTagArrayType:
+            X(DWORD) = (DWORD)((const struct symt_array*)type)->basetype;
+            break;
+        case SymTagPointerType:
+            X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
+            break;
+        case SymTagFunctionType:
+            X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
+            break;
+        case SymTagTypedef:
+            X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
+            break;
+            /* lexical => hierarchical */
+        case SymTagData:
+            X(DWORD) = (DWORD)((const struct symt_data*)type)->type; 
+            break;
+        case SymTagFunction:
+            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) = ((const struct symt_udt*)type)->kind;
+        break;
+
+    case TI_GET_VALUE:
+        if (type->tag != SymTagData || ((const struct symt_data*)type)->kind != DataIsConstant)
+            return FALSE;
+        X(VARIANT) = ((const struct symt_data*)type)->u.value;
+        break;
+
+#undef X
+
+    case TI_GET_ADDRESSOFFSET:
+    case TI_GET_ARRAYINDEXTYPEID:
+    case TI_GET_CALLING_CONVENTION:
+    case TI_GET_CLASSPARENTID:
+    case TI_GET_SYMINDEX:
+    case TI_GET_THISADJUST:
+    case TI_GET_VIRTUALBASECLASS:
+    case TI_GET_VIRTUALBASEPOINTEROFFSET:
+    case TI_GET_VIRTUALTABLESHAPEID:
+    case TI_IS_EQUIV_TO:
+        FIXME("Unsupported GetInfo request (%u)\n", req);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		SymGetTypeInfo (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
+                           ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
+                           PVOID pInfo)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+
+    if (!pcs) return FALSE;
+
+    module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
+    if (!(module = module_get_debug(pcs, module)))
+    {
+        FIXME("Someone didn't properly set ModBase (%s)\n", wine_dbgstr_longlong(ModBase));
+        return FALSE;
+    }
+
+    return symt_get_info((struct symt*)TypeId, GetType, pInfo);
+}
+
+/******************************************************************
+ *		SymGetTypeFromName (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
+                               LPSTR Name, PSYMBOL_INFO Symbol)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+    struct symt*        type;
+
+    if (!pcs) return FALSE;
+    module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
+    if (!module) return FALSE;
+    type = symt_find_type_by_name(module, SymTagNull, Name);
+    if (!type) return FALSE;
+    Symbol->TypeIndex = (DWORD)type;
+
+    return TRUE;
+}

reactos/lib/dbghelp
symbol.c added at 1.1
diff -N symbol.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ symbol.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,1228 @@
+/*
+ * File symbol.c - management of symbols (lexical tree)
+ *
+ * Copyright (C) 1993, Eric Youngdale.
+ *               2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <assert.h>
+#ifdef HAVE_REGEX_H
+# include <regex.h>
+#endif
+
+#include "wine/debug.h"
+#include "dbghelp_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
+
+struct line_info
+{
+    unsigned long               is_first : 1,
+                                is_last : 1,
+                                is_source_file : 1,
+                                line_number;
+    union
+    {
+        unsigned long               pc_offset;   /* if is_source_file isn't set */
+        unsigned                    source_file; /* if is_source_file is set */
+    } u;
+};
+
+inline static int cmp_addr(ULONG64 a1, ULONG64 a2)
+{
+    if (a1 > a2) return 1;
+    if (a1 < a2) return -1;
+    return 0;
+}
+
+inline static int cmp_sorttab_addr(const struct module* module, int idx, ULONG64 addr)
+{
+    ULONG64     ref;
+
+    symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_ADDRESS, &ref);
+    return cmp_addr(ref, addr);
+}
+
+int symt_cmp_addr(const void* p1, const void* p2)
+{
+    const struct symt*  sym1 = *(const struct symt* const *)p1;
+    const struct symt*  sym2 = *(const struct symt* const *)p2;
+    ULONG64     a1, a2;
+
+    symt_get_info(sym1, TI_GET_ADDRESS, &a1);
+    symt_get_info(sym2, TI_GET_ADDRESS, &a2);
+    return cmp_addr(a1, a2);
+}
+
+static inline void re_append(char** mask, unsigned* len, char ch)
+{
+    *mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
+    (*mask)[*len - 2] = ch;
+}
+
+/* transforms a dbghelp's regular expression into a POSIX one
+ * Here are the valid dbghelp reg ex characters:
+ *      *       0 or more characters
+ *      ?       a single character
+ *      []      list
+ *      #       0 or more of preceding char
+ *      +       1 or more of preceding char
+ *      escapes \ on #, ?, [, ], *, +. don't work on -
+ */
+static void compile_regex(const char* str, int numchar, regex_t* re)
+{
+    char*       mask = HeapAlloc(GetProcessHeap(), 0, 1);
+    unsigned    len = 1;
+    BOOL        in_escape = FALSE;
+
+    re_append(&mask, &len, '^');
+
+    while (*str && numchar--)
+    {
+        /* FIXME: this shouldn't be valid on '-' */
+        if (in_escape)
+        {
+            re_append(&mask, &len, '\\');
+            re_append(&mask, &len, *str);
+            in_escape = FALSE;
+        }
+        else switch (*str)
+        {
+        case '\\': in_escape = TRUE; break;
+        case '*':  re_append(&mask, &len, '.'); re_append(&mask, &len, '*'); break;
+        case '?':  re_append(&mask, &len, '.'); break;
+        case '#':  re_append(&mask, &len, '*'); break;
+        /* escape some valid characters in dbghelp reg exp:s */
+        case '$':  re_append(&mask, &len, '\\'); re_append(&mask, &len, '$'); break;
+        /* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
+        default:   re_append(&mask, &len, *str); break;
+        }
+        str++;
+    }
+    if (in_escape)
+    {
+        re_append(&mask, &len, '\\');
+        re_append(&mask, &len, '\\');
+    }
+    re_append(&mask, &len, '$');
+    mask[len - 1] = '\0';
+    if (regcomp(re, mask, REG_NOSUB)) FIXME("Couldn't compile %s\n", mask);
+    HeapFree(GetProcessHeap(), 0, mask);
+}
+
+struct symt_compiland* symt_new_compiland(struct module* module, const char* name)
+{
+    struct symt_compiland*    sym;
+
+    TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n", 
+                         module->module.ModuleName, name);
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagCompiland;
+        sym->source   = source_new(module, name);
+        vector_init(&sym->vchildren, sizeof(struct symt*), 32);
+    }
+    return sym;
+}
+
+struct symt_public* symt_new_public(struct module* module, 
+                                    struct symt_compiland* compiland,
+                                    const char* name,
+                                    unsigned long address, unsigned size,
+                                    BOOL in_code, BOOL is_func)
+{
+    struct symt_public* sym;
+    struct symt**       p;
+
+    TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%lx\n", 
+                         module->module.ModuleName, name, address);
+    if ((dbghelp_options & SYMOPT_AUTO_PUBLICS) && 
+        symt_find_nearest(module, address) != -1)
+        return NULL;
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag      = SymTagPublicSymbol;
+        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 ? &compiland->symt : NULL;
+        sym->address       = address;
+        sym->size          = size;
+        sym->in_code       = in_code;
+        sym->is_function   = is_func;
+        if (compiland)
+        {
+            p = vector_add(&compiland->vchildren, &module->pool);
+            *p = &sym->symt;
+        }
+    }
+    return sym;
+}
+
+struct symt_data* symt_new_global_variable(struct module* module, 
+                                           struct symt_compiland* compiland, 
+                                           const char* name, unsigned is_static,
+                                           unsigned long addr, unsigned long size,
+                                           struct symt* type)
+{
+    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);
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag      = SymTagData;
+        sym->hash_elt.name = pool_strdup(&module->pool, name);
+        hash_table_add(&module->ht_symbols, &sym->hash_elt);
+        module->sortlist_valid = FALSE;
+        sym->kind          = is_static ? DataIsFileStatic : DataIsGlobal;
+        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);
+            *p = &sym->symt;
+        }
+    }
+    return sym;
+}
+
+struct symt_function* symt_new_function(struct module* module, 
+                                        struct symt_compiland* compiland, 
+                                        const char* name,
+                                        unsigned long addr, unsigned long size,
+                                        struct symt* sig_type)
+{
+    struct symt_function*       sym;
+    struct symt**               p;
+
+    TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n", 
+                         module->module.ModuleName, name, addr, addr + size - 1);
+
+    assert(!sig_type || sig_type->tag == SymTagFunctionType);
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag  = SymTagFunction;
+        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->type      = sig_type;
+        sym->size      = size;
+        vector_init(&sym->vlines,  sizeof(struct line_info), 64);
+        vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+        if (compiland)
+        {
+            p = vector_add(&compiland->vchildren, &module->pool);
+            *p = &sym->symt;
+        }
+    }
+    return sym;
+}
+
+void symt_add_func_line(struct module* module, struct symt_function* func,
+                        unsigned source_idx, int line_num, unsigned long offset)
+{
+    struct line_info*   dli;
+    BOOL                last_matches = FALSE;
+
+    if (func == NULL || !(dbghelp_options & SYMOPT_LOAD_LINES)) return;
+
+    TRACE_(dbghelp_symt)("(%p)%s:%lx %s:%u\n", 
+                         func, func->hash_elt.name, offset, 
+                         source_get(module, source_idx), line_num);
+
+    assert(func->symt.tag == SymTagFunction);
+
+    dli = NULL;
+    while ((dli = vector_iter_down(&func->vlines, dli)))
+    {
+        if (dli->is_source_file)
+        {
+            last_matches = (source_idx == dli->u.source_file);
+            break;
+        }
+    }
+
+    if (!last_matches)
+    {
+        /* we shouldn't have line changes on first line of function */
+        dli = vector_add(&func->vlines, &module->pool);
+        dli->is_source_file = 1;
+        dli->is_first       = dli->is_last = 0;
+        dli->line_number    = 0;
+        dli->u.source_file  = source_idx;
+    }
+    dli = vector_add(&func->vlines, &module->pool);
+    dli->is_source_file = 0;
+    dli->is_first       = dli->is_last = 0;
+    dli->line_number    = line_num;
+    dli->u.pc_offset    = func->address + offset;
+}
+
+struct symt_data* symt_add_func_local(struct module* module, 
+                                      struct symt_function* func, 
+                                      int regno, int offset, 
+                                      struct symt_block* block, 
+                                      struct symt* type, const char* name)
+{
+    struct symt_data*   locsym;
+    struct symt**       p;
+
+    assert(func);
+    assert(func->symt.tag == SymTagFunction);
+
+    TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %p\n", 
+                         module->module.ModuleName, func->hash_elt.name, 
+                         name, type);
+    locsym = pool_alloc(&module->pool, sizeof(*locsym));
+    locsym->symt.tag      = SymTagData;
+    locsym->hash_elt.name = pool_strdup(&module->pool, name);
+    locsym->hash_elt.next = NULL;
+    locsym->kind          = (offset < 0) ? DataIsParam : DataIsLocal;
+    locsym->container     = &block->symt;
+    locsym->type          = type;
+    if (regno)
+    {
+        locsym->u.s.reg_id = regno;
+        locsym->u.s.offset = 0;
+        locsym->u.s.length = 0;
+    }
+    else
+    {
+        locsym->u.s.reg_id = 0;
+        locsym->u.s.offset = offset * 8;
+        locsym->u.s.length = 0;
+    }
+    if (block)
+        p = vector_add(&block->vchildren, &module->pool);
+    else
+        p = vector_add(&func->vchildren, &module->pool);
+    *p = &locsym->symt;
+    return locsym;
+}
+
+struct symt_block* symt_open_func_block(struct module* module, 
+                                        struct symt_function* func,
+                                        struct symt_block* parent_block, 
+                                        unsigned pc, unsigned len)
+{
+    struct symt_block*  block;
+    struct symt**       p;
+
+    assert(func);
+    assert(func->symt.tag == SymTagFunction);
+
+    assert(!parent_block || parent_block->symt.tag == SymTagBlock);
+    block = pool_alloc(&module->pool, sizeof(*block));
+    block->symt.tag = SymTagBlock;
+    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);
+    if (parent_block)
+        p = vector_add(&parent_block->vchildren, &module->pool);
+    else
+        p = vector_add(&func->vchildren, &module->pool);
+    *p = &block->symt;
+
+    return block;
+}
+
+struct symt_block* symt_close_func_block(struct module* module, 
+                                         struct symt_function* func,
+                                         struct symt_block* block, unsigned pc)
+{
+    assert(func->symt.tag == SymTagFunction);
+
+    if (pc) block->size = func->address + pc - block->address;
+    return (block->container->tag == SymTagBlock) ? 
+        GET_ENTRY(block->container, struct symt_block, symt) : NULL;
+}
+
+struct symt_function_point* symt_add_function_point(struct module* module, 
+                                                    struct symt_function* func,
+                                                    enum SymTagEnum point, 
+                                                    unsigned offset, const char* name)
+{
+    struct symt_function_point* sym;
+    struct symt**               p;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = point;
+        sym->parent   = func;
+        sym->offset   = offset;
+        sym->name     = name ? pool_strdup(&module->pool, name) : NULL;
+        p = vector_add(&func->vchildren, &module->pool);
+        *p = &sym->symt;
+    }
+    return sym;
+}
+
+BOOL symt_normalize_function(struct module* module, struct symt_function* func)
+{
+    unsigned            len;
+    struct line_info*   dli;
+
+    assert(func);
+    /* We aren't adding any more locals or line numbers to this function.
+     * Free any spare memory that we might have allocated.
+     */
+    assert(func->symt.tag == SymTagFunction);
+
+/* EPP     vector_pool_normalize(&func->vlines,    &module->pool); */
+/* EPP     vector_pool_normalize(&func->vchildren, &module->pool); */
+
+    len = vector_length(&func->vlines);
+    if (len--)
+    {
+        dli = vector_at(&func->vlines,   0);  dli->is_first = 1;
+        dli = vector_at(&func->vlines, len);  dli->is_last  = 1;
+    }
+    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)
+{
+    const char* name;
+
+    sym_info->TypeIndex = (DWORD)sym;
+    sym_info->info = 0; /* TBD */
+    symt_get_info(sym, TI_GET_LENGTH, &sym_info->Size);
+    sym_info->ModBase = module->module.BaseOfImage;
+    sym_info->Flags = 0;
+    switch (sym->tag)
+    {
+    case SymTagData:
+        {
+            const struct symt_data*  data = (const struct symt_data*)sym;
+            switch (data->kind)
+            {
+            case DataIsLocal:
+            case DataIsParam:
+                if (data->u.s.reg_id)
+                {
+                    sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_REGISTER;
+                    sym_info->Register = data->u.s.reg_id;
+                    sym_info->Address = 0;
+                }
+                else
+                {
+                    if (data->u.s.offset < 0)
+                        sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_FRAMEREL;
+                    else
+                        sym_info->Flags |= SYMFLAG_PARAMETER | SYMFLAG_FRAMEREL;
+                    /* FIXME: needed ? moreover, it's i386 dependent !!! */
+                    sym_info->Register = CV_REG_EBP;
+                    sym_info->Address = data->u.s.offset;
+                }
+                break;
+            case DataIsGlobal:
+            case DataIsFileStatic:
+                symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+                sym_info->Register = 0;
+                break;
+            case DataIsConstant:
+                sym_info->Flags |= SYMFLAG_VALUEPRESENT;
+                switch (data->u.value.n1.n2.vt)
+                {
+                case VT_I4:  sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
+                case VT_I2:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
+                case VT_I1:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
+                case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
+                case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
+                case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
+                default:        
+                    FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
+                }
+                break;
+            default:
+                FIXME("Unhandled kind (%u) in sym data\n", data->kind);
+            }
+        }
+        break;
+    case SymTagPublicSymbol:
+        sym_info->Flags |= SYMFLAG_EXPORT;
+        symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+        break;
+    case SymTagFunction:
+        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;
+        break;
+    }
+    sym_info->Scope = 0; /* FIXME */
+    sym_info->Tag = sym->tag;
+    name = symt_get_name(sym);
+    if (sym_info->MaxNameLen)
+    {
+        if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) ||
+            (sym_info->NameLen = UnDecorateSymbolName(sym_info->Name, sym_info->Name, 
+                                                      sym_info->MaxNameLen, UNDNAME_COMPLETE) == 0))
+        {
+            sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1);
+            strncpy(sym_info->Name, name, sym_info->NameLen);
+            sym_info->Name[sym_info->NameLen] = '\0';
+        }
+    }
+    TRACE_(dbghelp_symt)("%p => %s %lu %s\n",
+                         sym, sym_info->Name, sym_info->Size,
+                         wine_dbgstr_longlong(sym_info->Address));
+}
+
+static BOOL symt_enum_module(struct module* module, regex_t* regex,
+                             PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user)
+{
+    char                        buffer[sizeof(SYMBOL_INFO) + 256];
+    SYMBOL_INFO*                sym_info = (SYMBOL_INFO*)buffer;
+    void*                       ptr;
+    struct symt_ht*             sym = NULL;
+    struct hash_table_iter      hti;
+
+    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);
+        if (sym->hash_elt.name &&
+            regexec(regex, sym->hash_elt.name, 0, NULL, 0) == 0)
+        {
+            sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
+            sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
+            symt_fill_sym_info(module, &sym->symt, sym_info);
+            if (!cb(sym_info, sym_info->Size, user)) return TRUE;
+        }
+    }   
+    return FALSE;
+}
+
+/***********************************************************************
+ *              resort_symbols
+ *
+ * Rebuild sorted list of symbols for a module.
+ */
+static BOOL resort_symbols(struct module* module)
+{
+    int		                nsym = 0;
+    void*                       ptr;
+    struct symt_ht*             sym;
+    struct hash_table_iter      hti;
+
+    hash_table_iter_init(&module->ht_symbols, &hti, NULL);
+    while ((ptr = hash_table_iter_up(&hti)))
+        nsym++;
+
+    if (!(module->module.NumSyms = nsym)) return FALSE;
+    
+    if (module->addr_sorttab)
+        module->addr_sorttab = HeapReAlloc(GetProcessHeap(), 0,
+                                           module->addr_sorttab, 
+                                           nsym * sizeof(struct symt_ht*));
+    else
+        module->addr_sorttab = HeapAlloc(GetProcessHeap(), 0,
+                                         nsym * sizeof(struct symt_ht*));
+    if (!module->addr_sorttab) return FALSE;
+
+    nsym = 0;
+    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);
+        assert(sym);
+        module->addr_sorttab[nsym++] = sym;
+    }
+    
+    qsort(module->addr_sorttab, nsym, sizeof(struct symt_ht*), symt_cmp_addr);
+    return module->sortlist_valid = TRUE;
+}
+
+/* assume addr is in module */
+int symt_find_nearest(struct module* module, DWORD addr)
+{
+    int         mid, high, low;
+    ULONG64     ref_addr;
+    DWORD       ref_size;
+
+    if (!module->sortlist_valid || !module->addr_sorttab)
+    {
+        if (!resort_symbols(module)) return -1;
+    }
+
+    /*
+     * Binary search to find closest symbol.
+     */
+    low = 0;
+    high = module->module.NumSyms;
+
+    symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
+    if (addr < ref_addr) return -1;
+    if (high)
+    {
+        symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
+        if (!symt_get_info(&module->addr_sorttab[high - 1]->symt,  TI_GET_LENGTH, &ref_size) || !ref_size)
+            ref_size = 0x1000; /* arbitrary value */
+        if (addr >= ref_addr + ref_size) return -1;
+    }
+    
+    while (high > low + 1)
+    {
+        mid = (high + low) / 2;
+        if (cmp_sorttab_addr(module, mid, addr) < 0)
+            low = mid;
+        else
+            high = mid;
+    }
+    if (low != high && high != module->module.NumSyms && 
+        cmp_sorttab_addr(module, high, addr) <= 0)
+        low = high;
+
+    /* If found symbol is a public symbol, check if there are any other entries that
+     * might also have the same address, but would get better information
+     */
+    if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
+    {   
+        symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
+        if (low > 0 &&
+            module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
+            !cmp_sorttab_addr(module, low - 1, ref_addr))
+            low--;
+        else if (low < module->module.NumSyms - 1 && 
+                 module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol &&
+                 !cmp_sorttab_addr(module, low + 1, ref_addr))
+            low++;
+    }
+    /* finally check that we fit into the found symbol */
+    symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
+    if (addr < ref_addr) return -1;
+    if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
+        ref_size = 0x1000; /* arbitrary value */
+    if (addr >= ref_addr + ref_size) return -1;
+
+    return low;
+}
+
+static BOOL symt_enum_locals_helper(struct process* pcs, struct module* module,
+                                    regex_t* preg, PSYM_ENUMERATESYMBOLS_CALLBACK cb,
+                                    PVOID user, SYMBOL_INFO* sym_info,
+                                    struct vector* v)
+{
+    struct symt**       plsym = NULL;
+    struct symt*        lsym = NULL;
+    DWORD               pc = pcs->ctx_frame.InstructionOffset;
+
+    while ((plsym = vector_iter_up(v, plsym)))
+    {
+        lsym = *plsym;
+        switch (lsym->tag)
+        {
+        case SymTagBlock:
+            {
+                struct symt_block*  block = (struct symt_block*)lsym;
+                if (pc < block->address || block->address + block->size <= pc)
+                    continue;
+                if (!symt_enum_locals_helper(pcs, module, preg, cb, user, 
+                                             sym_info, &block->vchildren))
+                    return FALSE;
+            }
+            break;
+        case SymTagData:
+            if (regexec(preg, symt_get_name(lsym), 0, NULL, 0) == 0)
+            {
+                symt_fill_sym_info(module, lsym, sym_info);
+                if (!cb(sym_info, sym_info->Size, user))
+                    return FALSE;
+            }
+            break;
+        case SymTagLabel:
+        case SymTagFuncDebugStart:
+        case SymTagFuncDebugEnd:
+            break;
+        default:
+            FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
+            assert(0);
+        }
+    }
+    return TRUE;
+}
+
+static BOOL symt_enum_locals(struct process* pcs, const char* mask,
+                             PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
+                             PVOID UserContext)
+{
+    struct module*      module;
+    struct symt_ht*     sym;
+    char                buffer[sizeof(SYMBOL_INFO) + 256];
+    SYMBOL_INFO*        sym_info = (SYMBOL_INFO*)buffer;
+    DWORD               pc = pcs->ctx_frame.InstructionOffset;
+    int                 idx;
+
+    sym_info->SizeOfStruct = sizeof(*sym_info);
+    sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
+
+    module = module_find_by_addr(pcs, pc, DMT_UNKNOWN);
+    if (!(module = module_get_debug(pcs, module))) return FALSE;
+    if ((idx = symt_find_nearest(module, pc)) == -1) return FALSE;
+
+    sym = module->addr_sorttab[idx];
+    if (sym->symt.tag == SymTagFunction)
+    {
+        BOOL            ret;
+        regex_t         preg;
+
+        compile_regex(mask ? mask : "*", -1, &preg);
+        ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback, 
+                                      UserContext, sym_info, 
+                                      &((struct symt_function*)sym)->vchildren);
+        regfree(&preg);
+        return ret;
+        
+    }
+    symt_fill_sym_info(module, &sym->symt, sym_info);
+    return EnumSymbolsCallback(sym_info, sym_info->Size, UserContext);
+}
+
+/******************************************************************
+ *		SymEnumSymbols (DBGHELP.@)
+ *
+ * cases BaseOfDll = 0
+ *      !foo fails always (despite what MSDN states)
+ *      RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2
+ *      no ! in Mask, lookup in local Context
+ * cases BaseOfDll != 0
+ *      !foo fails always (despite what MSDN states)
+ *      RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is)
+ */
+BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
+                           PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
+                           PVOID UserContext)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+    struct module*      dbg_module;
+    const char*         bang;
+    regex_t             mod_regex, sym_regex;
+
+    TRACE("(%p %s %s %p %p)\n", 
+          hProcess, wine_dbgstr_longlong(BaseOfDll), debugstr_a(Mask),
+          EnumSymbolsCallback, UserContext);
+
+    if (!pcs) return FALSE;
+
+    if (BaseOfDll == 0)
+    {
+        /* do local variables ? */
+        if (!Mask || !(bang = strchr(Mask, '!')))
+            return symt_enum_locals(pcs, Mask, EnumSymbolsCallback, UserContext);
+
+        if (bang == Mask) return FALSE;
+
+        compile_regex(Mask, bang - Mask, &mod_regex);
+        compile_regex(bang + 1, -1, &sym_regex);
+        
+        for (module = pcs->lmodules; module; module = module->next)
+        {
+            if (module->type == DMT_PE && (dbg_module = module_get_debug(pcs, module)))
+            {
+                if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 &&
+                    symt_enum_module(dbg_module, &sym_regex, 
+                                     EnumSymbolsCallback, UserContext))
+                    break;
+            }
+        }
+        /* not found in PE modules, retry on the ELF ones
+         */
+        if (!module && (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES))
+        {
+            for (module = pcs->lmodules; module; module = module->next)
+            {
+                if (module->type == DMT_ELF &&
+                    !module_get_containee(pcs, module) &&
+                    (dbg_module = module_get_debug(pcs, module)))
+                {
+                    if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 &&
+                        symt_enum_module(dbg_module, &sym_regex, EnumSymbolsCallback, UserContext))
+                    break;
+                }
+            }
+        }
+        regfree(&mod_regex);
+        regfree(&sym_regex);
+        return TRUE;
+    }
+    module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
+    if (!(module = module_get_debug(pcs, module)))
+        return FALSE;
+
+    /* we always ignore module name from Mask when BaseOfDll is defined */
+    if (Mask && (bang = strchr(Mask, '!')))
+    {
+        if (bang == Mask) return FALSE;
+        Mask = bang + 1;
+    }
+
+    compile_regex(Mask ? Mask : "*", -1, &sym_regex);
+    symt_enum_module(module, &sym_regex, EnumSymbolsCallback, UserContext);
+    regfree(&sym_regex);
+
+    return TRUE;
+}
+
+struct sym_enumerate
+{
+    void*                       ctx;
+    PSYM_ENUMSYMBOLS_CALLBACK   cb;
+};
+
+static BOOL CALLBACK sym_enumerate_cb(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
+{
+    struct sym_enumerate*       se = (struct sym_enumerate*)ctx;
+    return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
+}
+
+/***********************************************************************
+ *		SymEnumerateSymbols (DBGHELP.@)
+ */
+BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll,
+                                PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, 
+                                PVOID UserContext)
+{
+    struct sym_enumerate        se;
+
+    se.ctx = UserContext;
+    se.cb  = EnumSymbolsCallback;
+    
+    return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb, &se);
+}
+
+/******************************************************************
+ *		SymFromAddr (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, 
+                        DWORD64* Displacement, PSYMBOL_INFO Symbol)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+    struct symt_ht*     sym;
+    int                 idx;
+
+    if (!pcs) return FALSE;
+    module = module_find_by_addr(pcs, Address, DMT_UNKNOWN);
+    if (!(module = module_get_debug(pcs, module))) return FALSE;
+    if ((idx = symt_find_nearest(module, Address)) == -1) return FALSE;
+
+    sym = module->addr_sorttab[idx];
+
+    symt_fill_sym_info(module, &sym->symt, Symbol);
+    if (Displacement) *Displacement = Address - Symbol->Address;
+    return TRUE;
+}
+
+/******************************************************************
+ *		SymGetSymFromAddr (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymGetSymFromAddr(HANDLE hProcess, DWORD Address,
+                              PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol)
+{
+    char        buffer[sizeof(SYMBOL_INFO) + 256];
+    SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
+    size_t      len;
+    DWORD64     Displacement64;
+
+    if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
+    si->SizeOfStruct = sizeof(*si);
+    si->MaxNameLen = 256;
+    if (!SymFromAddr(hProcess, Address, &Displacement64, si))
+        return FALSE;
+
+    if (Displacement)
+        *Displacement = Displacement64;
+    Symbol->Address = si->Address;
+    Symbol->Size    = si->Size;
+    Symbol->Flags   = si->Flags;
+    len = min(Symbol->MaxNameLength, si->MaxNameLen);
+    strncpy(Symbol->Name, si->Name, len);
+    Symbol->Name[len - 1] = '\0';
+    return TRUE;
+}
+
+/******************************************************************
+ *		SymFromName (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol)
+{
+    struct process*             pcs = process_find_by_handle(hProcess);
+    struct module*              module;
+    struct hash_table_iter      hti;
+    void*                       ptr;
+    struct symt_ht*             sym = NULL;
+    const char*                 name;
+
+    TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol);
+    if (!pcs) return FALSE;
+    if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
+    name = strchr(Name, '!');
+    if (name)
+    {
+        char    tmp[128];
+        assert(name - Name < sizeof(tmp));
+        memcpy(tmp, Name, name - Name);
+        tmp[name - Name] = '\0';
+        module = module_find_by_name(pcs, tmp, DMT_UNKNOWN);
+        if (!module) return FALSE;
+        Name = (char*)(name + 1);
+    }
+    else module = pcs->lmodules;
+
+    /* FIXME: Name could be made out of a regular expression */
+    for (; module; module = (name) ? NULL : module->next)
+    {
+        if (module->module.SymType == SymNone) continue;
+        if (module->module.SymType == SymDeferred)
+        {
+            struct module*      xmodule = module_get_debug(pcs, module);
+            if (!xmodule || xmodule != module) continue;
+        }
+        hash_table_iter_init(&module->ht_symbols, &hti, Name);
+        while ((ptr = hash_table_iter_up(&hti)))
+        {
+            sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+
+            if (!strcmp(sym->hash_elt.name, Name))
+            {
+                symt_fill_sym_info(module, &sym->symt, Symbol);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
+/***********************************************************************
+ *		SymGetSymFromName (DBGHELP.@)
+ */
+BOOL WINAPI SymGetSymFromName(HANDLE hProcess, LPSTR Name, PIMAGEHLP_SYMBOL Symbol)
+{
+    char        buffer[sizeof(SYMBOL_INFO) + 256];
+    SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
+    size_t      len;
+
+    if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
+    si->SizeOfStruct = sizeof(*si);
+    si->MaxNameLen = 256;
+    if (!SymFromName(hProcess, Name, si)) return FALSE;
+
+    Symbol->Address = si->Address;
+    Symbol->Size    = si->Size;
+    Symbol->Flags   = si->Flags;
+    len = min(Symbol->MaxNameLength, si->MaxNameLen);
+    strncpy(Symbol->Name, si->Name, len);
+    Symbol->Name[len - 1] = '\0';
[truncated at 1000 lines; 232 more skipped]

reactos/lib/dbghelp
storage.c added at 1.1
diff -N storage.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ storage.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,335 @@
+/*
+ * Various storage structures (pool allocation, vector, hash table)
+ *
+ * Copyright (C) 1993, Eric Youngdale.
+ *               2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+#include <assert.h>
+#include <stdlib.h>
+#include "wine/debug.h"
+
+#include "dbghelp_private.h"
+#ifdef USE_STATS
+#include <math.h>
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+struct pool_arena
+{
+    struct pool_arena*  next;
+    char*               current;
+};
+
+void pool_init(struct pool* a, unsigned arena_size)
+{
+    a->arena_size = arena_size;
+    a->first = NULL;
+}
+
+void pool_destroy(struct pool* pool)
+{
+    struct pool_arena*  arena;
+    struct pool_arena*  next;
+
+#ifdef USE_STATS
+    unsigned    alloc, used, num;
+    
+    for (alloc = used = num = 0, arena = pool->first; arena; arena = arena->next)
+    {
+        alloc += pool->arena_size;
+        used += arena->current - (char*)arena;
+        num++;
+    }
+    FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
+          "\t\t\t\tnon-allocation ratio: %.2f%%\n",
+          pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
+#endif
+
+    for (arena = pool->first; arena; arena = next)
+    {
+        next = arena->next;
+        HeapFree(GetProcessHeap(), 0, arena);
+    }
+    pool_init(pool, 0);
+}
+
+void* pool_alloc(struct pool* pool, unsigned len)
+{
+    struct pool_arena** parena;
+    struct pool_arena*  arena;
+    void*               ret;
+
+    len = (len + 3) & ~3; /* round up size on DWORD boundary */
+    assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
+
+    for (parena = &pool->first; *parena; parena = &(*parena)->next)
+    {
+        if ((char*)(*parena) + pool->arena_size - (*parena)->current >= len)
+        {
+            ret = (*parena)->current;
+            (*parena)->current += len;
+            return ret;
+        }
+    }
+ 
+    arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
+    if (!arena) {FIXME("OOM\n");return NULL;}
+
+    *parena = arena;
+
+    ret = (char*)arena + sizeof(*arena);
+    arena->next = NULL;
+    arena->current = (char*)ret + len;
+    return ret;
+}
+
+static struct pool_arena* pool_is_last(struct pool* pool, void* p, unsigned old_size)
+{
+    struct pool_arena*  arena;
+
+    for (arena = pool->first; arena; arena = arena->next)
+    {
+        if (arena->current == (char*)p + old_size) return arena;
+    }
+    return NULL;
+}
+
+void* pool_realloc(struct pool* pool, void* p, unsigned old_size, unsigned new_size)
+{
+    struct pool_arena*  arena;
+    void*               new;
+
+    if ((arena = pool_is_last(pool, p, old_size)) && 
+        (char*)p + new_size <= (char*)arena + pool->arena_size)
+    {
+        arena->current = (char*)p + new_size;
+        return p;
+    }
+    if ((new = pool_alloc(pool, new_size)) && old_size)
+        memcpy(new, p, min(old_size, new_size));
+    return new;
+}
+
+char* pool_strdup(struct pool* pool, const char* str)
+{
+    char* ret;
+    if ((ret = pool_alloc(pool, strlen(str) + 1))) strcpy(ret, str);
+    return ret;
+}
+
+void vector_init(struct vector* v, unsigned esz, unsigned bucket_sz)
+{
+    v->buckets = NULL;
+    /* align size on DWORD boundaries */
+    v->elt_size = (esz + 3) & ~3;
+    switch (bucket_sz)
+    {
+    case    2: v->shift =  1; break;
+    case    4: v->shift =  2; break;
+    case    8: v->shift =  3; break;
+    case   16: v->shift =  4; break;
+    case   32: v->shift =  5; break;
+    case   64: v->shift =  6; break;
+    case  128: v->shift =  7; break;
+    case  256: v->shift =  8; break;
+    case  512: v->shift =  9; break;
+    case 1024: v->shift = 10; break;
+    default: assert(0);
+    }
+    v->num_buckets = 0;
+    v->num_elts = 0;
+}
+
+unsigned vector_length(const struct vector* v)
+{
+    return v->num_elts;
+}
+
+void* vector_at(const struct vector* v, unsigned pos)
+{
+    unsigned o;
+
+    if (pos >= v->num_elts) return NULL;
+    o = pos & ((1 << v->shift) - 1);
+    return (char*)v->buckets[pos >> v->shift] + o * v->elt_size;
+}
+
+void* vector_add(struct vector* v, struct pool* pool)
+{
+    unsigned    ncurr = v->num_elts++;
+
+    /* check that we don't wrap around */
+    assert(v->num_elts > ncurr);
+    if (ncurr == (v->num_buckets << v->shift))
+    {
+        v->buckets = pool_realloc(pool, v->buckets,
+                                  v->num_buckets * sizeof(void*),
+                                  (v->num_buckets + 1) * sizeof(void*));
+        v->buckets[v->num_buckets] = pool_alloc(pool, v->elt_size << v->shift);
+        return v->buckets[v->num_buckets++];
+    }
+    return vector_at(v, ncurr);
+}
+
+static unsigned vector_position(const struct vector* v, const void* elt)
+{
+    int i;
+
+    for (i = 0; i < v->num_buckets; i++)
+    {
+        if (v->buckets[i] <= elt && 
+            (const char*)elt < (const char*)v->buckets[i] + (v->elt_size << v->shift))
+        {
+            return (i << v->shift) + 
+                ((const char*)elt - (const char*)v->buckets[i]) / v->elt_size;
+        }
+    }
+    assert(0);
+    return 0;
+}
+
+void* vector_iter_up(const struct vector* v, void* elt)
+{
+    unsigned    pos;
+
+    if (!elt) return vector_at(v, 0);
+    pos = vector_position(v, elt) + 1;
+    if (pos >= vector_length(v)) return NULL;
+    return vector_at(v, pos);
+}
+
+void* vector_iter_down(const struct vector* v, void* elt)
+{
+    unsigned    pos;
+    if (!elt) return vector_at(v, vector_length(v) - 1);
+    pos = vector_position(v, elt);
+    if (pos == 0) return NULL;
+    return vector_at(v, pos - 1);
+}
+
+unsigned hash_table_hash(const char* name, unsigned num_buckets)
+{
+    unsigned    hash = 0;
+    while (*name)
+    {
+        hash += *name++;
+        hash += (hash << 10);
+        hash ^= (hash >> 6);
+    }
+    hash += (hash << 3);
+    hash ^= (hash >> 11);
+    hash += (hash << 15);
+    return hash % num_buckets;
+}
+
+void hash_table_init(struct pool* pool, struct hash_table* ht, unsigned num_buckets)
+{
+    ht->buckets = pool_alloc(pool, num_buckets * sizeof(struct hash_table_elt*));
+    assert(ht->buckets);
+    ht->num_buckets = num_buckets;
+    memset(ht->buckets, 0, num_buckets * sizeof(struct hash_table_elt*));
+}
+
+void hash_table_destroy(struct hash_table* ht)
+{
+#if defined(USE_STATS)
+    int                         i;
+    unsigned                    len;
+    unsigned                    num = 0, min = 0xffffffff, max = 0, sq = 0;
+    struct hash_table_elt*      elt;
+    double                      mean, variance;
+
+    for (i = 0; i < ht->num_buckets; i++)
+    {
+        for (len = 0, elt = ht->buckets[i]; elt; elt = elt->next) len++;
+        if (len < min) min = len;
+        if (len > max) max = len;
+        num += len;
+        sq += len * len;
+    }
+    mean = (double)num / ht->num_buckets;
+    variance = (double)sq / ht->num_buckets - mean * mean;
+    FIXME("STATS: elts[num:%-4u size:%u mean:%f] buckets[min:%-4u variance:%+f max:%-4u]\n",
+          num, ht->num_buckets, mean, min, variance, max);
+#if 1
+    for (i = 0; i < ht->num_buckets; i++)
+    {
+        for (len = 0, elt = ht->buckets[i]; elt; elt = elt->next) len++;
+        if (len == max)
+        {
+            FIXME("Longuest bucket:\n");
+            for (elt = ht->buckets[i]; elt; elt = elt->next)
+                FIXME("\t%s\n", elt->name);
+            break;
+        }
+
+    }
+#endif
+#endif
+}
+
+void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt)
+{
+    unsigned                    hash = hash_table_hash(elt->name, ht->num_buckets);
+    struct hash_table_elt**     p;
+
+    /* 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)
+{
+    unsigned                    hash = hash_table_hash(name, ht->num_buckets);
+    struct hash_table_elt*      elt;
+
+    for (elt = ht->buckets[hash]; elt; elt = elt->next)
+        if (!strcmp(name, elt->name)) return elt;
+    return NULL;
+}
+
+void hash_table_iter_init(const struct hash_table* ht, 
+                          struct hash_table_iter* hti, const char* name)
+{
+    hti->ht = ht;
+    if (name)
+    {
+        hti->last = hash_table_hash(name, ht->num_buckets);
+        hti->index = hti->last - 1;
+    }
+    else
+    {
+        hti->last = ht->num_buckets - 1;
+        hti->index = -1;
+    }
+    hti->element = NULL;
+}
+
+void* hash_table_iter_up(struct hash_table_iter* hti)
+{
+    if (hti->element) hti->element = hti->element->next;
+    while (!hti->element && hti->index < hti->last) 
+        hti->element = hti->ht->buckets[++hti->index];
+    return hti->element;
+}

reactos/lib/dbghelp
stack.c added at 1.1
diff -N stack.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ stack.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,388 @@
+/*
+ * Stack walking
+ *
+ * Copyright 1995 Alexandre Julliard
+ * Copyright 1996 Eric Youngdale
+ * Copyright 1999 Ove K�ven
+ * Copyright 2004 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "dbghelp_private.h"
+#include "winreg.h"
+#include "ntstatus.h"
+#include "thread.h" /* FIXME: must be included before winternl.h */
+#include "winternl.h"
+#include "wine/debug.h"
+#include "stackframe.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
+
+static const char* wine_dbgstr_addr(const ADDRESS* addr)
+{
+    if (!addr) return "(null)";
+    switch (addr->Mode)
+    {
+    case AddrModeFlat:
+        return wine_dbg_sprintf("flat<%08lx>", addr->Offset);
+    case AddrMode1616:
+        return wine_dbg_sprintf("1616<%04x:%04lx>", addr->Segment, addr->Offset);
+    case AddrMode1632:
+        return wine_dbg_sprintf("1632<%04x:%08lx>", addr->Segment, addr->Offset);
+    case AddrModeReal:
+        return wine_dbg_sprintf("real<%04x:%04lx>", addr->Segment, addr->Offset);
+    default:
+        return "unknown";
+    }
+}
+
+/* indexes in Reserved array */
+#define __CurrentMode     0
+#define __CurrentSwitch   1
+#define __NextSwitch      2
+
+#define curr_mode   (frame->Reserved[__CurrentMode])
+#define curr_switch (frame->Reserved[__CurrentSwitch])
+#define next_switch (frame->Reserved[__NextSwitch])
+
+/***********************************************************************
+ *		StackWalk (DBGHELP.@)
+ */
+BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
+                      LPSTACKFRAME frame, LPVOID ctx,
+                      PREAD_PROCESS_MEMORY_ROUTINE f_read_mem,
+                      PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+                      PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+                      PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr)
+{
+    STACK32FRAME        frame32;
+    STACK16FRAME        frame16;
+    char                ch;
+    ADDRESS             tmp;
+    DWORD               p;
+    WORD                val;
+    BOOL                do_switch;
+
+    TRACE("(%ld, %p, %p, %p, %p, %p, %p, %p, %p)\n",
+          MachineType, hProcess, hThread, frame, ctx,
+          f_read_mem, FunctionTableAccessRoutine,
+          GetModuleBaseRoutine, f_xlat_adr);
+
+    if (MachineType != IMAGE_FILE_MACHINE_I386)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* sanity check */
+    if (curr_mode >= stm_done) return FALSE;
+
+    if (!f_read_mem) f_read_mem = ReadProcessMemory;
+    if (!f_xlat_adr) f_xlat_adr = addr_to_linear;
+
+    TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08lx nSwitch=%08lx\n",
+          wine_dbgstr_addr(&frame->AddrPC), 
+          wine_dbgstr_addr(&frame->AddrFrame),
+          wine_dbgstr_addr(&frame->AddrReturn),
+          wine_dbgstr_addr(&frame->AddrStack), 
+          curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
+          curr_switch, next_switch);
+
+    if (curr_mode == stm_start)
+    {
+        THREAD_BASIC_INFORMATION info;
+
+        if ((frame->AddrPC.Mode == AddrModeFlat) &&
+            (frame->AddrFrame.Mode != AddrModeFlat))
+        {
+            WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
+            goto done_err;
+        }
+
+        /* Init done */
+        curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? 
+            stm_32bit : stm_16bit;
+
+        /* cur_switch holds address of curr_stack's field in TEB in debuggee
+         * address space
+         */
+        if (NtQueryInformationThread(hThread, ThreadBasicInformation, &info,    
+                                     sizeof(info), NULL) != STATUS_SUCCESS)
+            goto done_err;
+        curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, cur_stack);
+        if (!f_read_mem(hProcess, (void*)curr_switch, &next_switch, 
+                        sizeof(next_switch), NULL))
+        {
+            WARN("Can't read TEB:cur_stack\n");
+            goto done_err;
+        }
+        if (curr_mode == stm_16bit)
+        {
+            if (!f_read_mem(hProcess, (void*)next_switch, &frame32, 
+                            sizeof(frame32), NULL))
+            {
+                WARN("Bad stack frame 0x%08lx\n", next_switch);
+                goto done_err;
+            }
+            curr_switch = (DWORD)frame32.frame16;
+            tmp.Mode    = AddrMode1616;
+            tmp.Segment = SELECTOROF(curr_switch);
+            tmp.Offset  = OFFSETOF(curr_switch);
+            if (!f_read_mem(hProcess, (void*)f_xlat_adr(hProcess, hThread, &tmp),
+                            &ch, sizeof(ch), NULL))
+                curr_switch = 0xFFFFFFFF;
+            frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrMode1616;
+        }
+        else
+        {
+            tmp.Mode    = AddrMode1616;
+            tmp.Segment = SELECTOROF(next_switch);
+            tmp.Offset  = OFFSETOF(next_switch);
+            p = f_xlat_adr(hProcess, hThread, &tmp);
+            if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
+            {
+                WARN("Bad stack frame 0x%08lx\n", p);
+                goto done_err;
+            }
+            curr_switch = (DWORD)frame16.frame32;
+
+            if (!f_read_mem(hProcess, (void*)curr_switch, &ch, sizeof(ch), NULL))
+                curr_switch = 0xFFFFFFFF;
+            frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
+        }
+        /* don't set up AddrStack on first call. Either the caller has set it up, or
+         * we will get it in the next frame
+         */
+    }
+    else
+    {
+        if (frame->AddrFrame.Offset == 0) goto done_err;
+        if (frame->AddrFrame.Mode == AddrModeFlat)
+        {
+            assert(curr_mode == stm_32bit);
+            do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
+        }
+        else
+        {
+            assert(curr_mode == stm_16bit);
+            do_switch = OFFSETOF(curr_switch) && 
+                frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
+                frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
+        }
+	   
+        if (do_switch)
+        {
+            if (curr_mode == stm_16bit)
+            {
+                if (!f_read_mem(hProcess, (void*)next_switch, &frame32, 
+                                sizeof(frame32), NULL))
+                {
+                    WARN("Bad stack frame 0x%08lx\n", next_switch);
+                    goto done_err;
+                }
+
+                frame->AddrPC.Mode        = AddrModeFlat;
+                frame->AddrPC.Segment     = 0;
+                frame->AddrPC.Offset      = frame32.retaddr;
+                frame->AddrFrame.Mode     = AddrModeFlat;
+                frame->AddrFrame.Segment  = 0;
+                frame->AddrFrame.Offset   = frame32.ebp;
+
+                frame->AddrStack.Mode     = AddrModeFlat;
+                frame->AddrStack.Segment  = 0;
+                frame->AddrReturn.Mode    = AddrModeFlat;
+                frame->AddrReturn.Segment = 0;
+
+                next_switch = curr_switch;
+                tmp.Mode    = AddrMode1616;
+                tmp.Segment = SELECTOROF(next_switch);
+                tmp.Offset  = OFFSETOF(next_switch);
+                p = f_xlat_adr(hProcess, hThread, &tmp);
+
+                if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
+                {
+                    WARN("Bad stack frame 0x%08lx\n", p);
+                    goto done_err;
+                }
+                curr_switch = (DWORD)frame16.frame32;
+                curr_mode = stm_32bit;
+                if (!f_read_mem(hProcess, (void*)curr_switch, &ch, sizeof(ch), NULL))
+                    curr_switch = 0xFFFFFFFF;
+            }
+            else
+            {
+                tmp.Mode    = AddrMode1616;
+                tmp.Segment = SELECTOROF(next_switch);
+                tmp.Offset  = OFFSETOF(next_switch);
+                p = f_xlat_adr(hProcess, hThread, &tmp);
+
+                if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
+                {
+                    WARN("Bad stack frame 0x%08lx\n", p);
+                    goto done_err;
+                }
+
+                TRACE("Got a 16 bit stack switch:"
+                      "\n\tframe32: %08lx"
+                      "\n\tedx:%08lx ecx:%08lx ebp:%08lx"
+                      "\n\tds:%04x es:%04x fs:%04x gs:%04x"
+                      "\n\tcall_from_ip:%08lx module_cs:%04lx relay=%08lx"
+                      "\n\tentry_ip:%04x entry_point:%08lx"
+                      "\n\tbp:%04x ip:%04x cs:%04x\n",
+                      (unsigned long)frame16.frame32,
+                      frame16.edx, frame16.ecx, frame16.ebp,
+                      frame16.ds, frame16.es, frame16.fs, frame16.gs,
+                      frame16.callfrom_ip, frame16.module_cs, frame16.relay,
+                      frame16.entry_ip, frame16.entry_point,
+                      frame16.bp, frame16.ip, frame16.cs);
+
+                      
+                frame->AddrPC.Mode       = AddrMode1616;
+                frame->AddrPC.Segment    = frame16.cs;
+                frame->AddrPC.Offset     = frame16.ip;
+
+                frame->AddrFrame.Mode    = AddrMode1616;
+                frame->AddrFrame.Segment = SELECTOROF(next_switch);
+                frame->AddrFrame.Offset  = frame16.bp;
+
+                frame->AddrStack.Mode    = AddrMode1616;
+                frame->AddrStack.Segment = SELECTOROF(next_switch);
+
+                frame->AddrReturn.Mode    = AddrMode1616;
+                frame->AddrReturn.Segment = frame16.cs;
+
+                next_switch = curr_switch;
+                if (!f_read_mem(hProcess, (void*)next_switch, &frame32, sizeof(frame32),
+                                NULL))
+                {
+                    WARN("Bad stack frame 0x%08lx\n", next_switch);
+                    goto done_err;
+                }
+                curr_switch = (DWORD)frame32.frame16;
+                tmp.Mode    = AddrMode1616;
+                tmp.Segment = SELECTOROF(curr_switch);
+                tmp.Offset  = OFFSETOF(curr_switch);
+
+                if (!f_read_mem(hProcess, (void*)f_xlat_adr(hProcess, hThread, &tmp),
+                                &ch, sizeof(ch), NULL))
+                    curr_switch = 0xFFFFFFFF;
+                curr_mode = stm_16bit;
+            }
+        }
+        else
+        {
+            frame->AddrPC = frame->AddrReturn;
+            if (curr_mode == stm_16bit)
+            {
+                frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
+                /* "pop up" previous BP value */
+                if (!f_read_mem(hProcess, 
+                                (void*)f_xlat_adr(hProcess, hThread, &frame->AddrFrame),
+                                &val, sizeof(WORD), NULL))
+                    goto done_err;
+                frame->AddrFrame.Offset = val;
+            }
+            else
+            {
+                frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
+                /* "pop up" previous EBP value */
+                if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset, 
+                                &frame->AddrFrame.Offset, sizeof(DWORD), NULL))
+                    goto done_err;
+            }
+        }
+    }
+
+    if (curr_mode == stm_16bit)
+    {
+        int     i;
+
+        p = f_xlat_adr(hProcess, hThread, &frame->AddrFrame);
+        if (!f_read_mem(hProcess, (void*)(p + sizeof(WORD)), &val, sizeof(WORD), NULL))
+            goto done_err;
+        frame->AddrReturn.Offset = val;
+        /* get potential cs if a far call was used */
+        if (!f_read_mem(hProcess, (void*)(p + 2 * sizeof(WORD)), 
+                        &val, sizeof(WORD), NULL))
+            goto done_err;
+        if (frame->AddrFrame.Offset & 1)
+            frame->AddrReturn.Segment = val; /* far call assumed */
+        else
+        {
+            /* not explicitly marked as far call, 
+             * but check whether it could be anyway
+             */
+            if ((val & 7) == 7 && val != frame->AddrReturn.Segment)
+            {
+                LDT_ENTRY	le;
+
+                if (GetThreadSelectorEntry(hThread, val, &le) &&
+                    (le.HighWord.Bits.Type & 0x08)) /* code segment */
+                {
+                    /* it is very uncommon to push a code segment cs as
+                     * a parameter, so this should work in most cases 
+                     */
+                    frame->AddrReturn.Segment = val;
+                }
+	    }
+	}
+        frame->AddrFrame.Offset &= ~1;
+        /* we "pop" parameters as 16 bit entities... of course, this won't
+         * work if the parameter is in fact bigger than 16bit, but
+         * there's no way to know that here
+         */
+        for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
+        {
+            f_read_mem(hProcess, (void*)(p + (2 + i) * sizeof(WORD)), 
+                       &val, sizeof(val), NULL);
+            frame->Params[i] = val;
+        }
+    }
+    else
+    {
+        if (!f_read_mem(hProcess, 
+                        (void*)(frame->AddrFrame.Offset + sizeof(DWORD)),
+                        &frame->AddrReturn.Offset, sizeof(DWORD), NULL))
+            goto done_err;
+        f_read_mem(hProcess, 
+                   (void*)(frame->AddrFrame.Offset + 2 * sizeof(DWORD)), 
+                   frame->Params, sizeof(frame->Params), NULL);
+    }
+
+    frame->Far = FALSE;
+    frame->Virtual = FALSE;
+
+    TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08lx nSwitch=%08lx\n",
+          wine_dbgstr_addr(&frame->AddrPC), 
+          wine_dbgstr_addr(&frame->AddrFrame),
+          wine_dbgstr_addr(&frame->AddrReturn),
+          wine_dbgstr_addr(&frame->AddrStack), 
+          curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
+          curr_switch, next_switch);
+
+    return TRUE;
+done_err:
+    curr_mode = stm_done;
+    return FALSE;
+}

reactos/lib/dbghelp
stabs.c added at 1.1
diff -N stabs.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ stabs.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,1480 @@
+/*
+ * File stabs.c - read stabs information from the modules
+ *
+ * Copyright (C) 1996,      Eric Youngdale.
+ *		 1999-2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Maintenance Information
+ * -----------------------
+ *
+ * For documentation on the stabs format see for example
+ *   The "stabs" debug format
+ *     by Julia Menapace, Jim Kingdon, David Mackenzie
+ *     of Cygnus Support
+ *     available (hopefully) from http:\\sources.redhat.com\gdb\onlinedocs
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdio.h>
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#include <assert.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winnls.h"
+
+#include "dbghelp_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
+
+#ifndef N_UNDF
+#define N_UNDF		0x00
+#endif
+
+#define N_GSYM		0x20
+#define N_FUN		0x24
+#define N_STSYM		0x26
+#define N_LCSYM		0x28
+#define N_MAIN		0x2a
+#define N_ROSYM		0x2c
+#define N_OPT		0x3c
+#define N_RSYM		0x40
+#define N_SLINE		0x44
+#define N_SO		0x64
+#define N_LSYM		0x80
+#define N_BINCL		0x82
+#define N_SOL		0x84
+#define N_PSYM		0xa0
+#define N_EINCL		0xa2
+#define N_LBRAC		0xc0
+#define N_EXCL		0xc2
+#define N_RBRAC		0xe0
+
+struct stab_nlist
+{
+    union
+    {
+        char*                   n_name;
+        struct stab_nlist*      n_next;
+        long                    n_strx;
+    } n_un;
+    unsigned char       n_type;
+    char                n_other;
+    short               n_desc;
+    unsigned long       n_value;
+};
+
+static void stab_strcpy(char* dest, int sz, const char* source)
+{
+    /*
+     * A strcpy routine that stops when we hit the ':' character.
+     * Faster than copying the whole thing, and then nuking the
+     * ':'.
+     */
+    while (*source != '\0' && *source != ':' && sz-- > 0)
+        *dest++ = *source++;
+    *dest-- = '\0';
+    /* GCC seems to emit, in some cases, a .<digit>+ suffix.
+     * This is used for static variable inside functions, so
+     * that we can have several such variables with same name in
+     * the same compilation unit
+     * We simply ignore that suffix when present (we also get rid
+     * of it in ELF symtab parsing)
+     */
+    if (isdigit(*dest))
+    {
+        while (isdigit(*dest)) dest--;
+        if (*dest == '.') *dest = '\0';
+    }
+        
+    assert(sz > 0);
+}
+
+typedef struct
+{
+   char*		name;
+   unsigned long	value;
+   struct symt**        vector;
+   int			nrofentries;
+} include_def;
+
+#define MAX_INCLUDES	5120
+
+static include_def* 	        include_defs = NULL;
+static int	     	        num_include_def = 0;
+static int		        num_alloc_include_def = 0;
+static int                      cu_include_stack[MAX_INCLUDES];
+static int		        cu_include_stk_idx = 0;
+static struct symt**            cu_vector = NULL;
+static int 		        cu_nrofentries = 0;
+static struct symt_basic*       stabs_basic[36];
+
+static int stabs_new_include(const char* file, unsigned long val)
+{
+    if (num_include_def == num_alloc_include_def)
+    {
+        num_alloc_include_def += 256;
+        if (!include_defs)
+            include_defs = HeapAlloc(GetProcessHeap(), 0, 
+                                     sizeof(include_defs[0]) * num_alloc_include_def);
+        else
+            include_defs = HeapReAlloc(GetProcessHeap(), 0, include_defs,
+                                       sizeof(include_defs[0]) * num_alloc_include_def);
+        memset(include_defs + num_include_def, 0, sizeof(include_defs[0]) * 256);
+    }
+    include_defs[num_include_def].name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(file) + 1), file);
+    include_defs[num_include_def].value = val;
+    include_defs[num_include_def].vector = NULL;
+    include_defs[num_include_def].nrofentries = 0;
+
+    return num_include_def++;
+}
+
+static int stabs_find_include(const char* file, unsigned long val)
+{
+    int		i;
+
+    for (i = 0; i < num_include_def; i++)
+    {
+        if (val == include_defs[i].value &&
+            strcmp(file, include_defs[i].name) == 0)
+            return i;
+    }
+    return -1;
+}
+
+static int stabs_add_include(int idx)
+{
+    if (idx < 0) return -1;
+    cu_include_stk_idx++;
+
+    /* if this happens, just bump MAX_INCLUDES */
+    /* we could also handle this as another dynarray */
+    assert(cu_include_stk_idx < MAX_INCLUDES);
+    cu_include_stack[cu_include_stk_idx] = idx;
+    return cu_include_stk_idx;
+}
+
+static void stabs_reset_includes(void)
+{
+    /*
+     * The struct symt:s that we would need to use are reset when
+     * we start a new file. (at least the ones in filenr == 0)
+     */
+    cu_include_stk_idx = 0;/* keep 0 as index for the .c file itself */
+    memset(cu_vector, 0, sizeof(cu_vector[0]) * cu_nrofentries);
+}
+
+static void stabs_free_includes(void)
+{
+    int i;
+
+    stabs_reset_includes();
+    for (i = 0; i < num_include_def; i++)
+    {
+        HeapFree(GetProcessHeap(), 0, include_defs[i].name);
+        HeapFree(GetProcessHeap(), 0, include_defs[i].vector);
+    }
+    HeapFree(GetProcessHeap(), 0, include_defs);
+    include_defs = NULL;
+    num_include_def = 0;
+    num_alloc_include_def = 0;
+    HeapFree(GetProcessHeap(), 0, cu_vector);
+    cu_vector = NULL;
+    cu_nrofentries = 0;
+}
+
+static struct symt** stabs_find_ref(long filenr, long subnr)
+{
+    struct symt**       ret;
+
+    /* FIXME: I could perhaps create a dummy include_def for each compilation
+     * unit which would allow not to handle those two cases separately
+     */
+    if (filenr == 0)
+    {
+        if (cu_nrofentries <= subnr)
+	{
+            if (!cu_vector)
+                cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                                      sizeof(cu_vector[0]) * (subnr+1));
+            else
+                cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                                        cu_vector, sizeof(cu_vector[0]) * (subnr+1));
+            cu_nrofentries = subnr + 1;
+	}
+        ret = &cu_vector[subnr];
+    }
+    else
+    {
+        include_def*	idef;
+
+        assert(filenr <= cu_include_stk_idx);
+        idef = &include_defs[cu_include_stack[filenr]];
+
+        if (idef->nrofentries <= subnr)
+	{
+            if (!idef->vector)
+                idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                                         sizeof(idef->vector[0]) * (subnr+1));
+            else
+                idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                                           idef->vector, sizeof(idef->vector[0]) * (subnr+1));
+            idef->nrofentries = subnr + 1;
+	}
+        ret = &idef->vector[subnr];
+    }
+    TRACE("(%ld,%ld) => %p (%p)\n", filenr, subnr, ret, *ret);
+    return ret;
+}
+
+static struct symt** stabs_read_type_enum(const char** x)
+{
+    long        filenr, subnr;
+
+    if (**x == '(') 
+    {
+	(*x)++;					/* '('   */
+	filenr = strtol(*x, (char**)x, 10);	/* <int> */
+	(*x)++;					/* ','   */
+	subnr = strtol(*x, (char**)x, 10);	/* <int> */
+	(*x)++;					/* ')'   */
+    }
+    else
+    {
+    	filenr = 0;
+	subnr = strtol(*x, (char**)x, 10);      /* <int> */
+    }
+    return stabs_find_ref(filenr, subnr);
+}
+
+#define PTS_DEBUG
+struct ParseTypedefData
+{
+    const char*		ptr;
+    char		buf[1024];
+    int			idx;
+    struct module*      module;
+#ifdef PTS_DEBUG
+    struct PTS_Error 
+    {
+        const char*         ptr;
+        unsigned            line;
+    } errors[16];
+    int                 err_idx;
+#endif
+};
+
+#ifdef PTS_DEBUG
+static void stabs_pts_push(struct ParseTypedefData* ptd, unsigned line)
+{
+    assert(ptd->err_idx < sizeof(ptd->errors) / sizeof(ptd->errors[0]));
+    ptd->errors[ptd->err_idx].line = line;
+    ptd->errors[ptd->err_idx].ptr = ptd->ptr;
+    ptd->err_idx++;
+}
+#define PTS_ABORTIF(ptd, t) do { if (t) { stabs_pts_push((ptd), __LINE__); return -1;} } while (0)
+#else
+#define PTS_ABORTIF(ptd, t) do { if (t) return -1; } while (0)
+#endif
+
+static int stabs_get_basic(struct ParseTypedefData* ptd, unsigned basic, struct symt** symt)
+{
+    PTS_ABORTIF(ptd, basic >= sizeof(stabs_basic) / sizeof(stabs_basic[0]));
+
+    if (!stabs_basic[basic])
+    {
+        switch (basic)
+        {
+        case  1: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "int", 4); break;
+        case  2: stabs_basic[basic] = symt_new_basic(ptd->module, btChar,    "char", 1); break;
+        case  3: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "short int", 2); break;
+        case  4: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "long int", 4); break;
+        case  5: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned char", 1); break;
+        case  6: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "signed char", 1); break;
+        case  7: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned short int", 2); break;
+        case  8: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned int", 4); break;
+        case  9: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned", 2); break;
+        case 10: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned long int", 2); break;
+        case 11: stabs_basic[basic] = symt_new_basic(ptd->module, btVoid,    "void", 0); break;
+        case 12: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "float", 4); break;
+        case 13: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "double", 8); break;
+        case 14: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "long double", 12); break;
+        case 15: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "integer", 4); break;
+        case 16: stabs_basic[basic] = symt_new_basic(ptd->module, btBool,    "bool", 1); break;
+        /*    case 17: short real */
+        /*    case 18: real */
+        case 25: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "float complex", 8); break;
+        case 26: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "double complex", 16); break;
+        case 30: stabs_basic[basic] = symt_new_basic(ptd->module, btWChar,   "wchar_t", 2); break;
+        case 31: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "long long int", 8); break;
+        case 32: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "long long unsigned", 8); break;
+            /* starting at 35 are wine extensions (especially for R implementation) */
+        case 35: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "long double complex", 24); break;
+        default: PTS_ABORTIF(ptd, 1);
+        }
+    }   
+    *symt = &stabs_basic[basic]->symt;
+    return 0;
+}
+
+static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, 
+                                   const char* typename, struct symt** dt);
+
+static int stabs_pts_read_id(struct ParseTypedefData* ptd)
+{
+    const char*	        first = ptd->ptr;
+    unsigned int	len;
+
+    PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL);
+    len = ptd->ptr - first;
+    PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
+    memcpy(ptd->buf + ptd->idx, first, len);
+    ptd->buf[ptd->idx + len] = '\0';
+    ptd->idx += len + 1;
+    ptd->ptr++; /* ':' */
+    return 0;
+}
+
+static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
+{
+    char*	last;
+
+    *v = strtol(ptd->ptr, &last, 10);
+    PTS_ABORTIF(ptd, last == ptd->ptr);
+    ptd->ptr = last;
+    return 0;
+}
+
+static int stabs_pts_read_type_reference(struct ParseTypedefData* ptd,
+                                         long* filenr, long* subnr)
+{
+    if (*ptd->ptr == '(')
+    {
+	/* '(' <int> ',' <int> ')' */
+	ptd->ptr++;
+	PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, filenr) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+	PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ')');
+    }
+    else
+    {
+    	*filenr = 0;
+	PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
+    }
+    return 0;
+}
+
+struct pts_range_value
+{
+    unsigned long long  val;
+    int                 sign;
+};
+
+static int stabs_pts_read_range_value(struct ParseTypedefData* ptd, struct pts_range_value* prv)
+{
+    char*	last;
+
+    switch (*ptd->ptr)
+    {
+    case '0':
+        while (*ptd->ptr == '0') ptd->ptr++;
+        if (*ptd->ptr >= '1' && *ptd->ptr <= '7')
+        {
+            switch (ptd->ptr[1])
+            {
+            case '0': 
+                PTS_ABORTIF(ptd, ptd->ptr[0] != '1');
+                prv->sign = -1;
+                prv->val = 0;
+                while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
+                break;
+            case '7':
+                prv->sign = 1;
+                prv->val = 0;
+                while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
+                break;
+            default: PTS_ABORTIF(ptd, 1); break;
+            }
+        } else prv->sign = 0;
+        break;
+    case '-':
+        prv->sign = -1;
+        prv->val = strtoull(++ptd->ptr, &last, 10);
+        ptd->ptr = last;
+        break;
+    case '+':
+    default:    
+        prv->sign = 1;
+        prv->val = strtoull(ptd->ptr, &last, 10);
+        ptd->ptr = last;
+        break;
+    }
+    return 0;
+}
+
+static int stabs_pts_read_range(struct ParseTypedefData* ptd, const char* typename,
+                                struct symt** dt)
+{
+    struct symt*                ref;
+    struct pts_range_value      lo;
+    struct pts_range_value      hi;
+    unsigned                    size;
+    enum BasicType              bt;
+    int                         i;
+    unsigned long long          v;
+
+    /* type ';' <int> ';' <int> ';' */
+    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &lo) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &hi) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+
+    /* basically, we don't use ref... in some cases, for example, float is declared
+     * as a derivated type of int... which won't help us... so we guess the types
+     * from the various formats
+     */
+    if (lo.sign == 0 && hi.sign < 0)
+    {
+        bt = btUInt;
+        size = hi.val;
+    }
+    else if (lo.sign < 0 && hi.sign == 0)
+    {
+        bt = btUInt;
+        size = lo.val;
+    }
+    else if (lo.sign > 0 && hi.sign == 0)
+    {
+        bt = btFloat;
+        size = lo.val;
+    }
+    else if (lo.sign < 0 && hi.sign > 0)
+    {
+        v = 1 << 7;
+        for (i = 7; i < 64; i += 8)
+        {
+            if (lo.val == v && hi.val == v - 1)
+            {
+                bt = btInt;
+                size = (i + 1) / 8;
+                break;
+            }
+            v <<= 8;
+        }
+        PTS_ABORTIF(ptd, i >= 64);
+    }
+    else if (lo.sign == 0 && hi.sign > 0)
+    {
+        if (hi.val == 127) /* specific case for char... */
+        {
+            bt = btChar;
+            size = 1;
+        }
+        else
+        {
+            v = 1;
+            for (i = 8; i <= 64; i += 8)
+            {
+                v <<= 8;
+                if (hi.val + 1 == v)
+                {
+                    bt = btUInt;
+                    size = (i + 1) / 8;
+                    break;
+                }
+            }
+            PTS_ABORTIF(ptd, i > 64);
+        }
+    }
+    else PTS_ABORTIF(ptd, 1);
+
+    *dt = &symt_new_basic(ptd->module, bt, typename, size)->symt;
+    return 0;
+}
+
+static inline int stabs_pts_read_method_info(struct ParseTypedefData* ptd)
+{
+    struct symt*        dt;
+    char*               tmp;
+    char                mthd;
+
+    do
+    {
+        /* get type of return value */
+        PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+        if (*ptd->ptr == ';') ptd->ptr++;
+
+        /* get types of parameters */
+        if (*ptd->ptr == ':')
+        {
+            PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr + 1, ';')));
+            ptd->ptr = tmp + 1;
+        }
+        PTS_ABORTIF(ptd, !(*ptd->ptr >= '0' && *ptd->ptr <= '9'));
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, !(ptd->ptr[0] >= 'A' && *ptd->ptr <= 'D'));
+        mthd = *++ptd->ptr;
+        PTS_ABORTIF(ptd, mthd != '.' && mthd != '?' && mthd != '*');
+        ptd->ptr++;
+        if (mthd == '*')
+        {
+            long int            ofs;
+            struct symt*        dt;
+
+            PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+            PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+        }
+    } while (*ptd->ptr != ';');
+    ptd->ptr++;
+
+    return 0;
+}
+
+static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd, 
+                                           struct symt_udt* sdt)
+{
+    long        	sz, ofs;
+    struct symt*        adt;
+    struct symt*        dt = NULL;
+    int			idx;
+    int			doadd;
+
+    PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
+
+    doadd = symt_set_udt_size(ptd->module, sdt, sz);
+    if (*ptd->ptr == '!') /* C++ inheritence */
+    {
+        long     num_classes;
+
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &num_classes) == -1);
+        PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+        while (--num_classes >= 0)
+        {
+            ptd->ptr += 2; /* skip visibility and inheritence */
+            PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+
+            PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
+
+            if (doadd)
+            {
+                char    tmp[256];
+                WCHAR*  name;
+                DWORD   size;
+
+                symt_get_info(adt, TI_GET_SYMNAME, &name);
+                strcmp(tmp, "__inherited_class_");
+                WideCharToMultiByte(CP_ACP, 0, name, -1, 
+                                    tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
+                                    NULL, NULL);
+                HeapFree(GetProcessHeap(), 0, name);
+                /* FIXME: TI_GET_LENGTH will not always work, especially when adt
+                 * has just been seen as a forward definition and not the real stuff
+                 * yet.
+                 * As we don't use much the size of members in structs, this may not
+                 * be much of a problem
+                 */
+                symt_get_info(adt, TI_GET_LENGTH, &size);
+                symt_add_udt_element(ptd->module, sdt, tmp, adt, ofs, size * 8);
+            }
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+        }
+        
+    }
+    /* if the structure has already been filled, just redo the parsing
+     * but don't store results into the struct
+     * FIXME: there's a quite ugly memory leak in there...
+     */
+
+    /* Now parse the individual elements of the structure/union. */
+    while (*ptd->ptr != ';') 
+    {
+	/* agg_name : type ',' <int:offset> ',' <int:size> */
+	idx = ptd->idx;
+
+        if (ptd->ptr[0] == '$' && ptd->ptr[1] == 'v')
+        {
+            long        x;
+
+            if (ptd->ptr[2] == 'f')
+            {
+                /* C++ virtual method table */
+                ptd->ptr += 3;
+                stabs_read_type_enum(&ptd->ptr);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+                ptd->idx = idx;
+                continue;
+            }
+            else if (ptd->ptr[2] == 'b')
+            {
+                ptd->ptr += 3;
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+                ptd->idx = idx;
+                continue;
+            }
+        }
+
+	PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
+        /* Ref. TSDF R2.130 Section 7.4.  When the field name is a method name
+         * it is followed by two colons rather than one.
+         */
+        if (*ptd->ptr == ':')
+        {
+            ptd->ptr++; 
+            stabs_pts_read_method_info(ptd);
+            ptd->idx = idx;
+            continue;
+        }
+        else
+        {
+            /* skip C++ member protection /0 /1 or /2 */
+            if (*ptd->ptr == '/') ptd->ptr += 2;
+        }
+	PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
+
+        switch (*ptd->ptr++)
+        {
+        case ',':
+            PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+            PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+
+            if (doadd) symt_add_udt_element(ptd->module, sdt, ptd->buf + idx, adt, ofs, sz);
+            break;
+        case ':':
+            {
+                char* tmp;
+                /* method parameters... terminated by ';' */
+                PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr, ';')));
+                ptd->ptr = tmp + 1;
+            }
+            break;
+        default:
+            PTS_ABORTIF(ptd, TRUE);
+        }
+	ptd->idx = idx;
+    }
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+    if (*ptd->ptr == '~')
+    {
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, *ptd->ptr++ != '%');
+        PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
+        PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+    }
+    return 0;
+}
+
+static inline int stabs_pts_read_enum(struct ParseTypedefData* ptd, 
+                                      struct symt_enum* edt)
+{
+    long        value;
+    int		idx;
+
+    while (*ptd->ptr != ';')
+    {
+	idx = ptd->idx;
+	PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
+	PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &value) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+	symt_add_enum_element(ptd->module, edt, ptd->buf + idx, value);
+	ptd->idx = idx;
+    }
+    ptd->ptr++;
+    return 0;
+}
+
+static inline int stabs_pts_read_array(struct ParseTypedefData* ptd,
+                                       struct symt** adt)
+{
+    long                lo, hi;
+    struct symt*        rdt;
+
+    /* ar<typeinfo_nodef>;<int>;<int>;<typeinfo> */
+
+    PTS_ABORTIF(ptd, *ptd->ptr++ != 'r');
+    /* FIXME: range type is lost, always assume int */
+    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &rdt) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &lo) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &hi) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+
+    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &rdt) == -1);
+
+    *adt = &symt_new_array(ptd->module, lo, hi, rdt)->symt;
+    return 0;
+}
+
+static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typename,
+                                   struct symt** ret_dt)
+{
+    int			idx;
+    long                sz = -1;
+    struct symt*        new_dt = NULL; /* newly created data type */
+    struct symt*        ref_dt;		   /* referenced data type (pointer...) */
+    long		filenr1, subnr1, tmp;
+
+    /* things are a bit complicated because of the way the typedefs are stored inside
+     * the file, because addresses can change when realloc is done, so we must call
+     * over and over stabs_find_ref() to keep the correct values around
+     */
+    PTS_ABORTIF(ptd, stabs_pts_read_type_reference(ptd, &filenr1, &subnr1) == -1);
+
+    while (*ptd->ptr == '=')
+    {
+	ptd->ptr++;
+	PTS_ABORTIF(ptd, new_dt != btNoType);
+
+	/* first handle attribute if any */
+	switch (*ptd->ptr)      
+        {
+	case '@':
+	    if (*++ptd->ptr == 's')
+            {
+		ptd->ptr++;
+		if (stabs_pts_read_number(ptd, &sz) == -1)
+                {
+		    ERR("Not an attribute... NIY\n");
+		    ptd->ptr -= 2;
+		    return -1;
+		}
+		PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+	    }
+	    break;
+	}
+	/* then the real definitions */
+	switch (*ptd->ptr++)
+        {
+	case '*':
+        case '&':
+	    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
+	    new_dt = &symt_new_pointer(ptd->module, ref_dt)->symt;
+           break;
+        case 'k': /* 'const' modifier */
+        case 'B': /* 'volatile' modifier */
+            /* just kinda ignore the modifier, I guess -gmt */
+            PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, typename, &new_dt) == -1);
+	    break;
+	case '(':
+	    ptd->ptr--;
+            PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, typename, &new_dt) == -1);
+	    break;
+	case 'a':
+	    PTS_ABORTIF(ptd, stabs_pts_read_array(ptd, &new_dt) == -1);
+	    break;
+	case 'r':
+	    PTS_ABORTIF(ptd, stabs_pts_read_range(ptd, typename, &new_dt) == -1);
+	    assert(!*stabs_find_ref(filenr1, subnr1));
+	    *stabs_find_ref(filenr1, subnr1) = new_dt;
+	    break;
+	case 'f':
+	    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
+	    new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
+	    break;
+	case 'e':
+	    new_dt = &symt_new_enum(ptd->module, typename)->symt;
+	    PTS_ABORTIF(ptd, stabs_pts_read_enum(ptd, (struct symt_enum*)new_dt) == -1);
+	    break;
+	case 's':
+	case 'u':
+            {
+                struct symt_udt*    udt;
+                enum UdtKind kind = (ptd->ptr[-1] == 's') ? UdtStruct : UdtUnion;
+                /* udt can have been already defined in a forward definition */
+                udt = (struct symt_udt*)*stabs_find_ref(filenr1, subnr1);
+                if (!udt)
+                {
+                    udt = symt_new_udt(ptd->module, typename, 0, kind);
+                    /* we need to set it here, because a struct can hold a pointer
+                     * to itself
+                     */
+                    new_dt = *stabs_find_ref(filenr1, subnr1) = &udt->symt;
+                }
+                else
+                {
+                    if (udt->symt.tag != SymTagUDT)
+                    {
+                        ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n",
+                            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;
+                }
+                PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1);
+	    }
+	    break;
+	case 'x':
+	    idx = ptd->idx;
+            tmp = *ptd->ptr++;
+	    PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
+	    switch (tmp)
+            {
+	    case 'e':
+                new_dt = &symt_new_enum(ptd->module, ptd->buf + idx)->symt;
+                break;
+	    case 's':
+                new_dt = &symt_new_udt(ptd->module, ptd->buf + idx, 0, UdtStruct)->symt;
+	        break;
+            case 'u':
+                new_dt = &symt_new_udt(ptd->module, ptd->buf + idx, 0, UdtUnion)->symt;
+	        break;
+	    default:
+                return -1;
+	    }
+	    ptd->idx = idx;
+	    break;
+	case '-':
+            {
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &tmp) == -1);
+                PTS_ABORTIF(ptd, stabs_get_basic(ptd, tmp, &new_dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+            }
+	    break;
+        case '#':
+            if (*ptd->ptr == '#')
+            {
+                ptd->ptr++;
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
+                new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
+            }
+            else
+            {
+                struct symt*    cls_dt;
+                struct symt*    pmt_dt;
+
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &cls_dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
+                new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
+                while (*ptd->ptr == ',')
+                {
+                    ptd->ptr++;
+                    PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &pmt_dt) == -1);
+                }
+            }
+            break;
+        case 'R':
+            {
+                long    type, len, unk;
+                int     basic;
+                
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &type) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &len) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+                PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &unk) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+
+                switch (type) /* see stabs_get_basic for the details */
+                {
+                case 1: basic = 12; break;
+                case 2: basic = 13; break;
+                case 3: basic = 25; break;
+                case 4: basic = 26; break;
+                case 5: basic = 35; break;
+                case 6: basic = 14; break;
+                default: PTS_ABORTIF(ptd, 1);
+                }
+                PTS_ABORTIF(ptd, stabs_get_basic(ptd, basic, &new_dt) == -1);
+            }
+            break;
+	default:
+	    ERR("Unknown type '%c'\n", ptd->ptr[-1]);
+	    return -1;
+	}
+    }
+
+    if (!new_dt)
+    {
+        /* is it a forward declaration that has been filled ? */
+	new_dt = *stabs_find_ref(filenr1, subnr1);
+        /* if not, this should be void (which is defined as a ref to itself, but we
+         * don't correctly catch it)
+         */
+        if (!new_dt && typename)
+        {
+            new_dt = &symt_new_basic(ptd->module, btVoid, typename, 0)->symt;
+            PTS_ABORTIF(ptd, strcmp(typename, "void"));
+        }
+    }            
+
+    *stabs_find_ref(filenr1, subnr1) = *ret_dt = new_dt;
+
+    TRACE("Adding (%ld,%ld) %s\n", filenr1, subnr1, typename);
+
+    return 0;
+}
+
+static int stabs_parse_typedef(struct module* module, const char* ptr, 
+                               const char* typename)
+{
+    struct ParseTypedefData	ptd;
+    struct symt*                dt;
+    int				ret = -1;
+
+    /* check for already existing definition */
+
+    TRACE("%s\n", debugstr_a(ptr));
+    ptd.module = module;
+    ptd.idx = 0;
+#ifdef PTS_DEBUG
+    ptd.err_idx = 0;
+#endif
+    for (ptd.ptr = ptr - 1; ;)
+    {
+        ptd.ptr = strchr(ptd.ptr + 1, ':');
+        if (ptd.ptr == NULL || *++ptd.ptr != ':') break;
+    }
+    if (ptd.ptr)
+    {
+	if (*ptd.ptr != '(') ptd.ptr++;
+        /* most of type definitions take one char, except Tt */
+	if (*ptd.ptr != '(') ptd.ptr++;
+	ret = stabs_pts_read_type_def(&ptd, typename, &dt);
+    }
+
+    if (ret == -1 || *ptd.ptr) 
+    {
+#ifdef PTS_DEBUG
+        int     i;
[truncated at 1000 lines; 484 more skipped]

reactos/lib/dbghelp
source.c added at 1.1
diff -N source.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ source.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,138 @@
+/*
+ * File source.c - source files management
+ *
+ * Copyright (C) 2004,      Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "dbghelp_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+/******************************************************************
+ *		source_find
+ *
+ * check whether a source file has already been stored
+ */
+static unsigned source_find(const struct module* module, const char* name)
+{
+    char*       ptr = module->sources;
+
+    while (*ptr)
+    {
+        if (strcmp(ptr, name) == 0) return ptr - module->sources;
+        ptr += strlen(ptr) + 1;
+    }
+    return (unsigned)-1;
+}
+
+/******************************************************************
+ *		source_new
+ *
+ * checks if source exists. if not, add it
+ */
+unsigned source_new(struct module* module, const char* name)
+{
+    int         len;
+    unsigned    ret;
+
+    if (!name) return (unsigned)-1;
+    if (module->sources && (ret = source_find(module, name)) != (unsigned)-1)
+        return ret;
+
+    len = strlen(name) + 1;
+    if (module->sources_used + len + 1 > module->sources_alloc)
+    {
+        /* Alloc by block of 256 bytes */
+        module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
+        if (!module->sources)
+            module->sources = HeapAlloc(GetProcessHeap(), 0, module->sources_alloc);
+        else
+            module->sources = HeapReAlloc(GetProcessHeap(), 0, module->sources,
+                                          module->sources_alloc);
+    }
+    ret = module->sources_used;
+    strcpy(module->sources + module->sources_used, name);
+    module->sources_used += len;
+    module->sources[module->sources_used] = '\0';
+    return ret;
+}
+
+/******************************************************************
+ *		source_get
+ *
+ * returns a stored source file name
+ */
+const char* source_get(const struct module* module, unsigned idx)
+{
+    if (idx == -1) return "";
+    assert(module->sources);
+    return module->sources + idx;
+}
+
+/******************************************************************
+ *		SymEnumSourceFiles (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, LPSTR Mask,
+                               PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,
+                               PVOID UserContext)
+{
+    struct process*     pcs;
+    struct module*      module;
+    SOURCEFILE          sf;
+    char*               ptr;
+    
+    if (!cbSrcFiles) return FALSE;
+    pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE;
+         
+    if (ModBase)
+    {
+        module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
+        if (!(module = module_get_debug(pcs, module))) return FALSE;
+    }
+    else
+    {
+        if (Mask[0] == '!')
+        {
+            module = module_find_by_name(pcs, Mask + 1, DMT_UNKNOWN);
+            if (!(module = module_get_debug(pcs, module))) return FALSE;
+        }
+        else
+        {
+            FIXME("Unsupported yet (should get info from current context)\n");
+            return FALSE;
+        }
+    }
+    if (!module->sources) return FALSE;
+    for (ptr = module->sources; *ptr; ptr += strlen(ptr) + 1)
+    {
+        /* FIXME: not using Mask */
+        sf.ModBase = ModBase;
+        sf.FileName = ptr;
+        if (!cbSrcFiles(&sf, UserContext)) break;
+    }
+
+    return TRUE;
+}

reactos/lib/dbghelp
pe_module.c added at 1.1
diff -N pe_module.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pe_module.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,424 @@
+/*
+ * File pe_module.c - handle PE module information
+ *
+ * Copyright (C) 1996,      Eric Youngdale.
+ * Copyright (C) 1999-2000, Ulrich Weigand.
+ * Copyright (C) 2004,      Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "dbghelp_private.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+/******************************************************************
+ *		pe_load_stabs
+ *
+ * look for stabs information in PE header (it's how the mingw compiler provides 
+ * its debugging information)
+ */
+static BOOL pe_load_stabs(const struct process* pcs, struct module* module, 
+                          const void* mapping, IMAGE_NT_HEADERS* nth)
+{
+    IMAGE_SECTION_HEADER*       section;
+    int                         i, stabsize = 0, stabstrsize = 0;
+    unsigned int                stabs = 0, stabstr = 0;
+    BOOL                        ret = FALSE;
+
+    section = (IMAGE_SECTION_HEADER*)
+        ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
+    for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
+    {
+        if (!strcasecmp(section->Name, ".stab"))
+        {
+            stabs = section->VirtualAddress;
+            stabsize = section->SizeOfRawData;
+        }
+        else if (!strncasecmp(section->Name, ".stabstr", 8))
+        {
+            stabstr = section->VirtualAddress;
+            stabstrsize = section->SizeOfRawData;
+        }
+    }
+
+    if (stabstrsize && stabsize)
+    {
+        ret = stabs_parse(module, 
+                          module->module.BaseOfImage - nth->OptionalHeader.ImageBase, 
+                          RtlImageRvaToVa(nth, (void*)mapping, stabs, NULL),
+                          stabsize,
+                          RtlImageRvaToVa(nth, (void*)mapping, stabstr, NULL),
+                          stabstrsize);
+    }
+    return ret;
+}
+
+static BOOL CALLBACK dbg_match(char* file, void* user)
+{
+    /* accept first file */
+    return FALSE;
+}
+
+/******************************************************************
+ *		pe_load_dbg_file
+ *
+ * loads a .dbg file
+ */
+static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
+                             const char* dbg_name, DWORD timestamp)
+{
+    char                                tmp[MAX_PATH];
+    HANDLE                              hFile = INVALID_HANDLE_VALUE, hMap = 0;
+    const BYTE*                         dbg_mapping = NULL;
+    const IMAGE_SEPARATE_DEBUG_HEADER*  hdr;
+    const IMAGE_DEBUG_DIRECTORY*        dbg;
+    BOOL                                ret = FALSE;
+
+    WINE_TRACE("Processing DBG file %s\n", dbg_name);
+
+    if (SymFindFileInPath(pcs->handle, NULL, (char*)dbg_name, 
+                          NULL, 0, 0, 0,
+                          tmp, dbg_match, NULL) &&
+        (hFile = CreateFileA(tmp, GENERIC_READ, FILE_SHARE_READ, NULL, 
+                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE &&
+        ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
+        ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
+    {
+        hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)dbg_mapping;
+        if (hdr->TimeDateStamp != timestamp)
+        {
+            WINE_ERR("Warning - %s has incorrect internal timestamp\n",
+                     dbg_name);
+            /*
+             * Well, sometimes this happens to DBG files which ARE REALLY the
+             * right .DBG files but nonetheless this check fails. Anyway,
+             * WINDBG (debugger for Windows by Microsoft) loads debug symbols
+             * which have incorrect timestamps.
+             */
+        }
+        if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
+        {
+            /* section headers come immediately after debug header */
+            const IMAGE_SECTION_HEADER *sectp =
+                (const IMAGE_SECTION_HEADER*)(hdr + 1);
+            /* and after that and the exported names comes the debug directory */
+            dbg = (const IMAGE_DEBUG_DIRECTORY*) 
+                (dbg_mapping + sizeof(*hdr) + 
+                 hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
+                 hdr->ExportedNamesSize);
+
+
+            ret = pe_load_debug_directory(pcs, module, dbg_mapping, sectp,
+                                          hdr->NumberOfSections, dbg,
+                                          hdr->DebugDirectorySize / sizeof(*dbg));
+        }
+        else
+            ERR("Wrong signature in .DBG file %s\n", debugstr_a(tmp));
+    }
+    else
+        WINE_ERR("-Unable to peruse .DBG file %s (%s)\n", dbg_name, debugstr_a(tmp));
+
+    if (dbg_mapping) UnmapViewOfFile((void*)dbg_mapping);
+    if (hMap) CloseHandle(hMap);
+    if (hFile != NULL) CloseHandle(hFile);
+    return ret;
+}
+
+/******************************************************************
+ *		pe_load_msc_debug_info
+ *
+ * Process MSC debug information in PE file.
+ */
+static BOOL pe_load_msc_debug_info(const struct process* pcs, 
+                                   struct module* module,
+                                   const void* mapping, IMAGE_NT_HEADERS* nth)
+{
+    BOOL                        ret = FALSE;
+    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 FALSE;
+
+    dbg = RtlImageRvaToVa(nth, (void*)mapping, dir->VirtualAddress, NULL);
+
+    /* Parse debug directory */
+    if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
+    {
+        /* Debug info is stripped to .DBG file */
+        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)
+        {
+            WINE_ERR("-Debug info stripped, but no .DBG file in module %s\n",
+                     module->module.ModuleName);
+        }
+        else
+        {
+            ret = pe_load_dbg_file(pcs, module, misc->Data, nth->FileHeader.TimeDateStamp);
+        }
+    }
+    else
+    {
+        const IMAGE_SECTION_HEADER *sectp = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
+        /* Debug info is embedded into PE module */
+        ret = pe_load_debug_directory(pcs, module, mapping, sectp,
+            nth->FileHeader.NumberOfSections, dbg, nDbg);
+    }
+
+    return ret;
+}
+
+/***********************************************************************
+ *			pe_load_export_debug_info
+ */
+static BOOL pe_load_export_debug_info(const struct process* pcs, 
+                                      struct module* module, 
+                                      const void* mapping, IMAGE_NT_HEADERS* nth)
+{
+    unsigned int 		        i;
+    const IMAGE_EXPORT_DIRECTORY* 	exports;
+    DWORD			        base = module->module.BaseOfImage;
+    DWORD                               size;
+
+    if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
+
+#if 0
+    /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
+    /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
+    symt_new_public(module, NULL, module->module.ModuleName, base, 0,
+                    TRUE /* FIXME */, TRUE /* FIXME */);
+#endif
+    
+    /* Add entry point */
+    symt_new_public(module, NULL, "EntryPoint", 
+                    base + nth->OptionalHeader.AddressOfEntryPoint, 0,
+                    TRUE, TRUE);
+#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++) 
+    {
+	symt_new_public(module, NULL, section->Name, 
+                        RtlImageRvaToVa(nth, (void*)mapping, section->VirtualAddress, NULL), 
+                        0, TRUE /* FIXME */, TRUE /* FIXME */);
+    }
+#endif
+
+    /* Add exported functions */
+    if ((exports = RtlImageDirectoryEntryToData((void*)mapping, FALSE,
+                                                IMAGE_DIRECTORY_ENTRY_EXPORT, &size)))
+    {
+        const WORD*             ordinals = NULL;
+        const DWORD_PTR*	functions = NULL;
+        const DWORD*		names = NULL;
+        unsigned int		j;
+        char			buffer[16];
+
+        functions = RtlImageRvaToVa(nth, (void*)mapping, exports->AddressOfFunctions, NULL);
+        ordinals  = RtlImageRvaToVa(nth, (void*)mapping, exports->AddressOfNameOrdinals, NULL);
+        names     = RtlImageRvaToVa(nth, (void*)mapping, exports->AddressOfNames, NULL);
+
+        for (i = 0; i < exports->NumberOfNames; i++) 
+        {
+            if (!names[i]) continue;
+            symt_new_public(module, NULL, 
+                            RtlImageRvaToVa(nth, (void*)mapping, names[i], NULL),
+                            base + functions[ordinals[i]], 
+                            0, TRUE /* FIXME */, TRUE /* FIXME */);
+        }
+	    
+        for (i = 0; i < exports->NumberOfFunctions; i++) 
+        {
+            if (!functions[i]) continue;
+            /* Check if we already added it with a name */
+            for (j = 0; j < exports->NumberOfNames; j++)
+                if ((ordinals[j] == i) && names[j]) break;
+            if (j < exports->NumberOfNames) continue;
+            snprintf(buffer, sizeof(buffer), "%ld", i + exports->Base);
+            symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
+                            TRUE /* FIXME */, TRUE /* FIXME */);
+        }
+    }
+    /* no real debug info, only entry points */
+    if (module->module.SymType == SymDeferred)
+        module->module.SymType = SymExport;
+    return TRUE;
+}
+
+/******************************************************************
+ *		pe_load_debug_info
+ *
+ */
+BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
+{
+    BOOL                ret = FALSE;
+    HANDLE              hFile;
+    HANDLE              hMap;
+    void*               mapping;
+    IMAGE_NT_HEADERS*   nth;
+
+    hFile = CreateFileA(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ,
+                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hFile == INVALID_HANDLE_VALUE) return ret;
+    if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0)
+    {
+        if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+        {
+            nth = RtlImageNtHeader(mapping);
+
+            if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+            {
+                ret = pe_load_stabs(pcs, module, mapping, nth) ||
+                    pe_load_msc_debug_info(pcs, module, mapping, nth);
+                /* if we still have no debug info (we could only get SymExport at this
+                 * point), then do the SymExport except if we have an ELF container, 
+                 * in which case we'll rely on the export's on the ELF side
+                 */
+            }
+/* FIXME shouldn't we check that? if (!module_get_debug(pcs, module))l */
+            if (pe_load_export_debug_info(pcs, module, mapping, nth) && !ret)
+                ret = TRUE;
+            UnmapViewOfFile(mapping);
+        }
+        CloseHandle(hMap);
+    }
+    CloseHandle(hFile);
+
+    return ret;
+}
+
+/******************************************************************
+ *		pe_load_module
+ *
+ */
+struct module* pe_load_module(struct process* pcs, char* name,
+                              HANDLE hFile, DWORD base, DWORD size)
+{
+    struct module*      module = NULL;
+    BOOL                opened = FALSE;
+    HANDLE              hMap;
+    void*               mapping;
+    char                loaded_name[MAX_PATH];
+
+    loaded_name[0] = '\0';
+    if (!hFile)
+    {
+        if (!name)
+        {
+            /* FIXME SetLastError */
+            return NULL;
+        }
+        if ((hFile = FindExecutableImage(name, NULL, loaded_name)) == NULL)
+            return NULL;
+        opened = TRUE;
+    }
+    else if (name) strcpy(loaded_name, name);
+    else if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
+        FIXME("Trouble ahead (no module name passed in deferred mode)\n");
+    if (!(module = module_find_by_name(pcs, loaded_name, DMT_PE)) &&
+        (hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+    {
+        if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+        {
+            IMAGE_NT_HEADERS*   nth = RtlImageNtHeader(mapping);
+
+            if (nth)
+            {
+                if (!base) base = nth->OptionalHeader.ImageBase;
+                if (!size) size = nth->OptionalHeader.SizeOfImage;
+            
+                module = module_new(pcs, loaded_name, DMT_PE, base, size,
+                                    nth->FileHeader.TimeDateStamp, 
+                                    nth->OptionalHeader.CheckSum);
+                if (module)
+                {
+                    if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
+                        module->module.SymType = SymDeferred;
+                    else
+                        pe_load_debug_info(pcs, module);
+                }
+            }
+            UnmapViewOfFile(mapping);
+        }
+        CloseHandle(hMap);
+    }
+    if (opened) CloseHandle(hFile);
+
+    return module;
+}
+
+/******************************************************************
+ *		pe_load_module_from_pcs
+ *
+ */
+struct module* pe_load_module_from_pcs(struct process* pcs, const char* name, 
+                                       const char* mod_name, DWORD base, DWORD size)
+{
+    struct module*      module;
+    const char*         ptr;
+
+    if ((module = module_find_by_name(pcs, name, DMT_PE))) return module;
+    if (mod_name) ptr = mod_name;
+    else
+    {
+        for (ptr = name + strlen(name) - 1; ptr >= name; ptr--)
+        {
+            if (*ptr == '/' || *ptr == '\\')
+            {
+                ptr++;
+                break;
+            }
+        }
+    }
+    if (ptr && (module = module_find_by_name(pcs, ptr, DMT_PE))) return module;
+    if (base && pcs->dbg_hdr_addr)
+    {
+        IMAGE_DOS_HEADER    dos;
+        IMAGE_NT_HEADERS    nth;
+
+        if (ReadProcessMemory(pcs->handle, (char*)base, &dos, sizeof(dos), NULL) &&
+            dos.e_magic == IMAGE_DOS_SIGNATURE &&
+            ReadProcessMemory(pcs->handle, (char*)(base + dos.e_lfanew), 
+                              &nth, sizeof(nth), NULL) &&
+            nth.Signature == IMAGE_NT_SIGNATURE)
+        {
+            if (!size) size = nth.OptionalHeader.SizeOfImage;
+            module = module_new(pcs, name, DMT_PE, base, size,
+                                nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum);
+        }
+    }
+    return module;
+}

reactos/lib/dbghelp
path.c added at 1.1
diff -N path.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ path.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,272 @@
+/*
+ * File path.c - managing path in debugging environments
+ *
+ * Copyright (C) 2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "dbghelp_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
+
+static inline char* file_name(char* str)
+{
+    char*       p;
+
+    for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
+    return p + 1;
+}
+
+/******************************************************************
+ *		FindDebugInfoFile (DBGHELP.@)
+ *
+ */
+HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePath)
+{
+    HANDLE      h;
+
+    h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (h == INVALID_HANDLE_VALUE)
+    {
+        if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
+            return NULL;
+        h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
+                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    }
+    return (h == INVALID_HANDLE_VALUE) ? NULL : h;
+}
+ 
+/******************************************************************
+ *		FindDebugInfoFileEx (DBGHELP.@)
+ *
+ */
+HANDLE WINAPI FindDebugInfoFileEx(PSTR FileName, PSTR SymbolPath,
+                                  PSTR DebugFilePath, 
+                                  PFIND_DEBUG_FILE_CALLBACK Callback,
+                                  PVOID CallerData)
+{
+    FIXME("(%s %s %p %p %p): stub\n", 
+          FileName, SymbolPath, DebugFilePath, Callback, CallerData);
+    return NULL;
+}
+
+/******************************************************************
+ *		FindExecutableImage (DBGHELP.@)
+ *
+ */
+HANDLE WINAPI FindExecutableImage(PSTR FileName, PSTR SymbolPath, PSTR ImageFilePath)
+{
+    HANDLE h;
+    if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
+        return NULL;
+    h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, 
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    return (h == INVALID_HANDLE_VALUE) ? NULL : h;
+}
+
+/***********************************************************************
+ *           MakeSureDirectoryPathExists (DBGHELP.@)
+ */
+BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
+{
+    char path[MAX_PATH];
+    const char *p = DirPath;
+    int  n;
+
+    if (p[0] && p[1] == ':') p += 2;
+    while (*p == '\\') p++; /* skip drive root */
+    while ((p = strchr(p, '\\')) != NULL)
+    {
+       n = p - DirPath + 1;
+       memcpy(path, DirPath, n);
+       path[n] = '\0';
+       if( !CreateDirectoryA(path, NULL)            &&
+           (GetLastError() != ERROR_ALREADY_EXISTS))
+           return FALSE;
+       p++;
+    }
+    if (GetLastError() == ERROR_ALREADY_EXISTS)
+       SetLastError(ERROR_SUCCESS);
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		SymMatchFileName (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymMatchFileName(char* file, char* match,
+                             char** filestop, char** matchstop)
+{
+    char*       fptr;
+    char*       mptr;
+
+    TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
+
+    fptr = file + strlen(file) - 1;
+    mptr = match + strlen(match) - 1;
+
+    while (fptr >= file && mptr >= match)
+    {
+        if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
+            break;
+        fptr--; mptr--;
+    }
+    if (filestop) *filestop = fptr;
+    if (matchstop) *matchstop = mptr;
+
+    return mptr == match - 1;
+}
+
+static BOOL do_search(const char* file, char* buffer,
+                      PENUMDIRTREE_CALLBACK cb, void* user)
+{
+    HANDLE              h;
+    WIN32_FIND_DATAA    fd;
+    unsigned            pos;
+    BOOL                found = FALSE;
+
+    pos = strlen(buffer);
+    if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
+    strcpy(buffer + pos, "*.*");
+    if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
+        return FALSE;
+    /* doc doesn't specify how the tree is enumerated... 
+     * doing a depth first based on, but may be wrong
+     */
+    do
+    {
+        if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
+
+        strcpy(buffer + pos, fd.cFileName);
+        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+            found = do_search(file, buffer, cb, user);
+        else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
+        {
+            if (!cb || cb(buffer, user)) found = TRUE;
+        }
+    } while (!found && FindNextFileA(h, &fd));
+    if (!found) buffer[--pos] = '\0';
+    FindClose(h);
+
+    return found;
+}
+
+/***********************************************************************
+ *           SearchTreeForFile (DBGHELP.@)
+ */
+BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
+{
+    TRACE("(%s, %s, %p)\n", 
+          debugstr_a(root), debugstr_a(file), buffer);
+    strcpy(buffer, root);
+    return do_search(file, buffer, NULL, NULL);
+}
+
+/******************************************************************
+ *		EnumDirTree (DBGHELP.@)
+ *
+ *
+ */
+BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
+                        LPSTR buffer, PENUMDIRTREE_CALLBACK cb, PVOID user)
+{
+    TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
+
+    strcpy(buffer, root);
+    return do_search(file, buffer, cb, user);
+}
+
+struct sffip
+{
+    PVOID                       id;
+    DWORD                       two;
+    DWORD                       three;
+    DWORD                       flags;
+    PFINDFILEINPATHCALLBACK     cb;
+    void*                       user;
+};
+
+static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
+{
+    struct sffip*       s = (struct sffip*)user;
+
+    /* FIXME: should check that id/two/three match the file pointed
+     * by buffer
+     */
+    /* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
+     * convention to stop/continue enumeration. sigh.
+     */
+    return !(s->cb)((char*)buffer, s->user);
+}
+
+/******************************************************************
+ *		SymFindFileInPath (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
+                              PVOID id, DWORD two, DWORD three, DWORD flags,
+                              LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
+                              PVOID user)
+{
+    struct sffip        s;
+    struct process*     pcs = process_find_by_handle(hProcess);
+    char                tmp[MAX_PATH];
+    char*               ptr;
+
+    TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
+          hProcess, searchPath, file, id, two, three, flags, 
+          buffer, cb, user);
+
+    if (!pcs) return FALSE;
+    if (!searchPath) searchPath = pcs->search_path;
+
+    s.id = id;
+    s.two = two;
+    s.three = three;
+    s.flags = flags;
+    s.cb = cb;
+    s.user = user;
+
+    file = file_name(file);
+
+    while (searchPath)
+    {
+        ptr = strchr(searchPath, ';');
+        if (ptr)
+        {
+            memcpy(tmp, searchPath, ptr - searchPath);
+            tmp[ptr - searchPath] = 0;
+            searchPath = ptr + 1;
+        }
+        else
+        {
+            strcpy(tmp, searchPath);
+            searchPath = NULL;
+        }
+        if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
+    }
+    return FALSE;
+}

reactos/lib/dbghelp
mscvpdb.h added at 1.1
diff -N mscvpdb.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mscvpdb.h	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,1424 @@
+/*
+ * MS debug information definitions.
+ *
+ * Copyright (C) 1996 Eric Youngdale
+ * Copyright (C) 1999-2000 Ulrich Weigand
+ * Copyright (C) 2004 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* MS has stored all its debug information in a set of structures
+ * which has been rather consistent across the years (ie you can grasp
+ * some continuity, and not so many drastic changes).
+ *
+ * A bit of history on the various formats
+ *      MSVC 1.0        PDB v1 (new format for debug info)
+ *      MSVC 2.0        Inclusion in link of debug info (PDB v2)
+ *      MSVC 5.0        Types are 24 bits (instead of 16 for <= 4.x)
+ *      MSVC x.0        PDB (change in internal streams layout)
+ *        
+ *      .DBG            Contains COFF, FPO and Codeview info
+ *      .PDB            New format for debug info (information is
+ *                      derived from Codeview information)
+ *      VCx0.PDB        x major MSVC number, stores types, while
+ *                      <project>.PDB stores symbols.
+ *
+ * Debug information can either be found in the debug section of a PE
+ * module (in something close to a .DBG file), or the debug section
+ * can actually refer to an external file, which can be in turn,
+ * either a .DBG or .PDB file. 
+ *
+ * Regarding PDB files:
+ * -------------------
+ * They are implemented as a set of internal files (as a small file
+ * system). The file is split into blocks, an internal file is made
+ * of a set of blocks. Internal files are accessed through
+ * numbers. For example, 
+ * 1/ is the ROOT (basic information on the file)
+ * 2/ is the Symbol information (global symbols, local variables...)
+ * 3/ is the Type internal file (each the symbols can have type
+ * information associated with it).
+ *
+ * Over the years, three formats existed for the PDB:
+ * - ?? was rather linked to 16 bit code (our support shall be rather
+ *   bad)
+ * - JG: it's the signature embedded in the file header. This format
+ *   has been used in MSVC 2.0 => 5.0.
+ * - DS: it's the signature embedded in the file header. It's the
+ *   current format supported my MS.
+ *
+ * Types internal stream
+ * ---------------------
+ * Types (from the Type internal file) have existed in three flavors
+ * (note that those flavors came as historical evolution, but there
+ * isn't a one to one link between types evolution and PDB formats'
+ * evolutions:
+ * - the first flavor (suffixed by V1 in this file), where the types
+ *   and subtypes are 16 bit entities; and where strings are in Pascal
+ *   format (first char is their length and are not 0 terminated) 
+ * - the second flavor (suffixed by V2) differs from first flavor with
+ *   types and subtypes as 32 bit entities. This forced some
+ *   reordering of fields in some types
+ * - the third flavor (suffixed by V3) differs from second flavor with
+ *   strings stored as C strings (ie are 0 terminated, instead of
+ *   length prefixed)
+ * The different flavors can coexist in the same file (is this really
+ * true ??)
+ * 
+ * For the evolution of types, the need of the second flavor was the
+ * number of types to be defined (limited to 0xFFFF, including the C
+ * basic types); the need of the third flavor is the increase of
+ * symbol size (to be greated than 256), which was likely needed for
+ * complex C++ types (nested + templates).
+ *
+ * It's somehow difficult to represent the layout of those types on
+ * disk because:
+ * - some integral values are stored as numeric leaf, which size is
+ *   variable depending on its value
+ * 
+ * Symbols internal stream
+ * -----------------------
+ * Here also we find three flavors (that we've suffixed with _V1, _V2
+ * and _V3) even if their evolution is closer to the evolution of
+ * types, there are not completly linked together.
+ */
+
+#include "pshpack1.h"
+
+/* ======================================== *
+ *             Type information
+ * ======================================== */
+
+struct p_string
+{
+    unsigned char               namelen;
+    char                        name[1];
+};
+
+union codeview_type
+{
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+    } generic;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               attribute;
+        short int               type;
+    } modifier_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        int                     type;
+        short int               attribute;
+    } modifier_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               attribute;
+        short int               datatype;
+        struct p_string         p_name;
+    } pointer_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned int            datatype;
+        unsigned int            attribute;
+        struct p_string         p_name;
+    } pointer_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned char           nbits;
+        unsigned char           bitoff;
+        unsigned short          type;
+    } bitfield_v1;
+    
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned int            type;
+        unsigned char           nbits;
+        unsigned char           bitoff;
+    } bitfield_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               elemtype;
+        short int               idxtype;
+        unsigned short int      arrlen;     /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } array_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned int            elemtype;
+        unsigned int            idxtype;
+        unsigned short int      arrlen;    /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } array_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned int            elemtype;
+        unsigned int            idxtype;
+        unsigned short int      arrlen;    /* numeric leaf */
+#if 0
+        char                    name[1];
+#endif
+    } array_v3;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               n_element;
+        short int               fieldlist;
+        short int               property;
+        short int               derived;
+        short int               vshape;
+        unsigned short int      structlen;  /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } struct_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               n_element;
+        short int               property;
+        unsigned int            fieldlist;
+        unsigned int            derived;
+        unsigned int            vshape;
+        unsigned short int      structlen;  /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } struct_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               n_element;
+        short int               property;
+        unsigned int            fieldlist;
+        unsigned int            derived;
+        unsigned int            vshape;
+        unsigned short int      structlen;  /* numeric leaf */
+#if 0
+        char                    name[1];
+#endif
+    } struct_v3;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               fieldlist;
+        short int               property;
+        unsigned short int      un_len;     /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } union_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               property;
+        unsigned int            fieldlist;
+        unsigned short int      un_len;     /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } union_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               property;
+        unsigned int            fieldlist;
+        unsigned short int      un_len;     /* numeric leaf */
+#if 0
+        char                    name[1];
+#endif
+    } union_v3;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               type;
+        short int               field;
+        short int               property;
+        struct p_string         p_name;
+    } enumeration_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               property;
+        unsigned int            type;
+        unsigned int            field;
+        struct p_string         p_name;
+    } enumeration_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        short int               count;
+        short int               property;
+        unsigned int            type;
+        unsigned int            field;
+        char                    name[1];
+    } enumeration_v3;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned char           list[1];
+    } fieldlist;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned short int      rvtype;
+        unsigned char           call;
+        unsigned char           reserved;
+        unsigned short int      params;
+        unsigned short int      arglist;
+    } procedure_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned int            rvtype;
+        unsigned char           call;
+        unsigned char           reserved;
+        unsigned short int      params;
+        unsigned int            arglist;
+    } procedure_v2;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned short int      rvtype;
+        unsigned short int      class_type;
+        unsigned short int      this_type;
+        unsigned char           call;
+        unsigned char           reserved;
+        unsigned short int      params;
+        unsigned short int      arglist;
+        unsigned int            this_adjust;
+    } mfunction_v1;
+
+    struct
+    {
+        unsigned short int      len;
+        short int               id;
+        unsigned                unknown1; /* could be this_type ??? */
+        unsigned int            class_type;
+        unsigned int            rvtype;
+        unsigned char           call;
+        unsigned char           reserved;
+        unsigned short          params;
+        unsigned int            arglist;
+        unsigned int            this_adjust;
+    } mfunction_v2;
+};
+
+union codeview_fieldtype
+{
+    struct
+    {
+        short int		id;
+    } generic;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+        short int		attribute;
+        unsigned short int	offset;     /* numeric leaf */
+    } bclass_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        type;
+        unsigned short int	offset;     /* numeric leaf */
+    } bclass_v2;
+
+    struct
+    {
+        short int		id;
+        short int		btype;
+        short int		vbtype;
+        short int		attribute;
+        unsigned short int	vbpoff;     /* numeric leaf */
+#if 0
+        unsigned short int	vboff;      /* numeric leaf */
+#endif
+    } vbclass_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        btype;
+        unsigned int	        vbtype;
+        unsigned short int	vbpoff;     /* numeric leaf */
+#if 0
+        unsigned short int	vboff;      /* numeric leaf */
+#endif
+    } vbclass_v2;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned short int	value;     /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } enumerate_v1;
+
+   struct
+    {
+        short int               id;
+        short int               attribute;
+        unsigned short int      value;     /* numeric leaf */
+#if 0
+        char                    name[1];
+#endif
+    } enumerate_v3;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+        struct p_string         p_name;
+    } friendfcn_v1;
+
+    struct
+    {
+        short int		id;
+        short int		_pad0;
+        unsigned int	        type;
+        struct p_string         p_name;
+    } friendfcn_v2;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+        short int		attribute;
+        unsigned short int	offset;    /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } member_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        type;
+        unsigned short int	offset;    /* numeric leaf */
+#if 0
+        struct p_string         p_name;
+#endif
+    } member_v2;
+
+    struct
+    {
+        short int               id;
+        short int               attribute;
+        unsigned int            type;
+        unsigned short int      offset; /* numeric leaf */
+#if 0
+        unsigned char           name[1];
+#endif
+    }
+    member_v3;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+        short int		attribute;
+        struct p_string         p_name;
+    } stmember_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        type;
+        struct p_string         p_name;
+    } stmember_v2;
+
+    struct
+    {
+        short int		id;
+        short int		count;
+        short int		mlist;
+        struct p_string         p_name;
+    } method_v1;
+
+    struct
+    {
+        short int		id;
+        short int		count;
+        unsigned int	        mlist;
+        struct p_string         p_name;
+    } method_v2;
+
+    struct
+    {
+        short int		id;
+        short int		index;
+        struct p_string         p_name;
+    } nesttype_v1;
+
+    struct
+    {
+        short int		id;
+        short int		_pad0;
+        unsigned int	        index;
+        struct p_string         p_name;
+    } nesttype_v2;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+    } vfunctab_v1;
+
+    struct
+    {
+        short int		id;
+        short int		_pad0;
+        unsigned int	        type;
+    } vfunctab_v2;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+    } friendcls_v1;
+
+    struct
+    {
+        short int		id;
+        short int		_pad0;
+        unsigned int	        type;
+    } friendcls_v2;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        short int		type;
+        struct p_string         p_name;
+    } onemethod_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        short int		type;
+        unsigned int	        vtab_offset;
+        struct p_string         p_name;
+    } onemethod_virt_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int 	        type;
+        struct p_string         p_name;
+    } onemethod_v2;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        type;
+        unsigned int	        vtab_offset;
+        struct p_string         p_name;
+    } onemethod_virt_v2;
+
+    struct
+    {
+        short int		id;
+        short int		type;
+        unsigned int	        offset;
+    } vfuncoff_v1;
+
+    struct
+    {
+        short int		id;
+        short int		_pad0;
+        unsigned int	        type;
+        unsigned int	        offset;
+    } vfuncoff_v2;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        short int		index;
+        struct p_string         p_name;
+    } nesttypeex_v1;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        index;
+        struct p_string         p_name;
+    } nesttypeex_v2;
+
+    struct
+    {
+        short int		id;
+        short int		attribute;
+        unsigned int	        type;
+        struct p_string         p_name;
+    } membermodify_v2;
+
+};
+
+
+/*
+ * This covers the basic datatypes that VC++ seems to be using these days.
+ * 32 bit mode only.  There are additional numbers for the pointers in 16
+ * bit mode.  There are many other types listed in the documents, but these
+ * are apparently not used by the compiler, or represent pointer types
+ * that are not used.
+ */
+#define T_NOTYPE	        0x0000	/* Notype */
+#define T_ABS		        0x0001	/* Abs */
+#define T_VOID		        0x0003	/* Void */
+#define T_CHAR		        0x0010	/* signed char */
+#define T_SHORT		        0x0011	/* short */
+#define T_LONG		        0x0012	/* long */
+#define T_QUAD		        0x0013	/* long long */
+#define T_UCHAR		        0x0020	/* unsigned  char */
+#define T_USHORT	        0x0021	/* unsigned short */
+#define T_ULONG		        0x0022	/* unsigned long */
+#define T_UQUAD		        0x0023	/* unsigned long long */
+#define T_REAL32	        0x0040	/* float */
+#define T_REAL64	        0x0041	/* double */
+#define T_RCHAR		        0x0070	/* real char */
+#define T_WCHAR		        0x0071	/* wide char */
+#define T_INT4		        0x0074	/* int */
+#define T_UINT4		        0x0075	/* unsigned int */
+
+#define T_32PVOID	        0x0403	/* 32 bit near pointer to void */
+#define T_32PCHAR	        0x0410  /* 16:32 near pointer to signed char */
+#define T_32PSHORT	        0x0411  /* 16:32 near pointer to short */
+#define T_32PLONG	        0x0412  /* 16:32 near pointer to int */
+#define T_32PQUAD	        0x0413  /* 16:32 near pointer to long long */
+#define T_32PUCHAR	        0x0420  /* 16:32 near pointer to unsigned char */
+#define T_32PUSHORT	        0x0421  /* 16:32 near pointer to unsigned short */
+#define T_32PULONG	        0x0422	/* 16:32 near pointer to unsigned int */
+#define T_32PUQUAD	        0x0423  /* 16:32 near pointer to long long */
+#define T_32PREAL32	        0x0440	/* 16:32 near pointer to float */
+#define T_32PREAL64	        0x0441	/* 16:32 near pointer to float */
+#define T_32PRCHAR	        0x0470	/* 16:32 near pointer to real char */
+#define T_32PWCHAR	        0x0471	/* 16:32 near pointer to real char */
+#define T_32PINT4	        0x0474	/* 16:32 near pointer to int */
+#define T_32PUINT4	        0x0475  /* 16:32 near pointer to unsigned int */
+
+
+#define LF_MODIFIER_V1          0x0001
+#define LF_POINTER_V1           0x0002
+#define LF_ARRAY_V1             0x0003
+#define LF_CLASS_V1             0x0004
+#define LF_STRUCTURE_V1         0x0005
+#define LF_UNION_V1             0x0006
+#define LF_ENUM_V1              0x0007
+#define LF_PROCEDURE_V1         0x0008
+#define LF_MFUNCTION_V1         0x0009
+#define LF_VTSHAPE_V1           0x000a
+#define LF_COBOL0_V1            0x000b
+#define LF_COBOL1_V1            0x000c
+#define LF_BARRAY_V1            0x000d
+#define LF_LABEL_V1             0x000e
+#define LF_NULL_V1              0x000f
+#define LF_NOTTRAN_V1           0x0010
+#define LF_DIMARRAY_V1          0x0011
+#define LF_VFTPATH_V1           0x0012
+#define LF_PRECOMP_V1           0x0013
+#define LF_ENDPRECOMP_V1        0x0014
+#define LF_OEM_V1               0x0015
+#define LF_TYPESERVER_V1        0x0016
+
+#define LF_MODIFIER_V2          0x1001     /* variants with new 32-bit type indices (V2) */
+#define LF_POINTER_V2           0x1002
+#define LF_ARRAY_V2             0x1003
+#define LF_CLASS_V2             0x1004
+#define LF_STRUCTURE_V2         0x1005
+#define LF_UNION_V2             0x1006
+#define LF_ENUM_V2              0x1007
+#define LF_PROCEDURE_V2         0x1008
+#define LF_MFUNCTION_V2         0x1009
+#define LF_COBOL0_V2            0x100a
+#define LF_BARRAY_V2            0x100b
+#define LF_DIMARRAY_V2          0x100c
+#define LF_VFTPATH_V2           0x100d
+#define LF_PRECOMP_V2           0x100e
+#define LF_OEM_V2               0x100f
+
+#define LF_SKIP_V1              0x0200
+#define LF_ARGLIST_V1           0x0201
+#define LF_DEFARG_V1            0x0202
+#define LF_LIST_V1              0x0203
+#define LF_FIELDLIST_V1         0x0204
+#define LF_DERIVED_V1           0x0205
+#define LF_BITFIELD_V1          0x0206
+#define LF_METHODLIST_V1        0x0207
+#define LF_DIMCONU_V1           0x0208
+#define LF_DIMCONLU_V1          0x0209
+#define LF_DIMVARU_V1           0x020a
+#define LF_DIMVARLU_V1          0x020b
+#define LF_REFSYM_V1            0x020c
+
+#define LF_SKIP_V2              0x1200    /* variants with new 32-bit type indices (V2) */
+#define LF_ARGLIST_V2           0x1201
+#define LF_DEFARG_V2            0x1202
+#define LF_FIELDLIST_V2         0x1203
+#define LF_DERIVED_V2           0x1204
+#define LF_BITFIELD_V2          0x1205
+#define LF_METHODLIST_V2        0x1206
+#define LF_DIMCONU_V2           0x1207
+#define LF_DIMCONLU_V2          0x1208
+#define LF_DIMVARU_V2           0x1209
+#define LF_DIMVARLU_V2          0x120a
+
+/* Field lists */
+#define LF_BCLASS_V1            0x0400
+#define LF_VBCLASS_V1           0x0401
+#define LF_IVBCLASS_V1          0x0402
+#define LF_ENUMERATE_V1         0x0403
+#define LF_FRIENDFCN_V1         0x0404
+#define LF_INDEX_V1             0x0405
+#define LF_MEMBER_V1            0x0406
+#define LF_STMEMBER_V1          0x0407
+#define LF_METHOD_V1            0x0408
+#define LF_NESTTYPE_V1          0x0409
+#define LF_VFUNCTAB_V1          0x040a
+#define LF_FRIENDCLS_V1         0x040b
+#define LF_ONEMETHOD_V1         0x040c
+#define LF_VFUNCOFF_V1          0x040d
+#define LF_NESTTYPEEX_V1        0x040e
+#define LF_MEMBERMODIFY_V1      0x040f
+
+#define LF_BCLASS_V2            0x1400    /* variants with new 32-bit type indices (V2) */
+#define LF_VBCLASS_V2           0x1401
+#define LF_IVBCLASS_V2          0x1402
+#define LF_FRIENDFCN_V2         0x1403
+#define LF_INDEX_V2             0x1404
+#define LF_MEMBER_V2            0x1405
+#define LF_STMEMBER_V2          0x1406
+#define LF_METHOD_V2            0x1407
+#define LF_NESTTYPE_V2          0x1408
+#define LF_VFUNCTAB_V2          0x1409
+#define LF_FRIENDCLS_V2         0x140a
+#define LF_ONEMETHOD_V2         0x140b
+#define LF_VFUNCOFF_V2          0x140c
+#define LF_NESTTYPEEX_V2        0x140d
+
+#define LF_ENUMERATE_V3         0x1502
+#define LF_ARRAY_V3             0x1503
+#define LF_CLASS_V3             0x1504
+#define LF_STRUCTURE_V3         0x1505
+#define LF_UNION_V3             0x1506
+#define LF_ENUM_V3              0x1507
+#define LF_MEMBER_V3            0x150d
+
+#define LF_NUMERIC              0x8000    /* numeric leaf types */
+#define LF_CHAR                 0x8000
+#define LF_SHORT                0x8001
+#define LF_USHORT               0x8002
+#define LF_LONG                 0x8003
+#define LF_ULONG                0x8004
+#define LF_REAL32               0x8005
+#define LF_REAL64               0x8006
+#define LF_REAL80               0x8007
+#define LF_REAL128              0x8008
+#define LF_QUADWORD             0x8009
+#define LF_UQUADWORD            0x800a
+#define LF_REAL48               0x800b
+#define LF_COMPLEX32            0x800c
+#define LF_COMPLEX64            0x800d
+#define LF_COMPLEX80            0x800e
+#define LF_COMPLEX128           0x800f
+#define LF_VARSTRING            0x8010
+
+/* ======================================== *
+ *            Symbol information
+ * ======================================== */
+
+union codeview_symbol
+{
+    struct
+    {
+        short int	        len;
+        short int	        id;
+    } generic;
+
+    struct
+    {
+	short int	        len;
+	short int	        id;
+	unsigned int	        offset;
+	unsigned short	        segment;
+	unsigned short	        symtype;
+        struct p_string         p_name;
+    } data_v1;
+
+    struct
+    {
+	short int	        len;
+	short int	        id;
+	unsigned int	        symtype;
+	unsigned int	        offset;
+	unsigned short	        segment;
+        struct p_string         p_name;
+    } data_v2;
+
+    struct
+    {
+        short int               len;
+        short int               id;
+        unsigned int            symtype;
+        unsigned int            offset;
+        unsigned short          segment;
+        char                    name[1];
+    } data_v3;
+
+    struct
+    {
+	short int	        len;
+	short int	        id;
+	unsigned int	        pparent;
+	unsigned int	        pend;
+	unsigned int	        next;
+	unsigned int	        offset;
+	unsigned short	        segment;
+	unsigned short	        thunk_len;
+	unsigned char	        thtype;
+        struct p_string         p_name;
+    } thunk_v1;
+
+    struct
+    {
+        short int               len;
+        short int               id;
+        unsigned int            pparent;
+        unsigned int            pend;
+        unsigned int            next;
+        unsigned int            offset;
+        unsigned short          segment;
+        unsigned short          thunk_len;
+        unsigned char           thtype;
+        char                    name[1];
+    } thunk_v3;
+
+    struct
+    {
+	short int	        len;
+	short int	        id;
+	unsigned int	        pparent;
+	unsigned int	        pend;
+	unsigned int	        next;
+	unsigned int	        proc_len;
+	unsigned int	        debug_start;
+	unsigned int	        debug_end;
+	unsigned int	        offset;
+	unsigned short	        segment;
+	unsigned short	        proctype;
+	unsigned char	        flags;
+        struct p_string         p_name;
+    } proc_v1;
+
+    struct
+    {
+	short int	        len;
+	short int	        id;
+	unsigned int	        pparent;
+	unsigned int	        pend;
+	unsigned int	        next;
+	unsigned int	        proc_len;
+	unsigned int	        debug_start;
+	unsigned int	        debug_end;
+	unsigned int	        proctype;
+	unsigned int	        offset;
+	unsigned short	        segment;
+	unsigned char	        flags;
+        struct p_string         p_name;
+    } proc_v2;
+
+    struct
+    {
+        short int               len;
+        short int               id;
+        unsigned int            pparent;
+        unsigned int            pend;
+        unsigned int            next;
+        unsigned int            proc_len;
+        unsigned int            debug_start;
+        unsigned int            debug_end;
+        unsigned int            proctype;
+        unsigned int            offset;
+        unsigned short          segment;
+        unsigned char           flags;
+        char                    name[1];
+    } proc_v3;
+
+    struct
+    {
+	short int	        len;	        /* Total length of this entry */
+	short int	        id;		/* Always S_BPREL_V1 */
+	unsigned int	        offset;	        /* Stack offset relative to BP */
+	unsigned short	        symtype;
+        struct p_string         p_name;
+    } stack_v1;
+
+    struct
+    {
+	short int	        len;	        /* Total length of this entry */
+	short int	        id;		/* Always S_BPREL_V2 */
+	unsigned int	        offset;	        /* Stack offset relative to EBP */
+	unsigned int	        symtype;
+        struct p_string         p_name;
+    } stack_v2;
+
+    struct
+    {
+        short int               len;            /* Total length of this entry */
+        short int               id;             /* Always S_BPREL_V3 */
+        int                     offset;         /* Stack offset relative to BP */
+        unsigned int            symtype;
+        char                    name[1];
+    } stack_v3;
+
+    struct
+    {
+	short int	        len;	        /* Total length of this entry */
+	short int	        id;		/* Always S_REGISTER */
+        unsigned short          type;
+        unsigned short          reg;
+        struct p_string         p_name;
+        /* don't handle register tracking */
+    } register_v1;
+
+    struct
+    {
+	short int	        len;	        /* Total length of this entry */
+	short int	        id;		/* Always S_REGISTER_V2 */
+        unsigned int            type;           /* check whether type & reg are correct */
+        unsigned int            reg;
+        struct p_string         p_name;
+        /* don't handle register tracking */
+    } register_v2;
+
+    struct
+    {
+        short int               len;
+        short int               id;
+        unsigned int            parent;
+        unsigned int            end;
+        unsigned int            length;
+        unsigned int            offset;
+        unsigned short          segment;
+        struct p_string         p_name;
+    } block_v1;
+
+    struct
+    {
+        short int               len;
[truncated at 1000 lines; 428 more skipped]

reactos/lib/dbghelp
msc.c added at 1.1
diff -N msc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ msc.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,2332 @@
+/*
+ * File msc.c - read VC++ debug information from COFF and eventually
+ * from PDB files.
+ *
+ * Copyright (C) 1996,      Eric Youngdale.
+ * Copyright (C) 1999-2000, Ulrich Weigand.
+ * Copyright (C) 2004,      Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Note - this handles reading debug information for 32 bit applications
+ * that run under Windows-NT for example.  I doubt that this would work well
+ * for 16 bit applications, but I don't think it really matters since the
+ * file format is different, and we should never get in here in such cases.
+ *
+ * TODO:
+ *	Get 16 bit CV stuff working.
+ *	Add symbol size to internal symbol table.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
+
+#include "wine/exception.h"
+#include "wine/debug.h"
+#include "excpt.h"
+#include "dbghelp_private.h"
+#include "mscvpdb.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_msc);
+
+#define MAX_PATHNAME_LEN 1024
+
+/*========================================================================
+ * Debug file access helper routines
+ */
+
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
+        return EXCEPTION_EXECUTE_HANDLER;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void dump(const void* ptr, unsigned len)
+{
+    int         i, j;
+    BYTE        msg[128];
+    const char* hexof = "0123456789abcdef";
+    const BYTE* x = (const BYTE*)ptr;
+
+    for (i = 0; i < len; i += 16)
+    {
+        sprintf(msg, "%08x: ", i);
+        memset(msg + 10, ' ', 3 * 16 + 1 + 16);
+        for (j = 0; j < min(16, len - i); j++)
+        {
+            msg[10 + 3 * j + 0] = hexof[x[i + j] >> 4];
+            msg[10 + 3 * j + 1] = hexof[x[i + j] & 15];
+            msg[10 + 3 * j + 2] = ' ';
+            msg[10 + 3 * 16 + 1 + j] = (x[i + j] >= 0x20 && x[i + j] < 0x7f) ?
+                x[i + j] : '.';
+        }
+        msg[10 + 3 * 16] = ' ';
+        msg[10 + 3 * 16 + 1 + 16] = '\0';
+        FIXME("%s\n", msg);
+    }
+}
+
+/*========================================================================
+ * Process CodeView type information.
+ */
+
+#define MAX_BUILTIN_TYPES	0x0480
+#define FIRST_DEFINABLE_TYPE    0x1000
+
+static struct symt*     cv_basic_types[MAX_BUILTIN_TYPES];
+
+#define SymTagCVBitField        (SymTagMax + 0x100)
+struct codeview_bitfield
+{
+    struct symt         symt;
+    unsigned            subtype;
+    unsigned            bitposition;
+    unsigned            bitlength;
+};
+
+struct cv_defined_module
+{
+    BOOL                allowed;
+    unsigned int        num_defined_types;
+    struct symt**       defined_types;
+
+    struct codeview_bitfield* bitfields;
+    unsigned            num_bitfields;
+    unsigned            used_bitfields;
+};
+/* FIXME: don't make it static */
+#define CV_MAX_MODULES          32
+static struct cv_defined_module cv_zmodules[CV_MAX_MODULES];
+static struct cv_defined_module*cv_current_module;
+
+static void codeview_init_basic_types(struct module* module)
+{
+    /*
+     * These are the common builtin types that are used by VC++.
+     */
+    cv_basic_types[T_NOTYPE] = NULL;
+    cv_basic_types[T_ABS]    = NULL;
+    cv_basic_types[T_VOID]   = &symt_new_basic(module, btVoid,  "void", 0)->symt;
+    cv_basic_types[T_CHAR]   = &symt_new_basic(module, btChar,  "char", 1)->symt;
+    cv_basic_types[T_SHORT]  = &symt_new_basic(module, btInt,   "short int", 2)->symt;
+    cv_basic_types[T_LONG]   = &symt_new_basic(module, btInt,   "long int", 4)->symt;
+    cv_basic_types[T_QUAD]   = &symt_new_basic(module, btInt,   "long long int", 8)->symt;
+    cv_basic_types[T_UCHAR]  = &symt_new_basic(module, btUInt,  "unsigned char", 1)->symt;
+    cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt,  "unsigned short", 2)->symt;
+    cv_basic_types[T_ULONG]  = &symt_new_basic(module, btUInt,  "unsigned long", 4)->symt;
+    cv_basic_types[T_UQUAD]  = &symt_new_basic(module, btUInt,  "unsigned long long", 8)->symt;
+    cv_basic_types[T_REAL32] = &symt_new_basic(module, btFloat, "float", 4)->symt;
+    cv_basic_types[T_REAL64] = &symt_new_basic(module, btFloat, "double", 8)->symt;
+    cv_basic_types[T_RCHAR]  = &symt_new_basic(module, btInt,   "signed char", 1)->symt;
+    cv_basic_types[T_WCHAR]  = &symt_new_basic(module, btWChar, "wchar_t", 2)->symt;
+    cv_basic_types[T_INT4]   = &symt_new_basic(module, btInt,   "INT4", 4)->symt;
+    cv_basic_types[T_UINT4]  = &symt_new_basic(module, btUInt,  "UINT4", 4)->symt;
+
+    cv_basic_types[T_32PVOID]   = &symt_new_pointer(module, cv_basic_types[T_VOID])->symt;
+    cv_basic_types[T_32PCHAR]   = &symt_new_pointer(module, cv_basic_types[T_CHAR])->symt;
+    cv_basic_types[T_32PSHORT]  = &symt_new_pointer(module, cv_basic_types[T_SHORT])->symt;
+    cv_basic_types[T_32PLONG]   = &symt_new_pointer(module, cv_basic_types[T_LONG])->symt;
+    cv_basic_types[T_32PQUAD]   = &symt_new_pointer(module, cv_basic_types[T_QUAD])->symt;
+    cv_basic_types[T_32PUCHAR]  = &symt_new_pointer(module, cv_basic_types[T_UCHAR])->symt;
+    cv_basic_types[T_32PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT])->symt;
+    cv_basic_types[T_32PULONG]  = &symt_new_pointer(module, cv_basic_types[T_ULONG])->symt;
+    cv_basic_types[T_32PUQUAD]  = &symt_new_pointer(module, cv_basic_types[T_UQUAD])->symt;
+    cv_basic_types[T_32PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32])->symt;
+    cv_basic_types[T_32PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64])->symt;
+    cv_basic_types[T_32PRCHAR]  = &symt_new_pointer(module, cv_basic_types[T_RCHAR])->symt;
+    cv_basic_types[T_32PWCHAR]  = &symt_new_pointer(module, cv_basic_types[T_WCHAR])->symt;
+    cv_basic_types[T_32PINT4]   = &symt_new_pointer(module, cv_basic_types[T_INT4])->symt;
+    cv_basic_types[T_32PUINT4]  = &symt_new_pointer(module, cv_basic_types[T_UINT4])->symt;
+}
+
+static int numeric_leaf(int* value, const unsigned short int* leaf)
+{
+    unsigned short int type = *leaf++;
+    int length = 2;
+
+    if (type < LF_NUMERIC)
+    {
+        *value = type;
+    }
+    else
+    {
+        switch (type)
+        {
+        case LF_CHAR:
+            length += 1;
+            *value = *(const char*)leaf;
+            break;
+
+        case LF_SHORT:
+            length += 2;
+            *value = *(const short*)leaf;
+            break;
+
+        case LF_USHORT:
+            length += 2;
+            *value = *(const unsigned short*)leaf;
+            break;
+
+        case LF_LONG:
+            length += 4;
+            *value = *(const int*)leaf;
+            break;
+
+        case LF_ULONG:
+            length += 4;
+            *value = *(const unsigned int*)leaf;
+            break;
+
+        case LF_QUADWORD:
+        case LF_UQUADWORD:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 8;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL32:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 4;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL48:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 6;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL64:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 8;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL80:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 10;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL128:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 16;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_COMPLEX32:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 4;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_COMPLEX64:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 8;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_COMPLEX80:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 10;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_COMPLEX128:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 16;
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_VARSTRING:
+	    FIXME("Unsupported numeric leaf type %04x\n", type);
+            length += 2 + *leaf;
+            *value = 0;    /* FIXME */
+            break;
+
+        default:
+	    FIXME("Unknown numeric leaf type %04x\n", type);
+            *value = 0;
+            break;
+        }
+    }
+
+    return length;
+}
+
+/* convert a pascal string (as stored in debug information) into
+ * a C string (null terminated).
+ */
+static const char* terminate_string(const struct p_string* p_name)
+{
+    static char symname[256];
+
+    memcpy(symname, p_name->name, p_name->namelen);
+    symname[p_name->namelen] = '\0';
+
+    return (!*symname || strcmp(symname, "__unnamed") == 0) ? NULL : symname;
+}
+
+static struct symt*  codeview_get_type(unsigned int typeno, BOOL allow_special)
+{
+    struct symt*        symt = NULL;
+
+    /*
+     * Convert Codeview type numbers into something we can grok internally.
+     * Numbers < FIRST_DEFINABLE_TYPE are all fixed builtin types.
+     * Numbers from FIRST_DEFINABLE_TYPE and up are all user defined (structs, etc).
+     */
+    if (typeno < FIRST_DEFINABLE_TYPE)
+    {
+        if (typeno < MAX_BUILTIN_TYPES)
+	    symt = cv_basic_types[typeno];
+    }
+    else
+    {
+        unsigned        mod_index = typeno >> 24;
+        unsigned        mod_typeno = typeno & 0x00FFFFFF;
+        struct cv_defined_module*       mod;
+
+        mod = (mod_index == 0) ? cv_current_module : &cv_zmodules[mod_index];
+
+        if (mod_index >= CV_MAX_MODULES || !mod->allowed) 
+            FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index, typeno);
+        else
+        {
+            if (mod_typeno - FIRST_DEFINABLE_TYPE < mod->num_defined_types)
+                symt = mod->defined_types[mod_typeno - FIRST_DEFINABLE_TYPE];
+        }
+    }
+    if (!allow_special && symt && symt->tag == SymTagCVBitField)
+        FIXME("bitfields are only handled for UDTs\n");
+    if (!symt && typeno) FIXME("Returning NULL symt for type-id %x\n", typeno);
+    return symt;
+}
+
+static int codeview_add_type(unsigned int typeno, struct symt* dt)
+{
+    if (typeno < FIRST_DEFINABLE_TYPE)
+        FIXME("What the heck\n");
+    if (!cv_current_module)
+    {
+        FIXME("Adding %x to non allowed module\n", typeno);
+        return FALSE;
+    }
+    if ((typeno >> 24) != 0)
+        FIXME("No module index while inserting type-id assumption is wrong %x\n",
+              typeno);
+    while (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
+    {
+        cv_current_module->num_defined_types += 0x100;
+        if (cv_current_module->defined_types)
+            cv_current_module->defined_types = (struct symt**)
+                HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                            cv_current_module->defined_types,
+                            cv_current_module->num_defined_types * sizeof(struct symt*));
+        else
+            cv_current_module->defined_types = (struct symt**)
+                HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                          cv_current_module->num_defined_types * sizeof(struct symt*));
+
+        if (cv_current_module->defined_types == NULL) return FALSE;
+    }
+
+    cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE] = dt;
+    return TRUE;
+}
+
+static void codeview_clear_type_table(void)
+{
+    int i;
+
+    for (i = 0; i < CV_MAX_MODULES; i++)
+    {
+        if (cv_zmodules[i].allowed && cv_zmodules[i].defined_types)
+            HeapFree(GetProcessHeap(), 0, cv_zmodules[i].defined_types);
+        cv_zmodules[i].allowed = FALSE;
+        cv_zmodules[i].defined_types = NULL;
+        cv_zmodules[i].num_defined_types = 0;
+        if (cv_zmodules[i].bitfields)
+            HeapFree(GetProcessHeap(), 0, cv_zmodules[i].bitfields);
+        cv_zmodules[i].bitfields = NULL;
+        cv_zmodules[i].num_bitfields = cv_zmodules[i].used_bitfields = 0;
+    }
+    cv_current_module = NULL;
+}
+
+static int codeview_add_type_pointer(struct module* module, unsigned int typeno, 
+                                     unsigned int datatype)
+{
+    struct symt* symt = &symt_new_pointer(module,
+                                          codeview_get_type(datatype, FALSE))->symt;
+    return codeview_add_type(typeno, symt);
+}
+
+static int codeview_add_type_array(struct module* module, 
+                                   unsigned int typeno, const char* name,
+                                   unsigned int elemtype, unsigned int arr_len)
+{
+    struct symt*        symt;
+    struct symt*        elem = codeview_get_type(elemtype, FALSE);
+    DWORD               arr_max = 0;
+
+    if (elem)
+    {
+        DWORD elem_size;
+        symt_get_info(elem, TI_GET_LENGTH, &elem_size);
+        if (elem_size) arr_max = arr_len / elem_size;
+    }
+    symt = &symt_new_array(module, 0, arr_max, elem)->symt;
+    return codeview_add_type(typeno, symt);
+}
+
+static int codeview_add_type_bitfield(unsigned int typeno, unsigned int bitoff,
+                                      unsigned int nbits, unsigned int basetype)
+{
+    if (cv_current_module->used_bitfields >= cv_current_module->num_bitfields)
+    {
+        if (cv_current_module->bitfields)
+        {
+            cv_current_module->num_bitfields *= 2;
+            cv_current_module->bitfields = 
+                HeapReAlloc(GetProcessHeap(), 0, 
+                            cv_current_module->bitfields, 
+                            cv_current_module->num_bitfields * sizeof(struct codeview_bitfield));
+        }
+        else
+        {
+            cv_current_module->num_bitfields = 64;
+            cv_current_module->bitfields = 
+                HeapAlloc(GetProcessHeap(), 0, 
+                          cv_current_module->num_bitfields * sizeof(struct codeview_bitfield));
+        }
+        if (!cv_current_module->bitfields) return 0;
+    }
+    
+    cv_current_module->bitfields[cv_current_module->used_bitfields].symt.tag    = SymTagCVBitField;
+    cv_current_module->bitfields[cv_current_module->used_bitfields].subtype     = basetype;
+    cv_current_module->bitfields[cv_current_module->used_bitfields].bitposition = bitoff;
+    cv_current_module->bitfields[cv_current_module->used_bitfields].bitlength   = nbits;
+
+    return codeview_add_type(typeno, &cv_current_module->bitfields[cv_current_module->used_bitfields++].symt);
+}
+
+static int codeview_add_type_enum_field_list(struct module* module, 
+                                             unsigned int typeno, 
+                                             const unsigned char* list, int len)
+{
+    struct symt_enum*           symt;
+    const unsigned char*        ptr = list;
+
+    symt = symt_new_enum(module, NULL);
+    while (ptr - list < len)
+    {
+        const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
+
+        if (*ptr >= 0xf0)       /* LF_PAD... */
+        {
+            ptr += *ptr & 0x0f;
+            continue;
+        }
+
+        switch (type->generic.id)
+        {
+        case LF_ENUMERATE_V1:
+        {
+            int value, vlen = numeric_leaf(&value, &type->enumerate_v1.value);
+            const struct p_string* p_name = (const struct p_string*)((const unsigned char*)&type->enumerate_v1.value + vlen);
+
+            symt_add_enum_element(module, symt, terminate_string(p_name), value);
+            ptr += 2 + 2 + vlen + (1 + p_name->namelen);
+            break;
+        }
+        case LF_ENUMERATE_V3:
+        {
+            int value, vlen = numeric_leaf(&value, &type->enumerate_v3.value);
+            const char* name = (const char*)&type->enumerate_v3.value + vlen;
+
+            symt_add_enum_element(module, symt, name, value);
+            ptr += 2 + 2 + vlen + (1 + strlen(name));
+            break;
+        }
+
+        default:
+            FIXME("Unsupported type %04x in ENUM field list\n", type->generic.id);
+            return FALSE;
+        }
+    }
+
+    return codeview_add_type(typeno, &symt->symt);
+}
+
+static int codeview_add_type_struct_field_list(struct module* module, 
+                                               unsigned int typeno, 
+                                               const unsigned char* list, int len)
+{
+    struct symt_udt*            symt;
+    const unsigned char*        ptr = list;
+    int                         value, leaf_len, vpoff, vplen;
+    const struct p_string*      p_name;
+    const char*                 c_name;
+    struct symt*                subtype;
+    const unsigned short int* p_vboff;
+
+    symt = symt_new_udt(module, NULL, 0, UdtStruct /* don't care */);
+    while (ptr - list < len)
+    {
+        const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
+
+        if (*ptr >= 0xf0)       /* LF_PAD... */
+        {
+            ptr +=* ptr & 0x0f;
+            continue;
+        }
+
+        switch (type->generic.id)
+        {
+        case LF_BCLASS_V1:
+            leaf_len = numeric_leaf(&value, &type->bclass_v1.offset);
+
+            /* FIXME: ignored for now */
+
+            ptr += 2 + 2 + 2 + leaf_len;
+            break;
+
+        case LF_BCLASS_V2:
+            leaf_len = numeric_leaf(&value, &type->bclass_v2.offset);
+
+            /* FIXME: ignored for now */
+
+            ptr += 2 + 2 + 4 + leaf_len;
+            break;
+
+        case LF_VBCLASS_V1:
+        case LF_IVBCLASS_V1:
+            {
+                leaf_len = numeric_leaf(&value, &type->vbclass_v1.vbpoff);
+                p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v1.vbpoff + leaf_len);
+                vplen = numeric_leaf(&vpoff, p_vboff);
+
+                /* FIXME: ignored for now */
+
+                ptr += 2 + 2 + 2 + 2 + leaf_len + vplen;
+            }
+            break;
+
+        case LF_VBCLASS_V2:
+        case LF_IVBCLASS_V2:
+            {
+                leaf_len = numeric_leaf(&value, &type->vbclass_v2.vbpoff);
+                p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v2.vbpoff + leaf_len);
+                vplen = numeric_leaf(&vpoff, p_vboff);
+
+                /* FIXME: ignored for now */
+
+                ptr += 2 + 2 + 4 + 4 + leaf_len + vplen;
+            }
+            break;
+
+        case LF_MEMBER_V1:
+            leaf_len = numeric_leaf(&value, &type->member_v1.offset);
+            p_name = (const struct p_string*)((const char*)&type->member_v1.offset + leaf_len);
+            subtype = codeview_get_type(type->member_v1.type, TRUE);
+
+            if (!subtype || subtype->tag != SymTagCVBitField)
+            {
+                DWORD elem_size = 0;
+                if (subtype) symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
+                symt_add_udt_element(module, symt, terminate_string(p_name),
+                                     codeview_get_type(type->member_v1.type, TRUE),
+                                     value << 3, elem_size << 3);
+            }
+            else
+            {
+                struct codeview_bitfield* cvbf = (struct codeview_bitfield*)subtype;
+                symt_add_udt_element(module, symt, terminate_string(p_name),
+                                     codeview_get_type(cvbf->subtype, FALSE),
+                                     cvbf->bitposition, cvbf->bitlength);
+            }
+
+            ptr += 2 + 2 + 2 + leaf_len + (1 + p_name->namelen);
+            break;
+
+        case LF_MEMBER_V2:
+            leaf_len = numeric_leaf(&value, &type->member_v2.offset);
+            p_name = (const struct p_string*)((const unsigned char*)&type->member_v2.offset + leaf_len);
+            subtype = codeview_get_type(type->member_v2.type, TRUE);
+
+            if (!subtype || subtype->tag != SymTagCVBitField)
+            {
+                DWORD elem_size = 0;
+                if (subtype) symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
+                symt_add_udt_element(module, symt, terminate_string(p_name),
+                                     subtype, value << 3, elem_size << 3);
+            }
+            else
+            {
+                struct codeview_bitfield* cvbf = (struct codeview_bitfield*)subtype;
+                symt_add_udt_element(module, symt, terminate_string(p_name),
+                                     codeview_get_type(cvbf->subtype, FALSE),
+                                     cvbf->bitposition, cvbf->bitlength);
+            }
+
+            ptr += 2 + 2 + 4 + leaf_len + (1 + p_name->namelen);
+            break;
+
+        case LF_MEMBER_V3:
+            leaf_len = numeric_leaf(&value, &type->member_v3.offset);
+            c_name = (const char*)&type->member_v3.offset + leaf_len;
+            subtype = codeview_get_type(type->member_v3.type, TRUE);
+
+            if (!subtype || subtype->tag != SymTagCVBitField)
+            {
+                DWORD elem_size = 0;
+                if (subtype) symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
+                symt_add_udt_element(module, symt, c_name,
+                                     subtype, value << 3, elem_size << 3);
+            }
+            else
+            {
+                struct codeview_bitfield* cvbf = (struct codeview_bitfield*)subtype;
+                symt_add_udt_element(module, symt, c_name,
+                                     codeview_get_type(cvbf->subtype, FALSE),
+                                     cvbf->bitposition, cvbf->bitlength);
+            }
+
+            ptr += 2 + 2 + 4 + leaf_len + (strlen(c_name) + 1);
+            break;
+
+        case LF_STMEMBER_V1:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + 2 + (1 + type->stmember_v1.p_name.namelen);
+            break;
+
+        case LF_STMEMBER_V2:
+            /* FIXME: ignored for now */
+            ptr += 2 + 4 + 2 + (1 + type->stmember_v2.p_name.namelen);
+            break;
+
+        case LF_METHOD_V1:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + 2 + (1 + type->method_v1.p_name.namelen);
+            break;
+
+        case LF_METHOD_V2:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + 4 + (1 + type->method_v2.p_name.namelen);
+            break;
+
+        case LF_NESTTYPE_V1:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + (1 + type->nesttype_v1.p_name.namelen);
+            break;
+
+        case LF_NESTTYPE_V2:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + 4 + (1 + type->nesttype_v2.p_name.namelen);
+            break;
+
+        case LF_VFUNCTAB_V1:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2;
+            break;
+
+        case LF_VFUNCTAB_V2:
+            /* FIXME: ignored for now */
+            ptr += 2 + 2 + 4;
+            break;
+
+        case LF_ONEMETHOD_V1:
+            /* FIXME: ignored for now */
+            switch ((type->onemethod_v1.attribute >> 2) & 7)
+            {
+            case 4: case 6: /* (pure) introducing virtual method */
+                ptr += 2 + 2 + 2 + 4 + (1 + type->onemethod_virt_v1.p_name.namelen);
+                break;
+
+            default:
+                ptr += 2 + 2 + 2 + (1 + type->onemethod_v1.p_name.namelen);
+                break;
+            }
+            break;
+
+        case LF_ONEMETHOD_V2:
+            /* FIXME: ignored for now */
+            switch ((type->onemethod_v2.attribute >> 2) & 7)
+            {
+            case 4: case 6: /* (pure) introducing virtual method */
+                ptr += 2 + 2 + 4 + 4 + (1 + type->onemethod_virt_v2.p_name.namelen);
+                break;
+
+            default:
+                ptr += 2 + 2 + 4 + (1 + type->onemethod_v2.p_name.namelen);
+                break;
+            }
+            break;
+
+        default:
+            FIXME("Unsupported type %04x in STRUCT field list\n", type->generic.id);
+            return FALSE;
+        }
+    }
+
+    return codeview_add_type(typeno, &symt->symt);
+}
+
+static int codeview_add_type_enum(struct module* module, unsigned int typeno, 
+                                  const char* name, unsigned int fieldlist)
+{
+    struct symt_enum*   symt = symt_new_enum(module, name);
+    struct symt*        list = codeview_get_type(fieldlist, FALSE);
+
+    /* FIXME: this is rather ugly !!! */
+    if (list) symt->vchildren = ((struct symt_enum*)list)->vchildren;
+
+    return codeview_add_type(typeno, &symt->symt);
+}
+
+static int codeview_add_type_struct(struct module* module, unsigned int typeno, 
+                                    const char* name, int structlen, 
+                                    unsigned int fieldlist, enum UdtKind kind)
+{
+    struct symt_udt*    symt = symt_new_udt(module, name, structlen, kind);
+    struct symt*        list = codeview_get_type(fieldlist, FALSE);
+
+    /* FIXME: this is rather ugly !!! */
+    if (list) symt->vchildren = ((struct symt_udt*)list)->vchildren;
+
+    return codeview_add_type(typeno, &symt->symt);
+}
+
+static int codeview_new_func_signature(struct module* module, unsigned typeno,
+                                           unsigned ret_type)
+{
+    struct symt* symt;
+    symt = &symt_new_function_signature(module, 
+                                        codeview_get_type(ret_type, FALSE))->symt;
+    return codeview_add_type(typeno, symt);
+}
+
+static int codeview_parse_type_table(struct module* module, const char* table,
+                                     int len)
+{
+    unsigned int                curr_type = 0x1000;
+    const char*                 ptr = table;
+    int                         retv;
+    const union codeview_type*  type;
+    int                         value, leaf_len;
+    const struct p_string*      p_name;
+    const char*                 c_name;
+
+    while (ptr - table < len)
+    {
+        retv = TRUE;
+        type = (const union codeview_type*)ptr;
+
+        switch (type->generic.id)
+        {
+        case LF_MODIFIER_V1:
+            /* FIXME: we don't handle modifiers, 
+             * but readd previous type on the curr_type 
+             */
+            WARN("Modifier on %x: %s%s%s%s\n",
+                 type->modifier_v1.type,
+                 type->modifier_v1.attribute & 0x01 ? "const " : "",
+                 type->modifier_v1.attribute & 0x02 ? "volatile " : "",
+                 type->modifier_v1.attribute & 0x04 ? "unaligned " : "",
+                 type->modifier_v1.attribute & ~0x07 ? "unknown " : "");
+            codeview_add_type(curr_type, 
+                              codeview_get_type(type->modifier_v1.type, FALSE));
+            break;
+        case LF_MODIFIER_V2:
+            /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
+            WARN("Modifier on %x: %s%s%s%s\n",
+                 type->modifier_v2.type,
+                 type->modifier_v2.attribute & 0x01 ? "const " : "",
+                 type->modifier_v2.attribute & 0x02 ? "volatile " : "",
+                 type->modifier_v2.attribute & 0x04 ? "unaligned " : "",
+                 type->modifier_v2.attribute & ~0x07 ? "unknown " : "");
+            codeview_add_type(curr_type, 
+                              codeview_get_type(type->modifier_v2.type, FALSE));
+            break;
+
+        case LF_POINTER_V1:
+            retv = codeview_add_type_pointer(module, curr_type, 
+                                             type->pointer_v1.datatype);
+            break;
+        case LF_POINTER_V2:
+            retv = codeview_add_type_pointer(module, curr_type, 
+                                             type->pointer_v2.datatype);
+            break;
+
+        case LF_ARRAY_V1:
+            leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
+
+            retv = codeview_add_type_array(module, curr_type, terminate_string(p_name),
+                                           type->array_v1.elemtype, value);
+            break;
+        case LF_ARRAY_V2:
+            leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->array_v2.arrlen + leaf_len);
+
+            retv = codeview_add_type_array(module, curr_type, terminate_string(p_name),
+                                           type->array_v2.elemtype, value);
+            break;
+        case LF_ARRAY_V3:
+            leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
+            c_name = (const char*)&type->array_v3.arrlen + leaf_len;
+
+            retv = codeview_add_type_array(module, curr_type, c_name,
+                                           type->array_v3.elemtype, value);
+            break;
+
+        case LF_BITFIELD_V1:
+            /* a bitfield is a CodeView specific data type which represent a bitfield
+             * in a structure or a class. For now, we store it in a SymTag-like type
+             * (so that the rest of the process is seamless), but check at udt 
+             * inclusion type for its presence
+             */
+            retv = codeview_add_type_bitfield(curr_type, type->bitfield_v1.bitoff,
+                                              type->bitfield_v1.nbits,
+                                              type->bitfield_v1.type);
+            break;
+        case LF_BITFIELD_V2:
+            retv = codeview_add_type_bitfield(curr_type, type->bitfield_v2.bitoff,
+                                              type->bitfield_v2.nbits,
+                                              type->bitfield_v2.type);
+            break;
+        case LF_FIELDLIST_V1:
+        case LF_FIELDLIST_V2:
+           {
+               /*
+                * A 'field list' is a CodeView-specific data type which doesn't
+                * directly correspond to any high-level data type.  It is used
+                * to hold the collection of members of a struct, class, union
+                * or enum type.  The actual definition of that type will follow
+                * later, and refer to the field list definition record.
+                *
+                * As we don't have a field list type ourselves, we look ahead
+                * in the field list to try to find out whether this field list
+                * will be used for an enum or struct type, and create a dummy
+                * type of the corresponding sort.  Later on, the definition of
+                * the 'real' type will copy the member / enumeration data.
+                */
+               const char* list = type->fieldlist.list;
+               int   len  = (ptr + type->generic.len + 2) - list;
+
+               if (((const union codeview_fieldtype*)list)->generic.id == LF_ENUMERATE_V1 ||
+                   ((const union codeview_fieldtype*)list)->generic.id == LF_ENUMERATE_V3)
+                   retv = codeview_add_type_enum_field_list(module, curr_type, list, len);
+               else
+                   retv = codeview_add_type_struct_field_list(module, curr_type, list, len);
+           }
+           break;
+
+        case LF_STRUCTURE_V1:
+        case LF_CLASS_V1:
+            leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->struct_v1.structlen + leaf_len);
+
+            retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
+                                            value, type->struct_v1.fieldlist,
+                                            type->generic.id == LF_CLASS_V1 ? UdtClass : UdtStruct);
+            break;
+
+        case LF_STRUCTURE_V2:
+        case LF_CLASS_V2:
+            leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->struct_v2.structlen + leaf_len);
+
+            retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
+                                            value, type->struct_v2.fieldlist,
+                                            type->generic.id == LF_CLASS_V2 ? UdtClass : UdtStruct);
+            break;
+
+        case LF_STRUCTURE_V3:
+        case LF_CLASS_V3:
+            leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
+            c_name = (const char*)&type->struct_v3.structlen + leaf_len;
+
+            retv = codeview_add_type_struct(module, curr_type, c_name,
+                                            value, type->struct_v3.fieldlist,
+                                            type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct);
+            break;
+
+        case LF_UNION_V1:
+            leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
+            p_name = (const struct p_string*)((const unsigned char*)&type->union_v1.un_len + leaf_len);
+
+            retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
+                                            value, type->union_v1.fieldlist, UdtUnion);
+            break;
+        case LF_UNION_V2:
+            leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
+            p_name = (const struct p_string*)((const unsigned char*)&type->union_v2.un_len + leaf_len);
+
+            retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
+                                            value, type->union_v2.fieldlist, UdtUnion);
+            break;
+        case LF_UNION_V3:
+            leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
+            c_name = (const char*)&type->union_v3.un_len + leaf_len;
+
+            retv = codeview_add_type_struct(module, curr_type, c_name,
+                                            value, type->union_v3.fieldlist, UdtUnion);
+
+        case LF_ENUM_V1:
+            retv = codeview_add_type_enum(module, curr_type, terminate_string(&type->enumeration_v1.p_name),
+                                          type->enumeration_v1.field);
+            break;
+
+        case LF_ENUM_V2:
+            retv = codeview_add_type_enum(module, curr_type, terminate_string(&type->enumeration_v2.p_name),
+                                          type->enumeration_v2.field);
+            break;
+        case LF_ENUM_V3:
+            retv = codeview_add_type_enum(module, curr_type, type->enumeration_v3.name,
+                                          type->enumeration_v3.field);
+            break;
+        case LF_PROCEDURE_V1:
+            retv = codeview_new_func_signature(module, curr_type, 
+                                               type->procedure_v1.rvtype);
+            break;
+        case LF_PROCEDURE_V2:
+            retv = codeview_new_func_signature(module, curr_type, 
+                                               type->procedure_v2.rvtype);
+            break;
+        case LF_MFUNCTION_V1:
+            /* FIXME: for C++, this is plain wrong, but as we don't use arg types
+             * nor class information, this would just do for now
+             */
+            retv = codeview_new_func_signature(module, curr_type,
+                                               type->mfunction_v1.rvtype);
+            break;
+        case LF_MFUNCTION_V2:
+            /* FIXME: for C++, this is plain wrong, but as we don't use arg types
+             * nor class information, this would just do for now
+             */
+            retv = codeview_new_func_signature(module, curr_type,
+                                               type->mfunction_v2.rvtype);
+            break;
+        case LF_ARGLIST_V1:
+        case LF_ARGLIST_V2:
+            {
+                static int once;
+                if (!once++) 
+                    FIXME("Not adding parameters' types to function signature\n");
+            }
+            break;
+
+        default:
+            FIXME("Unsupported type-id leaf %x\n", type->generic.id);
+            dump(type, 2 + type->generic.len);
+            break;
+        }
+        if (!retv) return FALSE;
+        curr_type++;
+        ptr += type->generic.len + 2;
+    }
+
+    return TRUE;
+}
+
+/*========================================================================
+ * Process CodeView line number information.
+ */
+
+static struct codeview_linetab* codeview_snarf_linetab(struct module* module, 
+                                                       const char* linetab, int size,
+                                                       BOOL pascal_str)
+{
+    int				file_segcount;
+    char			filename[PATH_MAX];
+    const unsigned int*         filetab;
+    const struct p_string*      p_fn;
+    int				i;
+    int				k;
+    struct codeview_linetab*    lt_hdr;
+    const unsigned int*         lt_ptr;
+    int				nfile;
+    int				nseg;
+    union any_size		pnt;
+    union any_size		pnt2;
+    const struct startend*      start;
+    int				this_seg;
+    struct symt_compiland*      compiland;
+
+    /*
+     * Now get the important bits.
+     */
+    pnt.c = linetab;
+    nfile = *pnt.s++;
+    nseg = *pnt.s++;
+
[truncated at 1000 lines; 1336 more skipped]

reactos/lib/dbghelp
module.c added at 1.1
diff -N module.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ module.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,505 @@
+/*
+ * File module.c - module handling for the wine debugger
+ *
+ * Copyright (C) 1993,      Eric Youngdale.
+ * 		 2000-2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "dbghelp_private.h"
+#include "psapi.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "wine/debug.h"
+
+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>");
+        else if (len > 7 &&
+                 out[len - 7] == '.' && !strcasecmp(&out[len - 3], ".so"))
+        {
+            if (len + 3 < size) strcpy(&out[len - 3], "<elf>");
+            else WARN("Buffer too short: %s\n", out);
+        }
+    }
+    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 module_type type, 
+                          unsigned long mod_addr, unsigned long size,
+                          unsigned long stamp, unsigned long checksum) 
+{
+    struct module*      module;
+
+    if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
+	return NULL;
+
+    memset(module, 0, sizeof(*module));
+
+    module->next = pcs->lmodules;
+    pcs->lmodules = module;
+
+    TRACE("=> %s %08lx-%08lx %s\n", 
+          type == DMT_ELF ? "ELF" : (type == DMT_PE ? "PE" : "---"),
+          mod_addr, mod_addr + size, name);
+
+    pool_init(&module->pool, 65536);
+    
+    module->module.SizeOfStruct = sizeof(module->module);
+    module->module.BaseOfImage = mod_addr;
+    module->module.ImageSize = size;
+    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));
+    module->module.LoadedImageName[sizeof(module->module.LoadedImageName) - 1] = '\0';
+    module->module.SymType = SymNone;
+    module->module.NumSyms = 0;
+    module->module.TimeDateStamp = stamp;
+    module->module.CheckSum = checksum;
+
+    module->type              = type;
+    module->sortlist_valid    = FALSE;
+    module->addr_sorttab      = NULL;
+    /* FIXME: this seems a bit too high (on a per module basis)
+     * need some statistics about this
+     */
+    hash_table_init(&module->pool, &module->ht_symbols, 4096);
+    hash_table_init(&module->pool, &module->ht_types,   4096);
+    vector_init(&module->vtypes, sizeof(struct symt*),  32);
+
+    module->sources_used      = 0;
+    module->sources_alloc     = 0;
+    module->sources           = 0;
+
+    return module;
+}
+
+/***********************************************************************
+ *	module_find_by_name
+ *
+ */
+struct module* module_find_by_name(const struct process* pcs, 
+                                   const char* name, enum module_type type)
+{
+    struct module*      module;
+
+    if (type == DMT_UNKNOWN)
+    {
+        if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
+            (module = module_find_by_name(pcs, name, DMT_ELF)))
+            return module;
+    }
+    else
+    {
+        for (module = pcs->lmodules; module; module = module->next)
+        {
+            if (type == module->type && !strcasecmp(name, module->module.LoadedImageName)) 
+                return module;
+        }
+        for (module = pcs->lmodules; module; module = module->next)
+        {
+            if (type == module->type && !strcasecmp(name, module->module.ModuleName)) 
+                return module;
+        }
+    }
+    SetLastError(ERROR_INVALID_NAME);
+    return NULL;
+}
+
+/***********************************************************************
+ *           module_get_container
+ *
+ */
+struct module* module_get_container(const struct process* pcs, 
+                                    const struct module* inner)
+{
+    struct module*      module;
+     
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        if (module != inner &&
+            module->module.BaseOfImage <= inner->module.BaseOfImage &&
+            module->module.BaseOfImage + module->module.ImageSize >=
+            inner->module.BaseOfImage + inner->module.ImageSize)
+            return module;
+    }
+    return NULL;
+}
+
+/***********************************************************************
+ *           module_get_containee
+ *
+ */
+struct module* module_get_containee(const struct process* pcs, 
+                                    const struct module* outter)
+{
+    struct module*      module;
+     
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        if (module != outter &&
+            outter->module.BaseOfImage <= module->module.BaseOfImage &&
+            outter->module.BaseOfImage + outter->module.ImageSize >=
+            module->module.BaseOfImage + module->module.ImageSize)
+            return module;
+    }
+    return NULL;
+}
+
+/******************************************************************
+ *		module_get_debug
+ *
+ * get the debug information from a module:
+ * - if the module's type is deferred, then force loading of debug info (and return
+ *   the module itself)
+ * - if the module has no debug info and has an ELF container, then return the ELF
+ *   container (and also force the ELF container's debug info loading if deferred)
+ * - otherwise return the module itself if it has some debug info
+ */
+struct module* module_get_debug(const struct process* pcs, struct module* module)
+{
+    struct module*      parent;
+
+    if (!module) return NULL;
+    /* for a PE builtin, always get info from parent */
+    if ((parent = module_get_container(pcs, module)))
+        module = parent;
+    /* if deferred, force loading */
+    if (module->module.SymType == SymDeferred)
+    {
+        BOOL ret;
+
+        switch (module->type)
+        {
+        case DMT_ELF: ret = elf_load_debug_info(module);     break;
+        case DMT_PE:  ret = pe_load_debug_info(pcs, module); break;
+        default:      ret = FALSE;                           break;
+        }
+        if (!ret) module->module.SymType = SymNone;
+        assert(module->module.SymType != SymDeferred);
+    }
+    return (module && module->module.SymType != SymNone) ? module : NULL;
+}
+
+/***********************************************************************
+ *	module_find_by_addr
+ *
+ * either the addr where module is loaded, or any address inside the 
+ * module
+ */
+struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
+                                   enum module_type type)
+{
+    struct module*      module;
+    
+    if (type == DMT_UNKNOWN)
+    {
+        if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
+            (module = module_find_by_addr(pcs, addr, DMT_ELF)))
+            return module;
+    }
+    else
+    {
+        for (module = pcs->lmodules; module; module = module->next)
+        {
+            if (type == module->type && addr >= module->module.BaseOfImage &&
+                addr < module->module.BaseOfImage + module->module.ImageSize) 
+                return module;
+        }
+    }
+    SetLastError(ERROR_INVALID_ADDRESS);
+    return module;
+}
+
+static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName, 
+                                           const char* ModuleName)
+{
+    char                buffer[MAX_PATH];
+    size_t              len;
+    struct module*      module;
+
+    if (!ModuleName)
+    {
+        module_fill_module(ImageName, buffer, sizeof(buffer));
+        ModuleName = buffer;
+    }
+    len = strlen(ModuleName);
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        if (!strncasecmp(module->module.ModuleName, ModuleName, len) &&
+            module->type == DMT_ELF &&
+            !strcmp(module->module.ModuleName + len, "<elf>"))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/***********************************************************************
+ *			SymLoadModule (DBGHELP.@)
+ */
+DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
+                           char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
+{
+    struct process*     pcs;
+    struct module*	module = NULL;
+
+    TRACE("(%p %p %s %s %08lx %08lx)\n", 
+          hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 
+          BaseOfDll, SizeOfDll);
+
+    pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE;
+
+    /* force transparent ELF loading / unloading */
+    elf_synchronize_module_list(pcs);
+
+    /* this is a Wine extension to the API just to redo the synchronisation */
+    if (!ImageName && !hFile) return 0;
+
+    if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
+    {
+        /* force the loading of DLL as builtin */
+        if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
+            goto done;
+        WARN("Couldn't locate %s\n", ImageName);
+        return 0;
+    }
+    TRACE("Assuming %s as native DLL\n", ImageName);
+    if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
+    {
+        unsigned        len = strlen(ImageName);
+
+        if (!strcmp(ImageName + len - 3, ".so") &&
+            (module = elf_load_module(pcs, ImageName))) goto done;
+        FIXME("should have successfully loaded some debug information for image %s\n", ImageName);
+        if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
+            goto done;
+        WARN("Couldn't locate %s\n", ImageName);
+        return 0;
+    }
+
+done:
+    /* by default pe_load_module fills module.ModuleName from a derivation 
+     * of ImageName. Overwrite it, if we have better information
+     */
+    if (ModuleName)
+    {
+        strncpy(module->module.ModuleName, ModuleName, 
+                sizeof(module->module.ModuleName));
+        module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
+    }
+    strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
+    module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0';
+
+    return module->module.BaseOfImage;
+}
+
+/******************************************************************
+ *		module_remove
+ *
+ */
+BOOL module_remove(struct process* pcs, struct module* module)
+{
+    struct module**     p;
+
+    TRACE("%s (%p)\n", module->module.ModuleName, module);
+    hash_table_destroy(&module->ht_symbols);
+    hash_table_destroy(&module->ht_types);
+    HeapFree(GetProcessHeap(), 0, (char*)module->sources);
+    HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
+    pool_destroy(&module->pool);
+
+    for (p = &pcs->lmodules; *p; p = &(*p)->next)
+    {
+        if (*p == module)
+        {
+            *p = module->next;
+            HeapFree(GetProcessHeap(), 0, module);
+            return TRUE;
+        }
+    }
+    FIXME("This shouldn't happen\n");
+    return FALSE;
+}
+
+/******************************************************************
+ *		SymUnloadModule (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
+{
+    struct process*     pcs;
+    struct module*      module;
+
+    pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE;
+    module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
+    if (!module) return FALSE;
+    return module_remove(pcs, module);
+}
+
+/******************************************************************
+ *		SymEnumerateModules (DBGHELP.@)
+ *
+ */
+BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
+                                 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
+                                 PVOID UserContext)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+
+    if (!pcs) return FALSE;
+    
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type != DMT_PE)
+            continue;
+        if (!EnumModulesCallback(module->module.ModuleName, 
+                                 module->module.BaseOfImage, UserContext))
+            break;
+    }
+    return TRUE;
+}
+
+/******************************************************************
+ *		EnumerateLoadedModules (DBGHELP.@)
+ *
+ */
+BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
+                                    PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
+                                    PVOID UserContext)
+{
+    HMODULE*    hMods;
+    char        base[256], mod[256];
+    DWORD       i, sz;
+    MODULEINFO  mi;
+
+    hMods = HeapAlloc(GetProcessHeap(), 0, sz);
+    if (!hMods) return FALSE;
+
+    if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
+    {
+        /* hProcess should also be a valid process handle !! */
+        FIXME("If this happens, bump the number in mod\n");
+        HeapFree(GetProcessHeap(), 0, hMods);
+        return FALSE;
+    }
+    sz /= sizeof(HMODULE);
+    for (i = 0; i < sz; i++)
+    {
+        if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
+            !GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
+            continue;
+        module_fill_module(base, mod, sizeof(mod));
+
+        EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage, 
+                                  UserContext);
+    }
+    HeapFree(GetProcessHeap(), 0, hMods);
+
+    return sz != 0 && i == sz;
+}
+
+/******************************************************************
+ *		SymGetModuleInfo (DBGHELP.@)
+ *
+ */
+BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 
+                              PIMAGEHLP_MODULE ModuleInfo)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+
+    if (!pcs) return FALSE;
+    if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
+    module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
+    if (!module) return FALSE;
+
+    *ModuleInfo = module->module;
+    if (module->module.SymType == SymNone)
+    {
+        module = module_get_container(pcs, module);
+        if (module && module->module.SymType != SymNone)
+            ModuleInfo->SymType = module->module.SymType;
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *		SymGetModuleBase (IMAGEHLP.@)
+ */
+DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
+{
+    struct process*     pcs = process_find_by_handle(hProcess);
+    struct module*      module;
+
+    if (!pcs) return 0;
+    module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
+    if (!module) return 0;
+    return module->module.BaseOfImage;
+}
+
+/******************************************************************
+ *		module_reset_debug_info
+ * Removes any debug information linked to a given module.
+ */
+void module_reset_debug_info(struct module* module)
+{
+    module->sortlist_valid = TRUE;
+    module->addr_sorttab = NULL;
+    hash_table_destroy(&module->ht_symbols);
+    module->ht_symbols.num_buckets = 0;
+    module->ht_symbols.buckets = NULL;
+    hash_table_destroy(&module->ht_types);
+    module->ht_types.num_buckets = 0;
+    module->ht_types.buckets = NULL;
+    module->vtypes.num_elts = 0;
+    hash_table_destroy(&module->ht_symbols);
+    module->sources_used = module->sources_alloc = 0;
+    module->sources = NULL;
+}

reactos/lib/dbghelp
minidump.c added at 1.1
diff -N minidump.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ minidump.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,266 @@
+/*
+ * File minidump.c - management of dumps (read & write)
+ *
+ * Copyright (C) 2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <time.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "dbghelp_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+#if 0
+/* hard to see how we can generate this very easily (how to grab latest exception
+ * in a process ?)
+ */
+static  void    DumpException(struct process* pcs, HANDLE hFile, RVA* rva)
+{
+    MINIDUMP_EXCEPTION_STREAM   mdExcpt;
+
+    mdExcpt.ThreadId = DEBUG_CurrThread->tid;
+    mdExcpt.__alignment = 0;
+    mdExcpt.ExceptionRecord.
+
+    ULONG                       ExceptionCode;
+    ULONG                       ExceptionFlags;
+    ULONGLONG                   ExceptionRecord;
+    ULONGLONG                   ExceptionAddress;
+    ULONG                       NumberParameters;
+    ULONG                        __unusedAlignment;
+    ULONGLONG                   ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+}
+#endif
+
+/******************************************************************
+ *		dump_modules
+ *
+ * Write in File the modules from pcs
+ */
+static  void    dump_modules(struct process* pcs, HANDLE hFile, RVA* rva)
+{
+    MINIDUMP_MODULE             mdModule;
+    MINIDUMP_MODULE_LIST        mdModuleList;
+    DWORD                       written;
+    struct module*              module = NULL;
+
+    mdModuleList.NumberOfModules = 0;
+    for (module = pcs->lmodules; module; module = module->next)
+        mdModuleList.NumberOfModules++;
+    WriteFile(hFile, &mdModuleList.NumberOfModules, 
+              sizeof(mdModuleList.NumberOfModules), &written, NULL);
+    *rva += sizeof(mdModuleList.NumberOfModules) +      
+        sizeof(mdModule) * mdModuleList.NumberOfModules;
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        mdModule.BaseOfImage = (DWORD)module->module.BaseOfImage;
+        mdModule.SizeOfImage = module->module.ImageSize;
+        mdModule.CheckSum = module->module.CheckSum;
+        mdModule.TimeDateStamp = module->module.TimeDateStamp;
+        mdModule.ModuleNameRva = *rva;
+        *rva += strlen(module->module.ModuleName) + 1;
+        memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */
+        mdModule.CvRecord.DataSize = 0; /* FIXME */
+        mdModule.CvRecord.Rva = 0; /* FIXME */
+        mdModule.MiscRecord.DataSize = 0; /* FIXME */
+        mdModule.MiscRecord.Rva = 0; /* FIXME */
+        mdModule.Reserved0 = 0;
+        mdModule.Reserved1 = 0;
+        WriteFile(hFile, &mdModule, sizeof(mdModule), &written, NULL);
+    }
+    for (module = pcs->lmodules; module; module = module->next)
+    {
+        WriteFile(hFile, module->module.ModuleName, 
+                  strlen(module->module.ModuleName) + 1, &written, NULL);
+        FIXME("CV and misc records not written\n");
+    }
+}
+
+/******************************************************************
+ *		dump_system_info
+ *
+ * Dumps into File the information about the system
+ */
+static  void    dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva)
+{
+    MINIDUMP_SYSTEM_INFO        mdSysInfo;
+    SYSTEM_INFO                 sysInfo;
+    OSVERSIONINFOA              osInfo;
+    DWORD                       written;
+
+    GetSystemInfo(&sysInfo);
+    GetVersionExA(&osInfo);
+
+    mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
+    mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
+    mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
+    mdSysInfo.Reserved0 = 0;
+
+    mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
+    mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
+    mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
+    mdSysInfo.PlatformId = osInfo.dwPlatformId;
+
+    mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo);
+    mdSysInfo.Reserved1 = 0;
+
+    WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL);
+    *rva += sizeof(mdSysInfo);
+    WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1, 
+              &written, NULL);
+    *rva += strlen(osInfo.szCSDVersion) + 1;
+}
+
+/******************************************************************
+ *		dump_threads
+ *
+ * Dumps into File the information about running threads
+ */
+static  void    dump_threads(struct process* pcs, HANDLE hFile, RVA* rva)
+{
+#if 0
+    MINIDUMP_THREAD             mdThd;
+    MINIDUMP_THREAD_LIST        mdThdList;
+    DWORD                       written;
+    DBG_THREAD*                 thd;
+
+    mdThdList.NumberOfThreads = pcs->num_threads;
+    WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads), 
+              &written, NULL);
+    *rva += sizeof(mdThdList.NumberOfThreads) + 
+        mdThdList.NumberOfThreads * sizeof(mdThd);
+    for (thd = pcs->threads; thd; thd = thd->next)
+    {
+        mdThd.ThreadId = thd->tid;
+        mdThd.SuspendCount = 0; /* FIXME */
+        mdThd.PriorityClass = 0; /* FIXME */
+        mdThd.Priority = 0; /* FIXME */
+        mdThd.Teb = 0; /* FIXME */
+        mdThd.Stack.StartOfMemoryRange = 0; /* FIXME */
+        mdThd.Stack.Memory.DataSize = 0; /* FIXME */
+        mdThd.Stack.Memory.Rva = 0; /* FIXME */
+        mdThd.ThreadContext.DataSize = 0;/* FIXME */
+        mdThd.ThreadContext.Rva = 0; /* FIXME */
+
+        WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL);
+        FIXME("Stack & thread context not written\n");
+    }
+#endif
+}
+
+/******************************************************************
+ *		MiniDumpWriteDump (DEBUGHLP.@)
+ *
+ *
+ */
+BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
+                              MINIDUMP_TYPE DumpType,
+                              PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+                              PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+                              PMINIDUMP_CALLBACK_INFORMATION CallbackParam)
+{
+    struct process*     pcs;
+    MINIDUMP_HEADER     mdHead;
+    MINIDUMP_DIRECTORY  mdDir;
+    DWORD               currRva, written;
+    DWORD               i, nStream, addStream;
+    RVA                 rva;
+
+    pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE; /* FIXME: should try to load it ??? */
+
+    /* 1) init */
+
+    nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0;
+    addStream = 0;
+    if (DumpType & MiniDumpNormal)
+        addStream += 3; /* sure ? thread stack back trace */
+
+    if (DumpType & MiniDumpWithDataSegs)
+        FIXME("NIY MiniDumpWithDataSegs\n");
+    if (DumpType & MiniDumpWithFullMemory)
+        FIXME("NIY MiniDumpWithFullMemory\n");
+    if (DumpType & MiniDumpWithHandleData)
+        FIXME("NIY MiniDumpWithHandleData\n");
+    if (DumpType & MiniDumpFilterMemory)
+        FIXME("NIY MiniDumpFilterMemory\n");
+    if (DumpType & MiniDumpScanMemory)
+        FIXME("NIY MiniDumpScanMemory\n");
+
+    /* 2) write header */
+    rva = sizeof(mdHead);
+    mdHead.Signature = MINIDUMP_SIGNATURE;
+    mdHead.Version = MINIDUMP_VERSION;
+    mdHead.NumberOfStreams = nStream + addStream;
+    mdHead.StreamDirectoryRva = rva;
+    mdHead.u.TimeDateStamp = time(NULL);
+    mdHead.Flags = DumpType;
+    WriteFile(hFile, &mdHead, sizeof(mdHead), &written, NULL);
+    
+    /* 3) write stream directories */
+    rva += (nStream + addStream) * sizeof(mdDir);
+    /* 3.1) write data stream directories */
+    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
+    mdDir.StreamType = ModuleListStream;
+    mdDir.Location.Rva = rva;
+    dump_modules(pcs, hFile, &rva);
+    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
+    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
+    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+
+    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
+    mdDir.StreamType = ThreadListStream;
+    mdDir.Location.Rva = rva;
+    dump_threads(pcs, hFile, &rva);
+    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
+    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
+    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+
+    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
+    mdDir.StreamType = SystemInfoStream;
+    mdDir.Location.Rva = rva;
+    dump_system_info(pcs, hFile, &rva);
+    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
+    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
+    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+
+    /* 3.2) write user define stream */
+    for (i = 0; i < nStream; i++)
+    {
+        mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
+        mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
+        mdDir.Location.Rva = rva;
+        WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+        currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+        SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
+        WriteFile(hFile, 
+                  UserStreamParam->UserStreamArray[i].Buffer, 
+                  UserStreamParam->UserStreamArray[i].BufferSize, 
+                  &written, NULL);
+        rva += UserStreamParam->UserStreamArray[i].BufferSize;
+        SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
+    }
+
+    return TRUE;
+}

reactos/lib/dbghelp
memory.c added at 1.1
diff -N memory.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ memory.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,61 @@
+/*
+ * File memory.c - managing memory
+ *
+ * Copyright (C) 2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include "dbghelp_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+/******************************************************************
+ *		addr_to_linear
+ *
+ * converts an address into its linear value
+ */
+DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr)
+{
+    LDT_ENTRY	le;
+
+    switch (addr->Mode)
+    {
+    case AddrMode1616:
+        if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
+            return (le.HighWord.Bits.BaseHi << 24) + 
+                (le.HighWord.Bits.BaseMid << 16) + le.BaseLow + LOWORD(addr->Offset);
+        break;
+    case AddrMode1632:
+        if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
+            return (le.HighWord.Bits.BaseHi << 24) + 
+                (le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->Offset;
+        break;
+    case AddrModeReal:
+        return (DWORD)(LOWORD(addr->Segment) << 4) + addr->Offset;
+    case AddrModeFlat:
+        return addr->Offset;
+    default:
+        FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
+        return 0;
+    }
+    FIXME("Failed to linearize address %04x:%08lx (mode %x)\n",
+          addr->Segment, addr->Offset, addr->Mode);
+    return 0;
+}

reactos/lib/dbghelp
Makefile.ros-template added at 1.1
diff -N Makefile.ros-template
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.ros-template	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,21 @@
+# $Id: Makefile.ros-template,v 1.1 2004/12/16 17:42:10 sedwards Exp $
+
+TARGET_NAME = dbghelp
+
+TARGET_OBJECTS = @C_SRCS@
+
+TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
+
+TARGET_SDKLIBS = @IMPORTS@ winmm.a wine.a wine_uuid.a ntdll.a
+
+TARGET_BASE = $(TARGET_BASE_LIB_COMCTL32)
+
+TARGET_RC_SRCS = @RC_SRCS@
+TARGET_RC_BINSRC = @RC_BINSRC@
+TARGET_RC_BINARIES = @RC_BINARIES@
+
+default: all
+
+DEP_OBJECTS = $(TARGET_OBJECTS)
+
+include $(TOOLS_PATH)/depend.mk

reactos/lib/dbghelp
Makefile.in added at 1.1
diff -N Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.in	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,28 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = dbghelp.dll
+IMPORTS   = psapi kernel32 ntdll
+
+C_SRCS = \
+	coff.c \
+	dbghelp.c \
+	elf_module.c \
+	image.c \
+	memory.c \
+	minidump.c \
+	module.c \
+	msc.c \
+	path.c \
+	pe_module.c \
+	source.c \
+	stabs.c \
+	stack.c \
+	storage.c \
+	symbol.c \
+	type.c
+
+@MAKE_DLL_RULES@
+
+### Dependencies:

reactos/lib/dbghelp
Makefile added at 1.1
diff -N Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,409 @@
+TOPSRCDIR = ../..
+TOPOBJDIR = ../..
+SRCDIR    = .
+
+MODULE    = dbghelp.dll
+IMPORTS   = psapi kernel32 ntdll
+
+C_SRCS = \
+	coff.c \
+	dbghelp.c \
+	elf_module.c \
+	image.c \
+	memory.c \
+	minidump.c \
+	module.c \
+	msc.c \
+	path.c \
+	pe_module.c \
+	source.c \
+	stabs.c \
+	stack.c \
+	storage.c \
+	symbol.c \
+	type.c
+
+
+# Global rules for building dlls     -*-Makefile-*-
+#
+# Each individual makefile should define the following variables:
+# MODULE       : name of the main module being built
+# EXTRALIBS    : extra libraries to link in (optional)
+# SPEC_SRCS16  : interface definition files for 16-bit dlls (optional)
+# SUBSYSTEM    : (optional) subsystem (for native dlls)
+#
+# plus all variables required by the global Make.rules.in
+#
+
+DLLDEFS     = 
+DLLFLAGS    = -D_REENTRANT -fPIC
+DLLEXT      = .so
+DEFS        = -D__WINESRC__ $(DLLDEFS) $(EXTRADEFS)
+MAINSPEC    = $(MODULE:%.dll=%).spec
+SPEC_DEF    = $(MAINSPEC).def
+WIN16_FILES = $(SPEC_SRCS16:.spec=.spec.o) $(C_SRCS16:.c=.o) $(EXTRA_OBJS16)
+ALL_OBJS    = $(WIN16_FILES) $(OBJS) $(MODULE).dbg.o
+ALL_LIBS    = $(LIBWINE) $(EXTRALIBS) $(LIBPORT) $(LDFLAGS) $(LIBS)
+IMPORTLIBS  = $(DELAYIMPORTS:%=$(DLLDIR)/lib%.$(IMPLIBEXT)) $(IMPORTS:%=$(DLLDIR)/lib%.$(IMPLIBEXT))
+
+all: $(MODULE)$(DLLEXT) $(SUBDIRS)
+
+
+# Global rules shared by all makefiles     -*-Makefile-*-
+#
+# Each individual makefile must define the following variables:
+# TOPSRCDIR    : top-level source directory
+# TOPOBJDIR    : top-level object directory
+# SRCDIR       : source directory for this module
+# MODULE       : name of the module being built
+#
+# Each individual makefile may define the following additional variables:
+# C_SRCS       : C sources for the module
+# C_SRCS16     : 16-bit C sources for the module
+# RC_SRCS      : resource source files
+# EXTRA_SRCS   : extra source files for make depend
+# EXTRA_OBJS   : extra object files
+# IMPORTS      : dlls to import
+# DELAYIMPORTS : dlls to import in delayed mode
+# SUBDIRS      : subdirectories that contain a Makefile
+# EXTRASUBDIRS : subdirectories that do not contain a Makefile
+# INSTALLSUBDIRS : subdirectories to run make install/uninstall into
+
+# First some useful definitions
+
+SHELL     = /bin/sh
+CC        = gcc
+CFLAGS    = -g -O2
+CPPFLAGS  = 
+LIBS      = 
+BISON     = bison
+YACC      = $(BISON) -y
+LEX       = flex
+LEXLIB    = -lfl
+EXEEXT    = 
+OBJEXT    = o
+LIBEXT    = so
+DLLEXT    = .so
+IMPLIBEXT = def
+LDSHARED  = $(CC) -shared $(SONAME:%=-Wl,-soname,%) $(VERSCRIPT:%=-Wl,--version-script=%)
+DLLTOOL   = false
+DLLWRAP   = 
+AR        = ar rc
+RANLIB    = ranlib
+STRIP     = strip
+WINDRES   = false
+LN        = ln
+LN_S      = ln -s
+TOOLSDIR  = $(TOPOBJDIR)
+AS        = as
+LD        = ld
+LDFLAGS   = 
+RM        = rm -f
+MV        = mv
+LINT      = 
+LINTFLAGS = 
+FONTFORGE = false
+INCLUDES     = -I$(SRCDIR) -I. -I$(TOPSRCDIR)/include -I$(TOPOBJDIR)/include $(EXTRAINCL)
+EXTRACFLAGS  = -Wall -pipe -mpreferred-stack-boundary=2 -fno-strict-aliasing -gstabs+ -Wpointer-arith
+ALLCFLAGS    = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS)
+ALLLINTFLAGS = $(INCLUDES) $(DEFS) $(LINTFLAGS)
+IDLFLAGS     = $(INCLUDES) $(DEFS) $(EXTRAIDLFLAGS)
+MKINSTALLDIRS= $(TOPSRCDIR)/tools/mkinstalldirs -m 755
+WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check
+WINEWRAPPER  = $(TOPSRCDIR)/tools/winewrapper
+C2MAN        = $(TOPSRCDIR)/tools/c2man.pl
+RUNTEST      = $(TOPSRCDIR)/tools/runtest
+WINEBUILD    = $(TOOLSDIR)/tools/winebuild/winebuild
+MAKEDEP      = $(TOOLSDIR)/tools/makedep
+WRC          = $(TOOLSDIR)/tools/wrc/wrc
+BIN2RES      = $(TOOLSDIR)/tools/bin2res
+WMC          = $(TOOLSDIR)/tools/wmc/wmc
+WIDL         = $(TOOLSDIR)/tools/widl/widl
+WINEGCC      = $(TOOLSDIR)/tools/winegcc/winegcc
+SFNT2FNT     = $(TOOLSDIR)/tools/sfnt2fnt
+FNT2FON      = $(TOOLSDIR)/tools/fnt2fon
+RC           = $(WRC)
+RC16         = $(WRC)
+RCFLAGS      = --nostdinc $(INCLUDES) $(DEFS) $(EXTRARCFLAGS)
+RC16FLAGS    = -O res16 $(RCFLAGS)
+LDPATH       = LD_LIBRARY_PATH="$(TOOLSDIR)/libs/unicode:$$LD_LIBRARY_PATH"
+DLLDIR       = $(TOPOBJDIR)/dlls
+LIBDIR       = $(TOPOBJDIR)/libs
+LIBPORT      = -L$(TOPOBJDIR)/libs/port -lwine_port
+LIBUNICODE   = -L$(TOPOBJDIR)/libs/unicode -lwine_unicode
+LIBWINE      = -L$(TOPOBJDIR)/libs/wine -lwine
+
+
+
+# Installation infos
+
+INSTALL         = /usr/bin/ginstall -c $(INSTALL_FLAGS)
+INSTALL_PROGRAM = ${INSTALL} $(INSTALL_PROGRAM_FLAGS)
+INSTALL_SCRIPT  = ${INSTALL} $(INSTALL_SCRIPT_FLAGS)
+INSTALL_DATA    = ${INSTALL} -m 644 $(INSTALL_DATA_FLAGS)
+prefix          = /usr/local
+exec_prefix     = ${prefix}
+bindir          = ${exec_prefix}/bin
+libdir          = ${exec_prefix}/lib
+datadir         = ${prefix}/share
+infodir         = ${prefix}/info
+mandir          = ${prefix}/man
+sysconfdir      = ${prefix}/etc
+includedir      = ${prefix}/include/wine
+dlldir          = ${exec_prefix}/lib/wine
+prog_manext     = 1
+api_manext      = 3w
+conf_manext     = 5
+CLEAN_FILES     = *.o *.a *.so *.ln *.$(LIBEXT) \\\#*\\\# *~ *% .\\\#* *.bak *.orig *.rej \
+                  *.flc *.spec.c *.spec.def *.dbg.c *.tab.c *.tab.h lex.yy.c core
+
+OBJS = $(C_SRCS:.c=.o) $(EXTRA_OBJS)
+
+RCOBJS = $(RC_SRCS:.rc=.res.o)
+LINTS  = $(C_SRCS:.c=.ln)
+
+# Implicit rules
+
+.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.c .spec.def .idl .h .ok .sfd .ttf
+
+.c.o:
+	$(CC) -c $(ALLCFLAGS) -o $@ $<
+
+.s.o:
+	$(AS) -o $@ $<
+
+.mc.mc.rc:
+	$(LDPATH) $(WMC) -i -U -H /dev/null -o $@ $<
+
+.rc.res:
+	$(LDPATH) $(RC) $(RCFLAGS) -fo$@ $<
+
+.res.res.o:
+	$(WINDRES) -i $< -o $@
+
+.spec.spec.c:
+	$(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $<
+
+.spec.spec.def:
+	$(WINEBUILD) -w $(DEFS) -o $@ --def $<
+
+.idl.h:
+	$(WIDL) $(IDLFLAGS) -h -H $@ $<
+
+.c.ln:
+	$(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 )
+
+.c.ok:
+	$(RUNTEST) $(RUNTESTFLAGS) $< && touch $@
+
+.sfd.ttf:
+	$(FONTFORGE) -script $(TOPSRCDIR)/fonts/genttf.ff $<
+
+# 'all' target first in case the enclosing Makefile didn't define any target
+
+all: Makefile
+
+filter:
+	@$(TOPSRCDIR)/tools/winapi/make_filter --make $(MAKE) all
+
+.PHONY: all filter
+
+# Rules for resources
+
+$(RC_BINARIES): $(BIN2RES) $(RC_BINSRC)
+	$(BIN2RES) -f -o $@ $(SRCDIR)/$(RC_BINSRC)
+
+$(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res): $(WRC) $(RC_BINARIES)
+
+# Rule for main module debug channels
+
+$(MODULE).dbg.c: $(C_SRCS) $(C_SRCS16) $(WINEBUILD)
+	$(WINEBUILD) $(DEFS) -o $@ --debug -C$(SRCDIR) $(C_SRCS) $(C_SRCS16)
+
+# Rules for makefile
+
+Makefile: Makefile.in $(TOPSRCDIR)/configure
+	@echo Makefile is older than $?, please rerun $(TOPSRCDIR)/configure
+	@exit 1
+
+# Rule for linting
+
+$(MODULE).ln : $(LINTS)
+	if test "$(LINTS)" ; \
+	then \
+		$(LINT) $(ALLLINTFLAGS) -o$(MODULE) $(LINTS) ; \
+	        $(MV) llib-l$(MODULE).ln $(MODULE).ln ; \
+	else \
+		$(LINT) $(ALLLINTFLAGS) -C$(MODULE) /dev/null ; \
+	fi
+
+lint:: $(MODULE).ln
+
+# Rules for Windows API checking
+
+winapi_check:: dummy
+	$(WINAPI_CHECK) $(WINAPI_CHECK_FLAGS) $(WINAPI_CHECK_EXTRA_FLAGS) .
+
+.PHONY: winapi_check
+
+# Rules for dependencies
+
+$(SUBDIRS:%=%/__depend__): dummy
+	cd `dirname $@` && $(MAKE) depend
+
+depend: $(IDL_SRCS:.idl=.h) $(SUBDIRS:%=%/__depend__)
+	$(MAKEDEP) $(INCLUDES) -C$(SRCDIR) $(C_SRCS) $(C_SRCS16) $(RC_SRCS) $(RC_SRCS16) $(MC_SRCS) $(IDL_SRCS) $(EXTRA_SRCS)
+
+.PHONY: depend $(SUBDIRS:%=%/__depend__)
+
+# Rules for cleaning
+
+$(SUBDIRS:%=%/__clean__): dummy
+	cd `dirname $@` && $(MAKE) clean
+
+$(SUBDIRS:%=%/__testclean__): dummy
+	cd `dirname $@` && $(MAKE) testclean
+
+$(EXTRASUBDIRS:%=%/__clean__): dummy
+	-cd `dirname $@` && $(RM) $(CLEAN_FILES)
+
+testclean:: $(SUBDIRS:%=%/__testclean__)
+
+clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
+	$(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(IDL_SRCS:.idl=.h) $(PROGRAMS) $(RC_BINARIES)
+
+.PHONY: clean testclean $(SUBDIRS:%=%/__clean__) $(SUBDIRS:%=%/__testclean__) $(EXTRASUBDIRS:%=%/__clean__)
+
+# Rules for installing
+
+$(SUBDIRS:%=%/__install__): dummy
+	cd `dirname $@` && $(MAKE) install
+
+$(SUBDIRS:%=%/__install-lib__): dummy
+	cd `dirname $@` && $(MAKE) install-lib
+
+$(SUBDIRS:%=%/__install-dev__): dummy
+	cd `dirname $@` && $(MAKE) install-dev
+
+$(SUBDIRS:%=%/__uninstall__): dummy
+	cd `dirname $@` && $(MAKE) uninstall
+
+install:: $(INSTALLSUBDIRS:%=%/__install__)
+
+uninstall:: $(INSTALLSUBDIRS:%=%/__uninstall__)
+
+.PHONY: install install-lib install-dev uninstall \
+	$(SUBDIRS:%=%/__install__) $(SUBDIRS:%=%/__uninstall__) \
+	$(SUBDIRS:%=%/__install-lib__) $(SUBDIRS:%=%/__install-dev__)
+
+# Rules for checking that no imports are missing
+
+$(SUBDIRS:%=%/__checklink__): dummy
+	@cd `dirname $@` && $(MAKE) checklink
+
+.PHONY: checklink $(SUBDIRS:%=%/__checklink__)
+
+# Rules for testing
+
+$(SUBDIRS:%=%/__test__): dummy
+	@cd `dirname $@` && $(MAKE) test
+
+$(SUBDIRS:%=%/__crosstest__): dummy
+	@cd `dirname $@` && $(MAKE) crosstest
+
+.PHONY: check test crosstest $(SUBDIRS:%=%/__test__) $(SUBDIRS:%=%/__crosstest__)
+
+# Misc. rules
+
+$(MC_SRCS:.mc=.mc.rc): $(WMC)
+
+$(IDL_SRCS:.idl=.h): $(WIDL)
+
+$(SUBDIRS): dummy
+	@cd $@ && $(MAKE)
+
+dummy:
+
+.PHONY: dummy $(SUBDIRS)
+
+# End of global rules
+
+# Rules for .so files
+
+$(MODULE).so: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) Makefile.in
+	$(WINEGCC) -B$(TOOLSDIR)/tools/winebuild -shared $(SRCDIR)/$(MAINSPEC) $(ALL_OBJS) $(RC_SRCS:.rc=.res) $(SUBSYSTEM:%=-Wb,--subsystem,%) -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(IMPORTS:%=-l%) $(ALL_LIBS)
+
+# Rules for .dll files
+
+$(MODULE): $(RCOBJS) $(OBJS) $(MODULE).dbg.o $(SPEC_DEF) $(IMPORTLIBS) Makefile.in
+	$(DLLWRAP) -k --def $(SPEC_DEF) -o $@ $(RCOBJS) $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(ALL_LIBS)
+
+$(SPEC_DEF): $(WINEBUILD)
+
+# Rules for checking that no imports are missing
+
+.PHONY: checklink16 $(WIN16_FILES:%=__checklink16__%)
+
+$(WIN16_FILES:%=__checklink16__%): checklink16
+
+checklink16:: $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o dummy
+	$(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) -lm && $(RM) checklink $(MAINSPEC).c $(MAINSPEC).o
+
+checklink:: $(WIN16_FILES:%=__checklink16__%)
+
+# Rules for testing
+
+check test:: $(SUBDIRS:%=%/__test__)
+
+crosstest:: $(SUBDIRS:%=%/__crosstest__)
+
+# Rule to explicitly generate the .spec.c for debugging
+
+$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD)
+	$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
+
+# Rules for auto documentation
+
+man: $(C_SRCS)
+	$(C2MAN) -o $(TOPOBJDIR)/documentation/man$(api_manext) -R$(TOPOBJDIR) -S$(api_manext) $(INCLUDES) $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16)
+
+doc-html: $(C_SRCS)
+	$(C2MAN) -o $(TOPOBJDIR)/documentation/html -R$(TOPOBJDIR) $(INCLUDES) -Th $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16)
+
+doc-sgml: $(C_SRCS)
+	$(C2MAN) -o $(TOPOBJDIR)/documentation/api-guide -R$(TOPOBJDIR) $(INCLUDES) -Ts $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16)
+
+.PHONY: man doc-html doc-sgml
+
+# Rules for installation
+
+EXE_SPECS16 = $(SPEC_SRCS16:.exe.spec=.exe)
+DRV_SPECS16 = $(EXE_SPECS16:.drv.spec=.drv)
+ALL_SPECS16 = $(DRV_SPECS16:.spec=.dll)
+
+WIN16_INSTALL = $(ALL_SPECS16:%=_install_/%)
+
+.PHONY: install_lib $(ALL_SPECS16:%=_install_/%) $(ALL_SPECS16:%=_uninstall_/%)
+
+$(ALL_SPECS16:%=_install_/%): install_lib
+	cd $(dlldir) && $(RM) `basename $@`$(DLLEXT) && $(LN_S) $(MODULE)$(DLLEXT) `basename $@`$(DLLEXT)
+
+$(ALL_SPECS16:%=_uninstall_/%): dummy
+	$(RM) $(dlldir)/`basename $@`$(DLLEXT)
+
+install_lib: $(MODULE)$(DLLEXT)
+	$(MKINSTALLDIRS) $(dlldir)
+	$(INSTALL_PROGRAM) $(MODULE)$(DLLEXT) $(dlldir)/$(MODULE)$(DLLEXT)
+
+install:: install_lib $(WIN16_INSTALL)
+
+uninstall:: $(ALL_SPECS16:%=_uninstall_/%)
+	$(RM) $(dlldir)/$(MODULE)$(DLLEXT)
+
+# Misc. rules
+
+$(SPEC_SRCS16:.spec=.spec.c): $(WINEBUILD)
+
+# End of global dll rules
+
+### Dependencies:

reactos/lib/dbghelp
makefile added at 1.1
diff -N makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ makefile	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,9 @@
+# $Id: makefile,v 1.1 2004/12/16 17:42:10 sedwards Exp $
+
+PATH_TO_TOP = ../..
+
+TARGET_TYPE = winedll
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk

reactos/lib/dbghelp
image.c added at 1.1
diff -N image.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ image.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,61 @@
+/*
+ * File image.c - managing images
+ *
+ * Copyright (C) 2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "dbghelp_private.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+/***********************************************************************
+ *		GetTimestampForLoadedLibrary (DBGHELP.@)
+ */
+DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE Module)
+{
+    IMAGE_NT_HEADERS*   nth = RtlImageNtHeader(Module);
+    return (nth) ? nth->FileHeader.TimeDateStamp : 0;
+}
+
+/***********************************************************************
+ *		MapDebugInformation (DBGHELP.@)
+ */
+PIMAGE_DEBUG_INFORMATION WINAPI MapDebugInformation(HANDLE FileHandle, LPSTR FileName,
+                                                    LPSTR SymbolPath, DWORD ImageBase)
+{
+    FIXME("(%p, %s, %s, 0x%08lx): stub\n", FileHandle, FileName, SymbolPath, ImageBase);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return NULL;
+}
+
+/***********************************************************************
+ *		UnmapDebugInformation (DBGHELP.@)
+ */
+BOOL WINAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo)
+{
+    FIXME("(%p): stub\n", DebugInfo);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}

reactos/lib/dbghelp
elf_module.c added at 1.1
diff -N elf_module.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ elf_module.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,1176 @@
+/*
+ * File elf.c - processing of ELF files
+ *
+ * Copyright (C) 1996, Eric Youngdale.
+ *		 1999-2004 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+
+#include "dbghelp_private.h"
+
+#if defined(__svr4__) || defined(__sun)
+#define __ELF__
+#endif
+
+#ifdef HAVE_ELF_H
+# include <elf.h>
+#endif
+#ifdef HAVE_SYS_ELF32_H
+# include <sys/elf32.h>
+#endif
+#ifdef HAVE_SYS_EXEC_ELF_H
+# include <sys/exec_elf.h>
+#endif
+#if !defined(DT_NUM)
+# if defined(DT_COUNT)
+#  define DT_NUM DT_COUNT
+# else
+/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */
+#  define DT_NUM 24
+# endif
+#endif
+#ifdef HAVE_LINK_H
+# include <link.h>
+#endif
+#ifdef HAVE_SYS_LINK_H
+# include <sys/link.h>
+#endif
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+struct elf_module_info
+{
+    unsigned long               elf_addr;
+    unsigned short	        elf_mark : 1,
+                                elf_loader : 1;
+};
+
+#ifdef __ELF__
+
+#define ELF_INFO_DEBUG_HEADER   0x0001
+#define ELF_INFO_MODULE         0x0002
+
+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) */
+};
+
+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_hash_symtab
+ *
+ * creating an internal hash table to ease use ELF symtab information lookup
+ */
+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, j, nsym;
+    const char*                 strp;
+    const char*                 symname;
+    const char*                 filename = NULL;
+    const char*                 ptr;
+    const Elf32_Sym*            symp;
+    struct symtab_elt*          ste;
+
+    symp = (const Elf32_Sym*)(map_addr + symtab->sh_offset);
+    nsym = symtab->sh_size / sizeof(*symp);
+    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)
+        {
+            continue;
+        }
+
+        symname = strp + symp->st_name;
+
+        if (ELF32_ST_TYPE(symp->st_info) == STT_FILE)
+        {
+            filename = symname;
+            continue;
+        }
+        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;
+
+        /* FIXME: we don't need to handle them (GCC internals)
+         * Moreover, they screw up our symbol lookup :-/
+         */
+        if (symname[0] == '.' && symname[1] == 'L' && isdigit(symname[2]))
+            continue;
+
+        ste = pool_alloc(pool, sizeof(*ste));
+        /* GCC seems to emit, in some cases, a .<digit>+ suffix.
+         * This is used for static variable inside functions, so
+         * that we can have several such variables with same name in
+         * the same compilation unit
+         * We simply ignore that suffix when present (we also get rid
+         * of it in stabs parsing)
+         */
+        ptr = symname + strlen(symname) - 1;
+        ste->ht_elt.name = symname;
+        if (isdigit(*ptr))
+        {
+            while (*ptr >= '0' && *ptr <= '9' && ptr >= symname) ptr--;
+            if (ptr > symname && *ptr == '.')
+            {
+                char* n = pool_alloc(pool, ptr - symname + 1);
+                memcpy(n, symname, ptr - symname + 1);
+                n[ptr - symname] = '\0';
+                ste->ht_elt.name = n;
+            }
+        }
+        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 &&
+                ((struct symt_function*)sym)->size)
+            {
+                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;
+            } else FIXME("Couldn't find %s\n", sym->hash_elt.name);
+            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;
+                    ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ?
+                        DataIsFileStatic : DataIsGlobal;
+                }
+                break;
+            default:;
+            }
+            break;
+        default:
+            FIXME("Unsupported tag %u\n", sym->symt.tag);
+            break;
+        }
+    }
+    /* since we may have changed some addresses & sizes, mark the module to be resorted */
+    module->sortlist_valid = FALSE;
+}
+
+/******************************************************************
+ *		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;
+    int                         idx;
+
+    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
+        {
+            ULONG64     ref_addr;
+
+            idx = symt_find_nearest(module, addr);
+            if (idx != -1)
+                symt_get_info(&module->addr_sorttab[idx]->symt, 
+                              TI_GET_ADDRESS, &ref_addr);
+            if (idx == -1 || addr != ref_addr)
+            {
+                /* 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,
+                                             ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL,
+                                             addr, ste->symp->st_size, NULL);
+                }
+                /* FIXME: this is a hack !!!
+                 * we are adding new symbols, but as we're parsing a symbol table
+                 * (hopefully without duplicate symbols) we delay rebuilding the sorted
+                 * module table until we're done with the symbol table
+                 * Otherwise, as we intertwine symbols's add and lookup, performance
+                 * is rather bad
+                 */
+                module->sortlist_valid = TRUE;
+            }
+            else if (strcmp(ste->ht_elt.name, module->addr_sorttab[idx]->hash_elt.name))
+            {
+                ULONG64 xaddr = 0;
+                DWORD   xsize = 0, kind = -1;
+
+                symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_ADDRESS,  &xaddr);
+                symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_LENGTH,   &xsize);
+                symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_DATAKIND, &kind);
+
+                /* If none of symbols has a correct size, we consider they are both markers
+                 * Hence, we can silence this warning
+                 * Also, we check that we don't have two symbols, one local, the other 
+                 * global which is legal
+                 */
+                if ((xsize || ste->symp->st_size) && 
+                    (kind == (ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal))
+                    FIXME("Duplicate in %s: %s<%08lx-%08x> %s<%s-%08lx>\n", 
+                          module->module.ModuleName,
+                          ste->ht_elt.name, addr, ste->symp->st_size,
+                          module->addr_sorttab[idx]->hash_elt.name,
+                          wine_dbgstr_longlong(xaddr), xsize);
+            }
+        }
+    }
+    /* see comment above */
+    module->sortlist_valid = FALSE;
+    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)
+{
+    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;
+
+    /* FIXME: we're missing the ELF entry point here */
+
+    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);
+
+        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;
+}
+
+/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
+   the following calc_crc32 code or tables extracted from it, as desired without
+   restriction. */
+
+/**********************************************************************\
+|* Demonstration program to compute the 32-bit CRC used as the frame  *|
+|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|
+|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|
+|* protocol).  The 32-bit FCS was added via the Federal Register,     *|
+|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|
+|* this polynomial is or will be included in CCITT V.41, which        *|
+|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|
+|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|
+|* errors by a factor of 10^-5 over 16-bit FCS.                       *|
+\**********************************************************************/
+
+/* First, the polynomial itself and its table of feedback terms.  The  */
+/* polynomial is                                                       */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in  */
+/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
+/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
+/* the MSB being 1.                                                    */
+
+/* Note that the usual hardware shift register implementation, which   */
+/* is what we're using (we're merely optimizing it by doing eight-bit  */
+/* chunks at a time) shifts bits into the lowest-order term.  In our   */
+/* implementation, that means shifting towards the right.  Why do we   */
+/* do it this way?  Because the calculated CRC must be transmitted in  */
+/* order from highest-order term to lowest-order term.  UARTs transmit */
+/* characters in order from LSB to MSB.  By storing the CRC this way,  */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part.  Reception works similarly.                  */
+
+/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
+/*                                                                     */
+/*  1. The table can be generated at runtime if desired; code to do so */
+/*     is shown later.  It might not be obvious, but the feedback      */
+/*     terms simply represent the results of eight shift/xor opera-    */
+/*     tions for all combinations of data and CRC register values.     */
+/*                                                                     */
+/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
+/*     be they sixteen or thirty-two bits wide.  You simply choose the */
+/*     appropriate table.  Alternatively, because the table can be     */
+/*     generated at runtime, you can start by generating the table for */
+/*     the polynomial in question and use exactly the same "updcrc",   */
+/*     if your application needn't simultaneously handle two CRC       */
+/*     polynomials.  (Note, however, that XMODEM is strange.)          */
+/*                                                                     */
+/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
+/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
+/*                                                                     */
+/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
+/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
+/*     hardware you could probably optimize the shift in assembler by  */
+/*     using byte-swap instructions.                                   */
+
+
+static DWORD calc_crc32(const unsigned char *buf, size_t len)
+{
+#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+    static const DWORD crc_32_tab[] =
+    { /* CRC polynomial 0xedb88320 */
+        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+        0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+        0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+        0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+        0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+        0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+        0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+        0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+        0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+        0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+        0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+        0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+        0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+        0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+        0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+        0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+        0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+    };
+    size_t i;
+    DWORD crc = ~0;
+    for(i = 0; i < len; i++)
+        crc = UPDC32(buf[i], crc);
+    return ~crc;
+#undef UPDC32
+}
+
+
+/******************************************************************
+ *		elf_load_debug_info_from_file
+ *
+ * Loads the symbolic information from ELF module stored in 'file'
+ * the module has been loaded at 'load_offset' address, so symbols' address
+ * relocation is performed. crc optionally points to the CRC of the debug file
+ * to load.
+ * returns
+ *	0 if the file doesn't contain symbolic info (or this info cannot be
+ *	read or parsed)
+ *	1 on success
+ */
+static BOOL elf_load_debug_info_from_file(
+    struct module* module, const char* file, struct pool* pool,
+    struct hash_table* ht_symtab, const DWORD *crc)
+{
+    BOOL                ret = FALSE;
+    char*	        addr = (char*)0xffffffff;
+    int		        fd = -1;
+    struct stat	        statbuf;
+    const Elf32_Ehdr*   ehptr;
+    const Elf32_Shdr*   spnt;
+    const char*	        shstrtab;
+    int	       	        i;
+    int                 symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect, debuglink_sect;
+    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_info)
+    {
+	ERR("Bad elf module '%s'\n", module->module.LoadedImageName);
+	return FALSE;
+    }
+
+    TRACE("%s\n", file);
+    /* check that the file exists, and that the module hasn't been loaded yet */
+    if (stat(file, &statbuf) == -1) goto leave;
+    if (S_ISDIR(statbuf.st_mode)) goto leave;
+
+    /*
+     * Now open the file, so that we can mmap() it.
+     */
+    if ((fd = open(file, O_RDONLY)) == -1) goto leave;
+
+    /*
+     * Now mmap() the file.
+     */
+    addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == (char*)0xffffffff) goto leave;
+
+    if (crc && (*crc != calc_crc32(addr, statbuf.st_size)))
+    {
+        ERR("Bad CRC for file %s\n", file);
+        /* we don't tolerate mis-matched files */
+        goto leave;
+    }
+
+    /*
+     * Next, we need to find a few of the internal ELF headers within
+     * this thing.  We need the main executable header, and the section
+     * table.
+     */
+    ehptr = (Elf32_Ehdr*)addr;
+    spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
+    shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
+
+    symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = debuglink_sect = -1;
+
+    for (i = 0; i < ehptr->e_shnum; i++)
+    {
+	if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
+	    stab_sect = i;
+	if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
+	    stabstr_sect = i;
+	if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
+	    debug_sect = i;
+	if (strcmp(shstrtab + spnt[i].sh_name, ".gnu_debuglink") == 0)
+	    debuglink_sect = i;
+	if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
+	    (spnt[i].sh_type == SHT_SYMTAB))
+            symtab_sect = i;
+        if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
+            (spnt[i].sh_type == SHT_DYNSYM))
+            dynsym_sect = i;
+    }
+
+    if (symtab_sect == -1)
+    {
+        /* 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;
+    }
+
+    module->module.SymType = SymExport;
+
+    /* 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 (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+    {
+        if (stab_sect != -1 && stabstr_sect != -1)
+        {
+            /* OK, now just parse all of the stabs. */
+            ret = stabs_parse(module, module->elf_info->elf_addr,
+                              addr + spnt[stab_sect].sh_offset,
+                              spnt[stab_sect].sh_size,
+                              addr + spnt[stabstr_sect].sh_offset,
+                              spnt[stabstr_sect].sh_size);
+            if (!ret)
+            {
+                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 for %s\n", module->module.ModuleName);
+        }
+        else if (debuglink_sect != -1)
+        {
+            DWORD crc;
+            const char * file = (const char *)(addr + spnt[debuglink_sect].sh_offset);
+            /* crc is stored after the null terminated file string rounded
+             * up to the next 4 byte boundary */
+            crc = *(const DWORD *)(file + ((DWORD_PTR)(strlen(file) + 4) & ~3));
+            ret = elf_load_debug_info_from_file(module, file, pool, ht_symtab, &crc);
+            if (!ret)
+                WARN("Couldn't load linked debug file %s\n", file);
+        }
+    }
+    if (strstr(module->module.ModuleName, "<elf>") ||
+        !strcmp(module->module.ModuleName, "<wine-loader>"))
+    {
+        /* 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 all the public symbols from symtab */
+    if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE;
+
+leave:
+    if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
+    if (fd != -1) close(fd);
+
+    return ret;
+}
+
+/******************************************************************
+ *		elf_load_debug_info
+ *
+ * Loads ELF debugging information from the module image file.
+ */
+BOOL elf_load_debug_info(struct module* module)
+{
+    BOOL              ret;
+    struct pool       pool;
+    struct hash_table ht_symtab;
+
+    pool_init(&pool, 65536);
+    hash_table_init(&pool, &ht_symtab, 256);
+
+    ret = elf_load_debug_info_from_file(module,
+        module->module.LoadedImageName, &pool, &ht_symtab, NULL);
+
+    pool_destroy(&pool);
+
+    return ret;
+}
+
+
+/******************************************************************
+ *		is_dt_flag_valid
+ * returns true iff the section tag is valid 
+ */
+static unsigned is_dt_flag_valid(unsigned d_tag)
+{
+#ifndef DT_PROCNUM
+#define DT_PROCNUM 0
+#endif
+#ifndef DT_EXTRANUM
+#define DT_EXTRANUM 0
+#endif
+    return (d_tag >= 0 && d_tag < DT_NUM + DT_PROCNUM + DT_EXTRANUM)
+#if defined(DT_LOOS) && defined(DT_HIOS)
+        || (d_tag >= DT_LOOS && d_tag < DT_HIOS)
+#endif
+#if defined(DT_LOPROC) && defined(DT_HIPROC)
+        || (d_tag >= DT_LOPROC && d_tag < DT_HIPROC)
+#endif
+        ;
+}
+
+/******************************************************************
+ *		elf_load_file
+ *
+ * Loads the information for ELF module stored in 'filename'
+ * the module has been loaded at 'load_offset' address
+ * returns
+ *	-1 if the file cannot be found/opened
+ *	0 if the file doesn't contain symbolic info (or this info cannot be
+ *	read or parsed)
+ *	1 on success
+ */
+static BOOL elf_load_file(struct process* pcs, const char* filename,
+                          unsigned long load_offset, struct elf_info* elf_info)
+{
+    static const BYTE   elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
+    BOOL                ret = FALSE;
+    const char*	        addr = (char*)0xffffffff;
+    int		        fd = -1;
+    struct stat	        statbuf;
+    const Elf32_Ehdr*   ehptr;
+    const Elf32_Shdr*   spnt;
+    const Elf32_Phdr*	ppnt;
+    const char*         shstrtab;
+    int	       	        i;
+    DWORD	        size, start;
+    unsigned            tmp, page_mask = getpagesize() - 1;
+
+    TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset);
+
+    /* check that the file exists, and that the module hasn't been loaded yet */
+    if (stat(filename, &statbuf) == -1) goto leave;
+
+    /* Now open the file, so that we can mmap() it. */
+    if ((fd = open(filename, O_RDONLY)) == -1) goto leave;
+
+    /* Now mmap() the file. */
+    addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == (char*)-1) goto leave;
+
+    /* Next, we need to find a few of the internal ELF headers within
+     * this thing.  We need the main executable header, and the section
+     * table.
+     */
+    ehptr = (const Elf32_Ehdr*)addr;
+    if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
+
+    spnt = (const Elf32_Shdr*)(addr + ehptr->e_shoff);
+    shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
+
+    /* grab size of module once loaded in memory */
+    ppnt = (const Elf32_Phdr*)(addr + ehptr->e_phoff);
+    size = 0; start = ~0L;
+
+    for (i = 0; i < ehptr->e_phnum; i++)
+    {
+        if (ppnt[i].p_type == PT_LOAD)
+        {
+            tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask;
+            if (size < tmp) size = tmp;
+            if (ppnt[i].p_vaddr < start) start = ppnt[i].p_vaddr;
+        }
+    }
+
+    /* if non relocatable ELF, then remove fixed address from computation
+     * otherwise, all addresses are zero based and start has no effect
+     */
+    size -= start;
+    if (!start && !load_offset)
+        ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
+            filename);
+    if (start && load_offset)
+    {
+        WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. "
+             "Assuming load address is corrupt\n", filename, load_offset);
+        load_offset = 0;
+    }
+
+    if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
+    {
+        for (i = 0; i < ehptr->e_shnum; i++)
+        {
+            if (strcmp(shstrtab + spnt[i].sh_name, ".dynamic") == 0 &&
+                spnt[i].sh_type == SHT_DYNAMIC)
+            {
+                Elf32_Dyn       dyn;
+                char*           ptr = (char*)spnt[i].sh_addr;
+                unsigned long   len;
+
+                do
+                {
+                    if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) ||
+                        len != sizeof(dyn) || !is_dt_flag_valid(dyn.d_tag))
+                        dyn.d_tag = DT_NULL;
+                    ptr += sizeof(dyn);
+                } while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
+                if (dyn.d_tag == DT_NULL) goto leave;
+                elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
+            }
+	}
+    }
+
+    if (elf_info->flags & ELF_INFO_MODULE)
+    {
+        struct elf_module_info *elf_module_info = 
+            HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
+        if (!elf_module_info) goto leave;
+        elf_info->module = module_new(pcs, filename, DMT_ELF, 
+                                        (load_offset) ? load_offset : start, 
+                                        size, 0, 0);
+        if (!elf_info->module)
+        {
+            HeapFree(GetProcessHeap(), 0, elf_module_info);
+            goto leave;
+        }
+        elf_info->module->elf_info = elf_module_info;
+        elf_info->module->elf_info->elf_addr = load_offset;
+
+        if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
+        {
+            elf_info->module->module.SymType = SymDeferred;
+            ret = TRUE;
+        }
+        else ret = elf_load_debug_info(elf_info->module);
+
+        elf_info->module->elf_info->elf_mark = 1;
+        elf_info->module->elf_info->elf_loader = 0;
+    } else ret = TRUE;
+
+leave:
+    if (addr != (char*)0xffffffff) munmap((void*)addr, statbuf.st_size);
+    if (fd != -1) close(fd);
+
+    return ret;
+}
+
+/******************************************************************
+ *		elf_load_file_from_path
+ * tries to load an ELF file from a set of paths (separated by ':')
+ */
+static BOOL elf_load_file_from_path(HANDLE hProcess,
+                                    const char* filename,
+                                    unsigned long load_offset,
+                                    const char* path,
+                                    struct elf_info* elf_info)
+{
+    BOOL                ret = FALSE;
+    char                *s, *t, *fn;
+    char*	        paths = NULL;
+
+    if (!path) return FALSE;
+
+    paths = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(path) + 1), path);
+    for (s = paths; s && *s; s = (t) ? (t+1) : NULL) 
+    {
+	t = strchr(s, ':');
+	if (t) *t = '\0';
+	fn = HeapAlloc(GetProcessHeap(), 0, strlen(filename) + 1 + strlen(s) + 1);
+	if (!fn) break;
+	strcpy(fn, s);
+	strcat(fn, "/");
+	strcat(fn, filename);
+	ret = elf_load_file(hProcess, fn, load_offset, elf_info);
+	HeapFree(GetProcessHeap(), 0, fn);
+	if (ret) break;
+	s = (t) ? (t+1) : NULL;
+    }
+    
+    HeapFree(GetProcessHeap(), 0, paths);
+    return ret;
+}
+
+/******************************************************************
+ *		elf_search_and_load_file
+ *
+ * lookup a file in standard ELF locations, and if found, load it
+ */
+static BOOL elf_search_and_load_file(struct process* pcs, const char* filename,
+                                     unsigned long load_offset, 
+                                     struct elf_info* elf_info)
+{
+    BOOL                ret = FALSE;
+    struct module*      module;
+
+    if (filename == NULL || *filename == '\0') return FALSE;
+    if ((module = module_find_by_name(pcs, filename, DMT_ELF)))
+    {
+        elf_info->module = module;
+        module->elf_info->elf_mark = 1;
+        return module->module.SymType;
+    }
+
+    if (strstr(filename, "libstdc++")) return FALSE; /* We know we can't do it */
+    ret = elf_load_file(pcs, filename, load_offset, elf_info);
+    /* if relative pathname, try some absolute base dirs */
+    if (!ret && !strchr(filename, '/'))
+    {
+        ret = elf_load_file_from_path(pcs, filename, load_offset, 
+                                      getenv("PATH"), elf_info) ||
+            elf_load_file_from_path(pcs, filename, load_offset,
[truncated at 1000 lines; 180 more skipped]

reactos/lib/dbghelp
dbghelp_private.h added at 1.1
diff -N dbghelp_private.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp_private.h	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,448 @@
+/*
+ * File dbghelp_private.h - dbghelp internal definitions
+ *
+ * Copyright (C) 1995, Alexandre Julliard
+ * Copyright (C) 1996, Eric Youngdale.
+ * Copyright (C) 1999-2000, Ulrich Weigand.
+ * Copyright (C) 2004, Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winver.h"
+#include "dbghelp.h"
+#include "objbase.h"
+#include "oaidl.h"
+
+#include "cvconst.h"
+
+/* #define USE_STATS */
+
+struct pool /* poor's man */
+{
+    struct pool_arena*  first;
+    unsigned            arena_size;
+};
+
+void     pool_init(struct pool* a, unsigned arena_size);
+void     pool_destroy(struct pool* a);
+void*    pool_alloc(struct pool* a, unsigned len);
+/* void*    pool_realloc(struct pool* a, void* p,
+   unsigned old_size, unsigned new_size); */
+char*    pool_strdup(struct pool* a, const char* str);
+
+struct vector
+{
+    void**      buckets;
+    unsigned    elt_size;
+    unsigned    shift;
+    unsigned    num_elts;
+    unsigned    num_buckets;
+};
+
+void     vector_init(struct vector* v, unsigned elt_sz, unsigned bucket_sz);
+unsigned vector_length(const struct vector* v);
+void*    vector_at(const struct vector* v, unsigned pos);
+void*    vector_add(struct vector* v, struct pool* pool);
+/*void     vector_pool_normalize(struct vector* v, struct pool* pool); */
+void*    vector_iter_up(const struct vector* v, void* elt);
+void*    vector_iter_down(const struct vector* v, void* elt);
+
+struct hash_table_elt
+{
+    const char*                 name;
+    struct hash_table_elt*      next;
+};
+
+struct hash_table
+{
+    unsigned                    num_buckets;
+    struct hash_table_elt**     buckets;
+};
+
+void     hash_table_init(struct pool* pool, struct hash_table* ht,
+                         unsigned num_buckets);
+void     hash_table_destroy(struct hash_table* ht);
+void     hash_table_add(struct hash_table* ht, struct hash_table_elt* elt);
+void*    hash_table_find(const struct hash_table* ht, const char* name);
+unsigned hash_table_hash(const char* name, unsigned num_buckets);
+
+struct hash_table_iter
+{
+    const struct hash_table*    ht;
+    struct hash_table_elt*      element;
+    int                         index;
+    int                         last;
+};
+
+void     hash_table_iter_init(const struct hash_table* ht,
+                              struct hash_table_iter* hti, const char* name);
+void*    hash_table_iter_up(struct hash_table_iter* hti);
+
+#define GET_ENTRY(__i, __t, __f) \
+    ((__t*)((char*)(__i) - (unsigned int)(&((__t*)0)->__f)))
+
+
+extern unsigned dbghelp_options;
+/* some more Wine extensions */
+#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000
+
+struct symt
+{
+    enum SymTagEnum             tag;
+};
+
+struct symt_ht
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;        /* if global symbol or type */
+};
+
+/* lexical tree */
+struct symt_block
+{
+    struct symt                 symt;
+    unsigned long               address;
+    unsigned long               size;
+    struct symt*                container;      /* block, or func */
+    struct vector               vchildren;      /* sub-blocks & local variables */
+};
+
+struct symt_compiland
+{
+    struct symt                 symt;
+    unsigned                    source;
+    struct vector               vchildren;      /* global variables & functions */
+};
+
+struct symt_data
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;       /* if global symbol */
+    enum DataKind               kind;
+    struct symt*                container;
+    struct symt*                type;
+    union                                       /* depends on kind */
+    {
+        unsigned long           address;        /* DataIs{Global, FileStatic} */
+        struct
+        {
+            long                        offset; /* DataIs{Member,Local,Param} in bits*/
+            unsigned long               length; /* DataIs{Member} in bits */
+            unsigned long               reg_id; /* DataIs{Local} (0 if frame relative) */
+        } s;
+        VARIANT                 value;          /* DataIsConstant */
+    } u;
+};
+
+struct symt_function
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;       /* if global symbol */
+    unsigned long               address;
+    struct symt*                container;      /* compiland */
+    struct symt*                type;           /* points to function_signature */
+    unsigned long               size;
+    struct vector               vlines;
+    struct vector               vchildren;      /* locals, params, blocks, start/end, labels */
+};
+
+struct symt_function_point
+{
+    struct symt                 symt;           /* either SymTagFunctionDebugStart, SymTagFunctionDebugEnd, SymTagLabel */
+    struct symt_function*       parent;
+    unsigned long               offset;
+    const char*                 name;           /* for labels */
+};
+
+struct symt_public
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;
+    struct symt*                container;      /* compiland */
+    unsigned long               address;
+    unsigned long               size;
+    unsigned                    in_code : 1,
+                                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
+{
+    struct symt                 symt;
+    int		                start;
+    int		                end;
+    struct symt*                basetype;
+};
+
+struct symt_basic
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;
+    enum BasicType              bt;
+    unsigned long               size;
+};
+
+struct symt_enum
+{
+    struct symt                 symt;
+    const char*                 name;
+    struct vector               vchildren;
+};
+
+struct symt_function_signature
+{
+    struct symt                 symt;
+    struct symt*                rettype;
+    struct vector               vchildren;
+};
+
+struct symt_pointer
+{
+    struct symt                 symt;
+    struct symt*                pointsto;
+};
+
+struct symt_typedef
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;
+    struct symt*                type;
+};
+
+struct symt_udt
+{
+    struct symt                 symt;
+    struct hash_table_elt       hash_elt;
+    enum UdtKind                kind;
+    int		                size;
+    struct vector               vchildren;
+};
+
+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 module_type		type;
+    struct elf_module_info*	elf_info;
+    
+    /* memory allocation pool */
+    struct pool                 pool;
+
+    /* symbol tables */
+    int                         sortlist_valid;
+    struct symt_ht**            addr_sorttab;
+    struct hash_table           ht_symbols;
+
+    /* types */
+    struct hash_table           ht_types;
+    struct vector               vtypes;
+
+    /* source files */
+    unsigned                    sources_used;
+    unsigned                    sources_alloc;
+    char*                       sources;
+};
+
+struct process 
+{
+    struct process*             next;
+    HANDLE                      handle;
+    char*                       search_path;
+
+    struct module*              lmodules;
+    unsigned long               dbg_hdr_addr;
+
+    IMAGEHLP_STACK_FRAME        ctx_frame;
+};
+
+/* dbghelp.c */
+extern struct process* process_find_by_handle(HANDLE hProcess);
+extern HANDLE hMsvcrt;
+
+/* elf_module.c */
+extern BOOL         elf_load_debug_info(struct module* module);
+extern struct module*
+                    elf_load_module(struct process* pcs, const char* name);
+extern BOOL         elf_read_wine_loader_dbg_info(struct process* pcs);
+extern BOOL         elf_synchronize_module_list(struct process* pcs);
+
+extern DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr);
+
+/* module.c */
+extern struct module*
+                    module_find_by_addr(const struct process* pcs, unsigned long addr,
+                                        enum module_type type);
+extern struct module*
+                    module_find_by_name(const struct process* pcs, 
+                                        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 module_type type, unsigned long addr, 
+                               unsigned long size, unsigned long stamp, 
+                               unsigned long checksum);
+extern struct module*
+                    module_get_container(const struct process* pcs,
+                                         const struct module* inner);
+extern struct module*
+                    module_get_containee(const struct process* pcs,
+                                         const struct module* inner);
+extern void         module_reset_debug_info(struct module* module);
+extern BOOL         module_remove(struct process* pcs, 
+                                  struct module* module);
+/* msc.c */
+extern BOOL         pe_load_debug_directory(const struct process* pcs, 
+                                            struct module* module, 
+                                            const BYTE* mapping,
+                                            const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
+                                            const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
+/* pe_module.c */
+extern struct module*
+                    pe_load_module(struct process* pcs, char* name,
+                                   HANDLE hFile, DWORD base, DWORD size);
+extern struct module*
+                    pe_load_module_from_pcs(struct process* pcs, const char* name, 
+                                            const char* mod_name, DWORD base, DWORD size);
+extern BOOL         pe_load_debug_info(const struct process* pcs, 
+                                       struct module* module);
+/* source.c */
+extern unsigned     source_new(struct module* module, const char* source);
+extern const char*  source_get(const struct module* module, unsigned idx);
+
+/* stabs.c */
+extern BOOL         stabs_parse(struct module* module, unsigned long load_offset,
+                                const void* stabs, int stablen,
+                                const char* strs, int strtablen);
+
+/* 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);
+extern struct symt_public*
+                    symt_new_public(struct module* module, 
+                                    struct symt_compiland* parent, 
+                                    const char* typename,
+                                    unsigned long address, unsigned size,
+                                    BOOL in_code, BOOL is_func);
+extern struct symt_data*
+                    symt_new_global_variable(struct module* module, 
+                                             struct symt_compiland* parent,
+                                             const char* name, unsigned is_static,
+                                             unsigned long addr, unsigned long size, 
+                                             struct symt* type);
+extern struct symt_function*
+                    symt_new_function(struct module* module,
+                                      struct symt_compiland* parent,
+                                      const char* name,
+                                      unsigned long addr, unsigned long size,
+                                      struct symt* type);
+extern BOOL         symt_normalize_function(struct module* module, 
+                                            struct symt_function* func);
+extern void         symt_add_func_line(struct module* module,
+                                       struct symt_function* func, 
+                                       unsigned source_idx, int line_num, 
+                                       unsigned long offset);
+extern struct symt_data*
+                    symt_add_func_local(struct module* module, 
+                                        struct symt_function* func, 
+                                        int regno, int offset,
+                                        struct symt_block* block,
+                                        struct symt* type, const char* name);
+extern struct symt_block*
+                    symt_open_func_block(struct module* module, 
+                                         struct symt_function* func,
+                                         struct symt_block* block, 
+                                         unsigned pc, unsigned len);
+extern struct symt_block*
+                    symt_close_func_block(struct module* module, 
+                                          struct symt_function* func,
+                                          struct symt_block* block, unsigned pc);
+extern struct symt_function_point*
+                    symt_add_function_point(struct module* module, 
+                                            struct symt_function* func,
+                                            enum SymTagEnum point, 
+                                            unsigned offset, const char* name);
+extern BOOL         symt_fill_func_line_info(struct module* module,
+                                             struct symt_function* func, 
+                                             DWORD addr, IMAGEHLP_LINE* line);
+extern BOOL         symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line);
+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);
+extern BOOL         symt_get_info(const struct symt* type,
+                                  IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo);
+extern struct symt_basic*
+                    symt_new_basic(struct module* module, enum BasicType, 
+                                   const char* typename, unsigned size);
+extern struct symt_udt*
+                    symt_new_udt(struct module* module, const char* typename,
+                                 unsigned size, enum UdtKind kind);
+extern BOOL         symt_set_udt_size(struct module* module,
+                                      struct symt_udt* type, unsigned size);
+extern BOOL         symt_add_udt_element(struct module* module, 
+                                         struct symt_udt* udt_type, 
+                                         const char* name,
+                                         struct symt* elt_type, unsigned offset, 
+                                         unsigned size);
+extern struct symt_enum*
+                    symt_new_enum(struct module* module, const char* typename);
+extern BOOL         symt_add_enum_element(struct module* module, 
+                                          struct symt_enum* enum_type, 
+                                          const char* name, int value);
+extern struct symt_array*
+                    symt_new_array(struct module* module, int min, int max, 
+                                   struct symt* base);
+extern struct symt_function_signature*
+                    symt_new_function_signature(struct module* module, 
+                                                struct symt* ret_type);
+extern BOOL         symt_add_function_signature_parameter(struct module* module,
+                                                          struct symt_function_signature* sig,
+                                                          struct symt* param);
+extern struct symt_pointer*
+                    symt_new_pointer(struct module* module, 
+                                     struct symt* ref_type);
+extern struct symt_typedef*
+                    symt_new_typedef(struct module* module, struct symt* ref, 
+                                     const char* name);

reactos/lib/dbghelp
dbghelp.stubs.c added at 1.1
diff -N dbghelp.stubs.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp.stubs.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,74 @@
+/* File generated automatically from dbghelp.spec; do not edit! */
+/* This file can be copied, modified and distributed without restriction. */
+
+#ifdef __GNUC__
+static void __wine_unimplemented( const char *func ) __attribute__((noreturn));
+#endif
+
+struct exc_record {
+  unsigned int code, flags;
+  void *rec, *addr;
+  unsigned int params;
+  const void *info[15];
+};
+
+extern void __stdcall RtlRaiseException( struct exc_record * );
+
+static void __wine_unimplemented( const char *func )
+{
+  struct exc_record rec;
+  rec.code    = 0x80000100;
+  rec.flags   = 1;
+  rec.rec     = 0;
+  rec.params  = 2;
+  rec.info[0] = "dbghelp.dll";
+  rec.info[1] = func;
+#ifdef __GNUC__
+  rec.addr = __builtin_return_address(1);
+#else
+  rec.addr = 0;
+#endif
+  for (;;) RtlRaiseException( &rec );
+}
+
+void __wine_stub_dbghelp_dll_1(void) { __wine_unimplemented("DbgHelpCreateUserDump"); }
+void __wine_stub_dbghelp_dll_2(void) { __wine_unimplemented("DbgHelpCreateUserDumpW"); }
+void __wine_stub_dbghelp_dll_5(void) { __wine_unimplemented("EnumerateLoadedModules64"); }
+void __wine_stub_dbghelp_dll_6(void) { __wine_unimplemented("ExtensionApiVersion"); }
+void __wine_stub_dbghelp_dll_10(void) { __wine_unimplemented("FindExecutableImageEx"); }
+void __wine_stub_dbghelp_dll_11(void) { __wine_unimplemented("FindFileInPath"); }
+void __wine_stub_dbghelp_dll_12(void) { __wine_unimplemented("FindFileInSearchPath"); }
+void __wine_stub_dbghelp_dll_15(void) { __wine_unimplemented("ImageDirectoryEntryToDataEx"); }
+void __wine_stub_dbghelp_dll_23(void) { __wine_unimplemented("MiniDumpReadDumpStream"); }
+void __wine_stub_dbghelp_dll_24(void) { __wine_unimplemented("MiniDumpWriteDump"); }
+void __wine_stub_dbghelp_dll_27(void) { __wine_unimplemented("StackWalk64"); }
+void __wine_stub_dbghelp_dll_30(void) { __wine_unimplemented("SymEnumSym"); }
+void __wine_stub_dbghelp_dll_34(void) { __wine_unimplemented("SymEnumerateModules64"); }
+void __wine_stub_dbghelp_dll_36(void) { __wine_unimplemented("SymEnumerateSymbols64"); }
+void __wine_stub_dbghelp_dll_37(void) { __wine_unimplemented("SymEnumerateSymbolsW"); }
+void __wine_stub_dbghelp_dll_38(void) { __wine_unimplemented("SymEnumerateSymbolsW64"); }
+void __wine_stub_dbghelp_dll_43(void) { __wine_unimplemented("SymFunctionTableAccess64"); }
+void __wine_stub_dbghelp_dll_44(void) { __wine_unimplemented("SymGetFileLineOffsets64"); }
+void __wine_stub_dbghelp_dll_46(void) { __wine_unimplemented("SymGetLineFromAddr64"); }
+void __wine_stub_dbghelp_dll_47(void) { __wine_unimplemented("SymGetLineFromName"); }
+void __wine_stub_dbghelp_dll_48(void) { __wine_unimplemented("SymGetLineFromName64"); }
+void __wine_stub_dbghelp_dll_50(void) { __wine_unimplemented("SymGetLineNext64"); }
+void __wine_stub_dbghelp_dll_52(void) { __wine_unimplemented("SymGetLinePrev64"); }
+void __wine_stub_dbghelp_dll_54(void) { __wine_unimplemented("SymGetModuleBase64"); }
+void __wine_stub_dbghelp_dll_56(void) { __wine_unimplemented("SymGetModuleInfo64"); }
+void __wine_stub_dbghelp_dll_57(void) { __wine_unimplemented("SymGetModuleInfoW"); }
+void __wine_stub_dbghelp_dll_58(void) { __wine_unimplemented("SymGetModuleInfoW64"); }
+void __wine_stub_dbghelp_dll_62(void) { __wine_unimplemented("SymGetSymFromAddr64"); }
+void __wine_stub_dbghelp_dll_64(void) { __wine_unimplemented("SymGetSymFromName64"); }
+void __wine_stub_dbghelp_dll_66(void) { __wine_unimplemented("SymGetSymNext64"); }
+void __wine_stub_dbghelp_dll_68(void) { __wine_unimplemented("SymGetSymPrev64"); }
+void __wine_stub_dbghelp_dll_73(void) { __wine_unimplemented("SymLoadModule64"); }
+void __wine_stub_dbghelp_dll_74(void) { __wine_unimplemented("SymLoadModuleEx"); }
+void __wine_stub_dbghelp_dll_76(void) { __wine_unimplemented("SymMatchString"); }
+void __wine_stub_dbghelp_dll_78(void) { __wine_unimplemented("SymRegisterCallback64"); }
+void __wine_stub_dbghelp_dll_79(void) { __wine_unimplemented("SymRegisterFunctionEntryCallback"); }
+void __wine_stub_dbghelp_dll_80(void) { __wine_unimplemented("SymRegisterFunctionEntryCallback64"); }
+void __wine_stub_dbghelp_dll_84(void) { __wine_unimplemented("SymSetSymWithAddr64"); }
+void __wine_stub_dbghelp_dll_86(void) { __wine_unimplemented("SymUnDName64"); }
+void __wine_stub_dbghelp_dll_88(void) { __wine_unimplemented("SymUnloadModule64"); }
+void __wine_stub_dbghelp_dll_91(void) { __wine_unimplemented("WinDbgExtensionDllInit"); }

reactos/lib/dbghelp
dbghelp.spec.def added at 1.1
diff -N dbghelp.spec.def
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp.spec.def	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,96 @@
+; File generated automatically from dbghelp.spec; do not edit!
+
+LIBRARY dbghelp.dll
+
+EXPORTS
+  DbgHelpCreateUserDump=__wine_stub_dbghelp_dll_1 @1
+  DbgHelpCreateUserDumpW=__wine_stub_dbghelp_dll_2 @2
+  EnumDirTree@24 @3
+  EnumerateLoadedModules@12 @4
+  EnumerateLoadedModules64=__wine_stub_dbghelp_dll_5 @5
+  ExtensionApiVersion=__wine_stub_dbghelp_dll_6 @6
+  FindDebugInfoFile@12 @7
+  FindDebugInfoFileEx@20 @8
+  FindExecutableImage@12 @9
+  FindExecutableImageEx=__wine_stub_dbghelp_dll_10 @10
+  FindFileInPath=__wine_stub_dbghelp_dll_11 @11
+  FindFileInSearchPath=__wine_stub_dbghelp_dll_12 @12
+  GetTimestampForLoadedLibrary@4 @13
+  ImageDirectoryEntryToData@16=ntdll.RtlImageDirectoryEntryToData @14
+  ImageDirectoryEntryToDataEx=__wine_stub_dbghelp_dll_15 @15
+  ImageNtHeader@4=ntdll.RtlImageNtHeader @16
+  ImageRvaToSection@12=ntdll.RtlImageRvaToSection @17
+  ImageRvaToVa@16=ntdll.RtlImageRvaToVa @18
+  ImagehlpApiVersion@0 @19
+  ImagehlpApiVersionEx@4 @20
+  MakeSureDirectoryPathExists@4 @21
+  MapDebugInformation@16 @22
+  MiniDumpReadDumpStream=__wine_stub_dbghelp_dll_23 @23
+  MiniDumpWriteDump=__wine_stub_dbghelp_dll_24 @24
+  SearchTreeForFile@12 @25
+  StackWalk@36 @26
+  StackWalk64=__wine_stub_dbghelp_dll_27 @27
+  SymCleanup@4 @28
+  SymEnumSourceFiles@24 @29
+  SymEnumSym=__wine_stub_dbghelp_dll_30 @30
+  SymEnumSymbols@24 @31
+  SymEnumTypes@20 @32
+  SymEnumerateModules@12 @33
+  SymEnumerateModules64=__wine_stub_dbghelp_dll_34 @34
+  SymEnumerateSymbols@16 @35
+  SymEnumerateSymbols64=__wine_stub_dbghelp_dll_36 @36
+  SymEnumerateSymbolsW=__wine_stub_dbghelp_dll_37 @37
+  SymEnumerateSymbolsW64=__wine_stub_dbghelp_dll_38 @38
+  SymFindFileInPath@40 @39
+  SymFromAddr@20 @40
+  SymFromName@12 @41
+  SymFunctionTableAccess@8 @42
+  SymFunctionTableAccess64=__wine_stub_dbghelp_dll_43 @43
+  SymGetFileLineOffsets64=__wine_stub_dbghelp_dll_44 @44
+  SymGetLineFromAddr@16 @45
+  SymGetLineFromAddr64=__wine_stub_dbghelp_dll_46 @46
+  SymGetLineFromName=__wine_stub_dbghelp_dll_47 @47
+  SymGetLineFromName64=__wine_stub_dbghelp_dll_48 @48
+  SymGetLineNext@8 @49
+  SymGetLineNext64=__wine_stub_dbghelp_dll_50 @50
+  SymGetLinePrev@8 @51
+  SymGetLinePrev64=__wine_stub_dbghelp_dll_52 @52
+  SymGetModuleBase@8 @53
+  SymGetModuleBase64=__wine_stub_dbghelp_dll_54 @54
+  SymGetModuleInfo@12 @55
+  SymGetModuleInfo64=__wine_stub_dbghelp_dll_56 @56
+  SymGetModuleInfoW=__wine_stub_dbghelp_dll_57 @57
+  SymGetModuleInfoW64=__wine_stub_dbghelp_dll_58 @58
+  SymGetOptions@0 @59
+  SymGetSearchPath@12 @60
+  SymGetSymFromAddr@16 @61
+  SymGetSymFromAddr64=__wine_stub_dbghelp_dll_62 @62
+  SymGetSymFromName@12 @63
+  SymGetSymFromName64=__wine_stub_dbghelp_dll_64 @64
+  SymGetSymNext@8 @65
+  SymGetSymNext64=__wine_stub_dbghelp_dll_66 @66
+  SymGetSymPrev@8 @67
+  SymGetSymPrev64=__wine_stub_dbghelp_dll_68 @68
+  SymGetTypeFromName@20 @69
+  SymGetTypeInfo@24 @70
+  SymInitialize@12 @71
+  SymLoadModule@24 @72
+  SymLoadModule64=__wine_stub_dbghelp_dll_73 @73
+  SymLoadModuleEx=__wine_stub_dbghelp_dll_74 @74
+  SymMatchFileName@16 @75
+  SymMatchString=__wine_stub_dbghelp_dll_76 @76
+  SymRegisterCallback@12 @77
+  SymRegisterCallback64=__wine_stub_dbghelp_dll_78 @78
+  SymRegisterFunctionEntryCallback=__wine_stub_dbghelp_dll_79 @79
+  SymRegisterFunctionEntryCallback64=__wine_stub_dbghelp_dll_80 @80
+  SymSetContext@12 @81
+  SymSetOptions@4 @82
+  SymSetSearchPath@8 @83
+  SymSetSymWithAddr64=__wine_stub_dbghelp_dll_84 @84
+  SymUnDName@12 @85
+  SymUnDName64=__wine_stub_dbghelp_dll_86 @86
+  SymUnloadModule@8 @87
+  SymUnloadModule64=__wine_stub_dbghelp_dll_88 @88
+  UnDecorateSymbolName@16 @89
+  UnmapDebugInformation@4 @90
+  WinDbgExtensionDllInit=__wine_stub_dbghelp_dll_91 @91

reactos/lib/dbghelp
dbghelp.spec added at 1.1
diff -N dbghelp.spec
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp.spec	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,99 @@
+@ stub DbgHelpCreateUserDump
+@ stub DbgHelpCreateUserDumpW
+@ stdcall EnumDirTree(long str str ptr ptr ptr)
+@ stdcall EnumerateLoadedModules(long ptr ptr)
+@ stub EnumerateLoadedModules64
+@ stub ExtensionApiVersion
+@ stdcall FindDebugInfoFile(str str ptr)
+@ stdcall FindDebugInfoFileEx(str str ptr ptr ptr)
+@ stdcall FindExecutableImage(str str str)
+@ stub FindExecutableImageEx
+@ stub FindFileInPath
+@ stub FindFileInSearchPath
+@ stdcall GetTimestampForLoadedLibrary(long)
+@ stdcall ImageDirectoryEntryToData(ptr long long ptr) ntdll.RtlImageDirectoryEntryToData
+@ stub ImageDirectoryEntryToDataEx
+@ stdcall ImageNtHeader(ptr) ntdll.RtlImageNtHeader
+@ stdcall ImageRvaToSection(ptr ptr long) ntdll.RtlImageRvaToSection
+@ stdcall ImageRvaToVa(ptr ptr long ptr) ntdll.RtlImageRvaToVa
+@ stdcall ImagehlpApiVersion()
+@ stdcall ImagehlpApiVersionEx(ptr)
+@ stdcall MakeSureDirectoryPathExists(str)
+@ stdcall MapDebugInformation(long str str long)
+@ stub MiniDumpReadDumpStream
+@ stub MiniDumpWriteDump
+@ stdcall SearchTreeForFile(str str str)
+@ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr)
+@ stub StackWalk64
+@ stdcall SymCleanup(long)
+@ stdcall SymEnumSourceFiles(ptr long long str ptr ptr)
+@ stub SymEnumSym
+@ stdcall SymEnumSymbols(ptr long long str ptr ptr)
+@ stdcall SymEnumTypes(ptr long long ptr ptr)
+@ stdcall SymEnumerateModules(long ptr ptr)
+@ stub SymEnumerateModules64
+@ stdcall SymEnumerateSymbols(long long ptr ptr)
+@ stub SymEnumerateSymbols64
+@ stub SymEnumerateSymbolsW
+@ stub SymEnumerateSymbolsW64
+@ stdcall SymFindFileInPath(long str str ptr long long long ptr ptr ptr)
+@ stdcall SymFromAddr(ptr long long ptr ptr)
+@ stdcall SymFromName(long str ptr)
+@ stdcall SymFunctionTableAccess(long long)
+@ stub SymFunctionTableAccess64
+@ stub SymGetFileLineOffsets64
+@ stdcall SymGetLineFromAddr(long long ptr ptr)
+@ stub SymGetLineFromAddr64
+@ stub SymGetLineFromName
+@ stub SymGetLineFromName64
+@ stdcall SymGetLineNext(long ptr)
+@ stub SymGetLineNext64
+@ stdcall SymGetLinePrev(long ptr)
+@ stub SymGetLinePrev64
+@ stdcall SymGetModuleBase(long long)
+@ stub SymGetModuleBase64
+@ stdcall SymGetModuleInfo(long long ptr)
+@ stub SymGetModuleInfo64
+@ stub SymGetModuleInfoW
+@ stub SymGetModuleInfoW64
+@ stdcall SymGetOptions()
+@ stdcall SymGetSearchPath(long str long)
+@ stdcall SymGetSymFromAddr(long long ptr ptr)
+@ stub SymGetSymFromAddr64
+@ stdcall SymGetSymFromName(long str ptr)
+@ stub SymGetSymFromName64
+@ stdcall SymGetSymNext(long ptr)
+@ stub SymGetSymNext64
+@ stdcall SymGetSymPrev(long ptr)
+@ stub SymGetSymPrev64
+@ stdcall SymGetTypeFromName(ptr long long str ptr)
+@ stdcall SymGetTypeInfo(ptr long long long long ptr)
+@ stdcall SymInitialize(long str long)
+@ stdcall SymLoadModule(long long str str long long)
+@ stub SymLoadModule64
+@ stub SymLoadModuleEx
+@ stdcall SymMatchFileName(str str ptr ptr)
+@ stub SymMatchString
+@ stdcall SymRegisterCallback(long ptr ptr)
+@ stub SymRegisterCallback64
+@ stub SymRegisterFunctionEntryCallback
+@ stub SymRegisterFunctionEntryCallback64
+@ stdcall SymSetContext(long ptr ptr)
+@ stdcall SymSetOptions(long)
+@ stdcall SymSetSearchPath(long str)
+@ stub SymSetSymWithAddr64
+@ stdcall SymUnDName(ptr str long)
+@ stub SymUnDName64
+@ stdcall SymUnloadModule(long long)
+@ stub SymUnloadModule64
+@ stdcall UnDecorateSymbolName(str str long long)
+@ stdcall UnmapDebugInformation(ptr)
+@ stub WinDbgExtensionDllInit
+#@ stub dbghelp
+#@ stub dh
+#@ stub lm
+#@ stub lmi
+#@ stub omap
+#@ stub srcfiles
+#@ stub sym
+#@ stub vc7fpo

reactos/lib/dbghelp
dbghelp.rc added at 1.1
diff -N dbghelp.rc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp.rc	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1 @@
+#include "wine/wine_common_ver.rc"

reactos/lib/dbghelp
dbghelp.c added at 1.1
diff -N dbghelp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dbghelp.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,338 @@
+/*
+ * File dbghelp.c - generic routines (process) for dbghelp DLL
+ *
+ * Copyright (C) 2004, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "dbghelp_private.h"
+#include "winerror.h"
+#include "psapi.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+/* TODO
+ *  - support for symbols' types is still partly missing
+ *      + C++ support
+ *      + funcargtype:s are (partly) wrong: they should be a specific struct (like
+ *        typedef) pointing to the actual type (and not a direct access)
+ *      + we should store the underlying type for an enum in the symt_enum struct
+ *      + for enums, we store the names & values (associated to the enum type), 
+ *        but those values are not directly usable from a debugger (that's why, I
+ *        assume, that we have also to define constants for enum values, as 
+ *        Codeview does BTW.
+ *  - most options (dbghelp_options) are not used (loading lines...)
+ *  - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when
+ *    we're supposed to use RE, it doesn't make use of our hash tables. Therefore,
+ *    we could use hash if name isn't a RE, and fall back to a full search when we
+ *    get a full RE
+ *  - msc:
+ *      + we should add parameters' types to the function's signature
+ *        while processing a function's parameters
+ *      + get rid of MSC reading FIXME:s (lots of types are not defined)
+ *      + C++ management
+ *  - stabs: 
+ *      + when, in a same module, the same definition is used in several compilation
+ *        units, we get several definitions of the same object (especially 
+ *        struct/union). we should find a way not to duplicate them
+ *      + in some cases (dlls/user/dialog16.c DIALOG_GetControl16), the same static
+ *        global variable is defined several times (at different scopes). We are
+ *        getting several of those while looking for a unique symbol. Part of the 
+ *        issue is that we don't give a scope to a static variable inside a function
+ *      + C++ management
+ *  - implement the callback notification mechanism
+ */
+
+unsigned   dbghelp_options = SYMOPT_UNDNAME;
+HANDLE     hMsvcrt = NULL;
+
+/***********************************************************************
+ *           DllMain (DEBUGHLP.@)
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    switch (fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:    break;
+    case DLL_PROCESS_DETACH:
+        if (hMsvcrt) FreeLibrary(hMsvcrt);
+        break;
+    case DLL_THREAD_ATTACH:     break;
+    case DLL_THREAD_DETACH:     break;
+    default:                    break;
+    }
+    return TRUE;
+}
+
+static struct process* process_first /* = NULL */;
+
+/******************************************************************
+ *		process_find_by_handle
+ *
+ */
+struct process*    process_find_by_handle(HANDLE hProcess)
+{
+    struct process* p;
+
+    for (p = process_first; p && p->handle != hProcess; p = p->next);
+    if (!p) SetLastError(ERROR_INVALID_HANDLE);
+    return p;
+}
+
+/******************************************************************
+ *		SymSetSearchPath (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PSTR searchPath)
+{
+    struct process* pcs = process_find_by_handle(hProcess);
+
+    if (!pcs) return FALSE;
+    if (!searchPath) return FALSE;
+
+    HeapFree(GetProcessHeap(), 0, pcs->search_path);
+    pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(searchPath) + 1),
+                              searchPath);
+    return TRUE;
+}
+
+/***********************************************************************
+ *		SymGetSearchPath (DBGHELP.@)
+ */
+BOOL WINAPI SymGetSearchPath(HANDLE hProcess, LPSTR szSearchPath, 
+                             DWORD SearchPathLength)
+{
+    struct process* pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE;
+
+    strncpy(szSearchPath, pcs->search_path, SearchPathLength);
+    szSearchPath[SearchPathLength - 1] = '\0';
+    return TRUE;
+}
+
+/******************************************************************
+ *		invade_process
+ *
+ * SymInitialize helper: loads in dbghelp all known (and loaded modules)
+ * this assumes that hProcess is a handle on a valid process
+ */
+static BOOL process_invade(HANDLE hProcess)
+{
+    HMODULE     hMods[256];
+    char        img[256];
+    DWORD       i, sz;
+    MODULEINFO  mi;
+
+    if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &sz))
+        return FALSE; /* FIXME should grow hMods */
+    
+    for (i = 0; i < sz / sizeof(HMODULE); i++)
+    {
+        if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
+            !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
+            !SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
+            return FALSE;
+    }
+
+    return sz != 0;
+}
+
+/******************************************************************
+ *		SymInitialize (DBGHELP.@)
+ *
+ * The initialisation of a dbghelp's context.
+ * Note that hProcess doesn't need to be a valid process handle (except
+ * when fInvadeProcess is TRUE).
+ * Since, we're also allow to load ELF (pure) libraries and Wine ELF libraries 
+ * containing PE (and NE) module(s), here's how we handle it:
+ * - we load every module (ELF, NE, PE) passed in SymLoadModule
+ * - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
+ *   synchronization: hProcess should be a valid process handle, and we hook
+ *   ourselves on hProcess's loaded ELF-modules, and keep this list in sync with
+ *   our internal ELF modules representation (loading / unloading). This way,
+ *   we'll pair every loaded builtin PE module with its ELF counterpart (and
+ *   access its debug information).
+ * - if fInvadeProcess (in SymInitialize) is FALSE, we won't be able to
+ *   make the peering between a builtin PE module and its ELF counterpart, hence
+ *   we won't be able to provide the requested debug information. We'll
+ *   however be able to load native PE modules (and their debug information)
+ *   without any trouble.
+ * Note also that this scheme can be intertwined with the deferred loading 
+ * mechanism (ie only load the debug information when we actually need it).
+ */
+BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess)
+{
+    struct process*     pcs;
+
+    TRACE("(%p %s %u)\n", hProcess, debugstr_a(UserSearchPath), fInvadeProcess);
+
+    if (process_find_by_handle(hProcess))
+        FIXME("what to do ??\n");
+
+    pcs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pcs));
+    if (!pcs) return FALSE;
+
+    pcs->handle = hProcess;
+
+    if (UserSearchPath)
+    {
+        pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(UserSearchPath) + 1), 
+                                  UserSearchPath);
+    }
+    else
+    {
+        unsigned        size;
+        unsigned        len;
+
+        pcs->search_path = HeapAlloc(GetProcessHeap(), 0, len = MAX_PATH);
+        while ((size = GetCurrentDirectoryA(len, pcs->search_path)) >= len)
+            pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, len *= 2);
+        pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1);
+
+        len = GetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL, 0);
+        if (len)
+        {
+            pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
+            pcs->search_path[size] = ';';
+            GetEnvironmentVariableA("_NT_SYMBOL_PATH", pcs->search_path + size + 1, len);
+            size += 1 + len;
+        }
+        len = GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", NULL, 0);
+        if (len)
+        {
+            pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
+            pcs->search_path[size] = ';';
+            GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", pcs->search_path + size + 1, len);
+            size += 1 + len;
+        }
+    }
+
+    pcs->lmodules = NULL;
+    pcs->dbg_hdr_addr = 0;
+    pcs->next = process_first;
+    process_first = pcs;
+
+    if (fInvadeProcess)
+    {
+        if (!elf_read_wine_loader_dbg_info(pcs))
+        {
+            SymCleanup(hProcess);
+            return FALSE;
+        }
+        process_invade(hProcess);
+        elf_synchronize_module_list(pcs);
+    }
+    return TRUE;
+}
+
+/******************************************************************
+ *		SymCleanup (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymCleanup(HANDLE hProcess)
+{
+    struct process**    ppcs;
+    struct process*     next;
+
+    for (ppcs = &process_first; *ppcs; ppcs = &(*ppcs)->next)
+    {
+        if ((*ppcs)->handle == hProcess)
+        {
+            while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
+
+            HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
+            next = (*ppcs)->next;
+            HeapFree(GetProcessHeap(), 0, *ppcs);
+            *ppcs = next;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/******************************************************************
+ *		SymSetOptions (DBGHELP.@)
+ *
+ */
+DWORD WINAPI SymSetOptions(DWORD opts)
+{
+    return dbghelp_options = opts;
+}
+
+/******************************************************************
+ *		SymGetOptions (DBGHELP.@)
+ *
+ */
+DWORD WINAPI SymGetOptions(void)
+{
+    return dbghelp_options;
+}
+
+/******************************************************************
+ *		SymSetContext (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
+                          PIMAGEHLP_CONTEXT Context)
+{
+    struct process* pcs = process_find_by_handle(hProcess);
+    if (!pcs) return FALSE;
+
+    pcs->ctx_frame = *StackFrame;
+    /* MSDN states that Context is not (no longer?) used */
+    return TRUE;
+}
+
+/***********************************************************************
+ *		SymRegisterCallback (DBGHELP.@)
+ */
+BOOL WINAPI SymRegisterCallback(HANDLE hProcess, 
+                                PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
+                                PVOID UserContext)
+{
+    FIXME("(%p, %p, %p): stub\n", hProcess, CallbackFunction, UserContext);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/* This is imagehlp version not dbghelp !! */
+static API_VERSION api_version = { 4, 0, 2, 0 };
+
+/***********************************************************************
+ *           ImagehlpApiVersion (DBGHELP.@)
+ */
+LPAPI_VERSION WINAPI ImagehlpApiVersion(VOID)
+{
+    return &api_version;
+}
+
+/***********************************************************************
+ *           ImagehlpApiVersionEx (DBGHELP.@)
+ */
+LPAPI_VERSION WINAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion)
+{
+    if (!AppVersion) return NULL;
+
+    AppVersion->MajorVersion = api_version.MajorVersion;
+    AppVersion->MinorVersion = api_version.MinorVersion;
+    AppVersion->Revision = api_version.Revision;
+    AppVersion->Reserved = api_version.Reserved;
+
+    return AppVersion;
+}

reactos/lib/dbghelp
coff.c added at 1.1
diff -N coff.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ coff.c	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,454 @@
+/*
+ * Read VC++ debug information from COFF and eventually
+ * from PDB files.
+ *
+ * Copyright (C) 1996,      Eric Youngdale.
+ * Copyright (C) 1999-2000, Ulrich Weigand.
+ * Copyright (C) 2004,      Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Note - this handles reading debug information for 32 bit applications
+ * that run under Windows-NT for example.  I doubt that this would work well
+ * for 16 bit applications, but I don't think it really matters since the
+ * file format is different, and we should never get in here in such cases.
+ *
+ * TODO:
+ *	Get 16 bit CV stuff working.
+ *	Add symbol size to internal symbol table.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
+
+#include "wine/exception.h"
+#include "wine/debug.h"
+#include "excpt.h"
+#include "dbghelp_private.h"
+#include "mscvpdb.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_coff);
+
+/*========================================================================
+ * Process COFF debug information.
+ */
+
+struct CoffFile
+{
+    unsigned int                startaddr;
+    unsigned int                endaddr;
+    struct symt_compiland*      compiland;
+    int                         linetab_offset;
+    int                         linecnt;
+    struct symt**               entries;
+    int		                neps;
+    int		                neps_alloc;
+};
+
+struct CoffFileSet
+{
+    struct CoffFile*    files;
+    int		        nfiles;
+    int		        nfiles_alloc;
+};
+
+static const char*	coff_get_name(const IMAGE_SYMBOL* coff_sym, 
+                                      const char* coff_strtab)
+{
+    static	char	namebuff[9];
+    const char*		nampnt;
+
+    if (coff_sym->N.Name.Short)
+    {
+        memcpy(namebuff, coff_sym->N.ShortName, 8);
+        namebuff[8] = '\0';
+        nampnt = &namebuff[0];
+    }
+    else
+    {
+        nampnt = coff_strtab + coff_sym->N.Name.Long;
+    }
+
+    if (nampnt[0] == '_') nampnt++;
+    return nampnt;
+}
+
+static int coff_add_file(struct CoffFileSet* coff_files, struct module* module,
+                         const char* filename)
+{
+    struct CoffFile* file;
+
+    if (coff_files->nfiles + 1 >= coff_files->nfiles_alloc)
+    {
+	coff_files->nfiles_alloc += 10;
+        coff_files->files = (coff_files->files) ?
+            HeapReAlloc(GetProcessHeap(), 0, coff_files->files,
+                        coff_files->nfiles_alloc * sizeof(struct CoffFile)) :
+            HeapAlloc(GetProcessHeap(), 0,
+                      coff_files->nfiles_alloc * sizeof(struct CoffFile));
+    }
+    file = coff_files->files + coff_files->nfiles;
+    file->startaddr = 0xffffffff;
+    file->endaddr   = 0;
+    file->compiland = symt_new_compiland(module, filename);
+    file->linetab_offset = -1;
+    file->linecnt = 0;
+    file->entries = NULL;
+    file->neps = file->neps_alloc = 0;
+
+    return coff_files->nfiles++;
+}
+
+static void coff_add_symbol(struct CoffFile* coff_file, struct symt* sym)
+{
+    if (coff_file->neps + 1 >= coff_file->neps_alloc)
+    {
+        coff_file->neps_alloc += 10;
+        coff_file->entries = (coff_file->entries) ?
+            HeapReAlloc(GetProcessHeap(), 0, coff_file->entries,
+                        coff_file->neps_alloc * sizeof(struct symt*)) :
+            HeapAlloc(GetProcessHeap(), 0, 
+                      coff_file->neps_alloc * sizeof(struct symt*));
+    }
+    coff_file->entries[coff_file->neps++] = sym;
+}
+
+BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
+{
+    const IMAGE_AUX_SYMBOL*		aux;
+    const IMAGE_COFF_SYMBOLS_HEADER*	coff;
+    const IMAGE_LINENUMBER*		coff_linetab;
+    const IMAGE_LINENUMBER*		linepnt;
+    const char*                         coff_strtab;
+    const IMAGE_SYMBOL* 		coff_sym;
+    const IMAGE_SYMBOL* 		coff_symbols;
+    struct CoffFileSet	                coff_files;
+    int				        curr_file_idx = -1;
+    unsigned int		        i;
+    int			       	        j;
+    int			       	        k;
+    int			       	        l;
+    int		       		        linetab_indx;
+    const char*                         nampnt;
+    int		       		        naux;
+    BOOL                                ret = FALSE;
+    DWORD                               addr;
+
+    TRACE("Processing COFF symbols...\n");
+
+    assert(sizeof(IMAGE_SYMBOL) == IMAGE_SIZEOF_SYMBOL);
+    assert(sizeof(IMAGE_LINENUMBER) == IMAGE_SIZEOF_LINENUMBER);
+
+    coff_files.files = NULL;
+    coff_files.nfiles = coff_files.nfiles_alloc = 0;
+
+    coff = (const IMAGE_COFF_SYMBOLS_HEADER*)msc_dbg->root;
+
+    coff_symbols = (const IMAGE_SYMBOL*)((unsigned int)coff + 
+                                         coff->LvaToFirstSymbol);
+    coff_linetab = (const IMAGE_LINENUMBER*)((unsigned int)coff + 
+                                             coff->LvaToFirstLinenumber);
+    coff_strtab = (const char*)(coff_symbols + coff->NumberOfSymbols);
+
+    linetab_indx = 0;
+
+    for (i = 0; i < coff->NumberOfSymbols; i++)
+    {
+        coff_sym = coff_symbols + i;
+        naux = coff_sym->NumberOfAuxSymbols;
+
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE)
+	{
+            curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, 
+                                          (const char*)(coff_sym + 1));
+            TRACE("New file %s\n", (const char*)(coff_sym + 1));
+            i += naux;
+            continue;
+	}
+
+        if (curr_file_idx < 0)
+        {
+            assert(coff_files.nfiles == 0 && coff_files.nfiles_alloc == 0);
+            curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, "<none>");
+            TRACE("New file <none>\n");
+        }
+
+        /*
+         * This guy marks the size and location of the text section
+         * for the current file.  We need to keep track of this so
+         * we can figure out what file the different global functions
+         * go with.
+         */
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC &&
+            naux != 0 && coff_sym->Type == 0 && coff_sym->SectionNumber == 1)
+	{
+            aux = (const IMAGE_AUX_SYMBOL*) (coff_sym + 1);
+
+            if (coff_files.files[curr_file_idx].linetab_offset != -1)
+	    {
+                /*
+                 * Save this so we can still get the old name.
+                 */
+                const char* fn;
+
+                fn = source_get(msc_dbg->module, 
+                                coff_files.files[curr_file_idx].compiland->source);
+
+                TRACE("Duplicating sect from %s: %lx %x %x %d %d\n",
+                      fn, aux->Section.Length,
+                      aux->Section.NumberOfRelocations,
+                      aux->Section.NumberOfLinenumbers,
+                      aux->Section.Number, aux->Section.Selection);
+                TRACE("More sect %d %s %08lx %d %d %d\n",
+                      coff_sym->SectionNumber,
+                      coff_get_name(coff_sym, coff_strtab),
+                      coff_sym->Value, coff_sym->Type,
+                      coff_sym->StorageClass, coff_sym->NumberOfAuxSymbols);
+
+                /*
+                 * Duplicate the file entry.  We have no way to describe
+                 * multiple text sections in our current way of handling things.
+                 */
+                coff_add_file(&coff_files, msc_dbg->module, fn);
+	    }
+            else
+	    {
+                TRACE("New text sect from %s: %lx %x %x %d %d\n",
+                      source_get(msc_dbg->module, coff_files.files[curr_file_idx].compiland->source),
+                      aux->Section.Length,
+                      aux->Section.NumberOfRelocations,
+                      aux->Section.NumberOfLinenumbers,
+                      aux->Section.Number, aux->Section.Selection);
+	    }
+
+            if (coff_files.files[curr_file_idx].startaddr > coff_sym->Value)
+	    {
+                coff_files.files[curr_file_idx].startaddr = coff_sym->Value;
+	    }
+
+            if (coff_files.files[curr_file_idx].endaddr < coff_sym->Value + aux->Section.Length)
+	    {
+                coff_files.files[curr_file_idx].endaddr = coff_sym->Value + aux->Section.Length;
+	    }
+
+            coff_files.files[curr_file_idx].linetab_offset = linetab_indx;
+            coff_files.files[curr_file_idx].linecnt = aux->Section.NumberOfLinenumbers;
+            linetab_indx += aux->Section.NumberOfLinenumbers;
+            i += naux;
+            continue;
+	}
+
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0 && 
+            coff_sym->SectionNumber == 1)
+	{
+            DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+            /*
+             * This is a normal static function when naux == 0.
+             * Just register it.  The current file is the correct
+             * one in this instance.
+             */
+            nampnt = coff_get_name(coff_sym, coff_strtab);
+
+            TRACE("\tAdding static symbol %s\n", nampnt);
+
+            /* FIXME: was adding symbol to this_file ??? */
+            coff_add_symbol(&coff_files.files[curr_file_idx],
+                            &symt_new_function(msc_dbg->module, 
+                                               coff_files.files[curr_file_idx].compiland, 
+                                               nampnt,
+                                               msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                                               0 /* FIXME */,
+                                               NULL /* FIXME */)->symt);
+            i += naux;
+            continue;
+	}
+
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
+            ISFCN(coff_sym->Type) && coff_sym->SectionNumber > 0)
+	{
+            struct symt_compiland* compiland = NULL;
+            DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+            nampnt = coff_get_name(coff_sym, coff_strtab);
+
+            TRACE("%d: %lx %s\n",
+                  i, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                  nampnt);
+            TRACE("\tAdding global symbol %s (sect=%s)\n",
+                  nampnt, msc_dbg->sectp[coff_sym->SectionNumber - 1].Name);
+
+            /*
+             * Now we need to figure out which file this guy belongs to.
+             */
+            for (j = 0; j < coff_files.nfiles; j++)
+	    {
+                if (coff_files.files[j].startaddr <= base + coff_sym->Value
+                     && coff_files.files[j].endaddr > base + coff_sym->Value)
+		{
+                    compiland = coff_files.files[j].compiland;
+                    break;
+		}
+	    }
+            if (j < coff_files.nfiles)
+            {
+                coff_add_symbol(&coff_files.files[j],
+                                &symt_new_function(msc_dbg->module, compiland, nampnt, 
+                                                   msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                                                   0 /* FIXME */, NULL /* FIXME */)->symt);
+            } 
+            else 
+            {
+                symt_new_function(msc_dbg->module, NULL, nampnt, 
+                                  msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                                  0 /* FIXME */, NULL /* FIXME */);
+            }
+            i += naux;
+            continue;
+	}
+
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
+            coff_sym->SectionNumber > 0)
+	{
+            DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+            /*
+             * Similar to above, but for the case of data symbols.
+             * These aren't treated as entrypoints.
+             */
+            nampnt = coff_get_name(coff_sym, coff_strtab);
+
+            TRACE("%d: %lx %s\n",
+                  i, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                  nampnt);
+            TRACE("\tAdding global data symbol %s\n", nampnt);
+
+            /*
+             * Now we need to figure out which file this guy belongs to.
+             */
+            symt_new_global_variable(msc_dbg->module, NULL, nampnt, TRUE /* FIXME */,
+                                     msc_dbg->module->module.BaseOfImage + base + coff_sym->Value,
+                                     0 /* FIXME */, NULL /* FIXME */);
+            i += naux;
+            continue;
+	}
+
+        if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0)
+	{
+            /*
+             * Ignore these.  They don't have anything to do with
+             * reality.
+             */
+            i += naux;
+            continue;
+	}
+
+        TRACE("Skipping unknown entry '%s' %d %d %d\n",
+              coff_get_name(coff_sym, coff_strtab),
+              coff_sym->StorageClass, coff_sym->SectionNumber, naux);
+        
+        /*
+         * For now, skip past the aux entries.
+         */
+        i += naux;
+    }
+
+    if (coff_files.files != NULL)
+    {
+        /*
+         * OK, we now should have a list of files, and we should have a list
+         * of entrypoints.  We need to sort the entrypoints so that we are
+         * able to tie the line numbers with the given functions within the
+         * file.
+         */
+        for (j = 0; j < coff_files.nfiles; j++)
+        {
+            if (coff_files.files[j].entries != NULL)
+            {
+                qsort(coff_files.files[j].entries, coff_files.files[j].neps,
+                      sizeof(struct symt*), symt_cmp_addr);
+            }
+        }
+
+        /*
+         * Now pick apart the line number tables, and attach the entries
+         * to the given functions.
+         */
+        for (j = 0; j < coff_files.nfiles; j++)
+        {
+            l = 0;
+            if (coff_files.files[j].neps != 0)
+            {
+                for (k = 0; k < coff_files.files[j].linecnt; k++)
+                {
+                    linepnt = coff_linetab + coff_files.files[j].linetab_offset + k;
+                    /*
+                     * If we have spilled onto the next entrypoint, then
+                     * bump the counter..
+                     */
+                    for (;;)
+                    {
+                        if (l+1 >= coff_files.files[j].neps) break;
+                        symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
+                        if (((msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress) < addr))
+                            break;
+                        l++;
+                    }
+
+                    if (coff_files.files[j].entries[l+1]->tag == SymTagFunction)
+                    {
+                        /*
+                         * Add the line number.  This is always relative to the
+                         * start of the function, so we need to subtract that offset
+                         * first.
+                         */
+                        symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
+                        symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1], 
+                                           coff_files.files[j].compiland->source, linepnt->Linenumber,
+                                           msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress - addr);
+                    }
+                }
+            }
+        }
+
+        for (j = 0; j < coff_files.nfiles; j++)
+	{
+            if (coff_files.files[j].entries != NULL)
+	    {
+                HeapFree(GetProcessHeap(), 0, coff_files.files[j].entries);
+	    }
+	}
+        HeapFree(GetProcessHeap(), 0, coff_files.files);
+        msc_dbg->module->module.SymType = SymCoff;
+        ret = TRUE;
+    }
+
+    return ret;
+}

reactos/lib/dbghelp
.cvsignore added at 1.1
diff -N .cvsignore
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ .cvsignore	16 Dec 2004 17:42:10 -0000	1.1
@@ -0,0 +1,26 @@
+*.coff
+*.dll
+*.d
+*.a
+*.o
+*.sym
+*.map
+*.tmp
+Makefile.ros
+idb_hist_large.bmp
+idb_hist_small.bmp
+idb_std_small.bmp
+idb_std_large.bmp
+idb_view_large.bmp
+idb_view_small.bmp
+idc_copy.cur
+idc_divider.cur
+idc_divideropen.cur
+idc_movebutton.cur
+idi_dragarrow.ico
+idi_tt_error_sm.ico
+idi_tt_info_sm.ico
+idi_tt_warn_sm.ico
+idt_check.bmp
+comctl32.spec.def
+comctl32.stubs.c
CVSspam 0.2.8