Basically, current implem line management is broken: - in some code paths, same buffer is used both as input and output
this serie fixes it by putting in place a cleaner way of setting the returned buffer it also implements a couple of missing W64 variants of APIs
(this issue had been reported by Alistair a couple of months ago on wine-devel)
Changes in v2: - set internal flags on line info on the fly (use of func_normalize() was broken anyway)
A+ ---
Eric Pouech (6): dbghelp: let symt_fill_func_line_info and symt_get_func_line_next be a static function inside symbol.c dbghelp: introducing internal_line_t structure as help in Line manipulation dbghelp: implemented all SymGetLineNext* functions using internal_line_t dbghelp: (re)write SymGetLinePrev* with internal_line_t dbghelp: set is_first and is_last flags on the fly in symt_add_func_line dbghelp: get rid of useless symt_normalize_func()
dlls/dbghelp/dbghelp.spec | 4 +- dlls/dbghelp/dbghelp_private.h | 2 - dlls/dbghelp/dwarf.c | 1 - dlls/dbghelp/msc.c | 3 - dlls/dbghelp/stabs.c | 1 - dlls/dbghelp/symbol.c | 429 ++++++++++++++++++++------------- 6 files changed, 258 insertions(+), 182 deletions(-)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp_private.h | 4 ---- dlls/dbghelp/stabs.c | 6 ++++-- dlls/dbghelp/symbol.c | 6 +++--- 3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 0c324a827e9..162e8bc004d 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -772,10 +772,6 @@ extern struct symt_hierarchy_point* enum SymTagEnum point, const struct location* loc, const char* name) DECLSPEC_HIDDEN; -extern BOOL symt_fill_func_line_info(const struct module* module, - const struct symt_function* func, - DWORD64 addr, IMAGEHLP_LINE64* line) DECLSPEC_HIDDEN; -extern BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line) DECLSPEC_HIDDEN; extern struct symt_thunk* symt_new_thunk(struct module* module, struct symt_compiland* parent, diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index b011c123482..bdafb98bbd4 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1193,14 +1193,16 @@ static void stabs_finalize_function(struct module* module, struct symt_function* { IMAGEHLP_LINE64 il; struct location loc; + DWORD disp;
if (!func) return; symt_normalize_function(module, func); /* To define the debug-start of the function, we use the second line number. * Not 100% bullet proof, but better than nothing */ - if (symt_fill_func_line_info(module, func, func->address, &il) && - symt_get_func_line_next(module, &il)) + il.SizeOfStruct = sizeof(il); + if (SymGetLineFromAddr64(module->process->handle, func->address, &disp, &il) && + SymGetLineNext64(module->process->handle, &il)) { loc.kind = loc_absolute; loc.offset = il.Address - func->address; diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 09407e04fc0..b0e96569f15 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1521,8 +1521,8 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symb * * fills information about a file */ -BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func, - DWORD64 addr, IMAGEHLP_LINE64* line) +static BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func, + DWORD64 addr, IMAGEHLP_LINE64* line) { struct line_info* dli = NULL; BOOL found = FALSE; @@ -1775,7 +1775,7 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) return TRUE; }
-BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line) +static BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line) { struct line_info* li;
the rationale is that: - the file name in IMAGEHLP_LINE* structures is returned as a pointer to an internal buffer - in the W64 variant of APIs, two calls to fetch_buffer() are currently needed (one for first A allocation, second for W conversion) - this generate bugs as it's assumed the two buffers are different
so the internal_line_t purpose is to factorize the implementations of the 3 variants (A32, A64, W64) into a single code path this insures a unique allocation, and at most, one conversion
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/symbol.c | 206 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 146 insertions(+), 60 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index b0e96569f15..d79b32a0b5a 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1516,19 +1516,129 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symb return TRUE; }
+struct internal_line_t +{ + BOOL unicode; + PVOID key; + DWORD line_number; + union + { + CHAR* file_nameA; + WCHAR* file_nameW; + }; + DWORD64 address; +}; + +static void init_internal_line(struct internal_line_t* intl, BOOL unicode) +{ + intl->unicode = unicode; + intl->key = NULL; + intl->line_number = 0; + intl->file_nameA = NULL; + intl->address = 0; +} + +static BOOL internal_line_copy_toA32(const struct internal_line_t* intl, 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; + return TRUE; +} + +static BOOL internal_line_copy_toA64(const struct internal_line_t* intl, 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; + return TRUE; +} + +static BOOL internal_line_copy_toW64(const struct internal_line_t* intl, 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; + return TRUE; +} + +static BOOL internal_line_set_nameA(struct process* pcs, struct internal_line_t* intl, char* str, BOOL copy) +{ + DWORD len; + + if (intl->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); + } + else + { + if (copy) + { + len = strlen(str) + 1; + if (!(intl->file_nameA = fetch_buffer(pcs, len))) return FALSE; + memcpy(intl->file_nameA, str, len); + } + else + intl->file_nameA = str; + } + return TRUE; +} + +static BOOL internal_line_set_nameW(struct process* pcs, struct internal_line_t* intl, WCHAR* wstr, BOOL copy) +{ + DWORD len; + + if (intl->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); + } + else + intl->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); + } + return TRUE; +} + /****************************************************************** - * sym_fill_func_line_info + * get_line_from_addr * - * fills information about a file + * fills source file information from an address */ -static BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func, - DWORD64 addr, IMAGEHLP_LINE64* line) +static BOOL get_line_from_addr(HANDLE hProcess, DWORD64 addr, + PDWORD pdwDisplacement, struct internal_line_t* intl) { - struct line_info* dli = NULL; - BOOL found = FALSE; - int i; + struct line_info* dli = NULL; + BOOL found = FALSE; + int i; + struct module_pair pair; + struct symt_ht* symt; + struct symt_function* func;
- assert(func->symt.tag == SymTagFunction); + pair.pcs = process_find_by_handle(hProcess); + if (!pair.pcs) return FALSE; + pair.requested = module_find_by_addr(pair.pcs, addr, DMT_UNKNOWN); + if (!module_get_debug(&pair)) return FALSE; + if ((symt = symt_find_nearest(pair.effective, addr)) == NULL) return FALSE; + + if (symt->symt.tag != SymTagFunction) return FALSE; + func = (struct symt_function*)symt;
for (i=vector_length(&func->vlines)-1; i>=0; i--) { @@ -1536,28 +1646,28 @@ static BOOL symt_fill_func_line_info(const struct module* module, const struct s if (!dli->is_source_file) { if (found || dli->u.pc_offset > addr) continue; - line->LineNumber = dli->line_number; - line->Address = dli->u.pc_offset; - line->Key = dli; + intl->line_number = dli->line_number; + intl->address = dli->u.pc_offset; + intl->key = dli; found = TRUE; continue; } if (found) { + BOOL ret; if (dbghelp_opt_native) { /* Return native file paths when using winedbg */ - line->FileName = (char*)source_get(module, dli->u.source_file); + ret = internal_line_set_nameA(pair.pcs, intl, (char*)source_get(pair.effective, dli->u.source_file), FALSE); } else { - WCHAR *dospath = wine_get_dos_file_name(source_get(module, dli->u.source_file)); - DWORD len = WideCharToMultiByte(CP_ACP, 0, dospath, -1, NULL, 0, NULL, NULL); - line->FileName = fetch_buffer(module->process, len); - WideCharToMultiByte(CP_ACP, 0, dospath, -1, line->FileName, len, NULL, NULL); + 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); HeapFree( GetProcessHeap(), 0, dospath ); } - return TRUE; + if (ret) *pdwDisplacement = intl->address - func->address; + return ret; } } return FALSE; @@ -1622,22 +1732,6 @@ 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_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64) -{ - unsigned len; - - l64w->Key = l64->Key; - l64w->LineNumber = l64->LineNumber; - len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0); - if ((l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR)))) - MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, l64w->FileName, len); - l64w->Address = l64->Address; -} - /****************************************************************** * copy_line_32_from_64 (internal) * @@ -1658,13 +1752,14 @@ static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64) BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line) { - IMAGEHLP_LINE64 il64; + struct internal_line_t intl;
- il64.SizeOfStruct = sizeof(il64); - if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64)) - return FALSE; - copy_line_32_from_64(Line, &il64); - return TRUE; + 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); }
/****************************************************************** @@ -1674,24 +1769,14 @@ BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) { - struct module_pair pair; - struct symt_ht* symt; + struct internal_line_t intl;
- TRACE("%p %s %p %p\n", hProcess, wine_dbgstr_longlong(dwAddr), pdwDisplacement, Line); + TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - - pair.pcs = process_find_by_handle(hProcess); - if (!pair.pcs) return FALSE; - pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN); - if (!module_get_debug(&pair)) return FALSE; - if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE; - - if (symt->symt.tag != SymTagFunction) return FALSE; - if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt, - dwAddr, Line)) return FALSE; - *pdwDisplacement = dwAddr - Line->Address; - return TRUE; + init_internal_line(&intl, FALSE); + if (!get_line_from_addr(hProcess, dwAddr, pdwDisplacement, &intl)) return FALSE; + return internal_line_copy_toA64(&intl, Line); }
/****************************************************************** @@ -1701,13 +1786,14 @@ BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line) { - IMAGEHLP_LINE64 il64; + struct internal_line_t intl;
- il64.SizeOfStruct = sizeof(il64); - if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64)) - return FALSE; - copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64); - return TRUE; + 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); }
/******************************************************************
- added missing W64 variant - always regenerate the FileName field (as we don't know whether the internal buffer has been reused or not)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.spec | 2 + dlls/dbghelp/symbol.c | 69 ++++++++++++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index 73455c547e8..1d95c7a21ff 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -92,7 +92,7 @@ @ stdcall SymGetLineFromNameW64(long wstr wstr long ptr ptr) @ stdcall SymGetLineNext(long ptr) @ stdcall SymGetLineNext64(long ptr) -@ stub SymGetLineNextW64 +@ stdcall SymGetLineNextW64(long ptr) @ stdcall SymGetLinePrev(long ptr) @ stdcall SymGetLinePrev64(long ptr) @ stub SymGetLinePrevW64 diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index d79b32a0b5a..25bb21edeaa 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1861,24 +1861,35 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) return TRUE; }
-static BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line) +static BOOL symt_get_func_line_next(HANDLE hProcess, struct internal_line_t* intl, void* key, DWORD64 addr) { + struct module_pair pair; struct line_info* li; + struct line_info* srcli; + + if (key == NULL) return FALSE; + pair.pcs = process_find_by_handle(hProcess); + if (!pair.pcs) return FALSE; + pair.requested = module_find_by_addr(pair.pcs, addr, DMT_UNKNOWN); + if (!module_get_debug(&pair)) return FALSE;
- if (line->Key == 0) return FALSE; - li = line->Key; + /* search current source file */ + for (srcli = key; !srcli->is_source_file; srcli--); + + li = key; while (!li->is_last) { li++; if (!li->is_source_file) { - line->LineNumber = li->line_number; - line->Address = li->u.pc_offset; - line->Key = li; - return TRUE; + intl->line_number = li->line_number; + intl->address = li->u.pc_offset; + intl->key = li; + return internal_line_set_nameA(pair.pcs, intl, (char*)source_get(pair.effective, srcli->u.source_file), FALSE); } - line->FileName = (char*)source_get(module, li->u.source_file); + srcli = li; } + SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ return FALSE; }
@@ -1888,19 +1899,14 @@ static BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE6 */ BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) { - struct module_pair pair; + struct internal_line_t intl;
TRACE("(%p %p)\n", hProcess, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; - pair.pcs = process_find_by_handle(hProcess); - if (!pair.pcs) return FALSE; - pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN); - if (!module_get_debug(&pair)) return FALSE; - - if (symt_get_func_line_next(pair.effective, Line)) return TRUE; - SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ - 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); }
/****************************************************************** @@ -1909,13 +1915,30 @@ BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) */ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line) { - IMAGEHLP_LINE64 line64; + struct internal_line_t intl;
- line64.SizeOfStruct = sizeof(line64); - copy_line_64_from_32(&line64, Line); - if (!SymGetLineNext64(hProcess, &line64)) return FALSE; - copy_line_32_from_64(Line, &line64); - return TRUE; + 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); +} + +/****************************************************************** + * SymGetLineNextW64 (DBGHELP.@) + * + */ +BOOL WINAPI SymGetLineNextW64(HANDLE hProcess, PIMAGEHLP_LINEW64 Line) +{ + struct internal_line_t intl; + + 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); }
/***********************************************************************
- added missing W64 variant - always regenerate the FileName field (as we don't know whether the internal buffer has been reused or not)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.spec | 2 - dlls/dbghelp/symbol.c | 118 +++++++++++++++++++++------------------------ 2 files changed, 55 insertions(+), 65 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index 1d95c7a21ff..39820a98566 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -95,7 +95,7 @@ @ stdcall SymGetLineNextW64(long ptr) @ stdcall SymGetLinePrev(long ptr) @ stdcall SymGetLinePrev64(long ptr) -@ stub SymGetLinePrevW64 +@ stdcall SymGetLinePrevW64(long ptr) @ stdcall SymGetModuleBase(long long) @ stdcall SymGetModuleBase64(long int64) @ stdcall SymGetModuleInfo(long long ptr) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 25bb21edeaa..ee68967ce5d 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1719,32 +1719,6 @@ BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol) return FALSE; }
-/****************************************************************** - * copy_line_64_from_32 (internal) - * - */ -static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32) - -{ - l64->Key = l32->Key; - l64->LineNumber = l32->LineNumber; - l64->FileName = l32->FileName; - l64->Address = l32->Address; -} - -/****************************************************************** - * copy_line_32_from_64 (internal) - * - */ -static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64) - -{ - l32->Key = l64->Key; - l32->LineNumber = l64->LineNumber; - l32->FileName = l64->FileName; - l32->Address = l64->Address; -} - /****************************************************************** * SymGetLineFromAddr (DBGHELP.@) * @@ -1796,50 +1770,33 @@ BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, return internal_line_copy_toW64(&intl, Line); }
-/****************************************************************** - * SymGetLinePrev64 (DBGHELP.@) - * - */ -BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) +static BOOL symt_get_func_line_prev(HANDLE hProcess, struct internal_line_t* intl, void* key, DWORD64 addr) { struct module_pair pair; struct line_info* li; - BOOL in_search = FALSE; - - TRACE("(%p %p)\n", hProcess, Line); - - if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; + struct line_info* srcli;
pair.pcs = process_find_by_handle(hProcess); if (!pair.pcs) return FALSE; - pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN); + pair.requested = module_find_by_addr(pair.pcs, addr, DMT_UNKNOWN); if (!module_get_debug(&pair)) return FALSE;
- if (Line->Key == 0) return FALSE; - li = Line->Key; - /* things are a bit complicated because when we encounter a DLIT_SOURCEFILE - * element we have to go back until we find the prev one to get the real - * source file name for the DLIT_OFFSET element just before - * the first DLIT_SOURCEFILE - */ + if (key == NULL) return FALSE; + + li = key; + while (!li->is_first) { li--; if (!li->is_source_file) { - Line->LineNumber = li->line_number; - Line->Address = li->u.pc_offset; - Line->Key = li; - if (!in_search) return TRUE; - } - else - { - if (in_search) - { - Line->FileName = (char*)source_get(pair.effective, li->u.source_file); - return TRUE; - } - in_search = TRUE; + intl->line_number = li->line_number; + intl->address = li->u.pc_offset; + intl->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); } } SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ @@ -1847,18 +1804,51 @@ BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) }
/****************************************************************** - * SymGetLinePrev (DBGHELP.@) + * SymGetLinePrev64 (DBGHELP.@) + * + */ +BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) +{ + struct internal_line_t intl; + + 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); +} + +/****************************************************************** + * SymGetLinePrev (DBGHELP.@) * */ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) { - IMAGEHLP_LINE64 line64; + struct internal_line_t intl;
- line64.SizeOfStruct = sizeof(line64); - copy_line_64_from_32(&line64, Line); - if (!SymGetLinePrev64(hProcess, &line64)) return FALSE; - copy_line_32_from_64(Line, &line64); - return TRUE; + 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); +} + +/****************************************************************** + * SymGetLinePrevW64 (DBGHELP.@) + * + */ +BOOL WINAPI SymGetLinePrevW64(HANDLE hProcess, PIMAGEHLP_LINEW64 Line) +{ + struct internal_line_t intl; + + 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); }
static BOOL symt_get_func_line_next(HANDLE hProcess, struct internal_line_t* intl, void* key, DWORD64 addr)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/symbol.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index ee68967ce5d..86321a7d725 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -320,6 +320,8 @@ void symt_add_func_line(struct module* module, struct symt_function* func, unsigned source_idx, int line_num, ULONG_PTR offset) { struct line_info* dli; + unsigned vlen; + struct line_info* prev; BOOL last_matches = FALSE; int i;
@@ -340,19 +342,24 @@ void symt_add_func_line(struct module* module, struct symt_function* func, break; } } - + vlen = vector_length(&func->vlines); + prev = vlen ? vector_at(&func->vlines, vlen - 1) : NULL; if (!last_matches) { /* we shouldn't have line changes on first line of function */ dli = vector_add(&func->vlines, &module->pool); dli->is_source_file = 1; - dli->is_first = dli->is_last = 0; + dli->is_first = (prev == NULL) ? 1 : 0; + dli->is_last = 0; dli->line_number = 0; dli->u.source_file = source_idx; } + /* clear previous last */ + if (prev) prev->is_last = 0; dli = vector_add(&func->vlines, &module->pool); dli->is_source_file = 0; - dli->is_first = dli->is_last = 0; + dli->is_first = 0; /* only a source file can be first */ + dli->is_last = 1; dli->line_number = line_num; dli->u.pc_offset = func->address + offset; } @@ -465,9 +472,6 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module,
BOOL symt_normalize_function(struct module* module, const struct symt_function* func) { - unsigned len; - struct line_info* dli; - assert(func); /* We aren't adding any more locals or line numbers to this function. * Free any spare memory that we might have allocated. @@ -477,12 +481,6 @@ BOOL symt_normalize_function(struct module* module, const struct symt_function* /* EPP vector_pool_normalize(&func->vlines, &module->pool); */ /* EPP vector_pool_normalize(&func->vchildren, &module->pool); */
- len = vector_length(&func->vlines); - if (len--) - { - dli = vector_at(&func->vlines, 0); dli->is_first = 1; - dli = vector_at(&func->vlines, len); dli->is_last = 1; - } return TRUE; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp_private.h | 2 -- dlls/dbghelp/dwarf.c | 1 - dlls/dbghelp/msc.c | 3 --- dlls/dbghelp/stabs.c | 1 - dlls/dbghelp/symbol.c | 14 -------------- 5 files changed, 21 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 162e8bc004d..f9191ae1205 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -745,8 +745,6 @@ extern struct symt_function* const char* name, ULONG_PTR addr, ULONG_PTR size, struct symt* type) DECLSPEC_HIDDEN; -extern BOOL symt_normalize_function(struct module* module, - const struct symt_function* func) DECLSPEC_HIDDEN; extern void symt_add_func_line(struct module* module, struct symt_function* func, unsigned source_idx, int line_num, diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 319f5c2673c..af84fb660b8 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1983,7 +1983,6 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx, symt_add_function_point(ctx->module, subpgm.func, SymTagCustom, &subpgm.frame, NULL); } - if (subpgm.func) symt_normalize_function(subpgm.ctx->module, subpgm.func);
return di->symt; } diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 36ab355d0a3..c3e243879b2 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -1827,7 +1827,6 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo } else if (curr_func) { - symt_normalize_function(msc_dbg->module, curr_func); curr_func = NULL; } break; @@ -2035,8 +2034,6 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo } }
- if (curr_func) symt_normalize_function(msc_dbg->module, curr_func); - return TRUE; }
diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index bdafb98bbd4..7008f60ea82 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1196,7 +1196,6 @@ static void stabs_finalize_function(struct module* module, struct symt_function* DWORD disp;
if (!func) return; - symt_normalize_function(module, func); /* To define the debug-start of the function, we use the second line number. * Not 100% bullet proof, but better than nothing */ diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 86321a7d725..d72daa4fa8d 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -470,20 +470,6 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module, return sym; }
-BOOL symt_normalize_function(struct module* module, const struct symt_function* func) -{ - assert(func); - /* We aren't adding any more locals or line numbers to this function. - * Free any spare memory that we might have allocated. - */ - assert(func->symt.tag == SymTagFunction); - -/* EPP vector_pool_normalize(&func->vlines, &module->pool); */ -/* EPP vector_pool_normalize(&func->vchildren, &module->pool); */ - - return TRUE; -} - struct symt_thunk* symt_new_thunk(struct module* module, struct symt_compiland* compiland, const char* name, THUNK_ORDINAL ord,