mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-19 17:06:04 -07:00
Merge branch 'mr-split-pe-dwarf' into 'master'
Support separated debug information for PE images. See merge request wine/wine!6715
This commit is contained in:
commit
f451e95b28
4 changed files with 108 additions and 48 deletions
15
configure.ac
15
configure.ac
|
@ -1004,16 +1004,23 @@ This is an error since --enable-archs=$wine_arch was requested.])])
|
|||
if test "x$ac_debug_format_seen" = x
|
||||
then
|
||||
case $wine_crossdebug in
|
||||
*dwarf) WINE_TRY_PE_CFLAGS([-gdwarf-4]) ;;
|
||||
*dwarf) WINE_TRY_PE_CFLAGS([-gdwarf-4],[:],
|
||||
[WINE_TRY_PE_CFLAGS([-gdwarf-4 -Wl,-debug:dwarf],
|
||||
[AS_VAR_APPEND([${wine_arch}_CFLAGS],[" -gdwarf-4"])
|
||||
AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,-debug:dwarf"])])]) ;;
|
||||
pdb) WINE_TRY_PE_CFLAGS([-gcodeview]) ;;
|
||||
esac
|
||||
fi
|
||||
AS_VAR_SET([${wine_arch}_DEBUG],[$wine_crossdebug])
|
||||
|
||||
test "x$enable_werror" != xyes || WINE_TRY_PE_CFLAGS([-Werror])
|
||||
test "x$enable_build_id" != xyes || WINE_TRY_PE_CFLAGS([-Wl,--build-id],
|
||||
[AS_VAR_APPEND([${wine_arch}_CFLAGS],[" -Wl,--build-id"])
|
||||
AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,--build-id"])])
|
||||
if test "x$enable_build_id" = xyes
|
||||
then
|
||||
WINE_TRY_PE_CFLAGS([-Wl,--build-id],
|
||||
[AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,--build-id"])],
|
||||
[WINE_TRY_PE_CFLAGS([-Wl,-build-id],
|
||||
[AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,-build-id"])])])
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -664,69 +669,80 @@ static WCHAR* append_hex(WCHAR* dst, const BYTE* id, const BYTE* end)
|
|||
return dst;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* image_locate_build_id_target
|
||||
*
|
||||
* Try to find the .so file containing the debug info out of the build-id note information
|
||||
*/
|
||||
static struct image_file_map* image_locate_build_id_target(const BYTE* id, unsigned idlen)
|
||||
static BOOL image_locate_build_id_target_in_dir(struct image_file_map *fmap_link, const BYTE* id, unsigned idlen, const WCHAR *from)
|
||||
{
|
||||
struct image_file_map* fmap_link = NULL;
|
||||
DWORD sz;
|
||||
WCHAR* p;
|
||||
WCHAR* z;
|
||||
size_t from_len = wcslen(from);
|
||||
BOOL found = FALSE;
|
||||
WCHAR *p, *z;
|
||||
|
||||
fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
|
||||
if (!fmap_link) return NULL;
|
||||
|
||||
p = malloc(sizeof(L"/usr/lib/debug/.build-id/") +
|
||||
(idlen * 2 + 1) * sizeof(WCHAR) + sizeof(L".debug"));
|
||||
if (!p) goto fail;
|
||||
wcscpy(p, L"/usr/lib/debug/.build-id/");
|
||||
z = p + wcslen(p);
|
||||
if (idlen)
|
||||
if ((p = malloc((from_len + idlen * 2 + 1) * sizeof(WCHAR) + sizeof(L".debug"))))
|
||||
{
|
||||
memcpy(p, from, from_len * sizeof(WCHAR));
|
||||
z = p + from_len;
|
||||
z = append_hex(z, id, id + 1);
|
||||
if (idlen > 1)
|
||||
{
|
||||
*z++ = L'/';
|
||||
z = append_hex(z, id + 1, id + idlen);
|
||||
}
|
||||
}
|
||||
wcscpy(z, L".debug");
|
||||
TRACE("checking %s\n", debugstr_w(p));
|
||||
|
||||
if (image_check_debug_link_gnu_id(p, fmap_link, id, idlen))
|
||||
{
|
||||
*z = L'\0';
|
||||
TRACE("checking %s\n", debugstr_w(p));
|
||||
found = image_check_debug_link_gnu_id(p, fmap_link, id, idlen);
|
||||
if (!found)
|
||||
{
|
||||
wcscpy(z, L".debug");
|
||||
TRACE("checking %s\n", debugstr_w(p));
|
||||
found = image_check_debug_link_gnu_id(p, fmap_link, id, idlen);
|
||||
}
|
||||
free(p);
|
||||
return fmap_link;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* image_locate_build_id_target
|
||||
*
|
||||
* Try to find an image file containing the debug info out of the build-id
|
||||
* note information.
|
||||
*/
|
||||
static struct image_file_map* image_locate_build_id_target(const BYTE* id, unsigned idlen)
|
||||
{
|
||||
struct image_file_map* fmap_link;
|
||||
DWORD sz;
|
||||
|
||||
if (!idlen) return NULL;
|
||||
|
||||
if (!(fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link))))
|
||||
return NULL;
|
||||
if (image_locate_build_id_target_in_dir(fmap_link, id, idlen, L"/usr/lib/debug/.build-id/"))
|
||||
return fmap_link;
|
||||
if (image_locate_build_id_target_in_dir(fmap_link, id, idlen, L"/usr/lib/.build-id/"))
|
||||
return fmap_link;
|
||||
|
||||
sz = GetEnvironmentVariableW(L"WINEHOMEDIR", NULL, 0);
|
||||
if (sz)
|
||||
{
|
||||
z = realloc(p, sz * sizeof(WCHAR) +
|
||||
sizeof(L"\\.cache\\debuginfod_client\\") +
|
||||
idlen * 2 * sizeof(WCHAR) + sizeof(L"\\debuginfo") + 500);
|
||||
if (!z) goto fail;
|
||||
p = z;
|
||||
GetEnvironmentVariableW(L"WINEHOMEDIR", p, sz);
|
||||
z = p + sz - 1;
|
||||
wcscpy(z, L"\\.cache\\debuginfod_client\\");
|
||||
z += wcslen(z);
|
||||
z = append_hex(z, id, id + idlen);
|
||||
wcscpy(z, L"\\debuginfo");
|
||||
TRACE("checking %ls\n", p);
|
||||
if (image_check_debug_link_gnu_id(p, fmap_link, id, idlen))
|
||||
WCHAR *p, *z;
|
||||
p = malloc(sz * sizeof(WCHAR) +
|
||||
sizeof(L"\\.cache\\debuginfod_client\\") +
|
||||
idlen * 2 * sizeof(WCHAR) + sizeof(L"\\debuginfo") + 500);
|
||||
if (p && GetEnvironmentVariableW(L"WINEHOMEDIR", p, sz) == sz - 1)
|
||||
{
|
||||
BOOL found;
|
||||
|
||||
wcscpy(p + sz - 1, L"\\.cache\\debuginfod_client\\");
|
||||
z = p + wcslen(p);
|
||||
z = append_hex(z, id, id + idlen);
|
||||
wcscpy(z, L"\\debuginfo");
|
||||
TRACE("checking %ls\n", p);
|
||||
found = image_check_debug_link_gnu_id(p, fmap_link, id, idlen);
|
||||
free(p);
|
||||
return fmap_link;
|
||||
if (found) return fmap_link;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("not found\n");
|
||||
fail:
|
||||
free(p);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, fmap_link);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -838,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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue