- removed file extension from module (and suffixed ELF modules with

<elf>)
- added generic thunk support for builtin modules (with the help of
  winebuild's new markers for thunks)
- for ELF modules, no longer generating SymTagPublicSymbols objects
  from ELF public symbol table
- because of last point, rewrote stabs symbols' address and size
  management by parsing directly the symtab instead of using
  SymTagPublicSymbols objects
- cleaned up SymTagPublicSymbols object names for native modules
- fixed off by one errors in array management
- SymLoadModule(hProc,0,0,0,0) (wine extension) will force the
  resynchronization of internal ELF modules list)
- new option (0x40000000) for Sym{Get|Set}Option to report ELF modules
  in SymEnumModules (as well as loader with <wine-loader>)
- some minor internal clean-ups
- enhanced const correctness
This commit is contained in:
Eric Pouech 2004-05-18 21:29:09 +00:00 committed by Alexandre Julliard
parent d3f8f78c3a
commit 48a865983d
12 changed files with 707 additions and 361 deletions

View File

@ -42,9 +42,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
* + we should add parameters' types to the function's signature
* while processing a function's parameters
* + get rid of MSC reading FIXME:s (lots of types are not defined)
* + support the PUBLICS_ONLY, NO_PUBLICS and AUTO_PUBLICS options
* + C++ management
* - stabs:
* + should identify the relay code in Wine and mark it as thunk type
* + C++ management
* - implement the callback notification mechanism
*/
@ -122,7 +122,7 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, LPSTR szSearchPath,
static BOOL process_invade(HANDLE hProcess)
{
HMODULE hMods[256];
char img[256], mod[256];
char img[256];
DWORD i, sz;
MODULEINFO mi;
@ -133,8 +133,7 @@ static BOOL process_invade(HANDLE hProcess)
{
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)) ||
!SymLoadModule(hProcess, 0, img, mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
!SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
return FALSE;
}
@ -218,8 +217,7 @@ BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProc
if (fInvadeProcess)
{
pcs->dbg_hdr_addr = elf_read_wine_loader_dbg_info(pcs);
if (pcs->dbg_hdr_addr == 0)
if (!elf_read_wine_loader_dbg_info(pcs))
{
SymCleanup(hProcess);
return FALSE;

View File

@ -149,7 +149,7 @@ struct symt_function
{
struct symt symt;
struct hash_table_elt hash_elt; /* if global symbol */
unsigned long addr;
unsigned long address;
struct symt* container; /* compiland */
struct symt* type; /* points to function_signature */
unsigned long size;
@ -176,6 +176,16 @@ struct symt_public
is_function : 1;
};
struct symt_thunk
{
struct symt symt;
struct hash_table_elt hash_elt;
struct symt* container; /* compiland */
unsigned long address;
unsigned long size;
THUNK_ORDINAL ordinal; /* FIXME: doesn't seem to be accessible */
};
/* class tree */
struct symt_array
{
@ -229,15 +239,19 @@ struct symt_udt
struct vector vchildren;
};
enum DbgModuleType {DMT_UNKNOWN, DMT_ELF, DMT_NE, DMT_PE};
enum module_type
{
DMT_UNKNOWN, /* for lookup, not actually used for a module */
DMT_ELF, /* a real ELF shared module */
DMT_PE, /* a native or builtin PE module */
};
struct module
{
IMAGEHLP_MODULE module;
struct module* next;
enum DbgModuleType type;
unsigned short elf_mark : 1;
struct tagELF_DBG_INFO* elf_dbg_info;
enum module_type type;
struct elf_module_info* elf_info;
/* memory allocation pool */
struct pool pool;
@ -275,8 +289,7 @@ extern struct process* process_find_by_handle(HANDLE hProcess);
extern SYM_TYPE elf_load_debug_info(struct module* module);
extern struct module*
elf_load_module(struct process* pcs, const char* name);
extern unsigned long
elf_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL elf_synchronize_module_list(struct process* pcs);
/* memory.c */
@ -294,15 +307,15 @@ extern unsigned long WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDR
/* module.c */
extern struct module*
module_find_by_addr(const struct process* pcs, unsigned long addr,
enum DbgModuleType type);
enum module_type type);
extern struct module*
module_find_by_name(const struct process* pcs,
const char* name, enum DbgModuleType type);
const char* name, enum module_type type);
extern struct module*
module_get_debug(const struct process* pcs, struct module*);
extern struct module*
module_new(struct process* pcs, const char* name,
enum DbgModuleType type, unsigned long addr,
enum module_type type, unsigned long addr,
unsigned long size, unsigned long stamp,
unsigned long checksum);
@ -312,7 +325,7 @@ extern BOOL module_remove(struct process* pcs,
extern SYM_TYPE pe_load_debug_directory(const struct process* pcs,
struct module* module,
const BYTE* file_map,
PIMAGE_DEBUG_DIRECTORY dbg, int nDbg);
const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
/* pe_module.c */
extern struct module*
pe_load_module(struct process* pcs, char* name,
@ -335,6 +348,7 @@ extern SYM_TYPE stabs_parse(struct module* module, const char* addr,
/* 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);
@ -386,6 +400,11 @@ 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);
@ -424,3 +443,7 @@ extern struct symt_pointer*
extern struct symt_typedef*
symt_new_typedef(struct module* module, struct symt* ref,
const char* name);
/* some more Wine extensions */
#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000

View File

@ -70,10 +70,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
typedef struct tagELF_DBG_INFO
struct elf_module_info
{
unsigned long elf_addr;
} ELF_DBG_INFO;
unsigned long elf_addr;
unsigned short elf_mark : 1,
elf_loader : 1;
};
#ifdef __ELF__
@ -82,43 +84,57 @@ typedef struct tagELF_DBG_INFO
struct elf_info
{
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
};
struct symtab_elt
{
struct hash_table_elt ht_elt;
const Elf32_Sym* symp;
const char* filename;
unsigned used;
};
struct thunk_area
{
const char* symname;
THUNK_ORDINAL ordinal;
unsigned long rva_start;
unsigned long rva_end;
};
/******************************************************************
* elf_load_symtab
* elf_hash_symtab
*
* Walk through the entire symbol table and add any symbols we find there.
* This can be used in cases where we have stripped ELF shared libraries,
* or it can be used in cases where we have data symbols for which the address
* isn't encoded in the stabs.
*
* This is all really quite easy, since we don't have to worry about line
* numbers or local data variables.
* creating an internal hash table to ease use ELF symtab information lookup
*/
static int elf_load_symtab(struct module* module, const char* addr,
unsigned long load_addr, const Elf32_Shdr* symtab,
const Elf32_Shdr* strtab)
static void elf_hash_symtab(const struct module* module, struct pool* pool,
struct hash_table* ht_symtab, const char* map_addr,
const Elf32_Shdr* symtab, const Elf32_Shdr* strtab,
unsigned num_areas, struct thunk_area* thunks)
{
int i, nsym;
int i, j, nsym;
const char* strp;
const char* symname;
const char* filename = NULL;
const Elf32_Sym* symp;
struct symt_compiland* compiland = NULL;
struct symtab_elt* ste;
symp = (Elf32_Sym*)(addr + symtab->sh_offset);
symp = (const Elf32_Sym*)(map_addr + symtab->sh_offset);
nsym = symtab->sh_size / sizeof(*symp);
strp = (char*)(addr + strtab->sh_offset);
strp = (const char*)(map_addr + strtab->sh_offset);
for (j = 0; j < num_areas; j++)
thunks[j].rva_start = thunks[j].rva_end = 0;
for (i = 0; i < nsym; i++, symp++)
{
/* Ignore certain types of entries which really aren't of that much
* interest.
*/
if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION ||
symp->st_shndx == SHN_UNDEF)
if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION || symp->st_shndx == SHN_UNDEF)
{
continue;
}
@ -127,14 +143,252 @@ static int elf_load_symtab(struct module* module, const char* addr,
if (ELF32_ST_TYPE(symp->st_info) == STT_FILE)
{
compiland = symt_new_compiland(module, symname);
filename = symname;
continue;
}
symt_new_public(module, compiland, symname,
load_addr + symp->st_value, symp->st_size,
TRUE /* FIXME */, ELF32_ST_TYPE(symp->st_info) == STT_FUNC);
for (j = 0; j < num_areas; j++)
{
if (!strcmp(symname, thunks[j].symname))
{
thunks[j].rva_start = symp->st_value;
thunks[j].rva_end = symp->st_value + symp->st_size;
break;
}
}
if (j < num_areas) continue;
ste = pool_alloc(pool, sizeof(*ste));
ste->ht_elt.name = symname;
ste->symp = symp;
ste->filename = filename;
ste->used = 0;
hash_table_add(ht_symtab, &ste->ht_elt);
}
}
/******************************************************************
* elf_lookup_symtab
*
* lookup a symbol by name in our internal hash table for the symtab
*/
static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
const struct hash_table* ht_symtab,
const char* name, struct symt* compiland)
{
struct symtab_elt* weak_result = NULL; /* without compiland name */
struct symtab_elt* result = NULL;
struct hash_table_iter hti;
struct symtab_elt* ste;
const char* compiland_name;
const char* compiland_basename;
const char* base;
/* we need weak match up (at least) when symbols of same name,
* defined several times in different compilation units,
* are merged in a single one (hence a different filename for c.u.)
*/
if (compiland)
{
compiland_name = source_get(module,
((struct symt_compiland*)compiland)->source);
compiland_basename = strrchr(compiland_name, '/');
if (!compiland_basename++) compiland_basename = compiland_name;
}
else compiland_name = compiland_basename = NULL;
hash_table_iter_init(ht_symtab, &hti, name);
while ((ste = hash_table_iter_up(&hti)))
{
if (ste->used || strcmp(ste->ht_elt.name, name)) continue;
weak_result = ste;
if ((ste->filename && !compiland_name) || (!ste->filename && compiland_name))
continue;
if (ste->filename && compiland_name)
{
if (strcmp(ste->filename, compiland_name))
{
base = strrchr(ste->filename, '/');
if (!base++) base = ste->filename;
if (strcmp(base, compiland_basename)) continue;
}
}
if (result)
{
FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n",
name, compiland_name, result->filename, result->symp->st_value,
ste->filename, ste->symp->st_value);
}
else
{
result = ste;
ste->used = 1;
}
}
if (!result && !(result = weak_result))
{
FIXME("Couldn't find symbol %s.%s in symtab\n",
module->module.ModuleName, name);
return NULL;
}
return result->symp;
}
/******************************************************************
* elf_finish_stabs_info
*
* - get any relevant information (address & size) from the bits we got from the
* stabs debugging information
*/
static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
{
struct hash_table_iter hti;
void* ptr;
struct symt_ht* sym;
const Elf32_Sym* symp;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
switch (sym->symt.tag)
{
case SymTagFunction:
if (((struct symt_function*)sym)->address != module->elf_info->elf_addr)
break;
symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
((struct symt_function*)sym)->container);
if (symp)
{
((struct symt_function*)sym)->address = module->elf_info->elf_addr +
symp->st_value;
((struct symt_function*)sym)->size = symp->st_size;
}
break;
case SymTagData:
switch (((struct symt_data*)sym)->kind)
{
case DataIsGlobal:
case DataIsFileStatic:
if (((struct symt_data*)sym)->u.address != module->elf_info->elf_addr)
break;
symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
((struct symt_data*)sym)->container);
if (symp)
((struct symt_data*)sym)->u.address = module->elf_info->elf_addr +
symp->st_value;
break;
default:;
}
break;
default:
FIXME("Unsupported tag %u\n", sym->symt.tag);
break;
}
}
}
/******************************************************************
* elf_load_wine_thunks
*
* creating the thunk objects for a wine native DLL
*/
static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
unsigned num_areas, struct thunk_area* thunks)
{
int j;
struct symt_compiland* compiland = NULL;
const char* compiland_name = NULL;
struct hash_table_iter hti;
struct symtab_elt* ste;
DWORD addr;
hash_table_iter_init(ht_symtab, &hti, NULL);
while ((ste = hash_table_iter_up(&hti)))
{
if (ste->used) continue;
/* FIXME: this is not a good idea anyway... we are creating several
* compiland objects for a same compilation unit
* We try to cache the last compiland used, but it's not enough
* (we should here only create compilands if they are not yet
* defined)
*/
if (!compiland_name || compiland_name != ste->filename)
compiland = symt_new_compiland(module,
compiland_name = ste->filename);
addr = module->elf_info->elf_addr + ste->symp->st_value;
for (j = 0; j < num_areas; j++)
{
if (ste->symp->st_value >= thunks[j].rva_start &&
ste->symp->st_value < thunks[j].rva_end)
break;
}
if (j < num_areas) /* thunk found */
{
symt_new_thunk(module, compiland, ste->ht_elt.name, thunks[j].ordinal,
addr, ste->symp->st_size);
}
else if (symt_find_nearest(module, addr) == -1)
{
/* creating public symbols for all the ELF symbols which haven't been
* used yet (ie we have no debug information on them)
* That's the case, for example, of the .spec.c files
*/
if (ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC)
{
symt_new_function(module, compiland, ste->ht_elt.name,
addr, ste->symp->st_size, NULL);
}
else
{
symt_new_global_variable(module, compiland, ste->ht_elt.name,
FALSE /* FIXME */,
addr, ste->symp->st_size, NULL);
}
}
}
return TRUE;
}
/******************************************************************
* elf_new_public_symbols
*
* Creates a set of public symbols from an ELF symtab
*/
static int elf_new_public_symbols(struct module* module, struct hash_table* symtab,
BOOL dont_check)
{
struct symt_compiland* compiland = NULL;
const char* compiland_name = NULL;
struct hash_table_iter hti;
struct symtab_elt* ste;
if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) return TRUE;
hash_table_iter_init(symtab, &hti, NULL);
while ((ste = hash_table_iter_up(&hti)))
{
/* FIXME: this is not a good idea anyway... we are creating several
* compiland objects for a same compilation unit
* We try to cache the last compiland used, but it's not enough
* (we should here only create compilands if they are not yet
* defined)
*/
if (!compiland_name || compiland_name != ste->filename)
compiland = symt_new_compiland(module,
compiland_name = ste->filename);
if (dont_check || !(dbghelp_options & SYMOPT_AUTO_PUBLICS) ||
symt_find_nearest(module, module->elf_info->elf_addr + ste->symp->st_value) == -1)
{
symt_new_public(module, compiland, ste->ht_elt.name,
module->elf_info->elf_addr + ste->symp->st_value,
ste->symp->st_size, TRUE /* FIXME */,
ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
}
}
return TRUE;
}
@ -160,10 +414,22 @@ SYM_TYPE elf_load_debug_info(struct module* module)
const Elf32_Shdr* spnt;
const char* shstrtab;
int i;
int stabsect, stabstrsect, debugsect;
int symsect, dynsect;
int symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect;
struct pool pool;
struct hash_table ht_symtab;
struct thunk_area thunks[] =
{
{"__wine_spec_import_thunks", THUNK_ORDINAL_NOTYPE, 0, 0}, /* inter DLL calls */
{"__wine_spec_delayed_import_loaders", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
{"__wine_spec_delayed_import_thunks", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
{"__wine_delay_load", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
{"__wine_spec_thunk_text_16", -16, 0, 0}, /* 16 => 32 thunks */
{"__wine_spec_thunk_data_16", -16, 0, 0}, /* 16 => 32 thunks */
{"__wine_spec_thunk_text_32", -32, 0, 0}, /* 32 => 16 thunks */
{"__wine_spec_thunk_data_32", -32, 0, 0}, /* 32 => 16 thunks */
};
if (module->type != DMT_ELF || !module->elf_dbg_info)
if (module->type != DMT_ELF || !module->elf_info)
{
ERR("Bad elf module '%s'\n", module->module.LoadedImageName);
return sym_type;
@ -195,55 +461,86 @@ SYM_TYPE elf_load_debug_info(struct module* module)
spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
symsect = dynsect = stabsect = stabstrsect = debugsect = -1;
symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = -1;
for (i = 0; i < ehptr->e_shnum; i++)
{
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
stabsect = i;
stab_sect = i;
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
stabstrsect = i;
stabstr_sect = i;
if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
debugsect = i;
debug_sect = i;
if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
(spnt[i].sh_type == SHT_SYMTAB))
symsect = i;
if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
(spnt[i].sh_type == SHT_DYNSYM))
dynsect = i;
symtab_sect = i;
if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
(spnt[i].sh_type == SHT_DYNSYM))
dynsym_sect = i;
}
/* start loading dynamic symbol info (so that we can get the correct address) */
if (symsect != -1)
elf_load_symtab(module, addr, module->elf_dbg_info->elf_addr,
spnt + symsect, spnt + spnt[symsect].sh_link);
else if (dynsect != -1)
elf_load_symtab(module, addr, module->elf_dbg_info->elf_addr,
spnt + dynsect, spnt + spnt[dynsect].sh_link);
sym_type = SymExport;
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
if (symtab_sect == -1)
{
if (stabsect != -1 && stabstrsect != -1)
{
/* OK, now just parse all of the stabs. */
sym_type = stabs_parse(module, addr, module->elf_dbg_info->elf_addr,
spnt[stabsect].sh_offset, spnt[stabsect].sh_size,
spnt[stabstrsect].sh_offset,
spnt[stabstrsect].sh_size);
if (sym_type == -1)
{
WARN("Couldn't read correctly read stabs\n");
goto leave;
}
}
else if (debugsect != -1)
{
/* Dwarf 2 debug information */
FIXME("Unsupported Dwarf2 information\n");
sym_type = SymNone;
}
/* if we don't have a symtab but a dynsym, process the dynsym
* section instead. It'll contain less (relevant) information,
* but it'll be better than nothing
*/
if (dynsym_sect == -1) goto leave;
symtab_sect = dynsym_sect;
}
/* FIXME: guess a better size from ELF info */
pool_init(&pool, 65536);
hash_table_init(&pool, &ht_symtab, 256);
/* create a hash table for the symtab */
elf_hash_symtab(module, &pool, &ht_symtab, addr,
spnt + symtab_sect, spnt + spnt[symtab_sect].sh_link,
sizeof(thunks) / sizeof(thunks[0]), thunks);
if (stab_sect != -1 && stabstr_sect != -1 &&
!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
{
/* OK, now just parse all of the stabs. */
sym_type = stabs_parse(module, addr, module->elf_info->elf_addr,
spnt[stab_sect].sh_offset, spnt[stab_sect].sh_size,
spnt[stabstr_sect].sh_offset,
spnt[stabstr_sect].sh_size);
if (sym_type == -1)
{
WARN("Couldn't read correctly read stabs\n");
goto leave;
}
/* and fill in the missing information for stabs */
elf_finish_stabs_info(module, &ht_symtab);
}
else if (debug_sect != -1)
{
/* Dwarf 2 debug information */
FIXME("Unsupported Dwarf2 information\n");
sym_type = SymNone;
}
if (strstr(module->module.ModuleName, "<elf>"))
{
/* add the thunks for native libraries */
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
elf_new_wine_thunks(module, &ht_symtab,
sizeof(thunks) / sizeof(thunks[0]), thunks);
/* add the public symbols from symtab
* (only if they haven't been defined yet)
*/
elf_new_public_symbols(module, &ht_symtab, FALSE);
}
else
{
/* add all the public symbols from symtab */
elf_new_public_symbols(module, &ht_symtab, TRUE);
}
pool_destroy(&pool);
leave:
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
if (fd != -1) close(fd);
@ -298,6 +595,7 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
const char* shstrtab;
int i;
DWORD delta, size;
unsigned tmp, page_mask = getpagesize() - 1;
TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset);
@ -317,10 +615,10 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
* this thing. We need the main executable header, and the section
* table.
*/
ehptr = (Elf32_Ehdr*)addr;
ehptr = (const Elf32_Ehdr*)addr;
if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
spnt = (const Elf32_Shdr*)(addr + ehptr->e_shoff);
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
/* if non relocatable ELF, then remove fixed address from computation
@ -329,14 +627,14 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
delta = (load_offset == 0) ? ehptr->e_entry : 0;
/* grab size of module once loaded in memory */
ppnt = (Elf32_Phdr*)(addr + ehptr->e_phoff);
ppnt = (const Elf32_Phdr*)(addr + ehptr->e_phoff);
size = 0;
for (i = 0; i < ehptr->e_phnum; i++)
{
if (ppnt[i].p_type == PT_LOAD)
if (ppnt[i].p_type == PT_LOAD)
{
size += (ppnt[i].p_align <= 1) ? ppnt[i].p_memsz :
(ppnt[i].p_memsz + ppnt[i].p_align - 1) & ~(ppnt[i].p_align - 1);
tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask;
if (size < tmp) size = tmp;
}
}
@ -375,16 +673,19 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
size, 0, 0);
if (elf_info->module)
{
if ((elf_info->module->elf_dbg_info = HeapAlloc(GetProcessHeap(), 0, sizeof(ELF_DBG_INFO))) == NULL)
elf_info->module->elf_info = HeapAlloc(GetProcessHeap(),
0, sizeof(struct elf_module_info));
if (elf_info->module->elf_info == NULL)
{
ERR("OOM\n");
exit(0); /* FIXME */
}
elf_info->module->elf_dbg_info->elf_addr = load_offset;
elf_info->module->elf_info->elf_addr = load_offset;
elf_info->module->module.SymType = sym_type =
(dbghelp_options & SYMOPT_DEFERRED_LOADS) ? SymDeferred :
elf_load_debug_info(elf_info->module);
elf_info->module->elf_mark = 1;
elf_info->module->elf_info->elf_mark = 1;
elf_info->module->elf_info->elf_loader = 0;
}
else sym_type = -1;
}
@ -447,7 +748,7 @@ static SYM_TYPE elf_search_and_load_file(struct process* pcs, const char* filena
if ((module = module_find_by_name(pcs, filename, DMT_ELF)))
{
elf_info->module = module;
module->elf_mark = 1;
module->elf_info->elf_mark = 1;
return module->module.SymType;
}
@ -493,7 +794,7 @@ BOOL elf_synchronize_module_list(struct process* pcs)
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_ELF) module->elf_mark = 0;
if (module->type == DMT_ELF) module->elf_info->elf_mark = 0;
}
elf_info.flags = ELF_INFO_MODULE;
@ -519,7 +820,8 @@ BOOL elf_synchronize_module_list(struct process* pcs)
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_ELF && !module->elf_mark)
if (module->type == DMT_ELF && !module->elf_info->elf_mark &&
!module->elf_info->elf_loader)
{
module_remove(pcs, module);
/* restart all over */
@ -532,15 +834,15 @@ BOOL elf_synchronize_module_list(struct process* pcs)
/******************************************************************
* elf_read_wine_loader_dbg_info
*
* Try to find a decent wine executable which could have loader the debuggee
* Try to find a decent wine executable which could have loaded the debuggee
*/
unsigned long elf_read_wine_loader_dbg_info(struct process* pcs)
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
{
const char* ptr;
SYM_TYPE sym_type;
struct elf_info elf_info;
elf_info.flags = ELF_INFO_DEBUG_HEADER;
elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
/* All binaries are loaded with WINELOADER (if run from tree) or by the
* main executable (either wine-kthread or wine-pthread)
* Note: the heuristic use to know whether we need to load wine-pthread or
@ -553,7 +855,10 @@ unsigned long elf_read_wine_loader_dbg_info(struct process* pcs)
if ((sym_type = elf_search_and_load_file(pcs, "wine-kthread", 0, &elf_info)) == -1)
sym_type = elf_search_and_load_file(pcs, "wine-pthread", 0, &elf_info);
}
return (sym_type < 0) ? 0 : elf_info.dbg_hdr_addr;
if (sym_type < 0) return FALSE;
elf_info.module->elf_info->elf_loader = 1;
strcpy(elf_info.module->module.ModuleName, "<wine-loader>");
return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
}
/******************************************************************

View File

@ -33,16 +33,37 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static void module_fill_module(const char* in, char* out, unsigned size)
{
const char* ptr;
unsigned len;
for (ptr = in + strlen(in) - 1;
*ptr != '/' && *ptr != '\\' && ptr >= in;
ptr--);
if (ptr < in || *ptr == '/' || *ptr == '\\') ptr++;
strncpy(out, ptr, size);
out[size - 1] = '\0';
len = strlen(out);
if (len > 4 &&
(!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe")))
out[len - 4] = '\0';
else
if (len > 7 &&
(!strcasecmp(&out[len - 7], ".dll.so") || !strcasecmp(&out[len - 7], ".exe.so")))
strcpy(&out[len - 7], "<elf>");
while ((*out = tolower(*out))) out++;
}
/***********************************************************************
* Creates and links a new module to a process
*/
struct module* module_new(struct process* pcs, const char* name,
enum DbgModuleType type,
enum module_type type,
unsigned long mod_addr, unsigned long size,
unsigned long stamp, unsigned long checksum)
{
struct module* module;
const char* ptr;
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
return NULL;
@ -61,12 +82,7 @@ struct module* module_new(struct process* pcs, const char* name,
module->module.SizeOfStruct = sizeof(module->module);
module->module.BaseOfImage = mod_addr;
module->module.ImageSize = size;
for (ptr = name + strlen(name) - 1;
*ptr != '/' && *ptr != '\\' && ptr >= name;
ptr--);
if (ptr < name || *ptr == '/' || *ptr == '\\') ptr++;
strncpy(module->module.ModuleName, ptr, sizeof(module->module.ModuleName));
module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
module->module.ImageName[0] = '\0';
strncpy(module->module.LoadedImageName, name,
sizeof(module->module.LoadedImageName));
@ -97,7 +113,7 @@ struct module* module_new(struct process* pcs, const char* name,
*
*/
struct module* module_find_by_name(const struct process* pcs,
const char* name, enum DbgModuleType type)
const char* name, enum module_type type)
{
struct module* module;
@ -188,7 +204,7 @@ struct module* module_get_debug(const struct process* pcs, struct module* module
* module
*/
struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
enum DbgModuleType type)
enum module_type type)
{
struct module* module;
@ -227,6 +243,13 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
/* this is a Wine extension to the API */
if (!ImageName && !hFile)
{
elf_synchronize_module_list(pcs);
return 0;
}
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
{
unsigned len = strlen(ImageName);
@ -316,7 +339,8 @@ BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type != DMT_PE) continue;
if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type != DMT_PE)
continue;
if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext))
break;
@ -333,7 +357,7 @@ BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
PVOID UserContext)
{
HMODULE* hMods;
char img[256], mod[256];
char base[256], mod[256];
DWORD i, sz;
MODULEINFO mi;
@ -351,9 +375,10 @@ BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
for (i = 0; i < sz; i++)
{
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
break;
!GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
continue;
module_fill_module(base, mod, sizeof(mod));
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
UserContext);
}

View File

@ -70,9 +70,9 @@ struct msc_debug_info
{
struct module* module;
int nsect;
PIMAGE_SECTION_HEADER sectp;
const IMAGE_SECTION_HEADER* sectp;
int nomap;
OMAP_DATA* omapp;
const OMAP_DATA* omapp;
const BYTE* root;
};
@ -218,8 +218,8 @@ static SYM_TYPE coff_process_info(const struct msc_debug_info* msc_dbg)
if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE)
{
curr_file_idx = coff_add_file(&coff_files, msc_dbg->module,
(char*)(coff_sym + 1));
TRACE("New file %s\n", (char*)(coff_sym + 1));
(const char*)(coff_sym + 1));
TRACE("New file %s\n", (const char*)(coff_sym + 1));
i += naux;
continue;
}
@ -1111,27 +1111,27 @@ static int numeric_leaf(int* value, const unsigned short int* leaf)
{
case LF_CHAR:
length += 1;
*value = *(char*)leaf;
*value = *(const char*)leaf;
break;
case LF_SHORT:
length += 2;
*value = *(short*)leaf;
*value = *(const short*)leaf;
break;
case LF_USHORT:
length += 2;
*value = *(unsigned short*)leaf;
*value = *(const unsigned short*)leaf;
break;
case LF_LONG:
length += 4;
*value = *(int*)leaf;
*value = *(const int*)leaf;
break;
case LF_ULONG:
length += 4;
*value = *(unsigned int*)leaf;
*value = *(const unsigned int*)leaf;
break;
case LF_QUADWORD:
@ -1327,7 +1327,7 @@ static int codeview_add_type_enum_field_list(struct module* module,
symt = symt_new_enum(module, NULL);
while (ptr - list < len)
{
union codeview_fieldtype* type = (union codeview_fieldtype*)ptr;
const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
if (*ptr >= 0xf0) /* LF_PAD... */
{
@ -1340,7 +1340,7 @@ static int codeview_add_type_enum_field_list(struct module* module,
case LF_ENUMERATE:
{
int value, vlen = numeric_leaf(&value, &type->enumerate.value);
unsigned char* name = (unsigned char*)&type->enumerate.value + vlen;
const unsigned char* name = (const unsigned char*)&type->enumerate.value + vlen;
symt_add_enum_element(module, symt, terminate_string(name), value);
ptr += 2 + 2 + vlen + (1 + name[0]);
@ -1400,7 +1400,7 @@ static int codeview_add_type_struct_field_list(struct module* module,
case LF_IVBCLASS:
{
int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass.vbpoff);
const unsigned short int* p_vboff = (const unsigned short int*)((char*)&type->vbclass.vbpoff + vbpoff);
const unsigned short int* p_vboff = (const unsigned short int*)((const char*)&type->vbclass.vbpoff + vbpoff);
int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
/* FIXME: ignored for now */
@ -1413,7 +1413,7 @@ static int codeview_add_type_struct_field_list(struct module* module,
case LF_IVBCLASS_32:
{
int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass32.vbpoff);
const unsigned short int* p_vboff = (const unsigned short int*)((char*)&type->vbclass32.vbpoff + vbpoff);
const unsigned short int* p_vboff = (const unsigned short int*)((const char*)&type->vbclass32.vbpoff + vbpoff);
int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
/* FIXME: ignored for now */
@ -1759,16 +1759,16 @@ static struct codeview_linetab* codeview_snarf_linetab(struct module* module,
int file_segcount;
char filename[PATH_MAX];
const unsigned int* filetab;
char* fn;
const char* fn;
int i;
int k;
struct codeview_linetab* lt_hdr;
unsigned int* lt_ptr;
const unsigned int* lt_ptr;
int nfile;
int nseg;
union any_size pnt;
union any_size pnt2;
struct startend* start;
const struct startend* start;
int this_seg;
struct symt_compiland* compiland;
@ -1820,13 +1820,13 @@ static struct codeview_linetab* codeview_snarf_linetab(struct module* module,
file_segcount = *pnt2.s;
pnt2.ui++;
lt_ptr = (unsigned int*) pnt2.c;
start = (struct startend*)(lt_ptr + file_segcount);
lt_ptr = (const unsigned int*) pnt2.c;
start = (const struct startend*)(lt_ptr + file_segcount);
/*
* Now snarf the filename for all of the segments for this file.
*/
fn = (unsigned char*)(start + file_segcount);
fn = (const unsigned char*)(start + file_segcount);
memset(filename, 0, sizeof(filename));
memcpy(filename, fn + 1, *fn);
compiland = symt_new_compiland(module, filename);
@ -1840,7 +1840,7 @@ static struct codeview_linetab* codeview_snarf_linetab(struct module* module,
lt_hdr[this_seg].segno = *pnt2.s++;
lt_hdr[this_seg].nline = *pnt2.s++;
lt_hdr[this_seg].offtab = pnt2.ui;
lt_hdr[this_seg].linetab = (unsigned short*)(pnt2.ui + lt_hdr[this_seg].nline);
lt_hdr[this_seg].linetab = (const unsigned short*)(pnt2.ui + lt_hdr[this_seg].nline);
}
}
@ -2334,11 +2334,11 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
break;
case S_COMPILE:
TRACE("S-Compile %x %.*s\n", ((LPBYTE)sym)[4], ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
TRACE("S-Compile %x %.*s\n", ((const BYTE*)sym)[4], ((const BYTE*)sym)[8], (const BYTE*)sym + 9);
break;
case S_OBJNAME:
TRACE("S-ObjName %.*s\n", ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
TRACE("S-ObjName %.*s\n", ((const BYTE*)sym)[8], (const BYTE*)sym + 9);
break;
case S_LABEL:
@ -2347,7 +2347,7 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
if (curr_func)
{
symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel,
codeview_get_address(msc_dbg, sym->label.segment, sym->label.offset) - curr_func->addr,
codeview_get_address(msc_dbg, sym->label.segment, sym->label.offset) - curr_func->address,
symname);
}
else FIXME("No current function for label %s\n", symname);
@ -2407,7 +2407,7 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
case S_DATAREF:
case S_LPROCREF:
{
LPBYTE name = (LPBYTE)sym + length;
const BYTE* name = (const BYTE*)sym + length;
length += (*name + 1 + 3) & ~3;
}
break;
@ -2629,7 +2629,7 @@ static void pdb_convert_types_header(PDB_TYPES* types, const BYTE* image)
memset(types, 0, sizeof(PDB_TYPES));
if (!image) return;
if (*(DWORD*)image < 19960000) /* FIXME: correct version? */
if (*(const DWORD*)image < 19960000) /* FIXME: correct version? */
{
/* Old version of the types record header */
const PDB_TYPES_OLD* old = (const PDB_TYPES_OLD*)image;
@ -2653,7 +2653,7 @@ static void pdb_convert_symbols_header(PDB_SYMBOLS* symbols,
memset(symbols, 0, sizeof(PDB_SYMBOLS));
if (!image) return;
if (*(DWORD*)image != 0xffffffff)
if (*(const DWORD*)image != 0xffffffff)
{
/* Old version of the symbols record header */
const PDB_SYMBOLS_OLD* old = (const PDB_SYMBOLS_OLD*)image;
@ -2686,7 +2686,7 @@ static const char* get_last_sep(const char* str)
}
static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
char* filename)
const char* filename)
{
HANDLE h;
char dbg_file_path[MAX_PATH];
@ -2695,7 +2695,7 @@ static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
h = FindDebugInfoFile(filename, pcs->search_path, dbg_file_path);
h = FindDebugInfoFile((char*)filename, pcs->search_path, dbg_file_path);
if (h == NULL)
{
const char* p;
@ -2716,7 +2716,7 @@ static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
static SYM_TYPE pdb_process_file(const struct process* pcs,
const struct msc_debug_info* msc_dbg,
char* filename, DWORD timestamp)
const char* filename, DWORD timestamp)
{
SYM_TYPE sym_type = -1;
HANDLE hFile, hMap = NULL;
@ -2982,7 +2982,7 @@ static SYM_TYPE codeview_process_info(const struct process* pcs,
case CODEVIEW_NB10_SIG:
{
PCODEVIEW_PDB_DATA pdb = (PCODEVIEW_PDB_DATA)(cv + 1);
const CODEVIEW_PDB_DATA* pdb = (const CODEVIEW_PDB_DATA*)(cv + 1);
codeview_init_basic_types(msc_dbg->module);
sym_type = pdb_process_file(pcs, msc_dbg, pdb->name, pdb->timestamp);
@ -3001,17 +3001,17 @@ static SYM_TYPE codeview_process_info(const struct process* pcs,
* Process debug directory.
*/
SYM_TYPE pe_load_debug_directory(const struct process* pcs, struct module* module,
const BYTE* mapping, PIMAGE_DEBUG_DIRECTORY dbg,
const BYTE* mapping, const IMAGE_DEBUG_DIRECTORY* dbg,
int nDbg)
{
SYM_TYPE sym_type;
int i;
struct msc_debug_info msc_dbg;
IMAGE_NT_HEADERS* nth = RtlImageNtHeader((void*)mapping);
const IMAGE_NT_HEADERS* nth = RtlImageNtHeader((void*)mapping);
msc_dbg.module = module;
msc_dbg.nsect = nth->FileHeader.NumberOfSections;
msc_dbg.sectp = (PIMAGE_SECTION_HEADER)((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
msc_dbg.sectp = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
msc_dbg.nomap = 0;
msc_dbg.omapp = NULL;
@ -3025,7 +3025,7 @@ SYM_TYPE pe_load_debug_directory(const struct process* pcs, struct module* modul
if (dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)
{
msc_dbg.nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
msc_dbg.omapp = (OMAP_DATA*)(mapping + dbg[i].PointerToRawData);
msc_dbg.omapp = (const OMAP_DATA*)(mapping + dbg[i].PointerToRawData);
break;
}
}

View File

@ -78,22 +78,22 @@ static SYM_TYPE pe_load_stabs(const struct process* pcs, struct module* module,
* loads a .dbg file
*/
static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* module,
char* dbg_name, DWORD timestamp)
const char* dbg_name, DWORD timestamp)
{
char tmp[MAX_PATH];
HANDLE hFile, hMap = 0;
const BYTE* dbg_mapping = NULL;
PIMAGE_SEPARATE_DEBUG_HEADER hdr;
PIMAGE_DEBUG_DIRECTORY dbg;
SYM_TYPE sym_type = -1;
char tmp[MAX_PATH];
HANDLE hFile, hMap = 0;
const BYTE* dbg_mapping = NULL;
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
const IMAGE_DEBUG_DIRECTORY* dbg;
SYM_TYPE sym_type = -1;
WINE_TRACE("Processing DBG file %s\n", dbg_name);
if ((hFile = FindDebugInfoFile(dbg_name, pcs->search_path, tmp)) != NULL &&
if ((hFile = FindDebugInfoFile((char*)dbg_name, pcs->search_path, tmp)) != NULL &&
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
{
hdr = (PIMAGE_SEPARATE_DEBUG_HEADER)dbg_mapping;
hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)dbg_mapping;
if (hdr->TimeDateStamp != timestamp)
{
WINE_ERR("Warning - %s has incorrect internal timestamp\n",
@ -105,7 +105,7 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul
* which have incorrect timestamps.
*/
}
dbg = (PIMAGE_DEBUG_DIRECTORY)
dbg = (const IMAGE_DEBUG_DIRECTORY*)
(dbg_mapping + sizeof(*hdr) +
hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
hdr->ExportedNamesSize);
@ -133,24 +133,24 @@ static SYM_TYPE pe_load_msc_debug_info(const struct process* pcs,
struct module* module,
const void* mapping, IMAGE_NT_HEADERS* nth)
{
SYM_TYPE sym_type = -1;
PIMAGE_DATA_DIRECTORY dir;
PIMAGE_DEBUG_DIRECTORY dbg = NULL;
int nDbg;
SYM_TYPE sym_type = -1;
const IMAGE_DATA_DIRECTORY* dir;
const IMAGE_DEBUG_DIRECTORY*dbg = NULL;
int nDbg;
/* Read in debug directory */
dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
if (!nDbg) return sym_type;
dbg = (PIMAGE_DEBUG_DIRECTORY)((char*)mapping + dir->VirtualAddress);
dbg = (const IMAGE_DEBUG_DIRECTORY*)((const char*)mapping + dir->VirtualAddress);
/* Parse debug directory */
if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
{
/* Debug info is stripped to .DBG file */
PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)
((char*)mapping + dbg->PointerToRawData);
const IMAGE_DEBUG_MISC* misc = (const IMAGE_DEBUG_MISC*)
((const char*)mapping + dbg->PointerToRawData);
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
@ -179,7 +179,6 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
struct module* module,
const void* mapping, IMAGE_NT_HEADERS* nth)
{
char buffer[512];
unsigned int i;
IMAGE_DATA_DIRECTORY* dir;
DWORD base = module->module.BaseOfImage;
@ -196,21 +195,20 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
#endif
/* Add entry point */
snprintf(buffer, sizeof(buffer), "%s.EntryPoint", module->module.ModuleName);
symt_new_public(module, NULL, buffer,
symt_new_public(module, NULL, "EntryPoint",
base + nth->OptionalHeader.AddressOfEntryPoint, 0,
TRUE /* FIXME */, TRUE /* FIXME */);
#if 0
/* FIXME: we'd better store addresses linked to sections rather than
absolute values */
IMAGE_SECTION_HEADER* section;
/* Add start of sections */
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
snprintf(buffer, sizeof(buffer), "%s.%s",
module->module.ModuleName, section->Name);
symt_new_public(module, NULL, buffer, base + section->VirtualAddress, 0,
symt_new_public(module, NULL, section->Name, base + section->VirtualAddress, 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
#endif
@ -219,23 +217,22 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
if ((dir = RtlImageDirectoryEntryToData((void*)mapping, TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, NULL)))
{
IMAGE_EXPORT_DIRECTORY* exports;
WORD* ordinals = NULL;
void** functions = NULL;
DWORD* names = NULL;
unsigned int j;
const IMAGE_EXPORT_DIRECTORY* exports;
const WORD* ordinals = NULL;
const void* const* functions = NULL;
const DWORD* names = NULL;
unsigned int j;
char buffer[16];
exports = (void*)((char*)mapping + dir->VirtualAddress);
functions = (void*)((char*)mapping + exports->AddressOfFunctions);
ordinals = (void*)((char*)mapping + exports->AddressOfNameOrdinals);
names = (void*)((char*)mapping + exports->AddressOfNames);
exports = (const void*)((const char*)mapping + dir->VirtualAddress);
functions = (const void*)((const char*)mapping + exports->AddressOfFunctions);
ordinals = (const void*)((const char*)mapping + exports->AddressOfNameOrdinals);
names = (const void*)((const char*)mapping + exports->AddressOfNames);
for (i = 0; i < exports->NumberOfNames; i++)
{
if (!names[i]) continue;
snprintf(buffer, sizeof(buffer), "%s.%s",
module->module.ModuleName, (char*)base + names[i]);
symt_new_public(module, NULL, buffer,
symt_new_public(module, NULL, (const char*)base + names[i],
base + (DWORD)functions[ordinals[i]], 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
@ -247,9 +244,8 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
for (j = 0; j < exports->NumberOfNames; j++)
if ((ordinals[j] == i) && names[j]) break;
if (j < exports->NumberOfNames) continue;
snprintf(buffer, sizeof(buffer), "%s.%ld",
module->module.ModuleName, i + exports->Base);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
snprintf(buffer, sizeof(buffer), "%ld", i + exports->Base);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
}

View File

@ -57,10 +57,6 @@
#include "dbghelp_private.h"
#if defined(__svr4__) || defined(__sun)
#define __ELF__
#endif
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
@ -842,6 +838,9 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
udt, symt_get_name(&udt->symt), udt->symt.tag);
return -1;
}
if (strcmp(udt->hash_elt.name, typename))
ERR("Forward declaration name mismatch %s <> %s\n",
udt->hash_elt.name, typename);
/* should check typename is the same too */
new_dt = &udt->symt;
}
@ -1042,76 +1041,6 @@ struct pending_loc_var
unsigned regno;
};
static
struct symt_public* lookup_public(const struct module* module,
const struct symt_compiland* compiland,
const char* name)
{
unsigned nfind = 0;
struct symt_public* found = NULL;
struct symt_public* xfound = NULL;
struct symt_public* sym;
const char* xname;
const char* tmp;
void* ptr;
struct hash_table_iter hti;
const char* in_src;
const char* out_src;
if (compiland && compiland->symt.tag == SymTagCompiland)
in_src = source_get(module, compiland->source);
else in_src = NULL;
hash_table_iter_init(&module->ht_symbols, &hti, name);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_public, hash_elt);
if (sym->symt.tag == SymTagPublicSymbol)
{
xname = symt_get_name(&sym->symt);
if (!xname || strcmp(xname, name)) continue;
if (sym->container &&
sym->container->tag == SymTagCompiland)
out_src = source_get(module, ((struct symt_compiland*)sym->container)->source);
else out_src = NULL;
xfound = sym;
if ((in_src && !out_src) || (!in_src && out_src)) continue;
if (in_src)
{
if (strcmp(in_src, out_src) || (tmp = strrchr(in_src, '/')) == NULL ||
strcmp(tmp + 1, out_src))
continue;
}
/* we continue once found to insure uniqueness of public symbol's name */
if (nfind++)
{
FIXME("More than one public symbol (%s) in %s: [%u] %p {%lx,%lx} in %s\n",
name, in_src, nfind, sym, sym->address, sym->size, out_src);
}
else found = sym;
}
}
if (!nfind)
{
if (xfound) found = xfound;
else FIXME("Couldn't locate %s in public symbols\n", name);
}
if (found)
{
if (found->container &&
found->container->tag == SymTagCompiland)
out_src = source_get(module, ((struct symt_compiland*)found->container)->source);
else out_src = NULL;
TRACE("Found for %s in %s: %p {%lx,%lx} in %s\n",
name, in_src, found, found->address, found->size, out_src);
}
return found;
}
/******************************************************************
* stabs_finalize_function
*
@ -1128,11 +1057,11 @@ static void stabs_finalize_function(struct module* module, struct symt_function*
/* To define the debug-start of the function, we use the second line number.
* Not 100% bullet proof, but better than nothing
*/
if (symt_fill_func_line_info(module, func, func->addr, &il) &&
if (symt_fill_func_line_info(module, func, func->address, &il) &&
symt_get_func_line_next(module, &il))
{
symt_add_function_point(module, func, SymTagFuncDebugStart,
il.Address - func->addr, NULL);
il.Address - func->address, NULL);
}
}
@ -1142,7 +1071,6 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
{
struct symt_function* curr_func = NULL;
struct symt_block* block = NULL;
struct symt_public* public;
struct symt_compiland* compiland = NULL;
char currpath[PATH_MAX];
int i, j;
@ -1162,8 +1090,8 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
unsigned num_allocated_pending_vars = 0;
nstab = stablen / sizeof(struct stab_nlist);
stab_ptr = (struct stab_nlist*)(addr + staboff);
strs = (char*)(addr + strtaboff);
stab_ptr = (const struct stab_nlist*)(addr + staboff);
strs = (const char*)(addr + strtaboff);
memset(currpath, 0, sizeof(currpath));
memset(stabs_basic, 0, sizeof(stabs_basic));
@ -1270,16 +1198,9 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
* With a.out or mingw, they actually do make some amount of sense.
*/
stab_strcpy(symname, sizeof(symname), ptr);
#ifdef __ELF__
if ((public = lookup_public(module, compiland, symname)))
symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
public->address, public->size,
stabs_parse_type(ptr));
#else
symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
load_offset + stab_ptr->n_value, 0,
stabs_parse_type(ptr));
#endif
break;
case N_LCSYM:
case N_STSYM:
@ -1396,19 +1317,8 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
if (curr_func != NULL)
{
assert(source_idx >= 0);
#ifdef __ELF__
symt_add_func_line(module, curr_func, source_idx,
stab_ptr->n_desc, stab_ptr->n_value);
#else
/*
* This isn't right. The order of the stabs is different under
* a.out, and as a result we would end up attaching the line
* number to the wrong function.
*/
symt_add_func_line(module, curr_func, source_idx,
stab_ptr->n_desc,
stab_ptr->n_value - curr_func->addr);
#endif
}
break;
case N_FUN:
@ -1433,16 +1343,9 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
struct symt_function_signature* func_type;
func_type = symt_new_function_signature(module,
stabs_parse_type(ptr));
#ifdef __ELF__
if ((public = lookup_public(module, compiland, symname)))
curr_func = symt_new_function(module, compiland, symname,
public->address, public->size,
&func_type->symt);
#else
curr_func = symt_new_function(module, compiland, symname,
load_offset + stab_ptr->n_value, 0,
&func_type->symt);
#endif
}
else
{

View File

@ -288,10 +288,15 @@ void hash_table_destroy(struct hash_table* ht)
void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt)
{
unsigned hash = hash_table_hash(elt->name, ht->num_buckets);
unsigned hash = hash_table_hash(elt->name, ht->num_buckets);
struct hash_table_elt** p;
elt->next = ht->buckets[hash];
ht->buckets[hash] = elt;
/* in some cases, we need to get back the symbols of same name in the order
* in which they've been inserted. So insert new elements at the end of the list.
*/
for (p = &ht->buckets[hash]; *p; p = &((*p)->next));
*p = elt;
elt->next = NULL;
}
void* hash_table_find(const struct hash_table* ht, const char* name)

View File

@ -70,8 +70,8 @@ inline static int cmp_sorttab_addr(const struct module* module, int idx, DWORD a
int symt_cmp_addr(const void* p1, const void* p2)
{
struct symt* sym1 = *(struct symt**)p1;
struct symt* sym2 = *(struct symt**)p2;
const struct symt* sym1 = *(const struct symt* const *)p1;
const struct symt* sym2 = *(const struct symt* const *)p2;
DWORD a1, a2;
symt_get_info(sym1, TI_GET_ADDRESS, &a1);
@ -188,6 +188,7 @@ struct symt_data* symt_new_global_variable(struct module* module,
{
struct symt_data* sym;
struct symt** p;
DWORD tsz;
TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n",
module->module.ModuleName, name, addr, type);
@ -201,6 +202,12 @@ struct symt_data* symt_new_global_variable(struct module* module,
sym->container = compiland ? &compiland->symt : NULL;
sym->type = type;
sym->u.address = addr;
if (type && size && symt_get_info(type, TI_GET_LENGTH, &tsz))
{
if (tsz != size)
FIXME("Size mismatch for %s.%s between type (%lu) and src (%lu)\n",
module->module.ModuleName, name, tsz, size);
}
if (compiland)
{
p = vector_add(&compiland->vchildren, &module->pool);
@ -230,10 +237,9 @@ struct symt_function* symt_new_function(struct module* module,
hash_table_add(&module->ht_symbols, &sym->hash_elt);
module->sortlist_valid = FALSE;
sym->container = &compiland->symt;
sym->addr = addr;
sym->address = addr;
sym->type = sig_type;
sym->size = size;
sym->addr = addr;
vector_init(&sym->vlines, sizeof(struct line_info), 64);
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
if (compiland)
@ -282,7 +288,7 @@ void symt_add_func_line(struct module* module, struct symt_function* func,
dli->is_source_file = 0;
dli->is_first = dli->is_last = 0;
dli->line_number = line_num;
dli->u.pc_offset = func->addr + offset;
dli->u.pc_offset = func->address + offset;
}
struct symt_data* symt_add_func_local(struct module* module,
@ -341,7 +347,7 @@ struct symt_block* symt_open_func_block(struct module* module,
assert(!parent_block || parent_block->symt.tag == SymTagBlock);
block = pool_alloc(&module->pool, sizeof(*block));
block->symt.tag = SymTagBlock;
block->address = func->addr + pc;
block->address = func->address + pc;
block->size = len;
block->container = parent_block ? &parent_block->symt : &func->symt;
vector_init(&block->vchildren, sizeof(struct symt*), 4);
@ -360,7 +366,7 @@ struct symt_block* symt_close_func_block(struct module* module,
{
assert(func->symt.tag == SymTagFunction);
if (pc) block->size = func->addr + pc - block->address;
if (pc) block->size = func->address + pc - block->address;
return (block->container->tag == SymTagBlock) ?
GET_ENTRY(block->container, struct symt_block, symt) : NULL;
}
@ -408,6 +414,37 @@ BOOL symt_normalize_function(struct module* module, struct symt_function* func)
return TRUE;
}
struct symt_thunk* symt_new_thunk(struct module* module,
struct symt_compiland* compiland,
const char* name, THUNK_ORDINAL ord,
unsigned long addr, unsigned long size)
{
struct symt_thunk* sym;
TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n",
module->module.ModuleName, name, addr, addr + size - 1);
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
{
sym->symt.tag = SymTagThunk;
sym->hash_elt.name = pool_strdup(&module->pool, name);
hash_table_add(&module->ht_symbols, &sym->hash_elt);
module->sortlist_valid = FALSE;
sym->container = &compiland->symt;
sym->address = addr;
sym->size = size;
sym->ordinal = ord;
if (compiland)
{
struct symt** p;
p = vector_add(&compiland->vchildren, &module->pool);
*p = &sym->symt;
}
}
return sym;
}
/* expect sym_info->MaxNameLen to be set before being called */
static void symt_fill_sym_info(const struct module* module,
const struct symt* sym, SYMBOL_INFO* sym_info)
@ -423,7 +460,7 @@ static void symt_fill_sym_info(const struct module* module,
{
case SymTagData:
{
struct symt_data* data = (struct symt_data*)sym;
const struct symt_data* data = (const struct symt_data*)sym;
switch (data->kind)
{
case DataIsLocal:
@ -476,6 +513,10 @@ static void symt_fill_sym_info(const struct module* module,
sym_info->Flags |= SYMFLAG_FUNCTION;
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
break;
case SymTagThunk:
sym_info->Flags |= SYMFLAG_THUNK;
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
break;
default:
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
sym_info->Register = 0;
@ -571,9 +612,10 @@ static BOOL resort_symbols(struct module* module)
}
/* assume addr is in module */
static int symt_find_nearest(struct module* module, DWORD addr)
int symt_find_nearest(struct module* module, DWORD addr)
{
int mid, high, low;
DWORD ref;
if (!module->sortlist_valid && !resort_symbols(module)) return -1;
@ -583,6 +625,15 @@ static int symt_find_nearest(struct module* module, DWORD addr)
low = 0;
high = module->module.NumSyms;
symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref);
if (addr < ref) return -1;
if (high)
{
symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref);
/* FIXME: use the size of symbol here if known */
if (addr > ref + 0x1000) return -1;
}
while (high > low + 1)
{
mid = (high + low) / 2;
@ -600,8 +651,6 @@ static int symt_find_nearest(struct module* module, DWORD addr)
*/
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
{
DWORD ref;
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref);
if (low > 0 &&
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&

View File

@ -80,15 +80,16 @@ const char* symt_get_name(const struct symt* sym)
switch (sym->tag)
{
/* lexical tree */
case SymTagData: return ((struct symt_data*)sym)->hash_elt.name;
case SymTagFunction: return ((struct symt_function*)sym)->hash_elt.name;
case SymTagPublicSymbol: return ((struct symt_public*)sym)->hash_elt.name;
case SymTagBaseType: return ((struct symt_basic*)sym)->hash_elt.name;
case SymTagLabel: return ((struct symt_function_point*)sym)->name;
case SymTagData: return ((const struct symt_data*)sym)->hash_elt.name;
case SymTagFunction: return ((const struct symt_function*)sym)->hash_elt.name;
case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name;
case SymTagBaseType: return ((const struct symt_basic*)sym)->hash_elt.name;
case SymTagLabel: return ((const struct symt_function_point*)sym)->name;
case SymTagThunk: return ((const struct symt_thunk*)sym)->hash_elt.name;
/* hierarchy tree */
case SymTagEnum: return ((struct symt_enum*)sym)->name;
case SymTagTypedef: return ((struct symt_typedef*)sym)->hash_elt.name;
case SymTagUDT: return ((struct symt_udt*)sym)->hash_elt.name;
case SymTagEnum: return ((const struct symt_enum*)sym)->name;
case SymTagTypedef: return ((const struct symt_typedef*)sym)->hash_elt.name;
case SymTagUDT: return ((const struct symt_udt*)sym)->hash_elt.name;
default:
FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
/* fall through */
@ -417,10 +418,10 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagUDT: v = &((struct symt_udt*)type)->vchildren; break;
case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
case SymTagFunctionType: v = &((struct symt_function_signature*)type)->vchildren; break;
case SymTagFunction: v = &((struct symt_function*)type)->vchildren; break;
case SymTagUDT: v = &((const struct symt_udt*)type)->vchildren; break;
case SymTagEnum: v = &((const struct symt_enum*)type)->vchildren; break;
case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
case SymTagFunction: v = &((const struct symt_function*)type)->vchildren; break;
default:
FIXME("Unsupported sym-tag %s for find-children\n",
symt_get_tag_str(type->tag));
@ -438,26 +439,29 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagData:
switch (((struct symt_data*)type)->kind)
switch (((const struct symt_data*)type)->kind)
{
case DataIsGlobal:
case DataIsFileStatic:
X(DWORD) = ((struct symt_data*)type)->u.address;
X(DWORD) = ((const struct symt_data*)type)->u.address;
break;
default: return FALSE;
}
break;
case SymTagFunction:
X(DWORD) = ((struct symt_function*)type)->addr;
X(DWORD) = ((const struct symt_function*)type)->address;
break;
case SymTagPublicSymbol:
X(DWORD) = ((struct symt_public*)type)->address;
X(DWORD) = ((const struct symt_public*)type)->address;
break;
case SymTagFuncDebugStart:
case SymTagFuncDebugEnd:
case SymTagLabel:
X(DWORD) = ((struct symt_function_point*)type)->parent->addr +
((struct symt_function_point*)type)->offset;
X(DWORD) = ((const struct symt_function_point*)type)->parent->address +
((const struct symt_function_point*)type)->offset;
break;
case SymTagThunk:
X(DWORD) = ((const struct symt_thunk*)type)->address;
break;
default:
FIXME("Unsupported sym-tag %s for get-address\n",
@ -470,7 +474,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagBaseType:
X(DWORD) = ((struct symt_basic*)type)->bt;
X(DWORD) = ((const struct symt_basic*)type)->bt;
break;
case SymTagEnum:
X(DWORD) = btInt;
@ -482,29 +486,30 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
case TI_GET_BITPOSITION:
if (type->tag != SymTagData ||
((struct symt_data*)type)->kind != DataIsMember ||
((struct symt_data*)type)->u.s.length == 0)
((const struct symt_data*)type)->kind != DataIsMember ||
((const struct symt_data*)type)->u.s.length == 0)
return FALSE;
X(DWORD) = ((struct symt_data*)type)->u.s.offset & 7;
X(DWORD) = ((const struct symt_data*)type)->u.s.offset & 7;
break;
case TI_GET_CHILDRENCOUNT:
switch (type->tag)
{
case SymTagUDT:
X(DWORD) = vector_length(&((struct symt_udt*)type)->vchildren);
X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
break;
case SymTagEnum:
X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
break;
case SymTagFunctionType:
X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
break;
case SymTagFunction:
X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
break;
case SymTagPointerType: /* MS does it that way */
case SymTagArrayType: /* MS does it that way */
case SymTagThunk: /* MS does it that way */
X(DWORD) = 0;
break;
default:
@ -524,51 +529,54 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
* also include 'this' (GET_CHILDREN_COUNT+1)
*/
if (type->tag != SymTagArrayType) return FALSE;
X(DWORD) = ((struct symt_array*)type)->end -
((struct symt_array*)type)->start;
X(DWORD) = ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
break;
case TI_GET_DATAKIND:
if (type->tag != SymTagData) return FALSE;
X(DWORD) = ((struct symt_data*)type)->kind;
X(DWORD) = ((const struct symt_data*)type)->kind;
break;
case TI_GET_LENGTH:
switch (type->tag)
{
case SymTagBaseType:
X(DWORD) = ((struct symt_basic*)type)->size;
X(DWORD) = ((const struct symt_basic*)type)->size;
break;
case SymTagFunction:
X(DWORD) = ((struct symt_function*)type)->size;
X(DWORD) = ((const struct symt_function*)type)->size;
break;
case SymTagPointerType:
X(DWORD) = sizeof(void*);
break;
case SymTagUDT:
X(DWORD) = ((struct symt_udt*)type)->size;
X(DWORD) = ((const struct symt_udt*)type)->size;
break;
case SymTagEnum:
X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
break;
case SymTagData:
if (((struct symt_data*)type)->kind != DataIsMember ||
!((struct symt_data*)type)->u.s.length)
if (((const struct symt_data*)type)->kind != DataIsMember ||
!((const struct symt_data*)type)->u.s.length)
return FALSE;
X(DWORD) = ((struct symt_data*)type)->u.s.length;
X(DWORD) = ((const struct symt_data*)type)->u.s.length;
break;
case SymTagArrayType:
if (!symt_get_info(((struct symt_array*)type)->basetype,
if (!symt_get_info(((const struct symt_array*)type)->basetype,
TI_GET_LENGTH, pInfo))
return FALSE;
X(DWORD) *= ((struct symt_array*)type)->end -
((struct symt_array*)type)->start;
X(DWORD) *= ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
break;
case SymTagPublicSymbol:
X(DWORD) = ((struct symt_public*)type)->size;
X(DWORD) = ((const struct symt_public*)type)->size;
break;
case SymTagTypedef:
return symt_get_info(((struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
return symt_get_info(((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
break;
case SymTagThunk:
X(DWORD) = ((const struct symt_thunk*)type)->size;
break;
default:
FIXME("Unsupported sym-tag %s for get-length\n",
@ -581,10 +589,16 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagBlock:
X(DWORD) = (DWORD)((struct symt_block*)type)->container;
X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
break;
case SymTagData:
X(DWORD) = (DWORD)((struct symt_data*)type)->container;
X(DWORD) = (DWORD)((const struct symt_data*)type)->container;
break;
case SymTagFunction:
X(DWORD) = (DWORD)((const struct symt_function*)type)->container;
break;
case SymTagThunk:
X(DWORD) = (DWORD)((const struct symt_thunk*)type)->container;
break;
default:
FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
@ -609,16 +623,16 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagData:
switch (((struct symt_data*)type)->kind)
switch (((const struct symt_data*)type)->kind)
{
case DataIsParam:
case DataIsLocal:
case DataIsMember:
X(ULONG) = ((struct symt_data*)type)->u.s.offset >> 3;
X(ULONG) = ((const struct symt_data*)type)->u.s.offset >> 3;
break;
default:
FIXME("Unknown kind (%u) for get-offset\n",
((struct symt_data*)type)->kind);
((const struct symt_data*)type)->kind);
return FALSE;
}
break;
@ -650,41 +664,42 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
{
/* hierarchical => hierarchical */
case SymTagArrayType:
X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
X(DWORD) = (DWORD)((const struct symt_array*)type)->basetype;
break;
case SymTagPointerType:
X(DWORD) = (DWORD)((struct symt_pointer*)type)->pointsto;
X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
break;
case SymTagFunctionType:
X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
break;
case SymTagTypedef:
X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
break;
/* lexical => hierarchical */
case SymTagData:
X(DWORD) = (DWORD)((struct symt_data*)type)->type;
X(DWORD) = (DWORD)((const struct symt_data*)type)->type;
break;
case SymTagFunction:
X(DWORD) = (DWORD)((struct symt_function*)type)->type;
X(DWORD) = (DWORD)((const struct symt_function*)type)->type;
break;
/* FIXME: should also work for enums and FunctionArgType */
default:
FIXME("Unsupported sym-tag %s for get-type\n",
symt_get_tag_str(type->tag));
case SymTagThunk:
return FALSE;
}
break;
case TI_GET_UDTKIND:
if (type->tag != SymTagUDT) return FALSE;
X(DWORD) = ((struct symt_udt*)type)->kind;
X(DWORD) = ((const struct symt_udt*)type)->kind;
break;
case TI_GET_VALUE:
if (type->tag != SymTagData || ((struct symt_data*)type)->kind != DataIsConstant)
if (type->tag != SymTagData || ((const struct symt_data*)type)->kind != DataIsConstant)
return FALSE;
X(VARIANT) = ((struct symt_data*)type)->u.value;
X(VARIANT) = ((const struct symt_data*)type)->u.value;
break;
#undef X

View File

@ -421,3 +421,12 @@ enum CV_HREG_e
CV_M32R_ACLO = 33,
CV_M32R_PC = 34,
} CV_HREG_e;
typedef enum
{
THUNK_ORDINAL_NOTYPE,
THUNK_ORDINAL_ADJUSTOR,
THUNK_ORDINAL_VCALL,
THUNK_ORDINAL_PCODE,
THUNK_ORDINAL_LOAD
} THUNK_ORDINAL;

View File

@ -72,6 +72,9 @@ typedef struct _tagADDRESS
#define SYMF_EXPORT 0x00000200
#define SYMF_FORWARDER 0x00000400
#define SYMF_FUNCTION 0x00000800
#define SYMF_VIRTUAL 0x00001000
#define SYMF_THUNK 0x00002000
#define SYMF_TLSREL 0x00004000
typedef enum
{
@ -529,6 +532,11 @@ typedef struct _MINIDUMP_THREAD_LIST
MINIDUMP_THREAD Threads[1]; /* FIXME: no support of 0 sized array */
} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;
BOOL WINAPI MiniDumpWriteDump(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,const PMINIDUMP_EXCEPTION_INFORMATION,
const PMINIDUMP_USER_STREAM_INFORMATION,const PMINIDUMP_CALLBACK_INFORMATION);
BOOL WINAPI MiniDumpReadDumpStream(PVOID,ULONG,PMINIDUMP_DIRECTORY*,PVOID*,ULONG*);
/*************************
* MODULE handling *
*************************/
@ -586,7 +594,7 @@ typedef struct _SYMBOL_INFO
ULONG SizeOfStruct;
ULONG TypeIndex;
ULONG Reserved[2];
ULONG info;
ULONG info; /* sdk states info, while MSDN says it's Index... */
ULONG Size;
ULONG ModBase;
ULONG Flags;
@ -666,8 +674,12 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, DWORD BaseOfDll,
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD addr, DWORD* displacement,
SYMBOL_INFO* sym_info);
BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol);
BOOL WINAPI SymGetSymFromAddr(HANDLE,DWORD,PDWORD,PIMAGEHLP_SYMBOL);
BOOL WINAPI SymGetSymFromName(HANDLE,PSTR,PIMAGEHLP_SYMBOL);
BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, DWORD BaseOfDll, LPSTR Name,
PSYMBOL_INFO Symbol);
BOOL WINAPI SymGetSymNext(HANDLE,PIMAGEHLP_SYMBOL);
BOOL WINAPI SymGetSymPrev(HANDLE,PIMAGEHLP_SYMBOL);
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
PVOID UserContext);
@ -681,6 +693,7 @@ typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess, ULONG Acti
BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
PVOID UserContext);
BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL,PSTR,DWORD);
DWORD WINAPI UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName,
DWORD UndecoratedLength, DWORD Flags);
@ -731,6 +744,11 @@ PIMAGE_SECTION_HEADER WINAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,
PVOID Base, ULONG Rva);
PVOID WINAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders, PVOID Base,
ULONG Rva, OUT PIMAGE_SECTION_HEADER *LastRvaSection);
BOOL WINAPI SymGetSearchPath(HANDLE,PSTR,DWORD);
BOOL WINAPI SymSetSearchPath(HANDLE,PSTR);
DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE);
BOOL WINAPI MakeSureDirectoryPathExists(PCSTR);
BOOL WINAPI SearchTreeForFile(PSTR,PSTR,PSTR);
/*************************
* Context management *