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:
parent
ad44094094
commit
64144519a0
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ???) */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue