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:
parent
e6c88226ef
commit
1dc3ef5188
|
@ -3,6 +3,7 @@ IMPORTLIB = dbghelp
|
|||
EXTRADEFS = -D_IMAGEHLP_SOURCE_
|
||||
IMPORTS = psapi
|
||||
DELAYIMPORTS = version
|
||||
EXTRALIBS = @ZLIB@
|
||||
|
||||
C_SRCS = \
|
||||
coff.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);
|
||||
|
|
Loading…
Reference in New Issue