diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index d8761bd599a..8def6a7dae6 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -788,6 +788,8 @@ extern BOOL pe_unmap_directory(struct module* module, int dirno, const c extern DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info); extern const BYTE* pe_lock_region_from_rva(struct module *module, DWORD rva, DWORD size, DWORD *length); extern BOOL pe_unlock_region(struct module *module, const BYTE* region); +struct image_file_map; +extern BOOL pe_has_buildid_debug(struct image_file_map *fmap, GUID *guid); /* source.c */ extern unsigned source_new(struct module* module, const char* basedir, const char* source); diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 26a43be875b..61331c4c5b2 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -527,6 +527,7 @@ static BOOL image_check_debug_link_gnu_id(const WCHAR* file, struct image_file_m { struct image_section_map buildid_sect; DWORD read_bytes; + GUID guid; HANDLE handle; WCHAR *path; WORD magic; @@ -545,6 +546,9 @@ static BOOL image_check_debug_link_gnu_id(const WCHAR* file, struct image_file_m ret = elf_map_handle(handle, fmap); CloseHandle(handle); + if (ret && pe_has_buildid_debug(fmap, &guid)) + return TRUE; + if (ret && image_find_section(fmap, ".note.gnu.build-id", &buildid_sect)) { const UINT32* note; @@ -557,12 +561,13 @@ static BOOL image_check_debug_link_gnu_id(const WCHAR* file, struct image_file_m { if (note[1] == idlen && !memcmp(note + 3 + ((note[0] + 3) >> 2), id, idlen)) return TRUE; - WARN("mismatch in buildid information for %s\n", debugstr_w(file)); } } image_unmap_section(&buildid_sect); image_unmap_file(fmap); } + if (ret) + WARN("mismatch in buildid information for %s\n", debugstr_w(file)); return FALSE; } @@ -849,7 +854,18 @@ BOOL image_check_alternate(struct image_file_map* fmap, const struct module* mod struct image_file_map* fmap_link = NULL; /* if present, add the .gnu_debuglink file as an alternate to current one */ - if (image_find_section(fmap, ".note.gnu.build-id", &buildid_sect)) + if (fmap->modtype == DMT_PE) + { + GUID guid; + + if (pe_has_buildid_debug(fmap, &guid)) + { + /* reorder bytes to match little endian order */ + fmap_link = image_locate_build_id_target((const BYTE*)&guid, sizeof(guid)); + } + } + /* if present, add the .note.gnu.build-id as an alternate to current one */ + if (!fmap_link && image_find_section(fmap, ".note.gnu.build-id", &buildid_sect)) { const UINT32* note; diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 75060e2dfa6..bd3d6000535 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -1036,3 +1036,27 @@ DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) } return msc_get_file_indexinfo(image, dbg, dirsize / sizeof(*dbg), info); } + +/* check if image contains a debug entry that contains a gcc/mingw - clang build-id information */ +BOOL pe_has_buildid_debug(struct image_file_map *fmap, GUID *guid) +{ + BOOL ret = FALSE; + + if (fmap->modtype == DMT_PE) + { + SYMSRV_INDEX_INFOW info = {.sizeofstruct = sizeof(info)}; + const void *image = pe_map_full(fmap, NULL); + + if (image) + { + DWORD retval = pe_get_file_indexinfo((void*)image, GetFileSize(fmap->u.pe.hMap, NULL), &info); + if ((retval == ERROR_SUCCESS || retval == ERROR_BAD_EXE_FORMAT) && info.age && !info.pdbfile[0]) + { + *guid = info.guid; + ret = TRUE; + } + pe_unmap_full(fmap); + } + } + return ret; +}