27 added files
- FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
- FIXME ?? */
- FIXME we leak e */
- FIXME we leak e */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME("Unsupported sym-tag %s for find-children\n",
- FIXME("Unsupported sym-tag %s for get-address\n",
- FIXME("Unsupported sym-tag %s for get-children-count\n",
- FIXME: should be size of base-type of enum !!! */
- FIXME("Unsupported sym-tag %s for get-length\n",
- FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
- FIXME("Unknown kind (%u) for get-offset\n",
- FIXME("Unsupported sym-tag %s for get-offset\n",
- FIXME: should also work for enums and FunctionArgType */
- FIXME("Unsupported sym-tag %s for get-type\n",
- FIXME("Unsupported GetInfo request (%u)\n", req);
- FIXME("Someone didn't properly set ModBase (%s)\n", wine_dbgstr_longlong(ModBase));
- FIXME: this shouldn't be valid on '-' */
- FIXME("Couldn't compile %s\n", mask);
- FIXME("Size mismatch for %s.%s between type (%lu) and src (%lu)\n",
- FIXME: needed ? moreover, it's i386 dependent !!! */
- FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
- FIXME("Unhandled kind (%u) in sym data\n", data->kind);
- FIXME */
- FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
- FIXME: Name could be made out of a regular expression */
- FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
- FIXME("OOM\n");return NULL;}
- FIXME("STATS: elts[num:%-4u size:%u mean:%f] buckets[min:%-4u variance:%+f max:%-4u]\n",
- FIXME("Longuest bucket:\n");
- FIXME("\t%s\n", elt->name);
- FIXME: must be included before winternl.h */
- FIXME: I could perhaps create a dummy include_def for each compilation
- FIXME: TI_GET_LENGTH will not always work, especially when adt
- FIXME: there's a quite ugly memory leak in there...
- FIXME: range type is lost, always assume int */
- FIXME("Unsupported yet (should get info from current context)\n");
- FIXME: not using Mask */
- FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
- FIXME */, TRUE /* FIXME */);
- FIXME: we'd better store addresses linked to sections rather than
- FIXME */, TRUE /* FIXME */);
- FIXME */, TRUE /* FIXME */);
- FIXME */, TRUE /* FIXME */);
- FIXME shouldn't we check that? if (!module_get_debug(pcs, module))l */
- FIXME SetLastError */
- FIXME("Trouble ahead (no module name passed in deferred mode)\n");
- FIXME("(%s %s %p %p %p): stub\n",
- FIXME: should check that id/two/three match the file pointed
- TODO:
- FIXME("%s\n", msg);
- FIXME: don't make it static */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unsupported numeric leaf type %04x\n", type);
- FIXME */
- FIXME("Unknown numeric leaf type %04x\n", type);
- FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index, typeno);
- FIXME("bitfields are only handled for UDTs\n");
- FIXME("Returning NULL symt for type-id %x\n", typeno);
- FIXME("What the heck\n");
- FIXME("Adding %x to non allowed module\n", typeno);
- FIXME("No module index while inserting type-id assumption is wrong %x\n",
- FIXME("Unsupported type %04x in ENUM field list\n", type->generic.id);
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME: ignored for now */
- FIXME("Unsupported type %04x in STRUCT field list\n", type->generic.id);
- FIXME: this is rather ugly !!! */
- FIXME: this is rather ugly !!! */
- FIXME: we don't handle modifiers,
- FIXME: we don't handle modifiers, but readd previous type on the curr_type */
- FIXME: for C++, this is plain wrong, but as we don't use arg types
- FIXME: for C++, this is plain wrong, but as we don't use arg types
- FIXME("Not adding parameters' types to function signature\n");
- FIXME("Unsupported type-id leaf %x\n", type->generic.id);
- FIXME: this seems a bit too high (on a per module basis)
- FIXME("should have successfully loaded some debug information for image %s\n", ImageName);
- FIXME("This shouldn't happen\n");
- FIXME("If this happens, bump the number in mod\n");
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME("CV and misc records not written\n");
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME */
- FIXME("Stack & thread context not written\n");
- FIXME: should try to load it ??? */
- FIXME("NIY MiniDumpWithDataSegs\n");
- FIXME("NIY MiniDumpWithFullMemory\n");
- FIXME("NIY MiniDumpWithHandleData\n");
- FIXME("NIY MiniDumpFilterMemory\n");
- FIXME("NIY MiniDumpScanMemory\n");
- FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
- FIXME("Failed to linearize address %04x:%08lx (mode %x)\n",
- FIXME("(%p, %s, %s, 0x%08lx): stub\n", FileHandle, FileName, SymbolPath, ImageBase);
- FIXME("(%p): stub\n", DebugInfo);
- FIXME: we don't need to handle them (GCC internals)
- FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n",
- FIXME("Couldn't find symbol %s.%s in symtab\n",
- FIXME("Couldn't find %s\n", sym->hash_elt.name);
- FIXME("Unsupported tag %u\n", sym->symt.tag);
- FIXME: this is not a good idea anyway... we are creating several
- FIXME: this is a hack !!!
- FIXME("Duplicate in %s: %s<%08lx-%08x> %s<%s-%08lx>\n",
- FIXME: we're missing the ELF entry point here */
- FIXME: this is not a good idea anyway... we are creating several
- FIXME */,
- FIXME("Unsupported Dwarf2 information for %s\n", module->module.ModuleName);
- FIXME: doesn't seem to be accessible */
- TODO
- FIXME:s (lots of types are not defined)
- FIXME should grow hMods */
- FIXME("what to do ??\n");
- FIXME("(%p, %p, %p): stub\n", hProcess, CallbackFunction, UserContext);
- TODO:
- FIXME: was adding symbol to this_file ??? */
- FIXME */,
- FIXME */)->symt);
- FIXME */, NULL /* FIXME */)->symt);
- FIXME */, NULL /* FIXME */);
- FIXME */,
- FIXME */, NULL /* FIXME */);
reactos/lib/dbghelp
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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