From: Eric Pouech Subject: [PATCH 02/12] dbghelp: Added support for locating a .dwz file (GNU extension) attached to a debug file Message-Id: <163178339125.542088.16156899826897994360.stgit@euterpe> Date: Thu, 16 Sep 2021 11:09:51 +0200 In-Reply-To: <163178326421.542088.17939125251680595504.stgit@euterpe> References: <163178326421.542088.17939125251680595504.stgit@euterpe> A DWZ file contains additional Dwarf debug information, and can be shared across several debug info files. (see GNU dwz tool for more informations) Signed-off-by: Eric Pouech --- dlls/dbghelp/image_private.h | 1 dlls/dbghelp/module.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h index 83442ffb9e1..964e974e49d 100644 --- a/dlls/dbghelp/image_private.h +++ b/dlls/dbghelp/image_private.h @@ -194,6 +194,7 @@ struct macho64_nlist }; 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 pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index c71e016b824..826306cfb38 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -629,6 +629,106 @@ found: 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 *