diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index ca3f120a5d6..20b3314ea04 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -110,6 +110,7 @@ struct p_string typedef unsigned short cv_typ16_t; typedef unsigned int cv_typ_t; +typedef cv_typ_t cv_itemid_t; /* ======================================== * * Type information @@ -1819,6 +1820,56 @@ union codeview_symbol struct cv_addr_range range; struct cv_addr_gap gaps[0]; } defrange_registerrel_v3; + + struct + { + unsigned short int len; + unsigned short int id; + unsigned int pParent; + unsigned int pEnd; + cv_itemid_t inlinee; + unsigned char binaryAnnotations[0]; + } inline_site_v3; + + struct + { + unsigned short int len; + unsigned short int typ; + unsigned int off; + unsigned short sect; + unsigned short _pad0; + cv_typ_t typind; + } callsiteinfo_v3; + + struct + { + unsigned short int len; + unsigned short int id; + unsigned int pParent; + unsigned int pEnd; + cv_itemid_t inlinee; + unsigned int invocations; + unsigned char binaryAnnotations[0]; + } inline_site2_v3; + +}; + +enum BinaryAnnotationOpcode +{ + BA_OP_Invalid, + BA_OP_CodeOffset, + BA_OP_ChangeCodeOffsetBase, + BA_OP_ChangeCodeOffset, + BA_OP_ChangeCodeLength, + BA_OP_ChangeFile, + BA_OP_ChangeLineOffset, + BA_OP_ChangeLineEndDelta, + BA_OP_ChangeRangeKind, + BA_OP_ChangeColumnStart, + BA_OP_ChangeColumnEndDelta, + BA_OP_ChangeCodeOffsetAndLineOffset, + BA_OP_ChangeCodeLengthAndCodeOffset, + BA_OP_ChangeColumnEnd, }; #define S_COMPILE 0x0001 diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index d1d3674daca..aba14af8643 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1151,6 +1151,93 @@ static inline const char* get_last(const union codeview_symbol* sym) return (const char*)sym + sym->generic.len + 2; } +static unsigned binannot_uncompress(const unsigned char** pptr) +{ + unsigned res = (unsigned)(-1); + const unsigned char* ptr = *pptr; + + if ((*ptr & 0x80) == 0x00) + res = (unsigned)(*ptr++); + else if ((*ptr & 0xC0) == 0x80) + { + res = (unsigned)((*ptr++ & 0x3f) << 8); + res |= *ptr++; + } + else if ((*ptr & 0xE0) == 0xC0) + { + res = (*ptr++ & 0x1f) << 24; + res |= *ptr++ << 16; + res |= *ptr++ << 8; + res |= *ptr++; + } + else res = (unsigned)(-1); + *pptr = ptr; + return res; +} + +static void dump_binannot(const unsigned char* ba, const char* last, const char* pfx) +{ + while (ba < (const unsigned char*)last) + { + unsigned opcode = binannot_uncompress(&ba); + switch (opcode) + { + case BA_OP_Invalid: + /* not clear if param? */ + printf("%sInvalid\n", pfx); + break; + case BA_OP_CodeOffset: + printf("%sCodeOffset %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeCodeOffsetBase: + printf("%sChangeCodeOffsetBase %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeCodeOffset: + printf("%sChangeCodeOffset %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeCodeLength: + printf("%sChangeCodeLength %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeFile: + printf("%sChangeFile %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeLineOffset: + printf("%sChangeLineOffset %d\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeLineEndDelta: + printf("%sChangeLineEndDelta %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeRangeKind: + printf("%sChangeRangeKind %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeColumnStart: + printf("%sChangeColumnStart %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeColumnEndDelta: + printf("%sChangeColumnEndDelta %u\n", pfx, binannot_uncompress(&ba)); + break; + case BA_OP_ChangeCodeOffsetAndLineOffset: + { + unsigned p1 = binannot_uncompress(&ba); + printf("%sChangeCodeOffsetAndLineOffset %u %u (0x%x)\n", pfx, p1 & 0xf, p1 >> 4, p1); + } + break; + case BA_OP_ChangeCodeLengthAndCodeOffset: + { + unsigned p1 = binannot_uncompress(&ba); + unsigned p2 = binannot_uncompress(&ba); + printf("%sChangeCodeLengthAndCodeOffset %u %u\n", pfx, p1, p2); + } + break; + case BA_OP_ChangeColumnEnd: + printf("%sChangeColumnEnd %u\n", pfx, binannot_uncompress(&ba)); + break; + + default: printf("%sUnsupported op %d %x\n", pfx, opcode, opcode); /* may cause issues because of param */ + } + } +} + BOOL codeview_dump_symbols(const void* root, unsigned long size) { unsigned int i; @@ -1651,6 +1738,26 @@ BOOL codeview_dump_symbols(const void* root, unsigned long size) dump_defrange(&sym->defrange_registerrel_v3.range, get_last(sym), "\t\t"); break; + case S_CALLSITEINFO: + printf("Call-site-info V3 %04x:%08x typeindex:%x\n", + sym->callsiteinfo_v3.sect, sym->callsiteinfo_v3.off, sym->callsiteinfo_v3.typind); + break; + + case S_INLINESITE: + printf("Inline-site V3 parent:%x end:%x inlinee:%x\n", + sym->inline_site_v3.pParent, sym->inline_site_v3.pEnd, sym->inline_site_v3.inlinee); + dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), "\t\t"); + break; + case S_INLINESITE2: + printf("Inline-site2 V3 parent:%x end:%x inlinee:%x #inv:%u\n", + sym->inline_site2_v3.pParent, sym->inline_site2_v3.pEnd, sym->inline_site2_v3.inlinee, + sym->inline_site2_v3.invocations); + dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), "\t\t"); + break; + case S_INLINESITE_END: + printf("Inline-site-end\n"); + break; + default: printf("\n\t\t>>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2); dump_data((const void*)sym, sym->generic.len + 2, " ");