Commit 1dc3ef51 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Alexandre Julliard

dbghelp: Add support for zlib compressed debug sections.

Patch created with the assistance of Eric Pouech who helped diagnose the problem, wrote some parts of this patch and reviewed this patch.
parent e6c88226
...@@ -3,6 +3,7 @@ IMPORTLIB = dbghelp ...@@ -3,6 +3,7 @@ IMPORTLIB = dbghelp
EXTRADEFS = -D_IMAGEHLP_SOURCE_ EXTRADEFS = -D_IMAGEHLP_SOURCE_
IMPORTS = psapi IMPORTS = psapi
DELAYIMPORTS = version DELAYIMPORTS = version
EXTRALIBS = @ZLIB@
C_SRCS = \ C_SRCS = \
coff.c \ coff.c \
......
...@@ -42,7 +42,12 @@ ...@@ -42,7 +42,12 @@
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#include "windef.h" #include "windef.h"
#include "winternl.h"
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
#include "ole2.h" #include "ole2.h"
...@@ -157,6 +162,7 @@ typedef struct dwarf2_debug_info_s ...@@ -157,6 +162,7 @@ typedef struct dwarf2_debug_info_s
typedef struct dwarf2_section_s typedef struct dwarf2_section_s
{ {
BOOL compressed;
const unsigned char* address; const unsigned char* address;
unsigned size; unsigned size;
DWORD_PTR rva; DWORD_PTR rva;
...@@ -3282,29 +3288,134 @@ static void dwarf2_location_compute(struct process* pcs, ...@@ -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*)&sect[4];
li.u.LowPart = *(DWORD*)&sect[8];
#else
li.u.HighPart = RtlUlongByteSwap(*(DWORD*)&sect[4]);
li.u.LowPart = RtlUlongByteSwap(*(DWORD*)&sect[8]);
#endif
addr = HeapAlloc(GetProcessHeap(), 0, li.QuadPart);
if (!addr)
goto out;
z.next_in = &sect[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, 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; struct image_section_map local_ism;
if (!ism) ism = &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->address = (const BYTE*)image_map_section(ism);
section->size = 0; section->size = image_get_map_size(ism);
section->rva = 0; section->rva = image_get_map_rva(ism);
return FALSE; return TRUE;
} }
section->address = (const BYTE*)image_map_section(ism); section->address = NULL;
section->size = image_get_map_size(ism); section->size = 0;
section->rva = image_get_map_rva(ism); section->rva = 0;
return TRUE;
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, BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
...@@ -3318,12 +3429,12 @@ 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; BOOL ret = TRUE;
struct module_format* dwarf2_modfmt; struct module_format* dwarf2_modfmt;
dwarf2_init_section(&eh_frame, fmap, ".eh_frame", &eh_frame_sect); dwarf2_init_section(&eh_frame, fmap, ".eh_frame", NULL, &eh_frame_sect);
dwarf2_init_section(&section[section_debug], fmap, ".debug_info", &debug_sect); dwarf2_init_section(&section[section_debug], fmap, ".debug_info", ".zdebug_info", &debug_sect);
dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect); dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", ".zdebug_abbrev", &debug_abbrev_sect);
dwarf2_init_section(&section[section_string], fmap, ".debug_str", &debug_str_sect); dwarf2_init_section(&section[section_string], fmap, ".debug_str", ".zdebug_str", &debug_str_sect);
dwarf2_init_section(&section[section_line], fmap, ".debug_line", &debug_line_sect); dwarf2_init_section(&section[section_line], fmap, ".debug_line", ".zdebug_line", &debug_line_sect);
dwarf2_init_section(&section[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect); dwarf2_init_section(&section[section_ranges], fmap, ".debug_ranges", ".zdebug_ranges", &debug_ranges_sect);
/* to do anything useful we need either .eh_frame or .debug_info */ /* to do anything useful we need either .eh_frame or .debug_info */
if ((!eh_frame.address || eh_frame.address == IMAGE_NO_MAP) && if ((!eh_frame.address || eh_frame.address == IMAGE_NO_MAP) &&
...@@ -3365,8 +3476,8 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, ...@@ -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 /* As we'll need later some sections' content, we won't unmap these
* sections upon existing this function * 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_loc, fmap, ".debug_loc", ".zdebug_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_frame, fmap, ".debug_frame", ".zdebug_frame", NULL);
dwarf2_modfmt->u.dwarf2_info->eh_frame = eh_frame; dwarf2_modfmt->u.dwarf2_info->eh_frame = eh_frame;
while (mod_ctx.data < mod_ctx.end_data) while (mod_ctx.data < mod_ctx.end_data)
...@@ -3385,6 +3496,12 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, ...@@ -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; dwarf2_modfmt->u.dwarf2_info->word_size = fmap->addr_size / 8;
leave: leave:
dwarf2_fini_section(&section[section_debug]);
dwarf2_fini_section(&section[section_abbrev]);
dwarf2_fini_section(&section[section_string]);
dwarf2_fini_section(&section[section_line]);
dwarf2_fini_section(&section[section_ranges]);
image_unmap_section(&debug_sect); image_unmap_section(&debug_sect);
image_unmap_section(&debug_abbrev_sect); image_unmap_section(&debug_abbrev_sect);
image_unmap_section(&debug_str_sect); image_unmap_section(&debug_str_sect);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment