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*)&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->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(&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);




More information about the wine-cvs mailing list