Commit 433bc127 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

winedbg: Fix read access to variables with thread local storage.

No longer relying on loaded module info (getting index address out of PE image, and caching it in struct dbg_module). Co-authored-by: 's avatarEvan Tang <etang@codeweavers.com>
parent 224b33c2
......@@ -250,6 +250,7 @@ struct dbg_module
{
struct list entry;
DWORD_PTR base;
DWORD_PTR tls_index_offset;
};
struct dbg_delayed_bp
......
......@@ -61,6 +61,43 @@ static BOOL symbol_get_debug_start(const struct dbg_type* func, ULONG64* start)
return FALSE;
}
static BOOL fetch_tls_lvalue(const SYMBOL_INFO* sym, struct dbg_lvalue* lvalue)
{
struct dbg_module* mod = dbg_get_module(dbg_curr_process, sym->ModBase);
unsigned tlsindex;
struct dbg_lvalue lv_teb_tls, lv_index_addr, lv_module_tls;
dbg_lgint_t teb_tls_addr, index_addr, tls_module_addr;
char* teb_tls_storage;
if (!mod || !mod->tls_index_offset || !dbg_curr_thread)
return FALSE;
/* get ThreadLocalStoragePointer offset depending on debuggee bitness */
teb_tls_storage = (char*)dbg_curr_thread->teb;
if (ADDRSIZE == sizeof(void*))
/* debugger and debuggee have same bitness */
teb_tls_storage += offsetof(TEB, ThreadLocalStoragePointer);
else
/* debugger is 64bit, while debuggee is 32bit */
teb_tls_storage += 0x2000 /* TEB64 => TEB32 */ + offsetof(TEB32, ThreadLocalStoragePointer);
init_lvalue(&lv_teb_tls, TRUE, teb_tls_storage);
if (!memory_fetch_integer(&lv_teb_tls, ADDRSIZE, FALSE, &teb_tls_addr))
return FALSE;
init_lvalue(&lv_index_addr, TRUE, (void*)(DWORD_PTR)(sym->ModBase + mod->tls_index_offset));
if (!memory_fetch_integer(&lv_index_addr, ADDRSIZE, FALSE, &index_addr))
return FALSE;
if (!dbg_read_memory((const char*)(DWORD_PTR)index_addr, &tlsindex, sizeof(tlsindex)))
return FALSE;
init_lvalue(&lv_module_tls, TRUE, (void*)(DWORD_PTR)(teb_tls_addr + tlsindex * ADDRSIZE));
if (!memory_fetch_integer(&lv_module_tls, ADDRSIZE, FALSE, &tls_module_addr))
return FALSE;
init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(tls_module_addr + sym->Address));
return TRUE;
}
static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base,
struct dbg_lvalue* lvalue, char* buffer, size_t sz)
{
......@@ -128,46 +165,11 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base,
}
else if (sym->Flags & SYMFLAG_TLSREL)
{
PROCESS_BASIC_INFORMATION pbi;
THREAD_BASIC_INFORMATION tbi;
DWORD_PTR addr;
PEB peb;
PEB_LDR_DATA ldr_data;
PLIST_ENTRY head, current;
LDR_DATA_TABLE_ENTRY ldr_module;
unsigned tlsindex = -1;
if (NtQueryInformationProcess(dbg_curr_process->handle, ProcessBasicInformation,
&pbi, sizeof(pbi), NULL) ||
NtQueryInformationThread(dbg_curr_thread->handle, ThreadBasicInformation,
&tbi, sizeof(tbi), NULL))
if (!fetch_tls_lvalue(sym, lvalue))
{
tls_error:
if (buffer) snprintf(buffer, sz, "Cannot read TLS address\n");
return FALSE;
}
addr = (DWORD_PTR)&(((TEB*)tbi.TebBaseAddress)->ThreadLocalStoragePointer);
if (!dbg_read_memory((void*)addr, &addr, sizeof(addr)) ||
!dbg_read_memory(pbi.PebBaseAddress, &peb, sizeof(peb)) ||
!dbg_read_memory(peb.LdrData, &ldr_data, sizeof(ldr_data)))
goto tls_error;
current = ldr_data.InLoadOrderModuleList.Flink;
head = &((PEB_LDR_DATA*)peb.LdrData)->InLoadOrderModuleList;
do
{
if (!dbg_read_memory(CONTAINING_RECORD(current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
&ldr_module, sizeof(ldr_module))) goto tls_error;
if ((DWORD_PTR)ldr_module.DllBase == sym->ModBase)
{
tlsindex = ldr_module.TlsIndex;
break;
}
current = ldr_module.InLoadOrderLinks.Flink;
} while (current != head);
addr += tlsindex * sizeof(DWORD_PTR);
if (!dbg_read_memory((void*)addr, &addr, sizeof(addr))) goto tls_error;
init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(addr + sym->Address));
}
else
{
......
......@@ -386,6 +386,8 @@ BOOL dbg_load_module(HANDLE hProc, HANDLE hFile, const WCHAR* name, DWORD_PTR ba
struct dbg_process* pcs = dbg_get_process_h(hProc);
struct dbg_module* mod;
IMAGEHLP_MODULEW64 info;
HANDLE hMap;
void* image;
if (!pcs) return FALSE;
mod = malloc(sizeof(struct dbg_module));
......@@ -398,6 +400,33 @@ BOOL dbg_load_module(HANDLE hProc, HANDLE hFile, const WCHAR* name, DWORD_PTR ba
mod->base = base;
list_add_head(&pcs->modules, &mod->entry);
mod->tls_index_offset = 0;
if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)))
{
if ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)))
{
IMAGE_NT_HEADERS* nth = RtlImageNtHeader(image);
const void* tlsdir;
ULONG sz;
tlsdir = RtlImageDirectoryEntryToData(image, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &sz);
switch (nth->OptionalHeader.Magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
if (tlsdir && sz >= sizeof(IMAGE_TLS_DIRECTORY32))
mod->tls_index_offset = (const char*)tlsdir - (const char*)image +
offsetof(IMAGE_TLS_DIRECTORY32, AddressOfIndex);
break;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
if (tlsdir && sz >= sizeof(IMAGE_TLS_DIRECTORY64))
mod->tls_index_offset = (const char*)tlsdir - (const char*)image +
offsetof(IMAGE_TLS_DIRECTORY64, AddressOfIndex);
break;
}
UnmapViewOfFile(image);
}
CloseHandle(hMap);
}
info.SizeOfStruct = sizeof(info);
if (SymGetModuleInfoW64(hProc, base, &info))
if (info.PdbUnmatched || info.DbgUnmatched)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment