diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index d7e0cf39707..54ec4efdb7c 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -115,6 +115,24 @@ BOOL validate_addr64(DWORD64 addr) return TRUE; } +/****************************************************************** + * fetch_buffer + * + * Ensures process' internal buffer is large enough. + */ +void* fetch_buffer(struct process* pcs, unsigned size) +{ + if (size > pcs->buffer_size) + { + if (pcs->buffer) + pcs->buffer = HeapReAlloc(GetProcessHeap(), 0, pcs->buffer, size); + else + pcs->buffer = HeapAlloc(GetProcessHeap(), 0, size); + pcs->buffer_size = (pcs->buffer) ? size : 0; + } + return pcs->buffer; +} + /****************************************************************** * SymSetSearchPathW (DBGHELP.@) * diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index 7b3539705b6..3727474be26 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -70,7 +70,7 @@ @ stub SymGetHomeDirectoryW @ stdcall SymGetLineFromAddr(long long ptr ptr) @ stdcall SymGetLineFromAddr64(long double ptr ptr) -@ stub SymGetLineFromAddrW64 +@ stdcall SymGetLineFromAddrW64(long double ptr ptr) @ stub SymGetLineFromName @ stub SymGetLineFromName64 @ stdcall SymGetLineNext(long ptr) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index cfc9f92bafb..1abb2cc3ece 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -301,6 +301,9 @@ struct process unsigned long dbg_hdr_addr; IMAGEHLP_STACK_FRAME ctx_frame; + + unsigned buffer_size; + void* buffer; }; struct line_info @@ -327,6 +330,7 @@ extern struct process* process_find_by_handle(HANDLE hProcess); extern HANDLE hMsvcrt; extern BOOL validate_addr64(DWORD64 addr); extern BOOL pcs_callback(const struct process* pcs, ULONG action, void* data); +extern void* fetch_buffer(struct process* pcs, unsigned size); /* elf_module.c */ typedef BOOL (*elf_enum_modules_cb)(const char*, unsigned long addr, void* user); diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 1fb1c379a6b..e2a8754ac13 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1169,6 +1169,22 @@ static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32) l64->Address = l32->Address; } +/****************************************************************** + * copy_line_W64_from_32 (internal) + * + */ +static void copy_line_W64_from_32(struct process* pcs, IMAGEHLP_LINEW64* l64, const IMAGEHLP_LINE* l32) +{ + unsigned len; + + l64->Key = l32->Key; + l64->LineNumber = l32->LineNumber; + len = MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, NULL, 0); + if ((l64->FileName = fetch_buffer(pcs, len * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, l64->FileName, len); + l64->Address = l32->Address; +} + /****************************************************************** * copy_line_32_from_64 (internal) * @@ -1200,6 +1216,26 @@ BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, return TRUE; } +/****************************************************************** + * SymGetLineFromAddrW64 (DBGHELP.@) + * + */ +BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, + PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line) +{ + struct process* pcs = process_find_by_handle(hProcess); + IMAGEHLP_LINE line32; + + if (!pcs) return FALSE; + if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; + if (!validate_addr64(dwAddr)) return FALSE; + line32.SizeOfStruct = sizeof(line32); + if (!SymGetLineFromAddr(hProcess, (DWORD)dwAddr, pdwDisplacement, &line32)) + return FALSE; + copy_line_W64_from_32(pcs, Line, &line32); + return TRUE; +} + /****************************************************************** * SymGetLinePrev (DBGHELP.@) * diff --git a/include/dbghelp.h b/include/dbghelp.h index 79f97b3dd7f..03442b8bfaa 100644 --- a/include/dbghelp.h +++ b/include/dbghelp.h @@ -217,6 +217,15 @@ typedef struct _IMAGEHLP_LINE64 DWORD64 Address; } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; +typedef struct _IMAGEHLP_LINEW64 +{ + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PWCHAR FileName; + DWORD64 Address; +} IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64; + typedef struct _SOURCEFILE { DWORD64 ModBase; @@ -945,6 +954,7 @@ BOOL WINAPI SymEnumSourceFiles(HANDLE, ULONG64, PCSTR, PSYM_ENUMSOURCEFILES_CALL PVOID); BOOL WINAPI SymGetLineFromAddr(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE); BOOL WINAPI SymGetLineFromAddr64(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); +BOOL WINAPI SymGetLineFromAddrW64(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINEW64); BOOL WINAPI SymGetLinePrev(HANDLE, PIMAGEHLP_LINE); BOOL WINAPI SymGetLinePrev64(HANDLE, PIMAGEHLP_LINE64); BOOL WINAPI SymGetLineNext(HANDLE, PIMAGEHLP_LINE);