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.
This commit is contained in:
Maarten Lankhorst 2013-01-29 13:01:10 +01:00 committed by Alexandre Julliard
parent e6c88226ef
commit 1dc3ef5188
2 changed files with 138 additions and 20 deletions

View File

@ -3,6 +3,7 @@ IMPORTLIB = dbghelp
EXTRADEFS = -D_IMAGEHLP_SOURCE_
IMPORTS = psapi
DELAYIMPORTS = version
EXTRALIBS = @ZLIB@
C_SRCS = \
coff.c \

View File

@ -42,7 +42,12 @@
#include <assert.h>
#include <stdarg.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#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*)&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,
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->address = NULL;
section->size = 0;
section->rva = 0;
return FALSE;
}
section->compressed = FALSE;
if (image_find_section(fmap, sectname, ism))
{
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(&section[section_debug], fmap, ".debug_info", &debug_sect);
dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
dwarf2_init_section(&section[section_string], fmap, ".debug_str", &debug_str_sect);
dwarf2_init_section(&section[section_line], fmap, ".debug_line", &debug_line_sect);
dwarf2_init_section(&section[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect);
dwarf2_init_section(&eh_frame, fmap, ".eh_frame", NULL, &eh_frame_sect);
dwarf2_init_section(&section[section_debug], fmap, ".debug_info", ".zdebug_info", &debug_sect);
dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", ".zdebug_abbrev", &debug_abbrev_sect);
dwarf2_init_section(&section[section_string], fmap, ".debug_str", ".zdebug_str", &debug_str_sect);
dwarf2_init_section(&section[section_line], fmap, ".debug_line", ".zdebug_line", &debug_line_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 */
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(&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_abbrev_sect);
image_unmap_section(&debug_str_sect);