[PATCH 6/9] include/wine/mscvpdb.h, tools/winedump: update some line number oriented definitions
Eric Pouech
eric.pouech at gmail.com
Tue Nov 2 09:32:23 CDT 2021
Currently, they are described as linetab2 internally. And they miss quite
a number of elements.
>From MS' docs, they are described as debug subsection (inside PDB's SYMBOL
stream)
Update include/wine/mscvpdb.h to describe those.
Update tools/winedump to dump them properly.
Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
---
include/wine/mscvpdb.h | 103 +++++++++++++++++++++++++++++++++
tools/winedump/msc.c | 148 +++++++++++++++++++++++++++++++++---------------
2 files changed, 206 insertions(+), 45 deletions(-)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h
index ca5422c3a65..733b4ab5336 100644
--- a/include/wine/mscvpdb.h
+++ b/include/wine/mscvpdb.h
@@ -2162,6 +2162,109 @@ enum BinaryAnnotationOpcode
* Line number information
* ======================================== */
+enum DEBUG_S_SUBSECTION_TYPE
+{
+ DEBUG_S_IGNORE = 0x80000000, /* bit flag: when set, ignore whole subsection content */
+
+ DEBUG_S_SYMBOLS = 0xf1,
+ DEBUG_S_LINES,
+ DEBUG_S_STRINGTABLE,
+ DEBUG_S_FILECHKSMS,
+ DEBUG_S_FRAMEDATA,
+ DEBUG_S_INLINEELINES,
+ DEBUG_S_CROSSSCOPEIMPORTS,
+ DEBUG_S_CROSSSCOPEEXPORTS,
+
+ DEBUG_S_IL_LINES,
+ DEBUG_S_FUNC_MDTOKEN_MAP,
+ DEBUG_S_TYPE_MDTOKEN_MAP,
+ DEBUG_S_MERGED_ASSEMBLYINPUT,
+
+ DEBUG_S_COFF_SYMBOL_RVA,
+};
+
+struct CV_DebugSSubsectionHeader_t
+{
+ enum DEBUG_S_SUBSECTION_TYPE type;
+ unsigned cbLen;
+};
+
+struct CV_DebugSLinesHeader_t
+{
+ unsigned offCon;
+ unsigned short segCon;
+ unsigned short flags;
+ unsigned cbCon;
+};
+
+struct CV_DebugSLinesFileBlockHeader_t
+{
+ unsigned offFile;
+ unsigned nLines;
+ unsigned cbBlock;
+ /* followed by two variable length arrays
+ * CV_Line_t lines[nLines];
+ * ^ columns present when CV_DebugSLinesHeader_t.flags has CV_LINES_HAVE_COLUMNS set
+ * CV_Column_t columns[nLines];
+ */
+};
+
+#define CV_LINES_HAVE_COLUMNS 0x0001
+
+struct CV_Line_t
+{
+ unsigned offset;
+ unsigned linenumStart:24;
+ unsigned deltaLineEnd:7;
+ unsigned fStatement:1;
+};
+
+struct CV_Column_t
+{
+ unsigned short offColumnStart;
+ unsigned short offColumnEnd;
+};
+
+struct CV_Checksum_t /* this one is not defined in microsoft pdb information */
+{
+ unsigned strOffset; /* offset in string table for filename */
+ unsigned char size; /* size of checksum */
+ unsigned char method; /* method used to compute check sum */
+ unsigned char checksum[0]; /* (size) bytes */
+ /* result is padded on 4-byte boundary */
+};
+
+#define CV_INLINEE_SOURCE_LINE_SIGNATURE 0x0
+#define CV_INLINEE_SOURCE_LINE_SIGNATURE_EX 0x1
+
+typedef struct CV_InlineeSourceLine_t
+{
+ cv_itemid_t inlinee; /* function id */
+ unsigned fileId; /* offset in DEBUG_S_FILECHKSMS */
+ unsigned sourceLineNum; /* first line number */
+} InlineeSourceLine;
+
+typedef struct CV_InlineeSourceLineEx_t
+{
+ cv_itemid_t inlinee; /* function id */
+ unsigned fileId; /* offset in DEBUG_S_FILECHKSMS */
+ unsigned sourceLineNum; /* first line number */
+ unsigned int countOfExtraFiles;
+ unsigned extraFileId[0];
+} InlineeSourceLineEx;
+
+#ifdef __WINESRC__
+/* those are Wine only helpers */
+/* align ptr on sz boundary; sz must be a power of 2 */
+#define CV_ALIGN(ptr, sz) ((const void*)(((DWORD_PTR)(ptr) + ((sz) - 1)) & ~((sz) - 1)))
+/* move after (ptr) record */
+#define CV_RECORD_AFTER(ptr) ((const void*)((ptr) + 1))
+/* move after (ptr) record and a gap of sz bytes */
+#define CV_RECORD_GAP(ptr, sz) ((const void*)((const char*)((ptr) + 1) + (sz)))
+/* test whether ptr record is within limit boundary */
+#define CV_IS_INSIDE(ptr, limit) (CV_RECORD_AFTER(ptr) <= (const void*)(limit))
+#endif /* __WINESRC__ */
+
struct codeview_linetab_block
{
unsigned short seg;
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c
index d537764b442..79dd022a088 100644
--- a/tools/winedump/msc.c
+++ b/tools/winedump/msc.c
@@ -1927,61 +1927,119 @@ void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx
void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx)
{
unsigned i;
- 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;
-
- /* locate LT2_FILES_BLOCK (if any) */
- lt2 = (const struct codeview_linetab2*)linetab;
- while ((const char*)(lt2 + 1) < linetab + size)
+ const struct CV_DebugSSubsectionHeader_t* hdr;
+ const struct CV_DebugSSubsectionHeader_t* next_hdr;
+ const struct CV_DebugSLinesHeader_t* lines_hdr;
+ const struct CV_DebugSLinesFileBlockHeader_t* files_hdr;
+ const struct CV_Column_t* cols;
+ const struct CV_Checksum_t* chksms;
+ const struct CV_InlineeSourceLine_t* inlsrc;
+ const struct CV_InlineeSourceLineEx_t* inlsrcex;
+
+ static const char* subsect_types[] = /* starting at 0xf1 */
{
- if (lt2->header == LT2_FILES_BLOCK)
+ "SYMBOLS", "LINES", "STRINGTABLE", "FILECHKSMS",
+ "FRAMEDATA", "INLINEELINES", "CROSSSCOPEIMPORTS", "CROSSSCOPEEXPORTS",
+ "IL_LINES", "FUNC_MDTOKEN_MAP", "TYPE_MDTOKEN_MAP", "MERGED_ASSEMBLYINPUT",
+ "COFF_SYMBOL_RVA"
+ };
+ hdr = (const struct CV_DebugSSubsectionHeader_t*)linetab;
+ while (CV_IS_INSIDE(hdr, linetab + size))
+ {
+ next_hdr = CV_RECORD_GAP(hdr, hdr->cbLen);
+ if (hdr->type & DEBUG_S_IGNORE)
{
- lt2_files = lt2;
- break;
+ printf("%s------ debug subsection <ignored>\n", pfx);
+ hdr = next_hdr;
+ continue;
}
- 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------ debug subsection %s\n", pfx,
+ (hdr->type >= 0xf1 && hdr->type - 0xf1 < ARRAY_SIZE(subsect_types)) ?
+ subsect_types[hdr->type - 0xf1] : "<<unknown>>");
+ switch (hdr->type)
{
- 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++)
+ case DEBUG_S_LINES:
+ lines_hdr = CV_RECORD_AFTER(hdr);
+ printf("%s block from %04x:%08x flags:%x size=%u\n",
+ pfx, lines_hdr->segCon, lines_hdr->offCon, lines_hdr->flags, lines_hdr->cbCon);
+ files_hdr = CV_RECORD_AFTER(lines_hdr);
+ /* FIXME: as of today partial coverage:
+ * - only one files_hdr has been seen in PDB files
+ * OTOH, MS github presents two different structures
+ * llvm ? one or two
+ * - next files_hdr (depending on previous question, can be a void question)
+ * is code correct ; what do MS and llvm do?
+ */
+ while (CV_IS_INSIDE(files_hdr, next_hdr))
{
- printf("%s offset=%08x line=%d\n",
- pfx, lines_blk->l[i].offset, lines_blk->l[i].lineno ^ 0x80000000);
+ const struct CV_Line_t* lines;
+ printf("%s file=%u lines=%d size=%x\n", pfx, files_hdr->offFile,
+ files_hdr->nLines, files_hdr->cbBlock);
+ lines = CV_RECORD_AFTER(files_hdr);
+ cols = (const struct CV_Column_t*)&lines[files_hdr->nLines];
+ for (i = 0; i < files_hdr->nLines; i++)
+ {
+ printf("%s offset=%8x line=%d deltaLineEnd=%u %s",
+ pfx, lines[i].offset, lines[i].linenumStart, lines[i].deltaLineEnd,
+ lines[i].fStatement ? "statement" : "expression");
+ if (lines_hdr->flags & CV_LINES_HAVE_COLUMNS)
+ printf(" cols[start=%u end=%u]",
+ cols[i].offColumnStart, cols[i].offColumnEnd);
+ printf("\n");
+ }
+ if (lines_hdr->flags & CV_LINES_HAVE_COLUMNS)
+ files_hdr = (const struct CV_DebugSLinesFileBlockHeader_t*)&cols[files_hdr->nLines];
+ else
+ files_hdr = (const struct CV_DebugSLinesFileBlockHeader_t*)&lines[files_hdr->nLines];
}
break;
- case LT2_FILES_BLOCK: /* skip */
+ case DEBUG_S_FILECHKSMS:
+ chksms = CV_RECORD_AFTER(hdr);
+ while (CV_IS_INSIDE(chksms, next_hdr))
+ {
+ const char* meth[] = {"None", "MD5", "SHA1", "SHA256"};
+ printf("%s %d] name=%s size=%u method=%s checksum=[",
+ pfx, (unsigned)((const char*)chksms - (const char*)(hdr + 1)),
+ strimage ? strimage + chksms->strOffset : "--none--",
+ chksms->size, chksms->method < ARRAY_SIZE(meth) ? meth[chksms->method] : "<<unknown>>");
+ for (i = 0; i < chksms->size; ++i) printf("%02x", chksms->checksum[i]);
+ printf("]\n");
+ chksms = CV_ALIGN(CV_RECORD_GAP(chksms, chksms->size), 4);
+ }
+ break;
+ case DEBUG_S_INLINEELINES:
+ /* subsection starts with a DWORD signature */
+ switch (*(DWORD*)CV_RECORD_AFTER(hdr))
+ {
+ case CV_INLINEE_SOURCE_LINE_SIGNATURE:
+ inlsrc = CV_RECORD_GAP(hdr, sizeof(DWORD));
+ while (CV_IS_INSIDE(inlsrc, next_hdr))
+ {
+ printf("%s inlinee=%x fileref=%d srcstart=%d\n",
+ pfx, inlsrc->inlinee, inlsrc->fileId, inlsrc->sourceLineNum);
+ ++inlsrc;
+ }
+ break;
+ case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX:
+ inlsrcex = CV_RECORD_GAP(hdr, sizeof(DWORD));
+ while (CV_IS_INSIDE(inlsrcex, next_hdr))
+ {
+ printf("%s inlinee=%x fileref=%d srcstart=%d numExtraFiles=%d\n",
+ pfx, inlsrcex->inlinee, inlsrcex->fileId, inlsrcex->sourceLineNum,
+ inlsrcex->countOfExtraFiles);
+ inlsrcex = CV_RECORD_GAP(inlsrcex, inlsrcex->countOfExtraFiles * sizeof(inlsrcex->extraFileId[0]));
+ }
+ break;
+ default:
+ printf("%sUnknown signature %x in INLINEELINES subsection\n", pfx, *(DWORD*)CV_RECORD_AFTER(hdr));
+ break;
+ }
break;
default:
- printf("%sblock end %x\n", pfx, lt2->header);
- lt2 = (const struct codeview_linetab2*)(linetab + size);
- continue;
+ dump_data(CV_RECORD_AFTER(hdr), hdr->cbLen, pfx);
+ break;
}
- lt2 = codeview_linetab2_next_block(lt2);
+ hdr = next_hdr;
}
}
More information about the wine-devel
mailing list