📄 symbol.c
字号:
/* EPP vector_pool_normalize(&func->vchildren, &module->pool); */
len = vector_length(&func->vlines);
if (len--)
{
dli = vector_at(&func->vlines, 0); dli->is_first = 1;
dli = vector_at(&func->vlines, len); dli->is_last = 1;
}
return TRUE;
}
struct symt_thunk* symt_new_thunk(struct module* module,
struct symt_compiland* compiland,
const char* name, THUNK_ORDINAL ord,
unsigned long addr, unsigned long size)
{
struct symt_thunk* sym;
TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n",
module->module.ModuleName, name, addr, addr + size - 1);
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
{
sym->symt.tag = SymTagThunk;
sym->hash_elt.name = pool_strdup(&module->pool, name);
hash_table_add(&module->ht_symbols, &sym->hash_elt);
module->sortlist_valid = FALSE;
sym->container = &compiland->symt;
sym->address = addr;
sym->size = size;
sym->ordinal = ord;
if (compiland)
{
struct symt** p;
p = vector_add(&compiland->vchildren, &module->pool);
*p = &sym->symt;
}
}
return sym;
}
/* expect sym_info->MaxNameLen to be set before being called */
static void symt_fill_sym_info(const struct module* module,
const struct symt* sym, SYMBOL_INFO* sym_info)
{
const char* name;
sym_info->TypeIndex = (DWORD)sym;
sym_info->info = 0; /* TBD */
symt_get_info(sym, TI_GET_LENGTH, &sym_info->Size);
sym_info->ModBase = module->module.BaseOfImage;
sym_info->Flags = 0;
switch (sym->tag)
{
case SymTagData:
{
const struct symt_data* data = (const struct symt_data*)sym;
switch (data->kind)
{
case DataIsLocal:
case DataIsParam:
if (data->u.s.reg_id)
{
sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_REGISTER;
sym_info->Register = data->u.s.reg_id;
sym_info->Address = 0;
}
else
{
if (data->u.s.offset < 0)
sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_FRAMEREL;
else
sym_info->Flags |= SYMFLAG_PARAMETER | SYMFLAG_FRAMEREL;
/* FIXME: needed ? moreover, it's i386 dependent !!! */
sym_info->Register = CV_REG_EBP;
sym_info->Address = data->u.s.offset;
}
break;
case DataIsGlobal:
case DataIsFileStatic:
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
sym_info->Register = 0;
break;
case DataIsConstant:
sym_info->Flags |= SYMFLAG_VALUEPRESENT;
switch (data->u.value.n1.n2.vt)
{
case VT_I4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
case VT_I2: sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
case VT_I1: sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
default:
FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
}
break;
default:
FIXME("Unhandled kind (%u) in sym data\n", data->kind);
}
}
break;
case SymTagPublicSymbol:
sym_info->Flags |= SYMFLAG_EXPORT;
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
break;
case SymTagFunction:
sym_info->Flags |= SYMFLAG_FUNCTION;
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
break;
case SymTagThunk:
sym_info->Flags |= SYMFLAG_THUNK;
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
break;
default:
symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
sym_info->Register = 0;
break;
}
sym_info->Scope = 0; /* FIXME */
sym_info->Tag = sym->tag;
name = symt_get_name(sym);
if (sym_info->MaxNameLen)
{
if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) ||
(sym_info->NameLen = UnDecorateSymbolName(sym_info->Name, sym_info->Name,
sym_info->MaxNameLen, UNDNAME_COMPLETE) == 0))
{
sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1);
strncpy(sym_info->Name, name, sym_info->NameLen);
sym_info->Name[sym_info->NameLen] = '\0';
}
}
TRACE_(dbghelp_symt)("%p => %s %lu %s\n",
sym, sym_info->Name, sym_info->Size,
wine_dbgstr_longlong(sym_info->Address));
}
static BOOL symt_enum_module(struct module* module, regex_t* regex,
PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user)
{
char buffer[sizeof(SYMBOL_INFO) + 256];
SYMBOL_INFO* sym_info = (SYMBOL_INFO*)buffer;
void* ptr;
struct symt_ht* sym = NULL;
struct hash_table_iter hti;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
if (sym->hash_elt.name &&
regexec(regex, sym->hash_elt.name, 0, NULL, 0) == 0)
{
sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
symt_fill_sym_info(module, &sym->symt, sym_info);
if (!cb(sym_info, sym_info->Size, user)) return TRUE;
}
}
return FALSE;
}
/***********************************************************************
* resort_symbols
*
* Rebuild sorted list of symbols for a module.
*/
static BOOL resort_symbols(struct module* module)
{
int nsym = 0;
void* ptr;
struct symt_ht* sym;
struct hash_table_iter hti;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
nsym++;
if (!(module->module.NumSyms = nsym)) return FALSE;
if (module->addr_sorttab)
module->addr_sorttab = HeapReAlloc(GetProcessHeap(), 0,
module->addr_sorttab,
nsym * sizeof(struct symt_ht*));
else
module->addr_sorttab = HeapAlloc(GetProcessHeap(), 0,
nsym * sizeof(struct symt_ht*));
if (!module->addr_sorttab) return FALSE;
nsym = 0;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
assert(sym);
module->addr_sorttab[nsym++] = sym;
}
qsort(module->addr_sorttab, nsym, sizeof(struct symt_ht*), symt_cmp_addr);
return module->sortlist_valid = TRUE;
}
/* assume addr is in module */
int symt_find_nearest(struct module* module, DWORD addr)
{
int mid, high, low;
ULONG64 ref_addr;
DWORD ref_size;
if (!module->sortlist_valid || !module->addr_sorttab)
{
if (!resort_symbols(module)) return -1;
}
/*
* Binary search to find closest symbol.
*/
low = 0;
high = module->module.NumSyms;
symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref_addr) return -1;
if (high)
{
symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
ref_size = 0x1000; /* arbitrary value */
if (addr >= ref_addr + ref_size) return -1;
}
while (high > low + 1)
{
mid = (high + low) / 2;
if (cmp_sorttab_addr(module, mid, addr) < 0)
low = mid;
else
high = mid;
}
if (low != high && high != module->module.NumSyms &&
cmp_sorttab_addr(module, high, addr) <= 0)
low = high;
/* If found symbol is a public symbol, check if there are any other entries that
* might also have the same address, but would get better information
*/
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
{
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (low > 0 &&
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
!cmp_sorttab_addr(module, low - 1, ref_addr))
low--;
else if (low < module->module.NumSyms - 1 &&
module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol &&
!cmp_sorttab_addr(module, low + 1, ref_addr))
low++;
}
/* finally check that we fit into the found symbol */
symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref_addr) return -1;
if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
ref_size = 0x1000; /* arbitrary value */
if (addr >= ref_addr + ref_size) return -1;
return low;
}
static BOOL symt_enum_locals_helper(struct process* pcs, struct module* module,
regex_t* preg, PSYM_ENUMERATESYMBOLS_CALLBACK cb,
PVOID user, SYMBOL_INFO* sym_info,
struct vector* v)
{
struct symt** plsym = NULL;
struct symt* lsym = NULL;
DWORD pc = pcs->ctx_frame.InstructionOffset;
while ((plsym = vector_iter_up(v, plsym)))
{
lsym = *plsym;
switch (lsym->tag)
{
case SymTagBlock:
{
struct symt_block* block = (struct symt_block*)lsym;
if (pc < block->address || block->address + block->size <= pc)
continue;
if (!symt_enum_locals_helper(pcs, module, preg, cb, user,
sym_info, &block->vchildren))
return FALSE;
}
break;
case SymTagData:
if (regexec(preg, symt_get_name(lsym), 0, NULL, 0) == 0)
{
symt_fill_sym_info(module, lsym, sym_info);
if (!cb(sym_info, sym_info->Size, user))
return FALSE;
}
break;
case SymTagLabel:
case SymTagFuncDebugStart:
case SymTagFuncDebugEnd:
break;
default:
FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
assert(0);
}
}
return TRUE;
}
static BOOL symt_enum_locals(struct process* pcs, const char* mask,
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
PVOID UserContext)
{
struct module* module;
struct symt_ht* sym;
char buffer[sizeof(SYMBOL_INFO) + 256];
SYMBOL_INFO* sym_info = (SYMBOL_INFO*)buffer;
DWORD pc = pcs->ctx_frame.InstructionOffset;
int idx;
sym_info->SizeOfStruct = sizeof(*sym_info);
sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
module = module_find_by_addr(pcs, pc, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module))) return FALSE;
if ((idx = symt_find_nearest(module, pc)) == -1) return FALSE;
sym = module->addr_sorttab[idx];
if (sym->symt.tag == SymTagFunction)
{
BOOL ret;
regex_t preg;
compile_regex(mask ? mask : "*", -1, &preg);
ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback,
UserContext, sym_info,
&((struct symt_function*)sym)->vchildren);
regfree(&preg);
return ret;
}
symt_fill_sym_info(module, &sym->symt, sym_info);
return EnumSymbolsCallback(sym_info, sym_info->Size, UserContext);
}
/******************************************************************
* SymEnumSymbols (DBGHELP.@)
*
* cases BaseOfDll = 0
* !foo fails always (despite what MSDN states)
* RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2
* no ! in Mask, lookup in local Context
* cases BaseOfDll != 0
* !foo fails always (despite what MSDN states)
* RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is)
*/
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
PVOID UserContext)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
struct module* dbg_module;
const char* bang;
regex_t mod_regex, sym_regex;
TRACE("(%p %s %s %p %p)\n",
hProcess, wine_dbgstr_longlong(BaseOfDll), debugstr_a(Mask),
EnumSymbolsCallback, UserContext);
if (!pcs) return FALSE;
if (BaseOfDll == 0)
{
/* do local variables ? */
if (!Mask || !(bang = strchr(Mask, '!')))
return symt_enum_locals(pcs, Mask, EnumSymbolsCallback, UserContext);
if (bang == Mask) return FALSE;
compile_regex(Mask, bang - Mask, &mod_regex);
compile_regex(bang + 1, -1, &sym_regex);
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_PE && (dbg_module = module_get_debug(pcs, module)))
{
if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 &&
symt_enum_module(dbg_module, &sym_regex,
EnumSymbolsCallback, UserContext))
break;
}
}
/* not found in PE modules, retry on the ELF ones
*/
if (!module && (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES))
{
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_ELF &&
!module_get_containee(pcs, module) &&
(dbg_module = module_get_debug(pcs, module)))
{
if (regexec(&mod_regex, module->module.ModuleName, 0, NULL, 0) == 0 &&
symt_enum_module(dbg_module, &sym_regex, EnumSymbolsCallback, UserContext))
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -