- 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:
parent
d3f8f78c3a
commit
48a865983d
|
@ -42,9 +42,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||||
* + we should add parameters' types to the function's signature
|
* + we should add parameters' types to the function's signature
|
||||||
* while processing a function's parameters
|
* while processing a function's parameters
|
||||||
* + get rid of MSC reading FIXME:s (lots of types are not defined)
|
* + 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
|
* + C++ management
|
||||||
* - stabs:
|
* - stabs:
|
||||||
* + should identify the relay code in Wine and mark it as thunk type
|
|
||||||
* + C++ management
|
* + C++ management
|
||||||
* - implement the callback notification mechanism
|
* - implement the callback notification mechanism
|
||||||
*/
|
*/
|
||||||
|
@ -122,7 +122,7 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, LPSTR szSearchPath,
|
||||||
static BOOL process_invade(HANDLE hProcess)
|
static BOOL process_invade(HANDLE hProcess)
|
||||||
{
|
{
|
||||||
HMODULE hMods[256];
|
HMODULE hMods[256];
|
||||||
char img[256], mod[256];
|
char img[256];
|
||||||
DWORD i, sz;
|
DWORD i, sz;
|
||||||
MODULEINFO mi;
|
MODULEINFO mi;
|
||||||
|
|
||||||
|
@ -133,8 +133,7 @@ static BOOL process_invade(HANDLE hProcess)
|
||||||
{
|
{
|
||||||
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
|
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
|
||||||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
|
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
|
||||||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)) ||
|
!SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
|
||||||
!SymLoadModule(hProcess, 0, img, mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +217,7 @@ BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProc
|
||||||
|
|
||||||
if (fInvadeProcess)
|
if (fInvadeProcess)
|
||||||
{
|
{
|
||||||
pcs->dbg_hdr_addr = elf_read_wine_loader_dbg_info(pcs);
|
if (!elf_read_wine_loader_dbg_info(pcs))
|
||||||
if (pcs->dbg_hdr_addr == 0)
|
|
||||||
{
|
{
|
||||||
SymCleanup(hProcess);
|
SymCleanup(hProcess);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -149,7 +149,7 @@ struct symt_function
|
||||||
{
|
{
|
||||||
struct symt symt;
|
struct symt symt;
|
||||||
struct hash_table_elt hash_elt; /* if global symbol */
|
struct hash_table_elt hash_elt; /* if global symbol */
|
||||||
unsigned long addr;
|
unsigned long address;
|
||||||
struct symt* container; /* compiland */
|
struct symt* container; /* compiland */
|
||||||
struct symt* type; /* points to function_signature */
|
struct symt* type; /* points to function_signature */
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
@ -176,6 +176,16 @@ struct symt_public
|
||||||
is_function : 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 */
|
/* class tree */
|
||||||
struct symt_array
|
struct symt_array
|
||||||
{
|
{
|
||||||
|
@ -229,15 +239,19 @@ struct symt_udt
|
||||||
struct vector vchildren;
|
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
|
struct module
|
||||||
{
|
{
|
||||||
IMAGEHLP_MODULE module;
|
IMAGEHLP_MODULE module;
|
||||||
struct module* next;
|
struct module* next;
|
||||||
enum DbgModuleType type;
|
enum module_type type;
|
||||||
unsigned short elf_mark : 1;
|
struct elf_module_info* elf_info;
|
||||||
struct tagELF_DBG_INFO* elf_dbg_info;
|
|
||||||
|
|
||||||
/* memory allocation pool */
|
/* memory allocation pool */
|
||||||
struct pool 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 SYM_TYPE elf_load_debug_info(struct module* module);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
elf_load_module(struct process* pcs, const char* name);
|
elf_load_module(struct process* pcs, const char* name);
|
||||||
extern unsigned long
|
extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
|
||||||
elf_read_wine_loader_dbg_info(struct process* pcs);
|
|
||||||
extern BOOL elf_synchronize_module_list(struct process* pcs);
|
extern BOOL elf_synchronize_module_list(struct process* pcs);
|
||||||
|
|
||||||
/* memory.c */
|
/* memory.c */
|
||||||
|
@ -294,15 +307,15 @@ extern unsigned long WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDR
|
||||||
/* module.c */
|
/* module.c */
|
||||||
extern struct module*
|
extern struct module*
|
||||||
module_find_by_addr(const struct process* pcs, unsigned long addr,
|
module_find_by_addr(const struct process* pcs, unsigned long addr,
|
||||||
enum DbgModuleType type);
|
enum module_type type);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
module_find_by_name(const struct process* pcs,
|
module_find_by_name(const struct process* pcs,
|
||||||
const char* name, enum DbgModuleType type);
|
const char* name, enum module_type type);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
module_get_debug(const struct process* pcs, struct module*);
|
module_get_debug(const struct process* pcs, struct module*);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
module_new(struct process* pcs, const char* name,
|
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 size, unsigned long stamp,
|
||||||
unsigned long checksum);
|
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,
|
extern SYM_TYPE pe_load_debug_directory(const struct process* pcs,
|
||||||
struct module* module,
|
struct module* module,
|
||||||
const BYTE* file_map,
|
const BYTE* file_map,
|
||||||
PIMAGE_DEBUG_DIRECTORY dbg, int nDbg);
|
const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
|
||||||
/* pe_module.c */
|
/* pe_module.c */
|
||||||
extern struct module*
|
extern struct module*
|
||||||
pe_load_module(struct process* pcs, char* name,
|
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 */
|
/* symbol.c */
|
||||||
extern const char* symt_get_name(const struct symt* sym);
|
extern const char* symt_get_name(const struct symt* sym);
|
||||||
extern int symt_cmp_addr(const void* p1, const void* p2);
|
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*
|
extern struct symt_compiland*
|
||||||
symt_new_compiland(struct module* module,
|
symt_new_compiland(struct module* module,
|
||||||
const char* filename);
|
const char* filename);
|
||||||
|
@ -351,10 +365,10 @@ extern struct symt_data*
|
||||||
unsigned long addr, unsigned long size,
|
unsigned long addr, unsigned long size,
|
||||||
struct symt* type);
|
struct symt* type);
|
||||||
extern struct symt_function*
|
extern struct symt_function*
|
||||||
symt_new_function(struct module* module,
|
symt_new_function(struct module* module,
|
||||||
struct symt_compiland* parent,
|
struct symt_compiland* parent,
|
||||||
const char* name,
|
const char* name,
|
||||||
unsigned long addr, unsigned long size,
|
unsigned long addr, unsigned long size,
|
||||||
struct symt* type);
|
struct symt* type);
|
||||||
extern BOOL symt_normalize_function(struct module* module,
|
extern BOOL symt_normalize_function(struct module* module,
|
||||||
struct symt_function* func);
|
struct symt_function* func);
|
||||||
|
@ -386,6 +400,11 @@ extern BOOL symt_fill_func_line_info(struct module* module,
|
||||||
struct symt_function* func,
|
struct symt_function* func,
|
||||||
DWORD addr, IMAGEHLP_LINE* line);
|
DWORD addr, IMAGEHLP_LINE* line);
|
||||||
extern BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_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 */
|
/* type.c */
|
||||||
extern void symt_init_basic(struct module* module);
|
extern void symt_init_basic(struct module* module);
|
||||||
|
@ -424,3 +443,7 @@ extern struct symt_pointer*
|
||||||
extern struct symt_typedef*
|
extern struct symt_typedef*
|
||||||
symt_new_typedef(struct module* module, struct symt* ref,
|
symt_new_typedef(struct module* module, struct symt* ref,
|
||||||
const char* name);
|
const char* name);
|
||||||
|
|
||||||
|
|
||||||
|
/* some more Wine extensions */
|
||||||
|
#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000
|
||||||
|
|
|
@ -70,10 +70,12 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||||
|
|
||||||
typedef struct tagELF_DBG_INFO
|
struct elf_module_info
|
||||||
{
|
{
|
||||||
unsigned long elf_addr;
|
unsigned long elf_addr;
|
||||||
} ELF_DBG_INFO;
|
unsigned short elf_mark : 1,
|
||||||
|
elf_loader : 1;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __ELF__
|
#ifdef __ELF__
|
||||||
|
|
||||||
|
@ -82,43 +84,57 @@ typedef struct tagELF_DBG_INFO
|
||||||
|
|
||||||
struct elf_info
|
struct elf_info
|
||||||
{
|
{
|
||||||
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
|
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) */
|
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 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.
|
* creating an internal hash table to ease use ELF symtab information lookup
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
static int elf_load_symtab(struct module* module, const char* addr,
|
static void elf_hash_symtab(const struct module* module, struct pool* pool,
|
||||||
unsigned long load_addr, const Elf32_Shdr* symtab,
|
struct hash_table* ht_symtab, const char* map_addr,
|
||||||
const Elf32_Shdr* strtab)
|
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* strp;
|
||||||
const char* symname;
|
const char* symname;
|
||||||
|
const char* filename = NULL;
|
||||||
const Elf32_Sym* symp;
|
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);
|
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++)
|
for (i = 0; i < nsym; i++, symp++)
|
||||||
{
|
{
|
||||||
/* Ignore certain types of entries which really aren't of that much
|
/* Ignore certain types of entries which really aren't of that much
|
||||||
* interest.
|
* interest.
|
||||||
*/
|
*/
|
||||||
if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION ||
|
if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION || symp->st_shndx == SHN_UNDEF)
|
||||||
symp->st_shndx == SHN_UNDEF)
|
|
||||||
{
|
{
|
||||||
continue;
|
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)
|
if (ELF32_ST_TYPE(symp->st_info) == STT_FILE)
|
||||||
{
|
{
|
||||||
compiland = symt_new_compiland(module, symname);
|
filename = symname;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
symt_new_public(module, compiland, symname,
|
for (j = 0; j < num_areas; j++)
|
||||||
load_addr + symp->st_value, symp->st_size,
|
{
|
||||||
TRUE /* FIXME */, ELF32_ST_TYPE(symp->st_info) == STT_FUNC);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,10 +414,22 @@ SYM_TYPE elf_load_debug_info(struct module* module)
|
||||||
const Elf32_Shdr* spnt;
|
const Elf32_Shdr* spnt;
|
||||||
const char* shstrtab;
|
const char* shstrtab;
|
||||||
int i;
|
int i;
|
||||||
int stabsect, stabstrsect, debugsect;
|
int symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect;
|
||||||
int symsect, dynsect;
|
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);
|
ERR("Bad elf module '%s'\n", module->module.LoadedImageName);
|
||||||
return sym_type;
|
return sym_type;
|
||||||
|
@ -195,55 +461,86 @@ SYM_TYPE elf_load_debug_info(struct module* module)
|
||||||
spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
|
spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
|
||||||
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
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++)
|
for (i = 0; i < ehptr->e_shnum; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
|
||||||
stabsect = i;
|
stab_sect = i;
|
||||||
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
|
||||||
stabstrsect = i;
|
stabstr_sect = i;
|
||||||
if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
|
if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
|
||||||
debugsect = i;
|
debug_sect = i;
|
||||||
if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
|
if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
|
||||||
(spnt[i].sh_type == SHT_SYMTAB))
|
(spnt[i].sh_type == SHT_SYMTAB))
|
||||||
symsect = i;
|
symtab_sect = i;
|
||||||
if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
|
if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
|
||||||
(spnt[i].sh_type == SHT_DYNSYM))
|
(spnt[i].sh_type == SHT_DYNSYM))
|
||||||
dynsect = i;
|
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;
|
sym_type = SymExport;
|
||||||
|
|
||||||
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
if (symtab_sect == -1)
|
||||||
{
|
{
|
||||||
if (stabsect != -1 && stabstrsect != -1)
|
/* if we don't have a symtab but a dynsym, process the dynsym
|
||||||
{
|
* section instead. It'll contain less (relevant) information,
|
||||||
/* OK, now just parse all of the stabs. */
|
* but it'll be better than nothing
|
||||||
sym_type = stabs_parse(module, addr, module->elf_dbg_info->elf_addr,
|
*/
|
||||||
spnt[stabsect].sh_offset, spnt[stabsect].sh_size,
|
if (dynsym_sect == -1) goto leave;
|
||||||
spnt[stabstrsect].sh_offset,
|
symtab_sect = dynsym_sect;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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:
|
leave:
|
||||||
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
||||||
if (fd != -1) close(fd);
|
if (fd != -1) close(fd);
|
||||||
|
@ -298,6 +595,7 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
|
||||||
const char* shstrtab;
|
const char* shstrtab;
|
||||||
int i;
|
int i;
|
||||||
DWORD delta, size;
|
DWORD delta, size;
|
||||||
|
unsigned tmp, page_mask = getpagesize() - 1;
|
||||||
|
|
||||||
TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset);
|
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
|
* this thing. We need the main executable header, and the section
|
||||||
* table.
|
* table.
|
||||||
*/
|
*/
|
||||||
ehptr = (Elf32_Ehdr*)addr;
|
ehptr = (const Elf32_Ehdr*)addr;
|
||||||
if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
|
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);
|
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
/* if non relocatable ELF, then remove fixed address from computation
|
/* 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;
|
delta = (load_offset == 0) ? ehptr->e_entry : 0;
|
||||||
|
|
||||||
/* grab size of module once loaded in memory */
|
/* 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;
|
size = 0;
|
||||||
for (i = 0; i < ehptr->e_phnum; i++)
|
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 :
|
tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask;
|
||||||
(ppnt[i].p_memsz + ppnt[i].p_align - 1) & ~(ppnt[i].p_align - 1);
|
if (size < tmp) size = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,16 +673,19 @@ static SYM_TYPE elf_load_file(struct process* pcs, const char* filename,
|
||||||
size, 0, 0);
|
size, 0, 0);
|
||||||
if (elf_info->module)
|
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");
|
ERR("OOM\n");
|
||||||
exit(0); /* FIXME */
|
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 =
|
elf_info->module->module.SymType = sym_type =
|
||||||
(dbghelp_options & SYMOPT_DEFERRED_LOADS) ? SymDeferred :
|
(dbghelp_options & SYMOPT_DEFERRED_LOADS) ? SymDeferred :
|
||||||
elf_load_debug_info(elf_info->module);
|
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;
|
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)))
|
if ((module = module_find_by_name(pcs, filename, DMT_ELF)))
|
||||||
{
|
{
|
||||||
elf_info->module = module;
|
elf_info->module = module;
|
||||||
module->elf_mark = 1;
|
module->elf_info->elf_mark = 1;
|
||||||
return module->module.SymType;
|
return module->module.SymType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +794,7 @@ BOOL elf_synchronize_module_list(struct process* pcs)
|
||||||
|
|
||||||
for (module = pcs->lmodules; module; module = module->next)
|
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;
|
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)
|
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);
|
module_remove(pcs, module);
|
||||||
/* restart all over */
|
/* restart all over */
|
||||||
|
@ -532,15 +834,15 @@ BOOL elf_synchronize_module_list(struct process* pcs)
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* elf_read_wine_loader_dbg_info
|
* 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;
|
const char* ptr;
|
||||||
SYM_TYPE sym_type;
|
SYM_TYPE sym_type;
|
||||||
struct elf_info elf_info;
|
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
|
/* All binaries are loaded with WINELOADER (if run from tree) or by the
|
||||||
* main executable (either wine-kthread or wine-pthread)
|
* main executable (either wine-kthread or wine-pthread)
|
||||||
* Note: the heuristic use to know whether we need to load wine-pthread or
|
* 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)
|
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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
|
|
@ -33,16 +33,37 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
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
|
* Creates and links a new module to a process
|
||||||
*/
|
*/
|
||||||
struct module* module_new(struct process* pcs, const char* name,
|
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 mod_addr, unsigned long size,
|
||||||
unsigned long stamp, unsigned long checksum)
|
unsigned long stamp, unsigned long checksum)
|
||||||
{
|
{
|
||||||
struct module* module;
|
struct module* module;
|
||||||
const char* ptr;
|
|
||||||
|
|
||||||
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
|
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -61,12 +82,7 @@ struct module* module_new(struct process* pcs, const char* name,
|
||||||
module->module.SizeOfStruct = sizeof(module->module);
|
module->module.SizeOfStruct = sizeof(module->module);
|
||||||
module->module.BaseOfImage = mod_addr;
|
module->module.BaseOfImage = mod_addr;
|
||||||
module->module.ImageSize = size;
|
module->module.ImageSize = size;
|
||||||
for (ptr = name + strlen(name) - 1;
|
module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
|
||||||
*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->module.ImageName[0] = '\0';
|
module->module.ImageName[0] = '\0';
|
||||||
strncpy(module->module.LoadedImageName, name,
|
strncpy(module->module.LoadedImageName, name,
|
||||||
sizeof(module->module.LoadedImageName));
|
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,
|
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;
|
struct module* module;
|
||||||
|
|
||||||
|
@ -188,7 +204,7 @@ struct module* module_get_debug(const struct process* pcs, struct module* module
|
||||||
* module
|
* module
|
||||||
*/
|
*/
|
||||||
struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
|
struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
|
||||||
enum DbgModuleType type)
|
enum module_type type)
|
||||||
{
|
{
|
||||||
struct module* module;
|
struct module* module;
|
||||||
|
|
||||||
|
@ -227,6 +243,13 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
|
||||||
pcs = process_find_by_handle(hProcess);
|
pcs = process_find_by_handle(hProcess);
|
||||||
if (!pcs) return FALSE;
|
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)))
|
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
|
||||||
{
|
{
|
||||||
unsigned len = strlen(ImageName);
|
unsigned len = strlen(ImageName);
|
||||||
|
@ -316,7 +339,8 @@ BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
|
||||||
|
|
||||||
for (module = pcs->lmodules; module; module = module->next)
|
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,
|
if (!EnumModulesCallback(module->module.ModuleName,
|
||||||
module->module.BaseOfImage, UserContext))
|
module->module.BaseOfImage, UserContext))
|
||||||
break;
|
break;
|
||||||
|
@ -333,7 +357,7 @@ BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
|
||||||
PVOID UserContext)
|
PVOID UserContext)
|
||||||
{
|
{
|
||||||
HMODULE* hMods;
|
HMODULE* hMods;
|
||||||
char img[256], mod[256];
|
char base[256], mod[256];
|
||||||
DWORD i, sz;
|
DWORD i, sz;
|
||||||
MODULEINFO mi;
|
MODULEINFO mi;
|
||||||
|
|
||||||
|
@ -351,9 +375,10 @@ BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
|
||||||
for (i = 0; i < sz; i++)
|
for (i = 0; i < sz; i++)
|
||||||
{
|
{
|
||||||
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
|
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
|
||||||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
|
!GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
|
||||||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
|
continue;
|
||||||
break;
|
module_fill_module(base, mod, sizeof(mod));
|
||||||
|
|
||||||
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
|
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
|
||||||
UserContext);
|
UserContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,9 +70,9 @@ struct msc_debug_info
|
||||||
{
|
{
|
||||||
struct module* module;
|
struct module* module;
|
||||||
int nsect;
|
int nsect;
|
||||||
PIMAGE_SECTION_HEADER sectp;
|
const IMAGE_SECTION_HEADER* sectp;
|
||||||
int nomap;
|
int nomap;
|
||||||
OMAP_DATA* omapp;
|
const OMAP_DATA* omapp;
|
||||||
const BYTE* root;
|
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)
|
if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE)
|
||||||
{
|
{
|
||||||
curr_file_idx = coff_add_file(&coff_files, msc_dbg->module,
|
curr_file_idx = coff_add_file(&coff_files, msc_dbg->module,
|
||||||
(char*)(coff_sym + 1));
|
(const char*)(coff_sym + 1));
|
||||||
TRACE("New file %s\n", (char*)(coff_sym + 1));
|
TRACE("New file %s\n", (const char*)(coff_sym + 1));
|
||||||
i += naux;
|
i += naux;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1111,27 +1111,27 @@ static int numeric_leaf(int* value, const unsigned short int* leaf)
|
||||||
{
|
{
|
||||||
case LF_CHAR:
|
case LF_CHAR:
|
||||||
length += 1;
|
length += 1;
|
||||||
*value = *(char*)leaf;
|
*value = *(const char*)leaf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LF_SHORT:
|
case LF_SHORT:
|
||||||
length += 2;
|
length += 2;
|
||||||
*value = *(short*)leaf;
|
*value = *(const short*)leaf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LF_USHORT:
|
case LF_USHORT:
|
||||||
length += 2;
|
length += 2;
|
||||||
*value = *(unsigned short*)leaf;
|
*value = *(const unsigned short*)leaf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LF_LONG:
|
case LF_LONG:
|
||||||
length += 4;
|
length += 4;
|
||||||
*value = *(int*)leaf;
|
*value = *(const int*)leaf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LF_ULONG:
|
case LF_ULONG:
|
||||||
length += 4;
|
length += 4;
|
||||||
*value = *(unsigned int*)leaf;
|
*value = *(const unsigned int*)leaf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LF_QUADWORD:
|
case LF_QUADWORD:
|
||||||
|
@ -1327,7 +1327,7 @@ static int codeview_add_type_enum_field_list(struct module* module,
|
||||||
symt = symt_new_enum(module, NULL);
|
symt = symt_new_enum(module, NULL);
|
||||||
while (ptr - list < len)
|
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... */
|
if (*ptr >= 0xf0) /* LF_PAD... */
|
||||||
{
|
{
|
||||||
|
@ -1340,7 +1340,7 @@ static int codeview_add_type_enum_field_list(struct module* module,
|
||||||
case LF_ENUMERATE:
|
case LF_ENUMERATE:
|
||||||
{
|
{
|
||||||
int value, vlen = numeric_leaf(&value, &type->enumerate.value);
|
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);
|
symt_add_enum_element(module, symt, terminate_string(name), value);
|
||||||
ptr += 2 + 2 + vlen + (1 + name[0]);
|
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:
|
case LF_IVBCLASS:
|
||||||
{
|
{
|
||||||
int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass.vbpoff);
|
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);
|
int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
|
||||||
|
|
||||||
/* FIXME: ignored for now */
|
/* FIXME: ignored for now */
|
||||||
|
@ -1413,7 +1413,7 @@ static int codeview_add_type_struct_field_list(struct module* module,
|
||||||
case LF_IVBCLASS_32:
|
case LF_IVBCLASS_32:
|
||||||
{
|
{
|
||||||
int vbpoff, vbplen = numeric_leaf(&vbpoff, &type->vbclass32.vbpoff);
|
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);
|
int vpoff, vplen = numeric_leaf(&vpoff, p_vboff);
|
||||||
|
|
||||||
/* FIXME: ignored for now */
|
/* FIXME: ignored for now */
|
||||||
|
@ -1759,16 +1759,16 @@ static struct codeview_linetab* codeview_snarf_linetab(struct module* module,
|
||||||
int file_segcount;
|
int file_segcount;
|
||||||
char filename[PATH_MAX];
|
char filename[PATH_MAX];
|
||||||
const unsigned int* filetab;
|
const unsigned int* filetab;
|
||||||
char* fn;
|
const char* fn;
|
||||||
int i;
|
int i;
|
||||||
int k;
|
int k;
|
||||||
struct codeview_linetab* lt_hdr;
|
struct codeview_linetab* lt_hdr;
|
||||||
unsigned int* lt_ptr;
|
const unsigned int* lt_ptr;
|
||||||
int nfile;
|
int nfile;
|
||||||
int nseg;
|
int nseg;
|
||||||
union any_size pnt;
|
union any_size pnt;
|
||||||
union any_size pnt2;
|
union any_size pnt2;
|
||||||
struct startend* start;
|
const struct startend* start;
|
||||||
int this_seg;
|
int this_seg;
|
||||||
struct symt_compiland* compiland;
|
struct symt_compiland* compiland;
|
||||||
|
|
||||||
|
@ -1820,13 +1820,13 @@ static struct codeview_linetab* codeview_snarf_linetab(struct module* module,
|
||||||
file_segcount = *pnt2.s;
|
file_segcount = *pnt2.s;
|
||||||
|
|
||||||
pnt2.ui++;
|
pnt2.ui++;
|
||||||
lt_ptr = (unsigned int*) pnt2.c;
|
lt_ptr = (const unsigned int*) pnt2.c;
|
||||||
start = (struct startend*)(lt_ptr + file_segcount);
|
start = (const struct startend*)(lt_ptr + file_segcount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now snarf the filename for all of the segments for this file.
|
* 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));
|
memset(filename, 0, sizeof(filename));
|
||||||
memcpy(filename, fn + 1, *fn);
|
memcpy(filename, fn + 1, *fn);
|
||||||
compiland = symt_new_compiland(module, filename);
|
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].segno = *pnt2.s++;
|
||||||
lt_hdr[this_seg].nline = *pnt2.s++;
|
lt_hdr[this_seg].nline = *pnt2.s++;
|
||||||
lt_hdr[this_seg].offtab = pnt2.ui;
|
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;
|
break;
|
||||||
|
|
||||||
case S_COMPILE:
|
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;
|
break;
|
||||||
|
|
||||||
case S_OBJNAME:
|
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;
|
break;
|
||||||
|
|
||||||
case S_LABEL:
|
case S_LABEL:
|
||||||
|
@ -2347,7 +2347,7 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
|
||||||
if (curr_func)
|
if (curr_func)
|
||||||
{
|
{
|
||||||
symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel,
|
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);
|
symname);
|
||||||
}
|
}
|
||||||
else FIXME("No current function for label %s\n", 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_DATAREF:
|
||||||
case S_LPROCREF:
|
case S_LPROCREF:
|
||||||
{
|
{
|
||||||
LPBYTE name = (LPBYTE)sym + length;
|
const BYTE* name = (const BYTE*)sym + length;
|
||||||
length += (*name + 1 + 3) & ~3;
|
length += (*name + 1 + 3) & ~3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2629,7 +2629,7 @@ static void pdb_convert_types_header(PDB_TYPES* types, const BYTE* image)
|
||||||
memset(types, 0, sizeof(PDB_TYPES));
|
memset(types, 0, sizeof(PDB_TYPES));
|
||||||
if (!image) return;
|
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 */
|
/* Old version of the types record header */
|
||||||
const PDB_TYPES_OLD* old = (const PDB_TYPES_OLD*)image;
|
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));
|
memset(symbols, 0, sizeof(PDB_SYMBOLS));
|
||||||
if (!image) return;
|
if (!image) return;
|
||||||
|
|
||||||
if (*(DWORD*)image != 0xffffffff)
|
if (*(const DWORD*)image != 0xffffffff)
|
||||||
{
|
{
|
||||||
/* Old version of the symbols record header */
|
/* Old version of the symbols record header */
|
||||||
const PDB_SYMBOLS_OLD* old = (const PDB_SYMBOLS_OLD*)image;
|
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,
|
static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
|
||||||
char* filename)
|
const char* filename)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
char dbg_file_path[MAX_PATH];
|
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);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
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)
|
if (h == NULL)
|
||||||
{
|
{
|
||||||
const char* p;
|
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,
|
static SYM_TYPE pdb_process_file(const struct process* pcs,
|
||||||
const struct msc_debug_info* msc_dbg,
|
const struct msc_debug_info* msc_dbg,
|
||||||
char* filename, DWORD timestamp)
|
const char* filename, DWORD timestamp)
|
||||||
{
|
{
|
||||||
SYM_TYPE sym_type = -1;
|
SYM_TYPE sym_type = -1;
|
||||||
HANDLE hFile, hMap = NULL;
|
HANDLE hFile, hMap = NULL;
|
||||||
|
@ -2982,7 +2982,7 @@ static SYM_TYPE codeview_process_info(const struct process* pcs,
|
||||||
|
|
||||||
case CODEVIEW_NB10_SIG:
|
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);
|
codeview_init_basic_types(msc_dbg->module);
|
||||||
sym_type = pdb_process_file(pcs, msc_dbg, pdb->name, pdb->timestamp);
|
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.
|
* Process debug directory.
|
||||||
*/
|
*/
|
||||||
SYM_TYPE pe_load_debug_directory(const struct process* pcs, struct module* module,
|
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)
|
int nDbg)
|
||||||
{
|
{
|
||||||
SYM_TYPE sym_type;
|
SYM_TYPE sym_type;
|
||||||
int i;
|
int i;
|
||||||
struct msc_debug_info msc_dbg;
|
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.module = module;
|
||||||
msc_dbg.nsect = nth->FileHeader.NumberOfSections;
|
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.nomap = 0;
|
||||||
msc_dbg.omapp = NULL;
|
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)
|
if (dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)
|
||||||
{
|
{
|
||||||
msc_dbg.nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,22 +78,22 @@ static SYM_TYPE pe_load_stabs(const struct process* pcs, struct module* module,
|
||||||
* loads a .dbg file
|
* loads a .dbg file
|
||||||
*/
|
*/
|
||||||
static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* module,
|
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];
|
char tmp[MAX_PATH];
|
||||||
HANDLE hFile, hMap = 0;
|
HANDLE hFile, hMap = 0;
|
||||||
const BYTE* dbg_mapping = NULL;
|
const BYTE* dbg_mapping = NULL;
|
||||||
PIMAGE_SEPARATE_DEBUG_HEADER hdr;
|
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
|
||||||
PIMAGE_DEBUG_DIRECTORY dbg;
|
const IMAGE_DEBUG_DIRECTORY* dbg;
|
||||||
SYM_TYPE sym_type = -1;
|
SYM_TYPE sym_type = -1;
|
||||||
|
|
||||||
WINE_TRACE("Processing DBG file %s\n", dbg_name);
|
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) &&
|
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
|
||||||
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
|
((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)
|
if (hdr->TimeDateStamp != timestamp)
|
||||||
{
|
{
|
||||||
WINE_ERR("Warning - %s has incorrect internal timestamp\n",
|
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.
|
* which have incorrect timestamps.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
dbg = (PIMAGE_DEBUG_DIRECTORY)
|
dbg = (const IMAGE_DEBUG_DIRECTORY*)
|
||||||
(dbg_mapping + sizeof(*hdr) +
|
(dbg_mapping + sizeof(*hdr) +
|
||||||
hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
|
hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
|
||||||
hdr->ExportedNamesSize);
|
hdr->ExportedNamesSize);
|
||||||
|
@ -133,24 +133,24 @@ static SYM_TYPE pe_load_msc_debug_info(const struct process* pcs,
|
||||||
struct module* module,
|
struct module* module,
|
||||||
const void* mapping, IMAGE_NT_HEADERS* nth)
|
const void* mapping, IMAGE_NT_HEADERS* nth)
|
||||||
{
|
{
|
||||||
SYM_TYPE sym_type = -1;
|
SYM_TYPE sym_type = -1;
|
||||||
PIMAGE_DATA_DIRECTORY dir;
|
const IMAGE_DATA_DIRECTORY* dir;
|
||||||
PIMAGE_DEBUG_DIRECTORY dbg = NULL;
|
const IMAGE_DEBUG_DIRECTORY*dbg = NULL;
|
||||||
int nDbg;
|
int nDbg;
|
||||||
|
|
||||||
/* Read in debug directory */
|
/* Read in debug directory */
|
||||||
dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
|
dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
|
||||||
nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
|
nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
|
||||||
if (!nDbg) return sym_type;
|
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 */
|
/* Parse debug directory */
|
||||||
if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
|
if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
|
||||||
{
|
{
|
||||||
/* Debug info is stripped to .DBG file */
|
/* Debug info is stripped to .DBG file */
|
||||||
PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)
|
const IMAGE_DEBUG_MISC* misc = (const IMAGE_DEBUG_MISC*)
|
||||||
((char*)mapping + dbg->PointerToRawData);
|
((const char*)mapping + dbg->PointerToRawData);
|
||||||
|
|
||||||
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
|
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
|
||||||
misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
|
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,
|
struct module* module,
|
||||||
const void* mapping, IMAGE_NT_HEADERS* nth)
|
const void* mapping, IMAGE_NT_HEADERS* nth)
|
||||||
{
|
{
|
||||||
char buffer[512];
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
IMAGE_DATA_DIRECTORY* dir;
|
IMAGE_DATA_DIRECTORY* dir;
|
||||||
DWORD base = module->module.BaseOfImage;
|
DWORD base = module->module.BaseOfImage;
|
||||||
|
@ -196,21 +195,20 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Add entry point */
|
/* Add entry point */
|
||||||
snprintf(buffer, sizeof(buffer), "%s.EntryPoint", module->module.ModuleName);
|
symt_new_public(module, NULL, "EntryPoint",
|
||||||
symt_new_public(module, NULL, buffer,
|
|
||||||
base + nth->OptionalHeader.AddressOfEntryPoint, 0,
|
base + nth->OptionalHeader.AddressOfEntryPoint, 0,
|
||||||
TRUE /* FIXME */, TRUE /* FIXME */);
|
TRUE /* FIXME */, TRUE /* FIXME */);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
/* FIXME: we'd better store addresses linked to sections rather than
|
||||||
|
absolute values */
|
||||||
IMAGE_SECTION_HEADER* section;
|
IMAGE_SECTION_HEADER* section;
|
||||||
/* Add start of sections */
|
/* Add start of sections */
|
||||||
section = (IMAGE_SECTION_HEADER*)
|
section = (IMAGE_SECTION_HEADER*)
|
||||||
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
|
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
|
||||||
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
|
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
|
||||||
{
|
{
|
||||||
snprintf(buffer, sizeof(buffer), "%s.%s",
|
symt_new_public(module, NULL, section->Name, base + section->VirtualAddress, 0,
|
||||||
module->module.ModuleName, section->Name);
|
|
||||||
symt_new_public(module, NULL, buffer, base + section->VirtualAddress, 0,
|
|
||||||
TRUE /* FIXME */, TRUE /* FIXME */);
|
TRUE /* FIXME */, TRUE /* FIXME */);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -219,23 +217,22 @@ static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
|
||||||
if ((dir = RtlImageDirectoryEntryToData((void*)mapping, TRUE,
|
if ((dir = RtlImageDirectoryEntryToData((void*)mapping, TRUE,
|
||||||
IMAGE_DIRECTORY_ENTRY_EXPORT, NULL)))
|
IMAGE_DIRECTORY_ENTRY_EXPORT, NULL)))
|
||||||
{
|
{
|
||||||
IMAGE_EXPORT_DIRECTORY* exports;
|
const IMAGE_EXPORT_DIRECTORY* exports;
|
||||||
WORD* ordinals = NULL;
|
const WORD* ordinals = NULL;
|
||||||
void** functions = NULL;
|
const void* const* functions = NULL;
|
||||||
DWORD* names = NULL;
|
const DWORD* names = NULL;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
char buffer[16];
|
||||||
exports = (void*)((char*)mapping + dir->VirtualAddress);
|
|
||||||
functions = (void*)((char*)mapping + exports->AddressOfFunctions);
|
exports = (const void*)((const char*)mapping + dir->VirtualAddress);
|
||||||
ordinals = (void*)((char*)mapping + exports->AddressOfNameOrdinals);
|
functions = (const void*)((const char*)mapping + exports->AddressOfFunctions);
|
||||||
names = (void*)((char*)mapping + exports->AddressOfNames);
|
ordinals = (const void*)((const char*)mapping + exports->AddressOfNameOrdinals);
|
||||||
|
names = (const void*)((const char*)mapping + exports->AddressOfNames);
|
||||||
|
|
||||||
for (i = 0; i < exports->NumberOfNames; i++)
|
for (i = 0; i < exports->NumberOfNames; i++)
|
||||||
{
|
{
|
||||||
if (!names[i]) continue;
|
if (!names[i]) continue;
|
||||||
snprintf(buffer, sizeof(buffer), "%s.%s",
|
symt_new_public(module, NULL, (const char*)base + names[i],
|
||||||
module->module.ModuleName, (char*)base + names[i]);
|
|
||||||
symt_new_public(module, NULL, buffer,
|
|
||||||
base + (DWORD)functions[ordinals[i]], 0,
|
base + (DWORD)functions[ordinals[i]], 0,
|
||||||
TRUE /* FIXME */, TRUE /* FIXME */);
|
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++)
|
for (j = 0; j < exports->NumberOfNames; j++)
|
||||||
if ((ordinals[j] == i) && names[j]) break;
|
if ((ordinals[j] == i) && names[j]) break;
|
||||||
if (j < exports->NumberOfNames) continue;
|
if (j < exports->NumberOfNames) continue;
|
||||||
snprintf(buffer, sizeof(buffer), "%s.%ld",
|
snprintf(buffer, sizeof(buffer), "%ld", i + exports->Base);
|
||||||
module->module.ModuleName, i + exports->Base);
|
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
|
||||||
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
|
|
||||||
TRUE /* FIXME */, TRUE /* FIXME */);
|
TRUE /* FIXME */, TRUE /* FIXME */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,6 @@
|
||||||
|
|
||||||
#include "dbghelp_private.h"
|
#include "dbghelp_private.h"
|
||||||
|
|
||||||
#if defined(__svr4__) || defined(__sun)
|
|
||||||
#define __ELF__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
|
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);
|
udt, symt_get_name(&udt->symt), udt->symt.tag);
|
||||||
return -1;
|
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 */
|
/* should check typename is the same too */
|
||||||
new_dt = &udt->symt;
|
new_dt = &udt->symt;
|
||||||
}
|
}
|
||||||
|
@ -1042,76 +1041,6 @@ struct pending_loc_var
|
||||||
unsigned regno;
|
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
|
* 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.
|
/* To define the debug-start of the function, we use the second line number.
|
||||||
* Not 100% bullet proof, but better than nothing
|
* 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_get_func_line_next(module, &il))
|
||||||
{
|
{
|
||||||
symt_add_function_point(module, func, SymTagFuncDebugStart,
|
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_function* curr_func = NULL;
|
||||||
struct symt_block* block = NULL;
|
struct symt_block* block = NULL;
|
||||||
struct symt_public* public;
|
|
||||||
struct symt_compiland* compiland = NULL;
|
struct symt_compiland* compiland = NULL;
|
||||||
char currpath[PATH_MAX];
|
char currpath[PATH_MAX];
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -1162,8 +1090,8 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
||||||
unsigned num_allocated_pending_vars = 0;
|
unsigned num_allocated_pending_vars = 0;
|
||||||
|
|
||||||
nstab = stablen / sizeof(struct stab_nlist);
|
nstab = stablen / sizeof(struct stab_nlist);
|
||||||
stab_ptr = (struct stab_nlist*)(addr + staboff);
|
stab_ptr = (const struct stab_nlist*)(addr + staboff);
|
||||||
strs = (char*)(addr + strtaboff);
|
strs = (const char*)(addr + strtaboff);
|
||||||
|
|
||||||
memset(currpath, 0, sizeof(currpath));
|
memset(currpath, 0, sizeof(currpath));
|
||||||
memset(stabs_basic, 0, sizeof(stabs_basic));
|
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.
|
* With a.out or mingw, they actually do make some amount of sense.
|
||||||
*/
|
*/
|
||||||
stab_strcpy(symname, sizeof(symname), ptr);
|
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 */,
|
symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
|
||||||
load_offset + stab_ptr->n_value, 0,
|
load_offset + stab_ptr->n_value, 0,
|
||||||
stabs_parse_type(ptr));
|
stabs_parse_type(ptr));
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case N_LCSYM:
|
case N_LCSYM:
|
||||||
case N_STSYM:
|
case N_STSYM:
|
||||||
|
@ -1396,19 +1317,8 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
||||||
if (curr_func != NULL)
|
if (curr_func != NULL)
|
||||||
{
|
{
|
||||||
assert(source_idx >= 0);
|
assert(source_idx >= 0);
|
||||||
#ifdef __ELF__
|
|
||||||
symt_add_func_line(module, curr_func, source_idx,
|
symt_add_func_line(module, curr_func, source_idx,
|
||||||
stab_ptr->n_desc, stab_ptr->n_value);
|
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;
|
break;
|
||||||
case N_FUN:
|
case N_FUN:
|
||||||
|
@ -1433,16 +1343,9 @@ SYM_TYPE stabs_parse(struct module* module, const char* addr,
|
||||||
struct symt_function_signature* func_type;
|
struct symt_function_signature* func_type;
|
||||||
func_type = symt_new_function_signature(module,
|
func_type = symt_new_function_signature(module,
|
||||||
stabs_parse_type(ptr));
|
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,
|
curr_func = symt_new_function(module, compiland, symname,
|
||||||
load_offset + stab_ptr->n_value, 0,
|
load_offset + stab_ptr->n_value, 0,
|
||||||
&func_type->symt);
|
&func_type->symt);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
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];
|
/* in some cases, we need to get back the symbols of same name in the order
|
||||||
ht->buckets[hash] = elt;
|
* 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)
|
void* hash_table_find(const struct hash_table* ht, const char* name)
|
||||||
|
|
|
@ -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)
|
int symt_cmp_addr(const void* p1, const void* p2)
|
||||||
{
|
{
|
||||||
struct symt* sym1 = *(struct symt**)p1;
|
const struct symt* sym1 = *(const struct symt* const *)p1;
|
||||||
struct symt* sym2 = *(struct symt**)p2;
|
const struct symt* sym2 = *(const struct symt* const *)p2;
|
||||||
DWORD a1, a2;
|
DWORD a1, a2;
|
||||||
|
|
||||||
symt_get_info(sym1, TI_GET_ADDRESS, &a1);
|
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_data* sym;
|
||||||
struct symt** p;
|
struct symt** p;
|
||||||
|
DWORD tsz;
|
||||||
|
|
||||||
TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n",
|
TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n",
|
||||||
module->module.ModuleName, name, addr, type);
|
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->container = compiland ? &compiland->symt : NULL;
|
||||||
sym->type = type;
|
sym->type = type;
|
||||||
sym->u.address = addr;
|
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)
|
if (compiland)
|
||||||
{
|
{
|
||||||
p = vector_add(&compiland->vchildren, &module->pool);
|
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);
|
hash_table_add(&module->ht_symbols, &sym->hash_elt);
|
||||||
module->sortlist_valid = FALSE;
|
module->sortlist_valid = FALSE;
|
||||||
sym->container = &compiland->symt;
|
sym->container = &compiland->symt;
|
||||||
sym->addr = addr;
|
sym->address = addr;
|
||||||
sym->type = sig_type;
|
sym->type = sig_type;
|
||||||
sym->size = size;
|
sym->size = size;
|
||||||
sym->addr = addr;
|
|
||||||
vector_init(&sym->vlines, sizeof(struct line_info), 64);
|
vector_init(&sym->vlines, sizeof(struct line_info), 64);
|
||||||
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
|
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
|
||||||
if (compiland)
|
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_source_file = 0;
|
||||||
dli->is_first = dli->is_last = 0;
|
dli->is_first = dli->is_last = 0;
|
||||||
dli->line_number = line_num;
|
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,
|
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);
|
assert(!parent_block || parent_block->symt.tag == SymTagBlock);
|
||||||
block = pool_alloc(&module->pool, sizeof(*block));
|
block = pool_alloc(&module->pool, sizeof(*block));
|
||||||
block->symt.tag = SymTagBlock;
|
block->symt.tag = SymTagBlock;
|
||||||
block->address = func->addr + pc;
|
block->address = func->address + pc;
|
||||||
block->size = len;
|
block->size = len;
|
||||||
block->container = parent_block ? &parent_block->symt : &func->symt;
|
block->container = parent_block ? &parent_block->symt : &func->symt;
|
||||||
vector_init(&block->vchildren, sizeof(struct symt*), 4);
|
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);
|
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) ?
|
return (block->container->tag == SymTagBlock) ?
|
||||||
GET_ENTRY(block->container, struct symt_block, symt) : NULL;
|
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;
|
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 */
|
/* expect sym_info->MaxNameLen to be set before being called */
|
||||||
static void symt_fill_sym_info(const struct module* module,
|
static void symt_fill_sym_info(const struct module* module,
|
||||||
const struct symt* sym, SYMBOL_INFO* sym_info)
|
const struct symt* sym, SYMBOL_INFO* sym_info)
|
||||||
|
@ -423,7 +460,7 @@ static void symt_fill_sym_info(const struct module* module,
|
||||||
{
|
{
|
||||||
case SymTagData:
|
case SymTagData:
|
||||||
{
|
{
|
||||||
struct symt_data* data = (struct symt_data*)sym;
|
const struct symt_data* data = (const struct symt_data*)sym;
|
||||||
switch (data->kind)
|
switch (data->kind)
|
||||||
{
|
{
|
||||||
case DataIsLocal:
|
case DataIsLocal:
|
||||||
|
@ -476,6 +513,10 @@ static void symt_fill_sym_info(const struct module* module,
|
||||||
sym_info->Flags |= SYMFLAG_FUNCTION;
|
sym_info->Flags |= SYMFLAG_FUNCTION;
|
||||||
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
||||||
break;
|
break;
|
||||||
|
case SymTagThunk:
|
||||||
|
sym_info->Flags |= SYMFLAG_THUNK;
|
||||||
|
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
|
||||||
sym_info->Register = 0;
|
sym_info->Register = 0;
|
||||||
|
@ -571,9 +612,10 @@ static BOOL resort_symbols(struct module* module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assume addr is in 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;
|
int mid, high, low;
|
||||||
|
DWORD ref;
|
||||||
|
|
||||||
if (!module->sortlist_valid && !resort_symbols(module)) return -1;
|
if (!module->sortlist_valid && !resort_symbols(module)) return -1;
|
||||||
|
|
||||||
|
@ -582,6 +624,15 @@ static int symt_find_nearest(struct module* module, DWORD addr)
|
||||||
*/
|
*/
|
||||||
low = 0;
|
low = 0;
|
||||||
high = module->module.NumSyms;
|
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)
|
while (high > low + 1)
|
||||||
{
|
{
|
||||||
|
@ -600,8 +651,6 @@ static int symt_find_nearest(struct module* module, DWORD addr)
|
||||||
*/
|
*/
|
||||||
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
|
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
|
||||||
{
|
{
|
||||||
DWORD ref;
|
|
||||||
|
|
||||||
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref);
|
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref);
|
||||||
if (low > 0 &&
|
if (low > 0 &&
|
||||||
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
|
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
|
||||||
|
|
|
@ -80,15 +80,16 @@ const char* symt_get_name(const struct symt* sym)
|
||||||
switch (sym->tag)
|
switch (sym->tag)
|
||||||
{
|
{
|
||||||
/* lexical tree */
|
/* lexical tree */
|
||||||
case SymTagData: return ((struct symt_data*)sym)->hash_elt.name;
|
case SymTagData: return ((const struct symt_data*)sym)->hash_elt.name;
|
||||||
case SymTagFunction: return ((struct symt_function*)sym)->hash_elt.name;
|
case SymTagFunction: return ((const struct symt_function*)sym)->hash_elt.name;
|
||||||
case SymTagPublicSymbol: return ((struct symt_public*)sym)->hash_elt.name;
|
case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name;
|
||||||
case SymTagBaseType: return ((struct symt_basic*)sym)->hash_elt.name;
|
case SymTagBaseType: return ((const struct symt_basic*)sym)->hash_elt.name;
|
||||||
case SymTagLabel: return ((struct symt_function_point*)sym)->name;
|
case SymTagLabel: return ((const struct symt_function_point*)sym)->name;
|
||||||
|
case SymTagThunk: return ((const struct symt_thunk*)sym)->hash_elt.name;
|
||||||
/* hierarchy tree */
|
/* hierarchy tree */
|
||||||
case SymTagEnum: return ((struct symt_enum*)sym)->name;
|
case SymTagEnum: return ((const struct symt_enum*)sym)->name;
|
||||||
case SymTagTypedef: return ((struct symt_typedef*)sym)->hash_elt.name;
|
case SymTagTypedef: return ((const struct symt_typedef*)sym)->hash_elt.name;
|
||||||
case SymTagUDT: return ((struct symt_udt*)sym)->hash_elt.name;
|
case SymTagUDT: return ((const struct symt_udt*)sym)->hash_elt.name;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
|
FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
@ -417,10 +418,10 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
||||||
|
|
||||||
switch (type->tag)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagUDT: v = &((struct symt_udt*)type)->vchildren; break;
|
case SymTagUDT: v = &((const struct symt_udt*)type)->vchildren; break;
|
||||||
case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
|
case SymTagEnum: v = &((const struct symt_enum*)type)->vchildren; break;
|
||||||
case SymTagFunctionType: v = &((struct symt_function_signature*)type)->vchildren; break;
|
case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
|
||||||
case SymTagFunction: v = &((struct symt_function*)type)->vchildren; break;
|
case SymTagFunction: v = &((const struct symt_function*)type)->vchildren; break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s for find-children\n",
|
FIXME("Unsupported sym-tag %s for find-children\n",
|
||||||
symt_get_tag_str(type->tag));
|
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)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagData:
|
case SymTagData:
|
||||||
switch (((struct symt_data*)type)->kind)
|
switch (((const struct symt_data*)type)->kind)
|
||||||
{
|
{
|
||||||
case DataIsGlobal:
|
case DataIsGlobal:
|
||||||
case DataIsFileStatic:
|
case DataIsFileStatic:
|
||||||
X(DWORD) = ((struct symt_data*)type)->u.address;
|
X(DWORD) = ((const struct symt_data*)type)->u.address;
|
||||||
break;
|
break;
|
||||||
default: return FALSE;
|
default: return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymTagFunction:
|
case SymTagFunction:
|
||||||
X(DWORD) = ((struct symt_function*)type)->addr;
|
X(DWORD) = ((const struct symt_function*)type)->address;
|
||||||
break;
|
break;
|
||||||
case SymTagPublicSymbol:
|
case SymTagPublicSymbol:
|
||||||
X(DWORD) = ((struct symt_public*)type)->address;
|
X(DWORD) = ((const struct symt_public*)type)->address;
|
||||||
break;
|
break;
|
||||||
case SymTagFuncDebugStart:
|
case SymTagFuncDebugStart:
|
||||||
case SymTagFuncDebugEnd:
|
case SymTagFuncDebugEnd:
|
||||||
case SymTagLabel:
|
case SymTagLabel:
|
||||||
X(DWORD) = ((struct symt_function_point*)type)->parent->addr +
|
X(DWORD) = ((const struct symt_function_point*)type)->parent->address +
|
||||||
((struct symt_function_point*)type)->offset;
|
((const struct symt_function_point*)type)->offset;
|
||||||
|
break;
|
||||||
|
case SymTagThunk:
|
||||||
|
X(DWORD) = ((const struct symt_thunk*)type)->address;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s for get-address\n",
|
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)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagBaseType:
|
case SymTagBaseType:
|
||||||
X(DWORD) = ((struct symt_basic*)type)->bt;
|
X(DWORD) = ((const struct symt_basic*)type)->bt;
|
||||||
break;
|
break;
|
||||||
case SymTagEnum:
|
case SymTagEnum:
|
||||||
X(DWORD) = btInt;
|
X(DWORD) = btInt;
|
||||||
|
@ -482,29 +486,30 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
||||||
|
|
||||||
case TI_GET_BITPOSITION:
|
case TI_GET_BITPOSITION:
|
||||||
if (type->tag != SymTagData ||
|
if (type->tag != SymTagData ||
|
||||||
((struct symt_data*)type)->kind != DataIsMember ||
|
((const struct symt_data*)type)->kind != DataIsMember ||
|
||||||
((struct symt_data*)type)->u.s.length == 0)
|
((const struct symt_data*)type)->u.s.length == 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
X(DWORD) = ((struct symt_data*)type)->u.s.offset & 7;
|
X(DWORD) = ((const struct symt_data*)type)->u.s.offset & 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TI_GET_CHILDRENCOUNT:
|
case TI_GET_CHILDRENCOUNT:
|
||||||
switch (type->tag)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagUDT:
|
case SymTagUDT:
|
||||||
X(DWORD) = vector_length(&((struct symt_udt*)type)->vchildren);
|
X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
|
||||||
break;
|
break;
|
||||||
case SymTagEnum:
|
case SymTagEnum:
|
||||||
X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
|
X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
|
||||||
break;
|
break;
|
||||||
case SymTagFunctionType:
|
case SymTagFunctionType:
|
||||||
X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
|
X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
|
||||||
break;
|
break;
|
||||||
case SymTagFunction:
|
case SymTagFunction:
|
||||||
X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
|
X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
|
||||||
break;
|
break;
|
||||||
case SymTagPointerType: /* MS does it that way */
|
case SymTagPointerType: /* MS does it that way */
|
||||||
case SymTagArrayType: /* MS does it that way */
|
case SymTagArrayType: /* MS does it that way */
|
||||||
|
case SymTagThunk: /* MS does it that way */
|
||||||
X(DWORD) = 0;
|
X(DWORD) = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
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)
|
* also include 'this' (GET_CHILDREN_COUNT+1)
|
||||||
*/
|
*/
|
||||||
if (type->tag != SymTagArrayType) return FALSE;
|
if (type->tag != SymTagArrayType) return FALSE;
|
||||||
X(DWORD) = ((struct symt_array*)type)->end -
|
X(DWORD) = ((const struct symt_array*)type)->end -
|
||||||
((struct symt_array*)type)->start;
|
((const struct symt_array*)type)->start + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TI_GET_DATAKIND:
|
case TI_GET_DATAKIND:
|
||||||
if (type->tag != SymTagData) return FALSE;
|
if (type->tag != SymTagData) return FALSE;
|
||||||
X(DWORD) = ((struct symt_data*)type)->kind;
|
X(DWORD) = ((const struct symt_data*)type)->kind;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TI_GET_LENGTH:
|
case TI_GET_LENGTH:
|
||||||
switch (type->tag)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagBaseType:
|
case SymTagBaseType:
|
||||||
X(DWORD) = ((struct symt_basic*)type)->size;
|
X(DWORD) = ((const struct symt_basic*)type)->size;
|
||||||
break;
|
break;
|
||||||
case SymTagFunction:
|
case SymTagFunction:
|
||||||
X(DWORD) = ((struct symt_function*)type)->size;
|
X(DWORD) = ((const struct symt_function*)type)->size;
|
||||||
break;
|
break;
|
||||||
case SymTagPointerType:
|
case SymTagPointerType:
|
||||||
X(DWORD) = sizeof(void*);
|
X(DWORD) = sizeof(void*);
|
||||||
break;
|
break;
|
||||||
case SymTagUDT:
|
case SymTagUDT:
|
||||||
X(DWORD) = ((struct symt_udt*)type)->size;
|
X(DWORD) = ((const struct symt_udt*)type)->size;
|
||||||
break;
|
break;
|
||||||
case SymTagEnum:
|
case SymTagEnum:
|
||||||
X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
|
X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
|
||||||
break;
|
break;
|
||||||
case SymTagData:
|
case SymTagData:
|
||||||
if (((struct symt_data*)type)->kind != DataIsMember ||
|
if (((const struct symt_data*)type)->kind != DataIsMember ||
|
||||||
!((struct symt_data*)type)->u.s.length)
|
!((const struct symt_data*)type)->u.s.length)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
X(DWORD) = ((struct symt_data*)type)->u.s.length;
|
X(DWORD) = ((const struct symt_data*)type)->u.s.length;
|
||||||
break;
|
break;
|
||||||
case SymTagArrayType:
|
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))
|
TI_GET_LENGTH, pInfo))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
X(DWORD) *= ((struct symt_array*)type)->end -
|
X(DWORD) *= ((const struct symt_array*)type)->end -
|
||||||
((struct symt_array*)type)->start;
|
((const struct symt_array*)type)->start + 1;
|
||||||
break;
|
break;
|
||||||
case SymTagPublicSymbol:
|
case SymTagPublicSymbol:
|
||||||
X(DWORD) = ((struct symt_public*)type)->size;
|
X(DWORD) = ((const struct symt_public*)type)->size;
|
||||||
break;
|
break;
|
||||||
case SymTagTypedef:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s for get-length\n",
|
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)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagBlock:
|
case SymTagBlock:
|
||||||
X(DWORD) = (DWORD)((struct symt_block*)type)->container;
|
X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
|
||||||
break;
|
break;
|
||||||
case SymTagData:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
|
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)
|
switch (type->tag)
|
||||||
{
|
{
|
||||||
case SymTagData:
|
case SymTagData:
|
||||||
switch (((struct symt_data*)type)->kind)
|
switch (((const struct symt_data*)type)->kind)
|
||||||
{
|
{
|
||||||
case DataIsParam:
|
case DataIsParam:
|
||||||
case DataIsLocal:
|
case DataIsLocal:
|
||||||
case DataIsMember:
|
case DataIsMember:
|
||||||
X(ULONG) = ((struct symt_data*)type)->u.s.offset >> 3;
|
X(ULONG) = ((const struct symt_data*)type)->u.s.offset >> 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unknown kind (%u) for get-offset\n",
|
FIXME("Unknown kind (%u) for get-offset\n",
|
||||||
((struct symt_data*)type)->kind);
|
((const struct symt_data*)type)->kind);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -650,41 +664,42 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
||||||
{
|
{
|
||||||
/* hierarchical => hierarchical */
|
/* hierarchical => hierarchical */
|
||||||
case SymTagArrayType:
|
case SymTagArrayType:
|
||||||
X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
|
X(DWORD) = (DWORD)((const struct symt_array*)type)->basetype;
|
||||||
break;
|
break;
|
||||||
case SymTagPointerType:
|
case SymTagPointerType:
|
||||||
X(DWORD) = (DWORD)((struct symt_pointer*)type)->pointsto;
|
X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
|
||||||
break;
|
break;
|
||||||
case SymTagFunctionType:
|
case SymTagFunctionType:
|
||||||
X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
|
X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
|
||||||
break;
|
break;
|
||||||
case SymTagTypedef:
|
case SymTagTypedef:
|
||||||
X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
|
X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
|
||||||
break;
|
break;
|
||||||
/* lexical => hierarchical */
|
/* lexical => hierarchical */
|
||||||
case SymTagData:
|
case SymTagData:
|
||||||
X(DWORD) = (DWORD)((struct symt_data*)type)->type;
|
X(DWORD) = (DWORD)((const struct symt_data*)type)->type;
|
||||||
break;
|
break;
|
||||||
case SymTagFunction:
|
case SymTagFunction:
|
||||||
X(DWORD) = (DWORD)((struct symt_function*)type)->type;
|
X(DWORD) = (DWORD)((const struct symt_function*)type)->type;
|
||||||
break;
|
break;
|
||||||
/* FIXME: should also work for enums and FunctionArgType */
|
/* FIXME: should also work for enums and FunctionArgType */
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported sym-tag %s for get-type\n",
|
FIXME("Unsupported sym-tag %s for get-type\n",
|
||||||
symt_get_tag_str(type->tag));
|
symt_get_tag_str(type->tag));
|
||||||
|
case SymTagThunk:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TI_GET_UDTKIND:
|
case TI_GET_UDTKIND:
|
||||||
if (type->tag != SymTagUDT) return FALSE;
|
if (type->tag != SymTagUDT) return FALSE;
|
||||||
X(DWORD) = ((struct symt_udt*)type)->kind;
|
X(DWORD) = ((const struct symt_udt*)type)->kind;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TI_GET_VALUE:
|
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;
|
return FALSE;
|
||||||
X(VARIANT) = ((struct symt_data*)type)->u.value;
|
X(VARIANT) = ((const struct symt_data*)type)->u.value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#undef X
|
#undef X
|
||||||
|
|
|
@ -421,3 +421,12 @@ enum CV_HREG_e
|
||||||
CV_M32R_ACLO = 33,
|
CV_M32R_ACLO = 33,
|
||||||
CV_M32R_PC = 34,
|
CV_M32R_PC = 34,
|
||||||
} CV_HREG_e;
|
} CV_HREG_e;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
THUNK_ORDINAL_NOTYPE,
|
||||||
|
THUNK_ORDINAL_ADJUSTOR,
|
||||||
|
THUNK_ORDINAL_VCALL,
|
||||||
|
THUNK_ORDINAL_PCODE,
|
||||||
|
THUNK_ORDINAL_LOAD
|
||||||
|
} THUNK_ORDINAL;
|
||||||
|
|
|
@ -72,6 +72,9 @@ typedef struct _tagADDRESS
|
||||||
#define SYMF_EXPORT 0x00000200
|
#define SYMF_EXPORT 0x00000200
|
||||||
#define SYMF_FORWARDER 0x00000400
|
#define SYMF_FORWARDER 0x00000400
|
||||||
#define SYMF_FUNCTION 0x00000800
|
#define SYMF_FUNCTION 0x00000800
|
||||||
|
#define SYMF_VIRTUAL 0x00001000
|
||||||
|
#define SYMF_THUNK 0x00002000
|
||||||
|
#define SYMF_TLSREL 0x00004000
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -529,6 +532,11 @@ typedef struct _MINIDUMP_THREAD_LIST
|
||||||
MINIDUMP_THREAD Threads[1]; /* FIXME: no support of 0 sized array */
|
MINIDUMP_THREAD Threads[1]; /* FIXME: no support of 0 sized array */
|
||||||
} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;
|
} 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 *
|
* MODULE handling *
|
||||||
*************************/
|
*************************/
|
||||||
|
@ -586,7 +594,7 @@ typedef struct _SYMBOL_INFO
|
||||||
ULONG SizeOfStruct;
|
ULONG SizeOfStruct;
|
||||||
ULONG TypeIndex;
|
ULONG TypeIndex;
|
||||||
ULONG Reserved[2];
|
ULONG Reserved[2];
|
||||||
ULONG info;
|
ULONG info; /* sdk states info, while MSDN says it's Index... */
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
ULONG ModBase;
|
ULONG ModBase;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
|
@ -666,8 +674,12 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, DWORD BaseOfDll,
|
||||||
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD addr, DWORD* displacement,
|
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD addr, DWORD* displacement,
|
||||||
SYMBOL_INFO* sym_info);
|
SYMBOL_INFO* sym_info);
|
||||||
BOOL WINAPI SymFromName(HANDLE hProcess, LPSTR Name, PSYMBOL_INFO Symbol);
|
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,
|
BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, DWORD BaseOfDll, LPSTR Name,
|
||||||
PSYMBOL_INFO Symbol);
|
PSYMBOL_INFO Symbol);
|
||||||
|
BOOL WINAPI SymGetSymNext(HANDLE,PIMAGEHLP_SYMBOL);
|
||||||
|
BOOL WINAPI SymGetSymPrev(HANDLE,PIMAGEHLP_SYMBOL);
|
||||||
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
|
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG BaseOfDll, PCSTR Mask,
|
||||||
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
|
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
|
||||||
PVOID UserContext);
|
PVOID UserContext);
|
||||||
|
@ -681,6 +693,7 @@ typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess, ULONG Acti
|
||||||
BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
|
BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
|
||||||
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
|
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
|
||||||
PVOID UserContext);
|
PVOID UserContext);
|
||||||
|
BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL,PSTR,DWORD);
|
||||||
DWORD WINAPI UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName,
|
DWORD WINAPI UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName,
|
||||||
DWORD UndecoratedLength, DWORD Flags);
|
DWORD UndecoratedLength, DWORD Flags);
|
||||||
|
|
||||||
|
@ -731,6 +744,11 @@ PIMAGE_SECTION_HEADER WINAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,
|
||||||
PVOID Base, ULONG Rva);
|
PVOID Base, ULONG Rva);
|
||||||
PVOID WINAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders, PVOID Base,
|
PVOID WINAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders, PVOID Base,
|
||||||
ULONG Rva, OUT PIMAGE_SECTION_HEADER *LastRvaSection);
|
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 *
|
* Context management *
|
||||||
|
|
Loading…
Reference in New Issue