From: Evan Tang etang@codeweavers.com
--- programs/winedbg/debugger.h | 19 ++++++-- programs/winedbg/symbol.c | 96 +++++-------------------------------- programs/winedbg/winedbg.c | 62 +++++++++++++++++++++++- 3 files changed, 88 insertions(+), 89 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 8e00770917c..7b2ed7da422 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -250,6 +250,7 @@ struct dbg_module { struct list entry; DWORD_PTR base; + DWORD_PTR tls_idx_addr_offset; };
struct dbg_delayed_bp @@ -542,16 +543,26 @@ extern void dbg_init_console(void); /* gdbproxy.c */ extern int gdb_main(int argc, char* argv[]);
-static inline BOOL dbg_read_memory(const void* addr, void* buffer, size_t len) +static inline BOOL dbg_read_process_memory(const struct dbg_process* p, const void* addr, void* buffer, size_t len) { SIZE_T rlen; - return dbg_curr_process->process_io->read(dbg_curr_process->handle, addr, buffer, len, &rlen) && len == rlen; + return p->process_io->read(p->handle, addr, buffer, len, &rlen) && len == rlen; }
-static inline BOOL dbg_write_memory(void* addr, const void* buffer, size_t len) +static inline BOOL dbg_read_memory(const void* addr, void* buffer, size_t len) +{ + return dbg_read_process_memory(dbg_curr_process, addr, buffer, len); +} + +static inline BOOL dbg_write_process_memory(const struct dbg_process* p, void* addr, const void* buffer, size_t len) { SIZE_T wlen; - return dbg_curr_process->process_io->write(dbg_curr_process->handle, addr, buffer, len, &wlen) && len == wlen; + return p->process_io->write(p->handle, addr, buffer, len, &wlen) && len == wlen; +} + +static inline BOOL dbg_write_memory(void* addr, const void* buffer, size_t len) +{ + return dbg_write_process_memory(dbg_curr_process, addr, buffer, len); }
struct data_model diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index 126c36163c0..14e8fea8761 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -61,51 +61,6 @@ static BOOL symbol_get_debug_start(const struct dbg_type* func, ULONG64* start) return FALSE; }
-static BOOL read_image_directory_data(ULONG64 modbase, WORD dir, void* buffer, size_t* size, BOOL* is_64) -{ - IMAGE_DOS_HEADER dos_header; - IMAGE_DATA_DIRECTORY entry; - DWORD_PTR addr; - union { IMAGE_NT_HEADERS32 h32; IMAGE_NT_HEADERS64 h64; } nt_header; - - addr = (DWORD_PTR)modbase; - if (!dbg_read_memory((void*)addr, &dos_header, sizeof(dos_header))) - return FALSE; - if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) - return FALSE; - addr = (DWORD_PTR)(modbase + dos_header.e_lfanew); - if (!dbg_read_memory((void*)addr, &nt_header, sizeof(nt_header))) - return FALSE; - if (nt_header.h32.Signature != IMAGE_NT_SIGNATURE) - return FALSE; - if (nt_header.h32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) - { - if (dir >= nt_header.h32.OptionalHeader.NumberOfRvaAndSizes) - return FALSE; - if (!(entry = nt_header.h32.OptionalHeader.DataDirectory[dir]).VirtualAddress) - return FALSE; - *is_64 = FALSE; - } - else if (nt_header.h64.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) - { - if (dir >= nt_header.h64.OptionalHeader.NumberOfRvaAndSizes) - return FALSE; - if (!(entry = nt_header.h64.OptionalHeader.DataDirectory[dir]).VirtualAddress) - return FALSE; - *is_64 = TRUE; - } - else - { - return FALSE; - } - if (entry.Size < *size) - *size = entry.Size; - addr = (DWORD_PTR)(modbase + entry.VirtualAddress); - if (!dbg_read_memory((void*)addr, buffer, *size)) - return FALSE; - return TRUE; -} - static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base, struct dbg_lvalue* lvalue, char* buffer, size_t sz) { @@ -173,56 +128,29 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base, } else if (sym->Flags & SYMFLAG_TLSREL) { - PROCESS_BASIC_INFORMATION pbi; + struct dbg_module* mod = dbg_get_module(dbg_curr_process, sym->ModBase); + union { ULONGLONG _64; DWORD _32; } tls_idx_addr_raw; + DWORD_PTR tls_idx_addr; THREAD_BASIC_INFORMATION tbi; - union { IMAGE_TLS_DIRECTORY32 dir32; IMAGE_TLS_DIRECTORY64 dir64; } tls; - size_t read_size = sizeof(tls); - BOOL is_dir64; 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 (!mod || !mod->tls_idx_addr_offset || + FAILED(NtQueryInformationThread(dbg_curr_thread->handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL))) { 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))) + if (!dbg_read_memory((void*)(mod->base + mod->tls_idx_addr_offset), &tls_idx_addr_raw, sizeof(tls_idx_addr_raw))) + goto tls_error; + if (!(tls_idx_addr = dbg_curr_process->be_cpu->pointer_size == 8 ? tls_idx_addr_raw._64 : tls_idx_addr_raw._32)) + goto tls_error; + if (!dbg_read_memory((void*)tls_idx_addr, &tlsindex, sizeof(tlsindex))) goto tls_error; - current = ldr_data.InLoadOrderModuleList.Flink; - head = &((PEB_LDR_DATA*)peb.LdrData)->InLoadOrderModuleList; - do - { - DWORD_PTR index_addr; - 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) - { - if (ldr_module.TlsIndex != -1) - goto tls_error; - if (!read_image_directory_data(sym->ModBase, IMAGE_DIRECTORY_ENTRY_TLS, &tls, &read_size, &is_dir64)) - goto tls_error; - if (read_size < (is_dir64 ? sizeof(IMAGE_TLS_DIRECTORY64) : sizeof(IMAGE_TLS_DIRECTORY32))) - goto tls_error; - index_addr = (DWORD_PTR)(is_dir64 ? tls.dir64.AddressOfIndex : tls.dir32.AddressOfIndex); - if (!dbg_read_memory((void*)index_addr, &tlsindex, sizeof(tlsindex))) - goto tls_error; - break; - } - current = ldr_module.InLoadOrderLinks.Flink; - } while (current != head);
- addr += tlsindex * sizeof(DWORD_PTR); + addr = (DWORD_PTR)&(((TEB*)tbi.TebBaseAddress)->ThreadLocalStoragePointer); + addr += tlsindex * dbg_curr_process->be_cpu->pointer_size; if (!dbg_read_memory((void*)addr, &addr, sizeof(addr))) goto tls_error; init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(addr + sym->Address)); } diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index ab2e94f5673..7fa83ab5ddc 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -442,14 +442,74 @@ void dbg_del_thread(struct dbg_thread* t) free(t); }
+static DWORD get_data_directory_addr(DWORD numberOfRvaAndSizes, const IMAGE_DATA_DIRECTORY* directory, DWORD index, DWORD requiredSize) +{ + if (index >= numberOfRvaAndSizes || directory[index].Size < requiredSize) + return 0; + return directory[index].VirtualAddress; +} + +#define GET_DATA_DIRECTORY_ADDR(optionalHeader, index, type) get_data_directory_addr((optionalHeader)->NumberOfRvaAndSizes, (optionalHeader)->DataDirectory, index, sizeof(type)) + +static BOOL try_read_pe_module(const struct dbg_process* p, struct dbg_module* mod) +{ + IMAGE_DOS_HEADER dos_header; + DWORD entry; + DWORD_PTR addr; + union { IMAGE_NT_HEADERS32 h32; IMAGE_NT_HEADERS64 h64; } nt_header; + + addr = mod->base; + if (!dbg_read_process_memory(p, (void*)addr, &dos_header, sizeof(dos_header))) + return FALSE; + if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) + return FALSE; + + addr += dos_header.e_lfanew; + if (!dbg_read_process_memory(p, (void*)addr, &nt_header, sizeof(nt_header))) + return FALSE; + if (nt_header.h32.Signature != IMAGE_NT_SIGNATURE) + return FALSE; + if (nt_header.h32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + IMAGE_OPTIONAL_HEADER32* opt_header = &nt_header.h32.OptionalHeader; + if (p->be_cpu->pointer_size != 4) + { + WINE_ERR("32-bit module in a %lu-bit process???\n", p->be_cpu->pointer_size * 8); + return FALSE; + } + + if ((entry = GET_DATA_DIRECTORY_ADDR(opt_header, IMAGE_DIRECTORY_ENTRY_TLS, IMAGE_TLS_DIRECTORY32))) + mod->tls_idx_addr_offset = entry + offsetof(IMAGE_TLS_DIRECTORY32, AddressOfIndex); + } + else if (nt_header.h32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + IMAGE_OPTIONAL_HEADER64* opt_header = &nt_header.h64.OptionalHeader; + if (p->be_cpu->pointer_size != 8) + { + WINE_ERR("64-bit module in a %lu-bit process???\n", p->be_cpu->pointer_size * 8); + return FALSE; + } + + if ((entry = GET_DATA_DIRECTORY_ADDR(opt_header, IMAGE_DIRECTORY_ENTRY_TLS, IMAGE_TLS_DIRECTORY64))) + mod->tls_idx_addr_offset = entry + offsetof(IMAGE_TLS_DIRECTORY64, AddressOfIndex); + } + else + { + return FALSE; + } + + return TRUE; +} + struct dbg_module* dbg_add_module(struct dbg_process* p, DWORD_PTR base) { - struct dbg_module* mod = malloc(sizeof(struct dbg_module)); + struct dbg_module* mod = calloc(1, sizeof(struct dbg_module));
if (!mod) return NULL;
mod->base = base; + try_read_pe_module(p, mod);
list_add_head(&p->modules, &mod->entry);