winedump, dbghelp: In .pdb files (>= VC2005), handle the case where the codeview_linetab2_file structure is not the first one.

This commit is contained in:
Eric Pouech 2009-10-31 14:57:40 +01:00 committed by Alexandre Julliard
parent ad44094094
commit 64144519a0
3 changed files with 135 additions and 66 deletions

View File

@ -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);
}
}

View File

@ -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 <lineblk_offset>) 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 <seg>:<start>) for line number */
DWORD lineno; /* the line number (OR:ed with 0x80000000 why ???) */

View File

@ -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);
}
}