From 64144519a0cf3be1ea9203274a1ee95dfcdcb281 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sat, 31 Oct 2009 14:57:40 +0100 Subject: [PATCH] winedump, dbghelp: In .pdb files (>= VC2005), handle the case where the codeview_linetab2_file structure is not the first one. --- dlls/dbghelp/msc.c | 82 +++++++++++++++++++++++++++--------------- include/wine/mscvpdb.h | 47 ++++++++++++++++-------- tools/winedump/msc.c | 72 +++++++++++++++++++++++++------------ 3 files changed, 135 insertions(+), 66 deletions(-) diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 2932d2690f7..d31dd712dba 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -1362,48 +1362,72 @@ static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const B } static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const BYTE* linetab, DWORD size, - const char* strimage, DWORD strsize) + const char* strimage, DWORD strsize) { - DWORD offset; unsigned i; DWORD addr; - const struct codeview_linetab2_block* lbh; - const struct codeview_linetab2_file* fd; + const struct codeview_linetab2* lt2; + const struct codeview_linetab2* lt2_files = NULL; + const struct codeview_lt2blk_lines* lines_blk; + const struct codeview_linetab2_file*fd; unsigned source; struct symt_function* func; - if (*(const DWORD*)linetab != 0x000000f4) return; - offset = *((const DWORD*)linetab + 1); - - for (lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset); - (const BYTE*)lbh < linetab + size; - lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block)) + /* locate LT2_FILES_BLOCK (if any) */ + lt2 = (const struct codeview_linetab2*)linetab; + while ((const BYTE*)(lt2 + 1) < linetab + size) { - if (lbh->header != 0x000000f2) - /* FIXME: should also check that whole lbh fits in linetab + size */ + if (lt2->header == LT2_FILES_BLOCK) { - TRACE("block end %x\n", lbh->header); + lt2_files = lt2; break; } - addr = codeview_get_address(msc_dbg, lbh->seg, lbh->start); - TRACE("block from %04x:%08x #%x (%x lines)\n", - lbh->seg, lbh->start, lbh->size, lbh->nlines); - fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset); - /* FIXME: should check that string is within strimage + strsize */ - source = source_new(msc_dbg->module, NULL, strimage + fd->offset); - func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr); - /* FIXME: at least labels support line numbers */ - if (!func || func->symt.tag != SymTagFunction) + lt2 = codeview_linetab2_next_block(lt2); + } + if (!lt2_files) + { + TRACE("No LT2_FILES_BLOCK found\n"); + return; + } + + lt2 = (const struct codeview_linetab2*)linetab; + while ((const BYTE*)(lt2 + 1) < linetab + size) + { + /* FIXME: should also check that whole lines_blk fits in linetab + size */ + switch (lt2->header) { - WARN("--not a func at %04x:%08x %x tag=%d\n", - lbh->seg, lbh->start, addr, func ? func->symt.tag : -1); + case LT2_LINES_BLOCK: + lines_blk = (const struct codeview_lt2blk_lines*)lt2; + /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */ + addr = codeview_get_address(msc_dbg, lines_blk->seg, lines_blk->start); + TRACE("block from %04x:%08x #%x (%x lines)\n", + lines_blk->seg, lines_blk->start, lines_blk->size, lines_blk->nlines); + fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset); + /* FIXME: should check that string is within strimage + strsize */ + source = source_new(msc_dbg->module, NULL, strimage + fd->offset); + func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr); + /* FIXME: at least labels support line numbers */ + if (!func || func->symt.tag != SymTagFunction) + { + WARN("--not a func at %04x:%08x %x tag=%d\n", + lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1); + break; + } + for (i = 0; i < lines_blk->nlines; i++) + { + symt_add_func_line(msc_dbg->module, func, source, + lines_blk->l[i].lineno ^ 0x80000000, + lines_blk->l[i].offset - lines_blk->start); + } + break; + case LT2_FILES_BLOCK: /* skip */ + break; + default: + TRACE("Block end %x\n", lt2->header); + lt2 = (const struct codeview_linetab2*)((const char*)linetab + size); continue; } - for (i = 0; i < lbh->nlines; i++) - { - symt_add_func_line(msc_dbg->module, func, source, - lbh->l[i].lineno ^ 0x80000000, lbh->l[i].offset - lbh->start); - } + lt2 = codeview_linetab2_next_block(lt2); } } diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index 9d52a655b56..2aefa879a90 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -1642,14 +1642,28 @@ struct startend unsigned int end; }; +#define LT2_LINES_BLOCK 0x000000f2 +#define LT2_FILES_BLOCK 0x000000f4 + /* there's a new line tab structure from MS Studio 2005 and after - * it's made of: - * DWORD 000000f4 - * DWORD lineblk_offset (counting bytes after this field) - * an array of codeview_linetab2_file structures - * an array (starting at ) of codeview_linetab2_block structures + * it's made of a list of codeview_linetab2 blocks. + * We've only seen (so far) list with a single LT2_FILES_BLOCK and several + * LT2_LINES_BLOCK. The LT2_FILES block has been encountered either as first + * or last block of the list. + * A LT2_FILES contains one or several codeview_linetab2_file:s */ +struct codeview_linetab2 +{ + DWORD header; + DWORD size_of_block; +}; + +static inline const struct codeview_linetab2* codeview_linetab2_next_block(const struct codeview_linetab2* lt2) +{ + return (const struct codeview_linetab2*)((const char*)(lt2 + 1) + lt2->size_of_block); +} + struct codeview_linetab2_file { DWORD offset; /* offset in string table for filename */ @@ -1658,16 +1672,21 @@ struct codeview_linetab2_file WORD pad0; /* always 0 */ }; -struct codeview_linetab2_block +struct codeview_lt2blk_files { - DWORD header; /* 0x000000f2 */ - DWORD size_of_block; /* next block is at # bytes after this field */ - DWORD start; /* start address of function with line numbers */ - DWORD seg; /* segment of function with line numbers */ - DWORD size; /* size of function with line numbers */ - DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */ - DWORD nlines; /* number of lines in this block */ - DWORD size_lines; /* number of bytes following for line number information */ + struct codeview_linetab2 lt2; /* LT2_FILES */ + struct codeview_linetab2_file file[1]; +}; + +struct codeview_lt2blk_lines +{ + struct codeview_linetab2 lt2; /* LT2_LINE_BLOCK */ + DWORD start; /* start address of function with line numbers */ + DWORD seg; /* segment of function with line numbers */ + DWORD size; /* size of function with line numbers */ + DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */ + DWORD nlines; /* number of lines in this block */ + DWORD size_lines; /* number of bytes following for line number information */ struct { DWORD offset; /* offset (from :) for line number */ DWORD lineno; /* the line number (OR:ed with 0x80000000 why ???) */ diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index b0298528300..95cc2515296 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1417,36 +1417,62 @@ void codeview_dump_linetab(const char* linetab, DWORD size, BOOL pascal_str, con void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx) { - DWORD offset; unsigned i; - const struct codeview_linetab2_block* lbh; - const struct codeview_linetab2_file* fd; + const struct codeview_linetab2* lt2; + const struct codeview_linetab2* lt2_files = NULL; + const struct codeview_lt2blk_lines* lines_blk; + const struct codeview_linetab2_file*fd; - if (*(const DWORD*)linetab != 0x000000f4) return; - offset = *((const DWORD*)linetab + 1); - lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset); - while ((const char*)lbh < linetab + size) + /* locate LT2_FILES_BLOCK (if any) */ + lt2 = (const struct codeview_linetab2*)linetab; + while ((const char*)(lt2 + 1) < linetab + size) { - if (lbh->header != 0x000000f2) - /* FIXME: should also check that whole lbh fits in linetab + size */ + if (lt2->header == LT2_FILES_BLOCK) { - /* printf("%sblock end %x\n", pfx, lbh->header); */ + lt2_files = lt2; break; } - printf("%sblock from %04x:%08x #%x (%x lines)\n", - pfx, lbh->seg, lbh->start, lbh->size, lbh->nlines); - fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset); - printf("%s md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", - pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3], - fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7], - fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11], - fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15]); - /* FIXME: should check that string is within strimage + strsize */ - printf("%s file=%s\n", pfx, strimage ? strimage + fd->offset : "--none--"); - for (i = 0; i < lbh->nlines; i++) + lt2 = codeview_linetab2_next_block(lt2); + } + if (!lt2_files) + { + printf("%sNo LT2_FILES_BLOCK found\n", pfx); + return; + } + + lt2 = (const struct codeview_linetab2*)linetab; + while ((const char*)(lt2 + 1) < linetab + size) + { + /* FIXME: should also check that whole lbh fits in linetab + size */ + switch (lt2->header) { - printf("%s offset=%08x line=%d\n", pfx, lbh->l[i].offset, lbh->l[i].lineno ^ 0x80000000); + case LT2_LINES_BLOCK: + lines_blk = (const struct codeview_lt2blk_lines*)lt2; + printf("%sblock from %04x:%08x #%x (%x lines) fo=%x\n", + pfx, lines_blk->seg, lines_blk->start, lines_blk->size, + lines_blk->nlines, lines_blk->file_offset); + /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */ + fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset); + printf("%s md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3], + fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7], + fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11], + fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15]); + /* FIXME: should check that string is within strimage + strsize */ + printf("%s file=%s\n", pfx, strimage ? strimage + fd->offset : "--none--"); + for (i = 0; i < lines_blk->nlines; i++) + { + printf("%s offset=%08x line=%d\n", + pfx, lines_blk->l[i].offset, lines_blk->l[i].lineno ^ 0x80000000); + } + break; + case LT2_FILES_BLOCK: /* skip */ + break; + default: + printf("%sblock end %x\n", pfx, lt2->header); + lt2 = (const struct codeview_linetab2*)((const char*)linetab + size); + continue; } - lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block); + lt2 = codeview_linetab2_next_block(lt2); } }