This serie mainly moves line information for top level function (not including the inlined parts) into the new PDB reader.
In details: - cleaning up current internal private structure for line information (in order to share it with PDB backend) - introduce methods to get line info from address, move to next/prev location, enumeration of line numbers and source files.
Note for source files enumeration: - current implementation still needs some more fixes (no full scoping, but that's unrelated to PDB rewrite) - fixes by module scoping - it still uses the global source hash table (as there isn't one in PDB). No plan to improve that for now.
From: Eric Pouech epouech@codeweavers.com
Used in next patches as the structure & helpers are going to be used in other CUs.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/symbol.c | 208 +++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 104 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 7edf11a19b9..52c284f2c1e 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1754,7 +1754,7 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symb return TRUE; }
-struct internal_line_t +struct lineinfo_t { BOOL unicode; PVOID key; @@ -1767,95 +1767,95 @@ struct internal_line_t DWORD64 address; };
-static void init_internal_line(struct internal_line_t* intl, BOOL unicode) +static void init_lineinfo(struct lineinfo_t* line_info, BOOL unicode) { - intl->unicode = unicode; - intl->key = NULL; - intl->line_number = 0; - intl->file_nameA = NULL; - intl->address = 0; + line_info->unicode = unicode; + line_info->key = NULL; + line_info->line_number = 0; + line_info->file_nameA = NULL; + line_info->address = 0; }
-static BOOL internal_line_copy_toA32(const struct internal_line_t* intl, IMAGEHLP_LINE* l32) +static BOOL lineinfo_copy_toA32(const struct lineinfo_t* line_info, IMAGEHLP_LINE* l32) { - if (intl->unicode) return FALSE; - l32->Key = intl->key; - l32->LineNumber = intl->line_number; - l32->FileName = intl->file_nameA; - l32->Address = intl->address; + if (line_info->unicode) return FALSE; + l32->Key = line_info->key; + l32->LineNumber = line_info->line_number; + l32->FileName = line_info->file_nameA; + l32->Address = line_info->address; return TRUE; }
-static BOOL internal_line_copy_toA64(const struct internal_line_t* intl, IMAGEHLP_LINE64* l64) +static BOOL lineinfo_copy_toA64(const struct lineinfo_t* line_info, IMAGEHLP_LINE64* l64) { - if (intl->unicode) return FALSE; - l64->Key = intl->key; - l64->LineNumber = intl->line_number; - l64->FileName = intl->file_nameA; - l64->Address = intl->address; + if (line_info->unicode) return FALSE; + l64->Key = line_info->key; + l64->LineNumber = line_info->line_number; + l64->FileName = line_info->file_nameA; + l64->Address = line_info->address; return TRUE; }
-static BOOL internal_line_copy_toW64(const struct internal_line_t* intl, IMAGEHLP_LINEW64* l64) +static BOOL lineinfo_copy_toW64(const struct lineinfo_t* line_info, IMAGEHLP_LINEW64* l64) { - if (!intl->unicode) return FALSE; - l64->Key = intl->key; - l64->LineNumber = intl->line_number; - l64->FileName = intl->file_nameW; - l64->Address = intl->address; + if (!line_info->unicode) return FALSE; + l64->Key = line_info->key; + l64->LineNumber = line_info->line_number; + l64->FileName = line_info->file_nameW; + l64->Address = line_info->address; return TRUE; }
-static BOOL internal_line_set_nameA(struct process* pcs, struct internal_line_t* intl, char* str, BOOL copy) +static BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info, char* str, BOOL copy) { DWORD len;
- if (intl->unicode) + if (line_info->unicode) { len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); - if (!(intl->file_nameW = fetch_buffer(pcs, len * sizeof(WCHAR)))) return FALSE; - MultiByteToWideChar(CP_ACP, 0, str, -1, intl->file_nameW, len); + if (!(line_info->file_nameW = fetch_buffer(pcs, len * sizeof(WCHAR)))) return FALSE; + MultiByteToWideChar(CP_ACP, 0, str, -1, line_info->file_nameW, len); } else { if (copy) { len = strlen(str) + 1; - if (!(intl->file_nameA = fetch_buffer(pcs, len))) return FALSE; - memcpy(intl->file_nameA, str, len); + if (!(line_info->file_nameA = fetch_buffer(pcs, len))) return FALSE; + memcpy(line_info->file_nameA, str, len); } else - intl->file_nameA = str; + line_info->file_nameA = str; } return TRUE; }
-static BOOL internal_line_set_nameW(struct process* pcs, struct internal_line_t* intl, WCHAR* wstr, BOOL copy) +static BOOL lineinfo_set_nameW(struct process* pcs, struct lineinfo_t* line_info, WCHAR* wstr, BOOL copy) { DWORD len;
- if (intl->unicode) + if (line_info->unicode) { if (copy) { len = (lstrlenW(wstr) + 1) * sizeof(WCHAR); - if (!(intl->file_nameW = fetch_buffer(pcs, len))) return FALSE; - memcpy(intl->file_nameW, wstr, len); + if (!(line_info->file_nameW = fetch_buffer(pcs, len))) return FALSE; + memcpy(line_info->file_nameW, wstr, len); } else - intl->file_nameW = wstr; + line_info->file_nameW = wstr; } else { DWORD len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); - if (!(intl->file_nameA = fetch_buffer(pcs, len))) return FALSE; - WideCharToMultiByte(CP_ACP, 0, wstr, -1, intl->file_nameA, len, NULL, NULL); + if (!(line_info->file_nameA = fetch_buffer(pcs, len))) return FALSE; + WideCharToMultiByte(CP_ACP, 0, wstr, -1, line_info->file_nameA, len, NULL, NULL); } return TRUE; }
static BOOL get_line_from_function(struct module_pair* pair, struct symt_function* func, DWORD64 addr, - PDWORD pdwDisplacement, struct internal_line_t* intl) + PDWORD pdwDisplacement, struct lineinfo_t* line_info) { struct line_info* dli = NULL; struct line_info* found_dli = NULL; @@ -1867,9 +1867,9 @@ static BOOL get_line_from_function(struct module_pair* pair, struct symt_functio if (!dli->is_source_file) { if (found_dli || dli->u.address > addr) continue; - intl->line_number = dli->line_number; - intl->address = dli->u.address; - intl->key = dli; + line_info->line_number = dli->line_number; + line_info->address = dli->u.address; + line_info->key = dli; found_dli = dli; continue; } @@ -1879,12 +1879,12 @@ static BOOL get_line_from_function(struct module_pair* pair, struct symt_functio if (dbghelp_opt_source_actual_path) { /* Return native file paths when using winedbg */ - ret = internal_line_set_nameA(pair->pcs, intl, (char*)source_get(pair->effective, dli->u.source_file), FALSE); + ret = lineinfo_set_nameA(pair->pcs, line_info, (char*)source_get(pair->effective, dli->u.source_file), FALSE); } else { WCHAR *dospath = wine_get_dos_file_name(source_get(pair->effective, dli->u.source_file)); - ret = internal_line_set_nameW(pair->pcs, intl, dospath, TRUE); + ret = lineinfo_set_nameW(pair->pcs, line_info, dospath, TRUE); HeapFree( GetProcessHeap(), 0, dospath ); } if (ret && pdwDisplacement) *pdwDisplacement = addr - found_dli->u.address; @@ -1900,7 +1900,7 @@ static BOOL get_line_from_function(struct module_pair* pair, struct symt_functio * fills source file information from an address */ static BOOL get_line_from_addr(HANDLE hProcess, DWORD64 addr, - PDWORD pdwDisplacement, struct internal_line_t* intl) + PDWORD pdwDisplacement, struct lineinfo_t* line_info) { struct module_pair pair; struct symt_ht* symt; @@ -1909,7 +1909,7 @@ static BOOL get_line_from_addr(HANDLE hProcess, DWORD64 addr, symt = symt_find_symbol_at(pair.effective, addr);
if (!symt_check_tag(&symt->symt, SymTagFunction)) return FALSE; - return get_line_from_function(&pair, (struct symt_function*)symt, addr, pdwDisplacement, intl); + return get_line_from_function(&pair, (struct symt_function*)symt, addr, pdwDisplacement, line_info); }
/*********************************************************************** @@ -1965,14 +1965,14 @@ BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol) BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &intl)) return FALSE; - return internal_line_copy_toA32(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &line_info)) return FALSE; + return lineinfo_copy_toA32(&line_info, Line); }
/****************************************************************** @@ -1982,14 +1982,14 @@ BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &intl)) return FALSE; - return internal_line_copy_toA64(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &line_info)) return FALSE; + return lineinfo_copy_toA64(&line_info, Line); }
/****************************************************************** @@ -1999,17 +1999,17 @@ BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, TRUE); - if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &intl)) return FALSE; - return internal_line_copy_toW64(&intl, Line); + init_lineinfo(&line_info, TRUE); + if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &line_info)) return FALSE; + return lineinfo_copy_toW64(&line_info, Line); }
-static BOOL symt_get_func_line_prev(HANDLE hProcess, struct internal_line_t* intl, void* key, DWORD64 addr) +static BOOL symt_get_func_line_prev(HANDLE hProcess, struct lineinfo_t* line_info, void* key, DWORD64 addr) { struct module_pair pair; struct line_info* li; @@ -2026,13 +2026,13 @@ static BOOL symt_get_func_line_prev(HANDLE hProcess, struct internal_line_t* int li--; if (!li->is_source_file) { - intl->line_number = li->line_number; - intl->address = li->u.address; - intl->key = li; + line_info->line_number = li->line_number; + line_info->address = li->u.address; + line_info->key = li; /* search source file */ for (srcli = li; !srcli->is_source_file; srcli--);
- return internal_line_set_nameA(pair.pcs, intl, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); + return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); } } SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ @@ -2045,14 +2045,14 @@ static BOOL symt_get_func_line_prev(HANDLE hProcess, struct internal_line_t* int */ BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!symt_get_func_line_prev(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toA64(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!symt_get_func_line_prev(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toA64(&line_info, Line); }
/****************************************************************** @@ -2061,14 +2061,14 @@ BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) */ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!symt_get_func_line_prev(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toA32(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!symt_get_func_line_prev(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toA32(&line_info, Line); }
/****************************************************************** @@ -2077,17 +2077,17 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) */ BOOL WINAPI SymGetLinePrevW64(HANDLE hProcess, PIMAGEHLP_LINEW64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, TRUE); - if (!symt_get_func_line_prev(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toW64(&intl, Line); + init_lineinfo(&line_info, TRUE); + if (!symt_get_func_line_prev(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toW64(&line_info, Line); }
-static BOOL symt_get_func_line_next(HANDLE hProcess, struct internal_line_t* intl, void* key, DWORD64 addr) +static BOOL symt_get_func_line_next(HANDLE hProcess, struct lineinfo_t* line_info, void* key, DWORD64 addr) { struct module_pair pair; struct line_info* li; @@ -2105,10 +2105,10 @@ static BOOL symt_get_func_line_next(HANDLE hProcess, struct internal_line_t* int li++; if (!li->is_source_file) { - intl->line_number = li->line_number; - intl->address = li->u.address; - intl->key = li; - return internal_line_set_nameA(pair.pcs, intl, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); + line_info->line_number = li->line_number; + line_info->address = li->u.address; + line_info->key = li; + return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); } srcli = li; } @@ -2122,14 +2122,14 @@ static BOOL symt_get_func_line_next(HANDLE hProcess, struct internal_line_t* int */ BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!symt_get_func_line_next(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toA64(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!symt_get_func_line_next(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toA64(&line_info, Line); }
/****************************************************************** @@ -2138,14 +2138,14 @@ BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) */ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, FALSE); - if (!symt_get_func_line_next(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toA32(&intl, Line); + init_lineinfo(&line_info, FALSE); + if (!symt_get_func_line_next(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toA32(&line_info, Line); }
/****************************************************************** @@ -2154,14 +2154,14 @@ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line) */ BOOL WINAPI SymGetLineNextW64(HANDLE hProcess, PIMAGEHLP_LINEW64 Line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - init_internal_line(&intl, TRUE); - if (!symt_get_func_line_next(hProcess, &intl, Line->Key, Line->Address)) return FALSE; - return internal_line_copy_toW64(&intl, Line); + init_lineinfo(&line_info, TRUE); + if (!symt_get_func_line_next(hProcess, &line_info, Line->Key, Line->Address)) return FALSE; + return lineinfo_copy_toW64(&line_info, Line); }
/*********************************************************************** @@ -2727,7 +2727,7 @@ BOOL WINAPI SymFromInlineContextW(HANDLE hProcess, DWORD64 addr, ULONG inline_ct }
static BOOL get_line_from_inline_context(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, - struct internal_line_t* intl) + struct lineinfo_t* line_info) { struct module_pair pair; struct symt_function* inlined; @@ -2737,12 +2737,12 @@ static BOOL get_line_from_inline_context(HANDLE hProcess, DWORD64 addr, ULONG in { case IFC_MODE_INLINE: inlined = symt_find_inlined_site(pair.effective, addr, inline_ctx); - if (inlined && get_line_from_function(&pair, inlined, addr, disp, intl)) + if (inlined && get_line_from_function(&pair, inlined, addr, disp, line_info)) return TRUE; /* fall through: check if we can find line info at top function level */ case IFC_MODE_IGNORE: case IFC_MODE_REGULAR: - return get_line_from_addr(hProcess, addr, disp, intl); + return get_line_from_addr(hProcess, addr, disp, line_info); default: SetLastError(ERROR_INVALID_PARAMETER); return FALSE; @@ -2755,16 +2755,16 @@ static BOOL get_line_from_inline_context(HANDLE hProcess, DWORD64 addr, ULONG in */ BOOL WINAPI SymGetLineFromInlineContext(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, PIMAGEHLP_LINE64 line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p, %#I64x, 0x%lx, %#I64x, %p, %p)\n", hProcess, addr, inline_ctx, mod_addr, disp, line);
if (line->SizeOfStruct < sizeof(*line)) return FALSE; - init_internal_line(&intl, FALSE); + init_lineinfo(&line_info, FALSE);
- if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &intl)) return FALSE; - return internal_line_copy_toA64(&intl, line); + if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &line_info)) return FALSE; + return lineinfo_copy_toA64(&line_info, line); }
/****************************************************************** @@ -2773,16 +2773,16 @@ BOOL WINAPI SymGetLineFromInlineContext(HANDLE hProcess, DWORD64 addr, ULONG inl */ BOOL WINAPI SymGetLineFromInlineContextW(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, PIMAGEHLP_LINEW64 line) { - struct internal_line_t intl; + struct lineinfo_t line_info;
TRACE("(%p, %#I64x, 0x%lx, %#I64x, %p, %p)\n", hProcess, addr, inline_ctx, mod_addr, disp, line);
if (line->SizeOfStruct < sizeof(*line)) return FALSE; - init_internal_line(&intl, TRUE); + init_lineinfo(&line_info, TRUE);
- if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &intl)) return FALSE; - return internal_line_copy_toW64(&intl, line); + if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &line_info)) return FALSE; + return lineinfo_copy_toW64(&line_info, line); }
/******************************************************************
From: Eric Pouech epouech@codeweavers.com
Note: we were using string stored in source hash tree in line information. Better always copy into the internal buffer to avoid dbghelp caller to temper with internal data.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/symbol.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 52c284f2c1e..70b20b073bb 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1806,7 +1806,7 @@ static BOOL lineinfo_copy_toW64(const struct lineinfo_t* line_info, IMAGEHLP_LIN return TRUE; }
-static BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info, char* str, BOOL copy) +static BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info, char* str) { DWORD len;
@@ -1818,32 +1818,22 @@ static BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info } else { - if (copy) - { - len = strlen(str) + 1; - if (!(line_info->file_nameA = fetch_buffer(pcs, len))) return FALSE; - memcpy(line_info->file_nameA, str, len); - } - else - line_info->file_nameA = str; + len = strlen(str) + 1; + if (!(line_info->file_nameA = fetch_buffer(pcs, len))) return FALSE; + memcpy(line_info->file_nameA, str, len); } return TRUE; }
-static BOOL lineinfo_set_nameW(struct process* pcs, struct lineinfo_t* line_info, WCHAR* wstr, BOOL copy) +static BOOL lineinfo_set_nameW(struct process* pcs, struct lineinfo_t* line_info, WCHAR* wstr) { DWORD len;
if (line_info->unicode) { - if (copy) - { - len = (lstrlenW(wstr) + 1) * sizeof(WCHAR); - if (!(line_info->file_nameW = fetch_buffer(pcs, len))) return FALSE; - memcpy(line_info->file_nameW, wstr, len); - } - else - line_info->file_nameW = wstr; + len = (lstrlenW(wstr) + 1) * sizeof(WCHAR); + if (!(line_info->file_nameW = fetch_buffer(pcs, len))) return FALSE; + memcpy(line_info->file_nameW, wstr, len); } else { @@ -1879,12 +1869,12 @@ static BOOL get_line_from_function(struct module_pair* pair, struct symt_functio if (dbghelp_opt_source_actual_path) { /* Return native file paths when using winedbg */ - ret = lineinfo_set_nameA(pair->pcs, line_info, (char*)source_get(pair->effective, dli->u.source_file), FALSE); + ret = lineinfo_set_nameA(pair->pcs, line_info, (char*)source_get(pair->effective, dli->u.source_file)); } else { WCHAR *dospath = wine_get_dos_file_name(source_get(pair->effective, dli->u.source_file)); - ret = lineinfo_set_nameW(pair->pcs, line_info, dospath, TRUE); + ret = lineinfo_set_nameW(pair->pcs, line_info, dospath); HeapFree( GetProcessHeap(), 0, dospath ); } if (ret && pdwDisplacement) *pdwDisplacement = addr - found_dli->u.address; @@ -2032,7 +2022,7 @@ static BOOL symt_get_func_line_prev(HANDLE hProcess, struct lineinfo_t* line_inf /* search source file */ for (srcli = li; !srcli->is_source_file; srcli--);
- return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); + return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file)); } } SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ @@ -2108,7 +2098,7 @@ static BOOL symt_get_func_line_next(HANDLE hProcess, struct lineinfo_t* line_inf line_info->line_number = li->line_number; line_info->address = li->u.address; line_info->key = li; - return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); + return lineinfo_set_nameA(pair.pcs, line_info, (char*)source_get(pair.effective, srcli->u.source_file)); } srcli = li; }
From: Eric Pouech epouech@codeweavers.com
Introduce two new module_format methods: - source_info_search_by_addr - source_info_advance And move the current line info from vector inside SymTagFunction into it for new PDB reader.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 20 +- dlls/dbghelp/msc.c | 6 +- dlls/dbghelp/pdb.c | 332 ++++++++++++++++++++++++++++++++- dlls/dbghelp/symbol.c | 67 ++++--- 4 files changed, 393 insertions(+), 32 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index fb55e4c89f7..4fc11b322af 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -414,7 +414,21 @@ enum format_info DFI_LAST };
+struct lineinfo_t +{ + BOOL unicode; + PVOID key; + DWORD line_number; + union + { + CHAR* file_nameA; + WCHAR* file_nameW; + }; + DWORD64 address; +}; + struct module_format; +enum method_result {MR_SUCCESS, MR_FAILURE, MR_NOT_FOUND}; struct module_format_vtable { /* module handling */ @@ -423,6 +437,9 @@ struct module_format_vtable void (*loc_compute)(const struct module_format* modfmt, const struct symt_function* func, struct location* loc); + /* line information */ + enum method_result (*get_line_from_address)(struct module_format *modfmt, + DWORD64 address, struct lineinfo_t *line_info); };
struct module_format @@ -941,6 +958,7 @@ extern DWORD symt_ptr2index(struct module* module, const struct symt* sym extern struct symt_custom* symt_new_custom(struct module* module, const char* name, DWORD64 addr, DWORD size); +extern BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* intl, char* str);
/* type.c */ extern void symt_init_basic(struct module* module); @@ -1026,4 +1044,4 @@ extern BOOL pdb_old_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, struct pdb_reader; extern BOOL pdb_hack_get_main_info(struct module_format *modfmt, struct pdb_reader **pdb, unsigned *fpoext_stream); extern void pdb_reader_dispose(struct pdb_reader *pdb); -extern struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file); +extern struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections); diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index db06b186edb..5fd0b28894e 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3815,7 +3815,7 @@ static BOOL pdb_process_internal(const struct process *pcs, pdb_file->pdb_reader = NULL; CloseHandle(hFile); } - else if (!(pdb_file->pdb_reader = pdb_hack_reader_init(msc_dbg->module, hFile))) + else if (!(pdb_file->pdb_reader = pdb_hack_reader_init(msc_dbg->module, hFile, msc_dbg->sectp, msc_dbg->nsect))) { CloseHandle(hFile); UnmapViewOfFile(image); @@ -3971,7 +3971,7 @@ static BOOL pdb_process_internal(const struct process *pcs, return TRUE; }
-static const struct module_format_vtable pdb_module_format_vtable = +static const struct module_format_vtable old_pdb_module_format_vtable = { pdb_module_remove, pdb_location_compute, @@ -3996,7 +3996,7 @@ static BOOL pdb_process_file(const struct process *pcs, pdb_module_info = (void*)(modfmt + 1); msc_dbg->module->format_info[DFI_PDB] = modfmt; modfmt->module = msc_dbg->module; - modfmt->vtable = &pdb_module_format_vtable; + modfmt->vtable = &old_pdb_module_format_vtable; modfmt->u.pdb_info = pdb_module_info;
memset(cv_zmodules, 0, sizeof(cv_zmodules)); diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 7948dfd5f0b..994cae3c0e8 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -84,6 +84,12 @@ struct pdb_reader } *streams; char *stream_names;
+ /* cache PE module sections for mapping... + * we should rather use pe_module information + */ + const IMAGE_SECTION_HEADER *sections; + unsigned num_sections; + pdb_reader_fetch_t fetch; };
@@ -94,6 +100,8 @@ enum pdb_result R_PDB_OUT_OF_MEMORY, R_PDB_INVALID_ARGUMENT, R_PDB_INVALID_PDB_FILE, + R_PDB_MISSING_INFORMATION, + R_PDB_NOT_FOUND, R_PDB_BUFFER_TOO_SMALL, };
@@ -108,6 +116,14 @@ static enum pdb_result pdb_reader_fetch_file(struct pdb_reader *pdb, void *buffe static const char PDB_JG_IDENT[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0"; static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
+static enum pdb_result pdb_reader_get_segment_address(struct pdb_reader *pdb, unsigned segment, unsigned offset, DWORD64 *address) +{ + if (!segment || segment > pdb->num_sections) return R_PDB_INVALID_PDB_FILE; + *address = pdb->module->module.BaseOfImage + + pdb->sections[segment - 1].VirtualAddress + offset; + return R_PDB_SUCCESS; +} + static inline enum pdb_result pdb_reader_alloc(struct pdb_reader *pdb, size_t size, void **ptr) { return (*ptr = pool_alloc(&pdb->pool, size)) ? R_PDB_SUCCESS : R_PDB_OUT_OF_MEMORY; @@ -267,6 +283,7 @@ failure: void pdb_reader_dispose(struct pdb_reader *pdb) { CloseHandle(pdb->file); + /* note: pdb is allocated inside its pool, so this must be last line */ pool_destroy(&pdb->pool); }
@@ -274,9 +291,12 @@ static enum pdb_result pdb_reader_internal_read_advance(struct pdb_reader *pdb, void *buffer, pdbsize_t size) { pdbsize_t num_read; - enum pdb_result result = pdb_reader_read_from_stream(pdb, walker, buffer, size, &num_read); + enum pdb_result result; + + if (walker->offset + size > walker->last) return R_PDB_INVALID_ARGUMENT; + result = pdb_reader_read_from_stream(pdb, walker, buffer, size, &num_read); if (result) return result; - if (num_read != size) return R_PDB_INVALID_ARGUMENT; + if (num_read != size) return R_PDB_IOERROR; walker->offset += size; return R_PDB_SUCCESS; } @@ -306,6 +326,8 @@ static enum pdb_result pdb_reader_fetch_string_from_stream(struct pdb_reader *pd pdbsize_t num_read; char *zero;
+ if (walker->offset + length > walker->last) + length = walker->last - walker->offset; if ((result = pdb_reader_read_from_stream(pdb, walker, buffer, length, &num_read))) return result; if (!(zero = memchr(buffer, '\0', num_read))) @@ -330,7 +352,7 @@ static enum pdb_result pdb_reader_load_stream_name_table(struct pdb_reader *pdb) if (ds_root.Version != 20000404) { ERR("-Unknown root block version %u\n", ds_root.Version); - return R_PDB_INVALID_ARGUMENT; + return R_PDB_INVALID_PDB_FILE; }
if ((result = pdb_reader_alloc_and_read(pdb, &walker, ds_root.cbNames, (void**)&pdb->stream_names))) @@ -388,7 +410,7 @@ static enum pdb_result pdb_reader_get_stream_index_from_name(struct pdb_reader * *stream_id = i; return R_PDB_SUCCESS; } - return R_PDB_INVALID_ARGUMENT; + return R_PDB_NOT_FOUND; }
static enum pdb_result pdb_reader_alloc_and_fetch_string(struct pdb_reader *pdb, struct pdb_reader_walker *walker, char **string) @@ -420,6 +442,19 @@ static enum pdb_result pdb_reader_alloc_and_fetch_string(struct pdb_reader *pdb, } }
+static enum pdb_result pdb_reader_skip_string(struct pdb_reader *pdb, struct pdb_reader_walker *walker) +{ + char tmp[256]; + enum pdb_result result; + + while ((result = pdb_reader_fetch_string_from_stream(pdb, walker, tmp, ARRAY_SIZE(tmp)))) + { + if (result != R_PDB_BUFFER_TOO_SMALL) break; + walker->offset += ARRAY_SIZE(tmp); + } + return result; +} + static enum pdb_result pdb_reader_alloc_and_fetch_global_string(struct pdb_reader *pdb, pdbsize_t str_offset, char **buffer) { enum pdb_result result; @@ -433,10 +468,293 @@ static enum pdb_result pdb_reader_alloc_and_fetch_global_string(struct pdb_reade return pdb_reader_alloc_and_fetch_string(pdb, &walker, buffer); }
-struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file) +static enum pdb_result pdb_reader_read_DBI_header(struct pdb_reader* pdb, PDB_SYMBOLS *dbi_header, struct pdb_reader_walker *walker) +{ + enum pdb_result result; + + /* assuming we always have that size (even for old format) in stream */ + if ((result = pdb_reader_walker_init(pdb, 3, walker)) || + (result = pdb_reader_READ(pdb, walker, dbi_header))) return result; + if (dbi_header->signature != 0xffffffff) + { + /* Old version of the symbols record header */ + PDB_SYMBOLS_OLD old_dbi_header = *(const PDB_SYMBOLS_OLD*)dbi_header; + + dbi_header->version = 0; + dbi_header->module_size = old_dbi_header.module_size; + dbi_header->sectcontrib_size = old_dbi_header.sectcontrib_size; + dbi_header->segmap_size = old_dbi_header.segmap_size; + dbi_header->srcmodule_size = old_dbi_header.srcmodule_size; + dbi_header->pdbimport_size = 0; + dbi_header->global_hash_stream = old_dbi_header.global_hash_stream; + dbi_header->public_stream = old_dbi_header.public_stream; + dbi_header->gsym_stream = old_dbi_header.gsym_stream; + + walker->offset = sizeof(PDB_SYMBOLS_OLD); + } + + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_read_DBI_cu_header(struct pdb_reader* pdb, DWORD dbi_header_version, + struct pdb_reader_walker *walker, + PDB_SYMBOL_FILE_EX *dbi_cu_header) +{ + enum pdb_result result; + + if (dbi_header_version >= 19970000) + { + result = pdb_reader_READ(pdb, walker, dbi_cu_header); + } + else + { + PDB_SYMBOL_FILE old_dbi_cu_header; + if (!(result = pdb_reader_READ(pdb, walker, &old_dbi_cu_header))) + { + memset(dbi_cu_header, 0, sizeof(*dbi_cu_header)); + dbi_cu_header->stream = old_dbi_cu_header.stream; + dbi_cu_header->range.index = old_dbi_cu_header.range.index; + dbi_cu_header->symbol_size = old_dbi_cu_header.symbol_size; + dbi_cu_header->lineno_size = old_dbi_cu_header.lineno_size; + dbi_cu_header->lineno2_size = old_dbi_cu_header.lineno2_size; + } + } + return result; +} + +struct pdb_reader_compiland_iterator +{ + struct pdb_reader_walker dbi_walker; /* in DBI stream */ + PDB_SYMBOLS dbi_header; + PDB_SYMBOL_FILE_EX dbi_cu_header; +}; + +static enum pdb_result pdb_reader_compiland_iterator_init(struct pdb_reader *pdb, struct pdb_reader_compiland_iterator *iter) { - struct pdb_reader *pdb = pool_alloc(&module->pool, sizeof(*pdb)); - if (pdb && pdb_reader_init(pdb, module, file) == R_PDB_SUCCESS) return pdb; + enum pdb_result result; + if ((result = pdb_reader_read_DBI_header(pdb, &iter->dbi_header, &iter->dbi_walker))) return result; + iter->dbi_walker.last = iter->dbi_walker.offset + iter->dbi_header.module_size; + return pdb_reader_read_DBI_cu_header(pdb, iter->dbi_header.version, &iter->dbi_walker, &iter->dbi_cu_header); +} + +static enum pdb_result pdb_reader_compiland_iterator_next(struct pdb_reader *pdb, struct pdb_reader_compiland_iterator *iter) +{ + enum pdb_result result; + + if ((result = pdb_reader_skip_string(pdb, &iter->dbi_walker)) || + (result = pdb_reader_skip_string(pdb, &iter->dbi_walker))) + { + return result; + } + iter->dbi_walker.offset = (iter->dbi_walker.offset + 3) & ~3u; + return pdb_reader_read_DBI_cu_header(pdb, iter->dbi_header.version, &iter->dbi_walker, &iter->dbi_cu_header); +} + +static enum pdb_result pdb_reader_subsection_next(struct pdb_reader *pdb, struct pdb_reader_walker *in_walker, + enum DEBUG_S_SUBSECTION_TYPE subsection_type, + struct pdb_reader_walker *sub_walker) +{ + enum pdb_result result; + struct CV_DebugSSubsectionHeader_t hdr; + + for (; !(result = pdb_reader_READ(pdb, in_walker, &hdr)); in_walker->offset += hdr.cbLen) + { + if (hdr.type & DEBUG_S_IGNORE) continue; + if (subsection_type && hdr.type != subsection_type) continue; + *sub_walker = *in_walker; + sub_walker->last = sub_walker->offset + hdr.cbLen; + in_walker->offset += hdr.cbLen; + return R_PDB_SUCCESS; + } + return result && result != R_PDB_INVALID_ARGUMENT ? result : R_PDB_NOT_FOUND; +} + +struct pdb_reader_linetab2_location +{ + pdbsize_t dbi_cu_header_offset; /* in DBI stream */ + unsigned cu_stream_id; /* compilation unit stream id */ + pdbsize_t lines_hdr_offset; /* in cu_stream_id */ + pdbsize_t file_hdr_offset; /* in cu_stream_id (inside lines block) */ + pdbsize_t filename_offset; /* in global stream table (after S_FILECHKSUMS redirection) */ +}; + +static enum pdb_result pdb_find_matching_linetab2(struct CV_Line_t *lines, unsigned num_lines, DWORD64 delta, unsigned *index) +{ + unsigned i; + for (i = 0; i + 1 < num_lines; i++) + { + unsigned j; + for (j = i + 1; j < num_lines; j++) + if (lines[j].offset != lines[i].offset) break; + if (j >= num_lines) break; + if (delta < lines[j].offset) + { + *index = i; + return R_PDB_SUCCESS; + } + } + /* since the the address is inside the file_hdr, we assume then it's matched by last entry + * (for which we don't have the next entry) + */ + *index = num_lines - 1; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_walker_init_linetab2(struct pdb_reader *pdb, const PDB_SYMBOL_FILE_EX *dbi_cu_header, struct pdb_reader_walker *walker) +{ + walker->stream_id = dbi_cu_header->stream; + walker->offset = dbi_cu_header->symbol_size; + walker->last = walker->offset + dbi_cu_header->lineno2_size; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_locate_filehdr_in_linetab2(struct pdb_reader *pdb, struct pdb_reader_walker linetab2_walker, + DWORD64 address, DWORD64 *lineblk_base, + struct CV_DebugSLinesFileBlockHeader_t *files_hdr, struct CV_Line_t **lines) +{ + struct pdb_reader_walker sub_walker; + enum pdb_result result; + struct CV_DebugSLinesHeader_t lines_hdr; + + while (!(result = pdb_reader_subsection_next(pdb, &linetab2_walker, DEBUG_S_LINES, &sub_walker))) + { + /* Skip blocks that are too small - Intel C Compiler generates these. */ + if (sub_walker.offset + sizeof(lines_hdr) + sizeof(struct CV_DebugSLinesFileBlockHeader_t) > sub_walker.last) + continue; + if ((result = pdb_reader_READ(pdb, &sub_walker, &lines_hdr))) return result; + if ((result = pdb_reader_get_segment_address(pdb, lines_hdr.segCon, lines_hdr.offCon, lineblk_base))) + return result; + if (*lineblk_base > address || address >= *lineblk_base + lines_hdr.cbCon) + continue; + if ((result = pdb_reader_READ(pdb, &sub_walker, files_hdr))) return result; + return pdb_reader_alloc_and_read(pdb, &sub_walker, files_hdr->nLines * sizeof((*lines)[0]),(void**)lines); + /* + if (lines_hdr.flags & CV_LINES_HAVE_COLUMNS) + sub_walker.offset += files_hdr.nLines * sizeof(struct CV_Column_t); + */ + } + return R_PDB_NOT_FOUND; +} + +static enum pdb_result pdb_reader_set_lineinfo_filename(struct pdb_reader *pdb, struct pdb_reader_walker linetab2_walker, + unsigned file_offset, struct lineinfo_t *line_info) +{ + struct pdb_reader_walker checksum_walker; + struct CV_Checksum_t checksum; + enum pdb_result result; + char *string; + + if ((result = pdb_reader_subsection_next(pdb, &linetab2_walker, DEBUG_S_FILECHKSMS, &checksum_walker))) + { + WARN("No DEBUG_S_FILECHKSMS found\n"); + return R_PDB_MISSING_INFORMATION; + } + checksum_walker.offset += file_offset; + if ((result = pdb_reader_READ(pdb, &checksum_walker, &checksum))) return result; + if ((result = pdb_reader_alloc_and_fetch_global_string(pdb, checksum.strOffset, &string))) return result; + if (!lineinfo_set_nameA(pdb->module->process, line_info, string)) + result = R_PDB_OUT_OF_MEMORY; + pdb_reader_free(pdb, string); + return result; +} + +static enum pdb_result pdb_reader_search_linetab2(struct pdb_reader *pdb, const PDB_SYMBOL_FILE_EX *dbi_cu_header, + DWORD64 address, struct lineinfo_t *line_info) +{ + struct pdb_reader_walker linetab2_walker; + struct CV_DebugSLinesFileBlockHeader_t files_hdr; + enum pdb_result result; + DWORD64 lineblk_base; + struct CV_Line_t *lines; + + if ((result = pdb_reader_walker_init_linetab2(pdb, dbi_cu_header, &linetab2_walker))) return result; + + if (!pdb_reader_locate_filehdr_in_linetab2(pdb, linetab2_walker, address, &lineblk_base, &files_hdr, &lines)) + { + unsigned i; + + if (!pdb_find_matching_linetab2(lines, files_hdr.nLines, address - lineblk_base, &i)) + { + /* found block... */ + line_info->address = lineblk_base + lines[i].offset; + line_info->line_number = lines[i].linenumStart; + return pdb_reader_set_lineinfo_filename(pdb, linetab2_walker, files_hdr.offFile, line_info); + } + pdb_reader_free(pdb, lines); + } + return R_PDB_NOT_FOUND; +} + +static enum pdb_result pdb_reader_get_line_from_address_internal(struct pdb_reader *pdb, + DWORD64 address, struct lineinfo_t *line_info, + pdbsize_t *compiland_offset) +{ + enum pdb_result result; + struct pdb_reader_compiland_iterator compiland_iter; + + if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; + do + { + if (compiland_iter.dbi_cu_header.lineno2_size) + { + result = pdb_reader_search_linetab2(pdb, &compiland_iter.dbi_cu_header, address, line_info); + if (!result) + { + *compiland_offset = compiland_iter.dbi_walker.offset - sizeof(compiland_iter.dbi_cu_header); + return result; + } + if (result != R_PDB_NOT_FOUND) return result; + } + } while (pdb_reader_compiland_iterator_next(pdb, &compiland_iter) == R_PDB_SUCCESS); + + return R_PDB_NOT_FOUND; +} + +static enum method_result pdb_method_result(enum pdb_result result) +{ + switch (result) + { + case R_PDB_SUCCESS: return MR_SUCCESS; + case R_PDB_NOT_FOUND: return MR_NOT_FOUND; + default: return MR_FAILURE; + } +} + +static enum method_result pdb_method_get_line_from_address(struct module_format *modfmt, + DWORD64 address, struct lineinfo_t *line_info) +{ + enum pdb_result result; + struct pdb_reader *pdb; + pdbsize_t compiland_offset; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + result = pdb_reader_get_line_from_address_internal(pdb, address, line_info, &compiland_offset); + return pdb_method_result(result); +} + +static struct module_format_vtable pdb_module_format_vtable = +{ + NULL,/*pdb_module_remove*/ + NULL,/*pdb_location_compute*/ + pdb_method_get_line_from_address, +}; + +struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections) +{ + struct pdb_reader *pdb = pool_alloc(&module->pool, sizeof(*pdb) + num_sections * sizeof(*sections)); + if (pdb && pdb_reader_init(pdb, module, file) == R_PDB_SUCCESS) + { + pdb->sections = (void*)(pdb + 1); + memcpy((void *)pdb->sections, sections, num_sections * sizeof(*sections)); + pdb->num_sections = num_sections; + pdb->module = module; + /* hack (copy old pdb methods until they are moved here) */ + pdb_module_format_vtable.remove = module->format_info[DFI_PDB]->vtable->remove; + pdb_module_format_vtable.loc_compute = module->format_info[DFI_PDB]->vtable->loc_compute; + + module->format_info[DFI_PDB]->vtable = &pdb_module_format_vtable; + return pdb; + } pool_free(&module->pool, pdb); return NULL; } diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 70b20b073bb..5c3b01be40e 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1754,19 +1754,6 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symb return TRUE; }
-struct lineinfo_t -{ - BOOL unicode; - PVOID key; - DWORD line_number; - union - { - CHAR* file_nameA; - WCHAR* file_nameW; - }; - DWORD64 address; -}; - static void init_lineinfo(struct lineinfo_t* line_info, BOOL unicode) { line_info->unicode = unicode; @@ -1806,7 +1793,7 @@ static BOOL lineinfo_copy_toW64(const struct lineinfo_t* line_info, IMAGEHLP_LIN return TRUE; }
-static BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info, char* str) +BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* line_info, char* str) { DWORD len;
@@ -1892,14 +1879,27 @@ static BOOL get_line_from_function(struct module_pair* pair, struct symt_functio static BOOL get_line_from_addr(HANDLE hProcess, DWORD64 addr, PDWORD pdwDisplacement, struct lineinfo_t* line_info) { - struct module_pair pair; - struct symt_ht* symt; - + struct module_pair pair; + struct symt_ht* symt; + struct module_format_vtable_iterator iter = {}; + BOOL ret = FALSE; if (!module_init_pair(&pair, hProcess, addr)) return FALSE; + + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(get_line_from_address)))) + { + if (iter.modfmt->vtable->get_line_from_address(iter.modfmt, addr, line_info) == MR_SUCCESS) + { + if (pdwDisplacement) *pdwDisplacement = addr - line_info->address; + return TRUE; + } + } + symt = symt_find_symbol_at(pair.effective, addr); + if (symt_check_tag(&symt->symt, SymTagFunction)) + ret = get_line_from_function(&pair, (struct symt_function*)symt, addr, pdwDisplacement, line_info);
- if (!symt_check_tag(&symt->symt, SymTagFunction)) return FALSE; - return get_line_from_function(&pair, (struct symt_function*)symt, addr, pdwDisplacement, line_info); + return ret; }
/*********************************************************************** @@ -2006,7 +2006,19 @@ static BOOL symt_get_func_line_prev(HANDLE hProcess, struct lineinfo_t* line_inf struct line_info* srcli;
if (!module_init_pair(&pair, hProcess, addr)) return FALSE; - + if (key == NULL) + { + struct symt_ht* symt; + /* likely line_info has been filled in by pdb reader, but it can advance yet + * so force reloading the old information + */ + symt = symt_find_symbol_at(pair.effective, addr); + if (!symt_check_tag(&symt->symt, SymTagFunction) || + !get_line_from_function(&pair, (struct symt_function*)symt, addr, NULL, line_info)) + return FALSE; + if (line_info->key == NULL) return FALSE; + key = line_info->key; + } if (key == NULL) return FALSE;
li = key; @@ -2083,8 +2095,21 @@ static BOOL symt_get_func_line_next(HANDLE hProcess, struct lineinfo_t* line_inf struct line_info* li; struct line_info* srcli;
- if (key == NULL) return FALSE; if (!module_init_pair(&pair, hProcess, addr)) return FALSE; + if (key == NULL) + { + struct symt_ht* symt; + /* likely line_info has been filled in by pdb reader, but it can advance yet + * so force reloading the information from old reader + */ + symt = symt_find_symbol_at(pair.effective, addr); + if (!symt_check_tag(&symt->symt, SymTagFunction) || + !get_line_from_function(&pair, (struct symt_function*)symt, addr, NULL, line_info)) + return FALSE; + if (line_info->key == NULL) return FALSE; + key = line_info->key; + } + if (key == NULL) return FALSE;
/* search current source file */ for (srcli = key; !srcli->is_source_file; srcli--);
From: Eric Pouech epouech@codeweavers.com
Implement it in new PDB reader.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 2 + dlls/dbghelp/pdb.c | 74 ++++++++++++++++++++++++++++++++++ dlls/dbghelp/symbol.c | 48 ++++++++++++---------- 3 files changed, 102 insertions(+), 22 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 4fc11b322af..ad36233e3a8 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -440,6 +440,8 @@ struct module_format_vtable /* line information */ enum method_result (*get_line_from_address)(struct module_format *modfmt, DWORD64 address, struct lineinfo_t *line_info); + enum method_result (*advance_line_info)(struct module_format *modfmt, + struct lineinfo_t *line_info, BOOL forward); };
struct module_format diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 994cae3c0e8..76e0ed41359 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -732,11 +732,85 @@ static enum method_result pdb_method_get_line_from_address(struct module_format return pdb_method_result(result); }
+static enum pdb_result pdb_reader_advance_line_info(struct pdb_reader *pdb, + struct lineinfo_t *line_info, BOOL forward) +{ + struct pdb_reader_compiland_iterator compiland_iter; + struct pdb_reader_walker linetab2_walker; + struct CV_DebugSLinesFileBlockHeader_t files_hdr; + DWORD64 lineblk_base; + struct CV_Line_t *lines; + enum pdb_result result; + unsigned i; + + if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) + return result; + do + { + if (compiland_iter.dbi_cu_header.lineno2_size) + { + if ((result = pdb_reader_walker_init_linetab2(pdb, &compiland_iter.dbi_cu_header, &linetab2_walker))) + return result; + result = pdb_reader_locate_filehdr_in_linetab2(pdb, linetab2_walker, line_info->address, &lineblk_base, &files_hdr, &lines); + if (result == R_PDB_NOT_FOUND) continue; + if (result) return result; + if ((result = pdb_find_matching_linetab2(lines, files_hdr.nLines, line_info->address - lineblk_base, &i))) + return result; + + /* It happens that several entries have same address (yet potentially different line numbers) + * Simplify handling by getting the first entry (forward or backward) with a different address. + * More tests from native are required. + */ + if (forward) + { + for (; i + 1 < files_hdr.nLines; i++) + if (line_info->address != lineblk_base + lines[i + 1].offset) + { + line_info->address = lineblk_base + lines[i + 1].offset; + line_info->line_number = lines[i + 1].linenumStart; + break; + } + if (i + 1 >= files_hdr.nLines) + result = R_PDB_INVALID_ARGUMENT; + } + else + { + for (; i; --i) + { + if (line_info->address != lineblk_base + lines[i - 1].offset) + { + line_info->address = lineblk_base + lines[i - 1].offset; + line_info->line_number = lines[i - 1].linenumStart; + break; + } + } + if (!i) + result = R_PDB_INVALID_ARGUMENT; + } + pdb_reader_free(pdb, lines); + /* refresh filename in case it has been tempered with */ + return result ? result : pdb_reader_set_lineinfo_filename(pdb, linetab2_walker, files_hdr.offFile, line_info); + } + } while (pdb_reader_compiland_iterator_next(pdb, &compiland_iter) == R_PDB_SUCCESS); + + return R_PDB_NOT_FOUND; +} + +static enum method_result pdb_method_advance_line_info(struct module_format *modfmt, + struct lineinfo_t *line_info, BOOL forward) +{ + struct pdb_reader *pdb; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + return pdb_reader_advance_line_info(pdb, line_info, forward) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ NULL,/*pdb_location_compute*/ pdb_method_get_line_from_address, + pdb_method_advance_line_info, };
struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 5c3b01be40e..58a7338aed7 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -2004,20 +2004,24 @@ static BOOL symt_get_func_line_prev(HANDLE hProcess, struct lineinfo_t* line_inf struct module_pair pair; struct line_info* li; struct line_info* srcli; + struct module_format_vtable_iterator iter = {};
if (!module_init_pair(&pair, hProcess, addr)) return FALSE; - if (key == NULL) + + line_info->address = addr; + line_info->key = key; + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(advance_line_info)))) { - struct symt_ht* symt; - /* likely line_info has been filled in by pdb reader, but it can advance yet - * so force reloading the old information - */ - symt = symt_find_symbol_at(pair.effective, addr); - if (!symt_check_tag(&symt->symt, SymTagFunction) || - !get_line_from_function(&pair, (struct symt_function*)symt, addr, NULL, line_info)) + switch (iter.modfmt->vtable->advance_line_info(iter.modfmt, line_info, FALSE)) + { + case MR_SUCCESS: + return TRUE; + case MR_NOT_FOUND: /* continue */ + break; + default: return FALSE; - if (line_info->key == NULL) return FALSE; - key = line_info->key; + } } if (key == NULL) return FALSE;
@@ -2094,23 +2098,23 @@ static BOOL symt_get_func_line_next(HANDLE hProcess, struct lineinfo_t* line_inf struct module_pair pair; struct line_info* li; struct line_info* srcli; + struct module_format_vtable_iterator iter = {};
if (!module_init_pair(&pair, hProcess, addr)) return FALSE; - if (key == NULL) + + line_info->address = addr; + line_info->key = key; + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(advance_line_info)))) { - struct symt_ht* symt; - /* likely line_info has been filled in by pdb reader, but it can advance yet - * so force reloading the information from old reader - */ - symt = symt_find_symbol_at(pair.effective, addr); - if (!symt_check_tag(&symt->symt, SymTagFunction) || - !get_line_from_function(&pair, (struct symt_function*)symt, addr, NULL, line_info)) - return FALSE; - if (line_info->key == NULL) return FALSE; - key = line_info->key; + switch (iter.modfmt->vtable->advance_line_info(iter.modfmt, line_info, TRUE)) + { + case MR_SUCCESS: return TRUE; + default: break; + } } - if (key == NULL) return FALSE;
+ if (key == NULL) return FALSE; /* search current source file */ for (srcli = key; !srcli->is_source_file; srcli--);
From: Eric Pouech epouech@codeweavers.com
And implement it for new PDB reader.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 2 + dlls/dbghelp/pdb.c | 121 +++++++++++++++++++++++++++++++++ dlls/dbghelp/symbol.c | 22 ++++-- 3 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index ad36233e3a8..edcd09b03a3 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -442,6 +442,8 @@ struct module_format_vtable DWORD64 address, struct lineinfo_t *line_info); enum method_result (*advance_line_info)(struct module_format *modfmt, struct lineinfo_t *line_info, BOOL forward); + enum method_result (*enumerate_lines)(struct module_format *modfmt, const WCHAR* compiland_regex, + const WCHAR *source_file_regex, PSYM_ENUMLINES_CALLBACK cb, void *user); };
struct module_format diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 76e0ed41359..accc6166bdd 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -805,12 +805,133 @@ static enum method_result pdb_method_advance_line_info(struct module_format *mod return pdb_reader_advance_line_info(pdb, line_info, forward) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; }
+static enum pdb_result pdb_reader_enum_lines_linetab2(struct pdb_reader *pdb, const PDB_SYMBOL_FILE_EX *dbi_cu_header, + const WCHAR *source_file_regex, SRCCODEINFO *source_code_info, PSYM_ENUMLINES_CALLBACK cb, void *user) +{ + struct pdb_reader_walker linetab2_walker = {dbi_cu_header->stream, dbi_cu_header->symbol_size, dbi_cu_header->symbol_size + dbi_cu_header->lineno2_size}; + struct pdb_reader_walker walker, sub_walker, checksum_walker; + enum pdb_result result; + struct CV_DebugSLinesHeader_t lines_hdr; + struct CV_DebugSLinesFileBlockHeader_t files_hdr; + DWORD64 lineblk_base; + + for (checksum_walker = linetab2_walker; !(result = pdb_reader_subsection_next(pdb, &checksum_walker, DEBUG_S_FILECHKSMS, &sub_walker)); ) + { + checksum_walker = sub_walker; + break; + } + if (result) + { + WARN("No DEBUG_S_FILECHKSMS found\n"); + return R_PDB_MISSING_INFORMATION; + } + + for (walker = linetab2_walker; + !(result = pdb_reader_subsection_next(pdb, &walker, DEBUG_S_LINES, &sub_walker)); + ) + { + /* Skip blocks that are too small - Intel C Compiler generates these. */ + if (sub_walker.offset + sizeof(lines_hdr) + sizeof(struct CV_DebugSLinesFileBlockHeader_t) > sub_walker.last) + continue; + if ((result = pdb_reader_READ(pdb, &sub_walker, &lines_hdr))) return result; + if ((result = pdb_reader_get_segment_address(pdb, lines_hdr.segCon, lines_hdr.offCon, &lineblk_base))) + return result; + for (; (result = pdb_reader_READ(pdb, &sub_walker, &files_hdr)) == R_PDB_SUCCESS; /*lineblk_base += files_hdr.cbBlock*/) + { + pdbsize_t current_stream_offset; + struct CV_Checksum_t checksum; + struct CV_Line_t *lines; + char *string; + unsigned i; + BOOL match = TRUE; + + if ((result = pdb_reader_alloc_and_read(pdb, &sub_walker, files_hdr.nLines * sizeof(lines[0]), + (void**)&lines))) return result; + + /* should filter on filename */ + current_stream_offset = checksum_walker.offset; + checksum_walker.offset += files_hdr.offFile; + if ((result = pdb_reader_READ(pdb, &checksum_walker, &checksum))) return result; + if ((result = pdb_reader_alloc_and_fetch_global_string(pdb, checksum.strOffset, &string))) return result; + checksum_walker.offset = current_stream_offset; + + if (source_file_regex) + match = symt_match_stringAW(string, source_file_regex, FALSE); + if (!match) + { + sub_walker.offset += files_hdr.nLines * sizeof(struct CV_Line_t); + if (lines_hdr.flags & CV_LINES_HAVE_COLUMNS) + sub_walker.offset += files_hdr.nLines * sizeof(struct CV_Column_t); + continue; + } + if (strlen(string) < ARRAY_SIZE(source_code_info->FileName)) + strcpy(source_code_info->FileName, string); + else + source_code_info->FileName[0] = '\0'; + pdb_reader_free(pdb, string); + + for (i = 0; i < files_hdr.nLines; i++) + { + source_code_info->Address = lineblk_base + lines[i].offset; + source_code_info->LineNumber = lines[i].linenumStart; + if (!cb(source_code_info, user)) return R_PDB_NOT_FOUND; + } + pdb_reader_free(pdb, lines); + if (lines_hdr.flags & CV_LINES_HAVE_COLUMNS) + sub_walker.offset += files_hdr.nLines * sizeof(struct CV_Column_t); + } + } + return result == R_PDB_INVALID_ARGUMENT ? R_PDB_SUCCESS : result; +} + +static BOOL pdb_method_enumerate_lines_internal(struct pdb_reader *pdb, const WCHAR* compiland_regex, + const WCHAR *source_file_regex, PSYM_ENUMLINES_CALLBACK cb, void *user) +{ + struct pdb_reader_compiland_iterator compiland_iter; + enum pdb_result result; + SRCCODEINFO source_code_info; + + source_code_info.SizeOfStruct = sizeof(source_code_info); + source_code_info.ModBase = pdb->module->module.BaseOfImage; + + if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; + do + { + struct pdb_reader_walker walker = compiland_iter.dbi_walker; + + if ((result = pdb_reader_fetch_string_from_stream(pdb, &walker, source_code_info.Obj, sizeof(source_code_info.Obj)))) + { + if (result == R_PDB_BUFFER_TOO_SMALL) FIXME("NOT EXPECTED --too small\n"); + return result; + } + + /* FIXME should filter on compiland (if present) */ + if (compiland_iter.dbi_cu_header.lineno2_size) + { + result = pdb_reader_enum_lines_linetab2(pdb, &compiland_iter.dbi_cu_header, source_file_regex, &source_code_info, cb, user); + } + + } while (pdb_reader_compiland_iterator_next(pdb, &compiland_iter) == R_PDB_SUCCESS); + return R_PDB_SUCCESS; +} + +static enum method_result pdb_method_enumerate_lines(struct module_format *modfmt, const WCHAR* compiland_regex, + const WCHAR *source_file_regex, PSYM_ENUMLINES_CALLBACK cb, void *user) +{ + struct pdb_reader *pdb; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + + return pdb_method_result(pdb_method_enumerate_lines_internal(pdb, compiland_regex, source_file_regex, cb, user)); +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ NULL,/*pdb_location_compute*/ pdb_method_get_line_from_address, pdb_method_advance_line_info, + pdb_method_enumerate_lines, };
struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 58a7338aed7..5d376806c1a 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -2550,18 +2550,32 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland, struct module_pair pair; struct hash_table_iter hti; struct symt_ht* sym; - WCHAR* srcmask; + WCHAR* compiland_regex; + WCHAR* srcfile_regex; struct line_info* dli; void* ptr; SRCCODEINFO sci; const char* file; + struct module_format_vtable_iterator iter = {};
if (!cb) return FALSE; if (!(dbghelp_options & SYMOPT_LOAD_LINES)) return TRUE;
if (!module_init_pair(&pair, hProcess, base)) return FALSE; + if (!(compiland_regex = file_regex(compiland))) return FALSE; + if (!(srcfile_regex = file_regex(srcfile))) return FALSE; + + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(enumerate_lines)))) + { + enum method_result result = iter.modfmt->vtable->enumerate_lines(iter.modfmt, compiland_regex, srcfile_regex, cb, user); + HeapFree(GetProcessHeap(), 0, compiland_regex); + HeapFree(GetProcessHeap(), 0, srcfile_regex); + return result == MR_SUCCESS; + } + if (compiland) FIXME("Unsupported yet (filtering on compiland %s)\n", debugstr_a(compiland)); - if (!(srcmask = file_regex(srcfile))) return FALSE; + HeapFree(GetProcessHeap(), 0, compiland_regex);
sci.SizeOfStruct = sizeof(sci); sci.ModBase = base; @@ -2581,7 +2595,7 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland, if (dli->is_source_file) { file = source_get(pair.effective, dli->u.source_file); - if (file && symt_match_stringAW(file, srcmask, FALSE)) + if (file && symt_match_stringAW(file, srcfile_regex, FALSE)) strcpy(sci.FileName, file); else sci.FileName[0] = '\0'; @@ -2596,7 +2610,7 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland, } } } - HeapFree(GetProcessHeap(), 0, srcmask); + HeapFree(GetProcessHeap(), 0, srcfile_regex); return TRUE; }
From: Eric Pouech epouech@codeweavers.com
FIXME: method doesn't do what its name imply do we need to keep the vsources global vector??
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 4 +++ dlls/dbghelp/pdb.c | 61 ++++++++++++++++++++++++++++++++++ dlls/dbghelp/source.c | 20 ++++++++++- 3 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index edcd09b03a3..66282a2e6e9 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -444,6 +444,10 @@ struct module_format_vtable struct lineinfo_t *line_info, BOOL forward); enum method_result (*enumerate_lines)(struct module_format *modfmt, const WCHAR* compiland_regex, const WCHAR *source_file_regex, PSYM_ENUMLINES_CALLBACK cb, void *user); + + /* source files information */ + enum method_result (*enumerate_sources)(struct module_format *modfmt, const WCHAR *sourcefile_regex, + PSYM_ENUMSOURCEFILES_CALLBACKW cb, void *user); };
struct module_format diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index accc6166bdd..84f94e32338 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -84,6 +84,8 @@ struct pdb_reader } *streams; char *stream_names;
+ unsigned source_listed : 1; + /* cache PE module sections for mapping... * we should rather use pe_module information */ @@ -925,6 +927,64 @@ static enum method_result pdb_method_enumerate_lines(struct module_format *modfm return pdb_method_result(pdb_method_enumerate_lines_internal(pdb, compiland_regex, source_file_regex, cb, user)); }
+static enum pdb_result pdb_reader_load_sources_linetab2(struct pdb_reader *pdb, const PDB_SYMBOL_FILE_EX *dbi_cu_header) +{ + struct pdb_reader_walker linetab2_walker = {dbi_cu_header->stream, dbi_cu_header->symbol_size, dbi_cu_header->symbol_size + dbi_cu_header->lineno2_size}; + struct pdb_reader_walker sub_walker, checksum_walker; + enum pdb_result result; + struct CV_Checksum_t chksum; + + for (checksum_walker = linetab2_walker; !(result = pdb_reader_subsection_next(pdb, &checksum_walker, DEBUG_S_FILECHKSMS, &sub_walker)); ) + { + for (; (result = pdb_reader_READ(pdb, &sub_walker, &chksum)) == R_PDB_SUCCESS; sub_walker.offset = (sub_walker.offset + chksum.size + 3) & ~3) + { + char *string; + if ((result = pdb_reader_alloc_and_fetch_global_string(pdb, chksum.strOffset, &string))) return result; + source_new(pdb->module, NULL, string); + pdb_reader_free(pdb, string); + } + } + return result == R_PDB_NOT_FOUND ? R_PDB_SUCCESS : result; +} + +static enum pdb_result pdb_load_sources_internal(struct pdb_reader *pdb) +{ + enum pdb_result result; + struct pdb_reader_compiland_iterator compiland_iter; + + if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; + do + { + if (compiland_iter.dbi_cu_header.lineno2_size) + { + result = pdb_reader_load_sources_linetab2(pdb, &compiland_iter.dbi_cu_header); + } + } while (pdb_reader_compiland_iterator_next(pdb, &compiland_iter) == R_PDB_SUCCESS); + + return R_PDB_SUCCESS; +} + +static enum method_result pdb_method_enumerate_sources(struct module_format *modfmt, const WCHAR *source_file_regex, + PSYM_ENUMSOURCEFILES_CALLBACKW cb, void *user) +{ + struct pdb_reader *pdb; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return -1; + + /* Note: in PDB, each compiland lists its used files, which are all in global string table, + * but there's no global source files table AFAICT. + * So, just walk (once) all compilands to grab all sources, and store them in generic source table. + * But don't enumerate here, let generic function take care of it. + */ + if (!pdb->source_listed) + { + enum pdb_result result = pdb_load_sources_internal(pdb); + if (result) return pdb_method_result(result); + pdb->source_listed = 1; + } + return MR_NOT_FOUND; +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ @@ -932,6 +992,7 @@ static struct module_format_vtable pdb_module_format_vtable = pdb_method_get_line_from_address, pdb_method_advance_line_info, pdb_method_enumerate_lines, + pdb_method_enumerate_sources, };
struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, const IMAGE_SECTION_HEADER *sections, unsigned num_sections) diff --git a/dlls/dbghelp/source.c b/dlls/dbghelp/source.c index 2ef80deb1dc..24ba224a499 100644 --- a/dlls/dbghelp/source.c +++ b/dlls/dbghelp/source.c @@ -145,11 +145,12 @@ BOOL WINAPI SymEnumSourceFilesW(HANDLE hProcess, ULONG64 ModBase, PCWSTR Mask, char* ptr; WCHAR* conversion_buffer = NULL; DWORD conversion_buffer_len = 0; + struct module_format_vtable_iterator iter = {};
if (!cbSrcFiles) return FALSE; pair.pcs = process_find_by_handle(hProcess); if (!pair.pcs) return FALSE; - + if (ModBase) { pair.requested = module_find_by_addr(pair.pcs, ModBase); @@ -176,6 +177,23 @@ BOOL WINAPI SymEnumSourceFilesW(HANDLE hProcess, ULONG64 ModBase, PCWSTR Mask, return FALSE; } } + + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(enumerate_sources)))) + { + enum method_result result = iter.modfmt->vtable->enumerate_sources(iter.modfmt, NULL, cbSrcFiles, UserContext); + switch (result) + { + case MR_SUCCESS: + return TRUE; + case MR_NOT_FOUND: /* continue */ + break; + default: + /* SetLastError(...); */ + return FALSE; + } + } + if (!pair.effective->sources) return FALSE; for (ptr = pair.effective->sources; *ptr; ptr += strlen(ptr) + 1) {
From: Eric Pouech epouech@codeweavers.com
FIXME: module's has-line-info is no longer set!
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 5fd0b28894e..dfbd33bfcd2 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3912,15 +3912,19 @@ static BOOL pdb_process_internal(const struct process *pcs, FIXME("Both line info present... only supporting second\n"); else if (sfile.lineno_size) { - if (codeview_snarf_linetab(msc_dbg, + if (pdb_file->pdb_reader) + FIXME("New PDB reader doesn't support old line format\n"); + else if (codeview_snarf_linetab(msc_dbg, modimage + sfile.symbol_size, sfile.lineno_size, pdb_file->kind == PDB_JG)) *has_linenumber_info = TRUE; + else if (pdb_file->pdb_reader) + FIXME("Linetab1 is no longer supported in PDB reader\n"); } else if (sfile.lineno2_size) { - if (codeview_snarf_linetab2(msc_dbg, &cvmod)) + if (pdb_file->pdb_reader || codeview_snarf_linetab2(msc_dbg, &cvmod)) *has_linenumber_info = TRUE; } }
@julliard something's wrong with this?
There are a bunch of FIXMEs in your commit messages, shouldn't these things be fixed first?