diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in index fcbe40f6115..7cb0544c315 100644 --- a/dlls/dbghelp/Makefile.in +++ b/dlls/dbghelp/Makefile.in @@ -3,6 +3,7 @@ IMPORTLIB = dbghelp EXTRADEFS = -D_IMAGEHLP_SOURCE_ IMPORTS = psapi DELAYIMPORTS = version +EXTRALIBS = @ZLIB@ C_SRCS = \ coff.c \ diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2ce26fab983..8ded268351e 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -42,7 +42,12 @@ #include #include +#ifdef HAVE_ZLIB +#include +#endif + #include "windef.h" +#include "winternl.h" #include "winbase.h" #include "winuser.h" #include "ole2.h" @@ -157,6 +162,7 @@ typedef struct dwarf2_debug_info_s typedef struct dwarf2_section_s { + BOOL compressed; const unsigned char* address; unsigned size; DWORD_PTR rva; @@ -3282,29 +3288,134 @@ static void dwarf2_location_compute(struct process* pcs, } } -static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt) +#ifdef HAVE_ZLIB +static void *zalloc(void *priv, uInt items, uInt sz) { - HeapFree(GetProcessHeap(), 0, modfmt); + return HeapAlloc(GetProcessHeap(), 0, items * sz); } +static void zfree(void *priv, void *addr) +{ + HeapFree(GetProcessHeap(), 0, addr); +} + +static inline BOOL dwarf2_init_zsection(dwarf2_section_t* section, + const char* zsectname, + struct image_section_map* ism) +{ + z_stream z; + LARGE_INTEGER li; + int res; + BOOL ret = FALSE; + + BYTE *addr, *sect = (BYTE *)image_map_section(ism); + size_t sz = image_get_map_size(ism); + + if (sz <= 12 || memcmp(sect, "ZLIB", 4)) + { + ERR("invalid compressed section %s\n", zsectname); + goto out; + } + +#ifdef WORDS_BIGENDIAN + li.u.HighPart = *(DWORD*)§[4]; + li.u.LowPart = *(DWORD*)§[8]; +#else + li.u.HighPart = RtlUlongByteSwap(*(DWORD*)§[4]); + li.u.LowPart = RtlUlongByteSwap(*(DWORD*)§[8]); +#endif + + addr = HeapAlloc(GetProcessHeap(), 0, li.QuadPart); + if (!addr) + goto out; + + z.next_in = §[12]; + z.avail_in = sz - 12; + z.opaque = NULL; + z.zalloc = zalloc; + z.zfree = zfree; + + res = inflateInit(&z); + if (res != Z_OK) + { + FIXME("inflateInit failed with %i / %s\n", res, z.msg); + goto out_free; + } + + do { + z.next_out = addr + z.total_out; + z.avail_out = li.QuadPart - z.total_out; + res = inflate(&z, Z_FINISH); + } while (z.avail_in && res == Z_STREAM_END); + + if (res != Z_STREAM_END) + { + FIXME("Decompression failed with %i / %s\n", res, z.msg); + goto out_end; + } + + ret = TRUE; + section->compressed = TRUE; + section->address = addr; + section->rva = image_get_map_rva(ism); + section->size = z.total_out; + +out_end: + inflateEnd(&z); +out_free: + if (!ret) + HeapFree(GetProcessHeap(), 0, addr); +out: + image_unmap_section(ism); + return ret; +} + +#endif + static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap, - const char* sectname, struct image_section_map* ism) + const char* sectname, const char* zsectname, + struct image_section_map* ism) { struct image_section_map local_ism; if (!ism) ism = &local_ism; - if (!image_find_section(fmap, sectname, ism)) + + section->compressed = FALSE; + if (image_find_section(fmap, sectname, ism)) { - section->address = NULL; - section->size = 0; - section->rva = 0; - return FALSE; + section->address = (const BYTE*)image_map_section(ism); + section->size = image_get_map_size(ism); + section->rva = image_get_map_rva(ism); + return TRUE; } - section->address = (const BYTE*)image_map_section(ism); - section->size = image_get_map_size(ism); - section->rva = image_get_map_rva(ism); - return TRUE; + section->address = NULL; + section->size = 0; + section->rva = 0; + + if (zsectname && image_find_section(fmap, zsectname, ism)) + { +#ifdef HAVE_ZLIB + return dwarf2_init_zsection(section, zsectname, ism); +#else + FIXME("dbghelp not built with zlib, but compressed section found\n" ); +#endif + } + + return FALSE; +} + +static inline void dwarf2_fini_section(dwarf2_section_t* section) +{ + if (section->compressed) + HeapFree(GetProcessHeap(), 0, (void*)section->address); +} + +static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt) +{ + dwarf2_fini_section(&modfmt->u.dwarf2_info->debug_loc); + dwarf2_fini_section(&modfmt->u.dwarf2_info->debug_frame); + HeapFree(GetProcessHeap(), 0, modfmt); } BOOL dwarf2_parse(struct module* module, unsigned long load_offset, @@ -3318,12 +3429,12 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, BOOL ret = TRUE; struct module_format* dwarf2_modfmt; - dwarf2_init_section(&eh_frame, fmap, ".eh_frame", &eh_frame_sect); - dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect); - dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect); - dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect); - dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect); - dwarf2_init_section(§ion[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect); + dwarf2_init_section(&eh_frame, fmap, ".eh_frame", NULL, &eh_frame_sect); + dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", ".zdebug_info", &debug_sect); + dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", ".zdebug_abbrev", &debug_abbrev_sect); + dwarf2_init_section(§ion[section_string], fmap, ".debug_str", ".zdebug_str", &debug_str_sect); + dwarf2_init_section(§ion[section_line], fmap, ".debug_line", ".zdebug_line", &debug_line_sect); + dwarf2_init_section(§ion[section_ranges], fmap, ".debug_ranges", ".zdebug_ranges", &debug_ranges_sect); /* to do anything useful we need either .eh_frame or .debug_info */ if ((!eh_frame.address || eh_frame.address == IMAGE_NO_MAP) && @@ -3365,8 +3476,8 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, /* As we'll need later some sections' content, we won't unmap these * sections upon existing this function */ - dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_loc, fmap, ".debug_loc", NULL); - dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_frame, fmap, ".debug_frame", NULL); + dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_loc, fmap, ".debug_loc", ".zdebug_loc", NULL); + dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_frame, fmap, ".debug_frame", ".zdebug_frame", NULL); dwarf2_modfmt->u.dwarf2_info->eh_frame = eh_frame; while (mod_ctx.data < mod_ctx.end_data) @@ -3385,6 +3496,12 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, dwarf2_modfmt->u.dwarf2_info->word_size = fmap->addr_size / 8; leave: + dwarf2_fini_section(§ion[section_debug]); + dwarf2_fini_section(§ion[section_abbrev]); + dwarf2_fini_section(§ion[section_string]); + dwarf2_fini_section(§ion[section_line]); + dwarf2_fini_section(§ion[section_ranges]); + image_unmap_section(&debug_sect); image_unmap_section(&debug_abbrev_sect); image_unmap_section(&debug_str_sect);