dbghelp: Use an intermediate buffer in SymFunctionTableAccess (x86_64).
This mainly allows to release internal resources bound to image. Also follow chained RUNTIME_FUNCTION entries (if any). Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
parent
da22ef6c0d
commit
56193155a0
4 changed files with 81 additions and 19 deletions
|
@ -729,31 +729,46 @@ static BOOL x86_64_stack_walk(struct cpu_stack_walk *csw, STACKFRAME64 *frame,
|
|||
static void* x86_64_find_runtime_function(struct module* module, DWORD64 addr)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
RUNTIME_FUNCTION* rtf;
|
||||
ULONG size;
|
||||
int min, max;
|
||||
RUNTIME_FUNCTION *func = NULL;
|
||||
const RUNTIME_FUNCTION *rtf;
|
||||
ULONG size;
|
||||
|
||||
rtf = (RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size);
|
||||
if (rtf) for (min = 0, max = size / sizeof(*rtf); min <= max; )
|
||||
rtf = (const RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size);
|
||||
if (rtf)
|
||||
{
|
||||
int pos = (min + max) / 2;
|
||||
if (addr < module->module.BaseOfImage + rtf[pos].BeginAddress) max = pos - 1;
|
||||
else if (addr >= module->module.BaseOfImage + rtf[pos].EndAddress) min = pos + 1;
|
||||
else
|
||||
int lo, hi;
|
||||
|
||||
for (lo = 0, hi = size / sizeof(*rtf); lo <= hi; )
|
||||
{
|
||||
rtf += pos;
|
||||
while (rtf->UnwindData & 1) /* follow chained entry */
|
||||
int pos = (lo + hi) / 2;
|
||||
if (addr < module->module.BaseOfImage + rtf[pos].BeginAddress) hi = pos - 1;
|
||||
else if (addr >= module->module.BaseOfImage + rtf[pos].EndAddress) lo = pos + 1;
|
||||
else if ((func = fetch_buffer(module->process, sizeof(*func))))
|
||||
{
|
||||
FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
|
||||
return NULL;
|
||||
/* we need to read into the other process */
|
||||
/* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
|
||||
*func = rtf[pos];
|
||||
while (func && (func->UnwindData & 1))
|
||||
{
|
||||
const BYTE *next = pe_lock_region_from_rva(module, func->UnwindData & ~1, sizeof(*func), NULL);
|
||||
if (next)
|
||||
{
|
||||
*func = *(const RUNTIME_FUNCTION *)next;
|
||||
pe_unlock_region(module, next);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Couldn't find chained RUNTIME_FUNCTION\n");
|
||||
func = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return rtf;
|
||||
}
|
||||
pe_unmap_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, (const char*)rtf);
|
||||
}
|
||||
#endif
|
||||
return func;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned x86_64_map_dwarf_register(unsigned regno, const struct module* module, BOOL eh_frame)
|
||||
|
|
|
@ -781,7 +781,10 @@ extern struct module*
|
|||
extern BOOL pe_load_debug_info(const struct process* pcs,
|
||||
struct module* module);
|
||||
extern const char* pe_map_directory(struct module* module, int dirno, DWORD* size);
|
||||
extern BOOL pe_unmap_directory(struct module* module, int dirno, const char*);
|
||||
extern DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info);
|
||||
extern const BYTE* pe_lock_region_from_rva(struct module *module, DWORD rva, DWORD size, DWORD *length);
|
||||
extern BOOL pe_unlock_region(struct module *module, const BYTE* region);
|
||||
|
||||
/* source.c */
|
||||
extern unsigned source_new(struct module* module, const char* basedir, const char* source);
|
||||
|
|
|
@ -341,6 +341,52 @@ const char* pe_map_directory(struct module* module, int dirno, DWORD* size)
|
|||
nth->OptionalHeader.DataDirectory[dirno].VirtualAddress, NULL);
|
||||
}
|
||||
|
||||
BOOL pe_unmap_directory(struct module* module, int dirno, const char *dir)
|
||||
{
|
||||
if (module->type != DMT_PE || !module->format_info[DFI_PE]) return FALSE;
|
||||
if (dirno >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return FALSE;
|
||||
pe_unmap_full(&module->format_info[DFI_PE]->u.pe_info->fmap);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Locks a region from a mapped PE file, from its RVA, and for at least 'size' bytes.
|
||||
* Region must fit entirely inside a PE section.
|
||||
* 'length', upon success, gets the size from RVA until end of PE section.
|
||||
*/
|
||||
const BYTE* pe_lock_region_from_rva(struct module *module, DWORD rva, DWORD size, DWORD *length)
|
||||
{
|
||||
IMAGE_NT_HEADERS* nth;
|
||||
void* mapping;
|
||||
IMAGE_SECTION_HEADER *section;
|
||||
const BYTE *ret;
|
||||
|
||||
if (module->type != DMT_PE || !module->format_info[DFI_PE]) return NULL;
|
||||
if (!(mapping = pe_map_full(&module->format_info[DFI_PE]->u.pe_info->fmap, &nth)))
|
||||
return NULL;
|
||||
section = NULL;
|
||||
ret = RtlImageRvaToVa(nth, mapping, rva, §ion);
|
||||
if (ret)
|
||||
{
|
||||
if (rva + size <= section->VirtualAddress + section->SizeOfRawData)
|
||||
{
|
||||
if (length)
|
||||
*length = section->VirtualAddress + section->SizeOfRawData - rva;
|
||||
return ret;
|
||||
}
|
||||
if (rva + size <= section->VirtualAddress + section->Misc.VirtualSize)
|
||||
FIXME("Not able to lock regions not present on file\n");
|
||||
}
|
||||
pe_unmap_full(&module->format_info[DFI_PE]->u.pe_info->fmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL pe_unlock_region(struct module *module, const BYTE* region)
|
||||
{
|
||||
if (module->type != DMT_PE || !module->format_info[DFI_PE] || !region) return FALSE;
|
||||
pe_unmap_full(&module->format_info[DFI_PE]->u.pe_info->fmap);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void pe_module_remove(struct process* pcs, struct module_format* modfmt)
|
||||
{
|
||||
image_unmap_file(&modfmt->u.pe_info->fmap);
|
||||
|
|
|
@ -1523,10 +1523,8 @@ static void test_function_tables(void)
|
|||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||
ptr1 = test_function_table_main_module(test_live_modules);
|
||||
ptr2 = test_function_table_main_module(test_function_tables);
|
||||
todo_wine_if(ptr1)
|
||||
ok(ptr1 == ptr2, "Expecting unique storage area\n");
|
||||
ptr2 = test_function_table_module("kernel32.dll", "CreateFileMappingA");
|
||||
todo_wine_if(ptr1)
|
||||
ok(ptr1 == ptr2, "Expecting unique storage area\n");
|
||||
SymCleanup(GetCurrentProcess());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue