dbghelp: Added support for locating a .dwz file (GNU extension) attached to a debug file.

A DWZ file contains additional Dwarf debug information, and can be shared
across several debug info files.

Signed-off-by: Eric Pouech <eric.pouech@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Eric Pouech 2021-09-16 11:09:51 +02:00 committed by Alexandre Julliard
parent fc380e0691
commit e5dbf5f74e
2 changed files with 101 additions and 0 deletions

View File

@ -194,6 +194,7 @@ struct macho64_nlist
}; };
BOOL image_check_alternate(struct image_file_map* fmap, const struct module* module) DECLSPEC_HIDDEN; BOOL image_check_alternate(struct image_file_map* fmap, const struct module* module) DECLSPEC_HIDDEN;
struct image_file_map* image_load_debugaltlink(struct image_file_map* fmap, struct module* module) DECLSPEC_HIDDEN;
BOOL elf_map_handle(HANDLE handle, struct image_file_map* fmap) DECLSPEC_HIDDEN; BOOL elf_map_handle(HANDLE handle, struct image_file_map* fmap) DECLSPEC_HIDDEN;
BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) DECLSPEC_HIDDEN; BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) DECLSPEC_HIDDEN;

View File

@ -629,6 +629,106 @@ found:
return TRUE; return TRUE;
} }
/******************************************************************
* image_load_debugaltlink
*
* Handle a (potential) .gnu_debugaltlink section and the link to
* (another) alternate debug file.
* Return an heap-allocated image_file_map when the section .gnu_debugaltlink is present,
* and a matching debug file has been located.
*/
struct image_file_map* image_load_debugaltlink(struct image_file_map* fmap, struct module* module)
{
struct image_section_map debugaltlink_sect;
const char* data;
struct image_file_map* fmap_link = NULL;
BOOL ret = FALSE;
for (; fmap; fmap = fmap->alternate)
{
if (image_find_section(fmap, ".gnu_debugaltlink", &debugaltlink_sect)) break;
}
if (!fmap)
{
TRACE("No .gnu_debugaltlink section found for %s\n", debugstr_w(module->modulename));
return NULL;
}
data = image_map_section(&debugaltlink_sect);
if (data != IMAGE_NO_MAP)
{
unsigned sect_len;
const BYTE* id;
/* The content of the section is:
* + a \0 terminated string
* + followed by the build-id
* We try loading the dwz_alternate, either as absolute path, or relative to the embedded build-id
*/
sect_len = image_get_map_size(&debugaltlink_sect);
id = memchr(data, '\0', sect_len);
if (id)
{
id++;
fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
if (fmap_link)
{
unsigned filename_len = MultiByteToWideChar(CP_UNIXCP, 0, data, -1, NULL, 0);
/* Trying absolute path */
WCHAR* dst = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(WCHAR));
if (dst)
{
MultiByteToWideChar(CP_UNIXCP, 0, data, -1, dst, filename_len);
ret = image_check_debug_link_gnu_id(dst, fmap_link, id, data + sect_len - (const char*)id);
HeapFree(GetProcessHeap(), 0, dst);
}
/* Trying relative path to build-id directory */
if (!ret)
{
static const WCHAR globalDebugDirW[] =
{'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/','.','b','u','i','l','d','-','i','d','/'};
dst = HeapAlloc(GetProcessHeap(), 0, sizeof(globalDebugDirW) + (3 + filename_len) * sizeof(WCHAR));
if (dst)
{
WCHAR* p;
/* SIGH....
* some relative links are relative to /usr/lib/debug/.build-id, some others are from the directory
* where the alternate file is...
* so try both
*/
p = memcpy(dst, globalDebugDirW, sizeof(globalDebugDirW));
p += ARRAY_SIZE(globalDebugDirW);
MultiByteToWideChar(CP_UNIXCP, 0, data, -1, p, filename_len);
ret = image_check_debug_link_gnu_id(dst, fmap_link, id, data + sect_len - (const char*)id);
if (!ret)
{
p = dst + ARRAY_SIZE(globalDebugDirW);
if ((const char*)id < data + sect_len)
{
*p++ = "0123456789abcdef"[*id >> 4 ];
*p++ = "0123456789abcdef"[*id & 0x0F];
}
*p++ = '/';
MultiByteToWideChar(CP_UNIXCP, 0, data, -1, p, filename_len);
ret = image_check_debug_link_gnu_id(dst, fmap_link, id, data + sect_len - (const char*)id);
}
HeapFree(GetProcessHeap(), 0, dst);
}
}
if (!ret)
{
HeapFree(GetProcessHeap(), 0, fmap_link);
WARN("Couldn't find a match for .gnu_debugaltlink section %s for %s\n", data, debugstr_w(module->modulename));
fmap_link = NULL;
}
}
}
}
image_unmap_section(&debugaltlink_sect);
if (fmap_link) TRACE("Found match .gnu_debugaltlink section for %s\n", debugstr_w(module->modulename));
return fmap_link;
}
/****************************************************************** /******************************************************************
* image_locate_build_id_target * image_locate_build_id_target
* *