Maarten Lankhorst : dbghelp: Add support for zlib compressed debug sections .
Alexandre Julliard
julliard at winehq.org
Wed Jan 30 13:43:23 CST 2013
Module: wine
Branch: master
Commit: 1dc3ef518854173e545b9ec2b71be1dba461895d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1dc3ef518854173e545b9ec2b71be1dba461895d
Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Tue Jan 29 13:01:10 2013 +0100
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.
---
dlls/dbghelp/Makefile.in | 1 +
dlls/dbghelp/dwarf.c | 157 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 138 insertions(+), 20 deletions(-)
diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in
index fcbe40f..7cb0544 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 2ce26fa..8ded268 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -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*)§[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);
More information about the wine-cvs
mailing list