From 31189818cbfc6d0bebf82025f3df632a287b61d6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 18 Jun 2017 09:34:17 +0200 Subject: * when using mspdb120.dll (VS2013) or later, do not emit view helpers * remove method declarations from struct or class records (they confuse mspdb*.dll if having forward references?) --- CHANGES | 5 ++++ VERSION | 2 +- src/cv2pdb.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++--------------- src/cv2pdb.h | 3 +++ src/cvutil.h | 2 +- src/mscvpdb.h | 20 ++++++++++++++ 6 files changed, 93 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index b08c1ba..c99cfe0 100644 --- a/CHANGES +++ b/CHANGES @@ -251,3 +251,8 @@ unreleased Version 0.22 * for D version >= 2.068, write AA debug info compatible with dmd COFF output * prefer struct over class for internal structs * handle class/struct property "uniquename" + +2017-05-13 Version 0.41 + + * when using mspdb120.dll (VS2013) or later, do not emit view helpers + * remove method declarations from struct or class records (they confuse mspdb*.dll if having forward references?) diff --git a/VERSION b/VERSION index 26b7813..3393adc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.40 +VERSION = 0.41 diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index b93b21b..5fc8f12 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -38,7 +38,10 @@ CV2PDB::CV2PDB(PEImage& image) nextDwarfType = 0x1000; addClassTypeEnum = true; + addObjectViewHelper = true; addStringViewHelper = false; + methodListToOneMethod = true; + removeMethodLists = true; useTypedefEnum = false; useGlobalMod = true; thisIsNotRef = true; @@ -182,6 +185,10 @@ bool CV2PDB::openPDB(const TCHAR* pdbname, const TCHAR* pdbref) printf("TPI::QueryImplementationVersion() = %d\n", tpi->QueryImplementationVersion()); #endif + // only add helper for VS2012 or earlier, that default to the old debug engine + addClassTypeEnum = mspdb::vsVersion < 12; + addStringViewHelper = mspdb::vsVersion < 12; + addObjectViewHelper = mspdb::vsVersion < 12; return true; } @@ -479,12 +486,31 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft break; case LF_METHOD_V1: + { + auto prevdpos = dpos; + auto mlisttype = getTypeData(fieldtype->method_v1.mlist); if (dp) { - dfieldtype->method_v2.id = v3 ? LF_METHOD_V3 : LF_METHOD_V2; - dfieldtype->method_v2.count = fieldtype->method_v1.count; - dfieldtype->method_v2.mlist = fieldtype->method_v1.mlist; - dpos += sizeof(dfieldtype->method_v2) - sizeof(dfieldtype->method_v2.p_name); + if (methodListToOneMethod && fieldtype->method_v1.count == 1 && mlisttype) + { + dfieldtype->onemethod_v2.id = v3 ? LF_ONEMETHOD_V3 : LF_ONEMETHOD_V2; + dfieldtype->onemethod_v2.attribute = mlisttype->methodlist_v1.attr; + dfieldtype->onemethod_v2.type = translateType(mlisttype->methodlist_v1.fntype); + dpos += sizeof(dfieldtype->onemethod_v2) - sizeof(dfieldtype->onemethod_v2.p_name); + int mode = (mlisttype->methodlist_v1.attr >> 2) & 7; + if (mode == 4 || mode == 6) // introducing virtual + { + *(unsigned*)(dp + dpos) = mlisttype->methodlist_v1.vbaseoff[0]; + dpos += sizeof(unsigned); + } + } + else + { + dfieldtype->method_v2.id = v3 ? LF_METHOD_V3 : LF_METHOD_V2; + dfieldtype->method_v2.count = fieldtype->method_v1.count; + dfieldtype->method_v2.mlist = fieldtype->method_v1.mlist; + dpos += sizeof(dfieldtype->method_v2) - sizeof(dfieldtype->method_v2.p_name); + } } pos += sizeof(dfieldtype->method_v1) - sizeof(dfieldtype->method_v1.p_name); if (v3 && dp) @@ -492,18 +518,22 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft else copylen = pstrmemlen(&fieldtype->method_v1.p_name.namelen); - if(cmd == kCmdOffsetFirstVirtualMethod) - if(const codeview_type* cvtype = getTypeData(fieldtype->method_v1.mlist)) - if (cvtype->generic.id == LF_METHODLIST_V1 && cvtype->generic.len > 2) - { - // just check the first entry - const unsigned short *pattr = (const unsigned short*)(&cvtype->generic + 1); - int mode =(*pattr >> 2) & 7; - if(mode == 4 || mode == 6) - return *(const unsigned*)(&pattr[2]); - } + if(removeMethodLists && cmd != kCmdOffsetFirstVirtualMethod) + { + dpos = prevdpos; + pos += copylen; + continue; // throw away copy and do not count + } + if(cmd == kCmdOffsetFirstVirtualMethod && mlisttype) + if (mlisttype->generic.id == LF_METHODLIST_V1 && mlisttype->generic.len > 2) + { + // just check the first entry + int mode = (mlisttype->methodlist_v1.attr >> 2) & 7; + if(mode == 4 || mode == 6) + return mlisttype->methodlist_v1.vbaseoff[0]; + } break; - + } case LF_METHOD_V2: copylen = sizeof(dfieldtype->method_v2) - sizeof(dfieldtype->method_v2.p_name); copylen += pstrmemlen(&fieldtype->method_v2.p_name.namelen); @@ -1724,7 +1754,7 @@ int CV2PDB::appendObjectType (int object_type, int enumType, const char* classSy codeview_type* dtype; int viewHelperType = 0; - bool addViewHelper = object_type == kClassTypeObject; + bool addViewHelper = addObjectViewHelper && object_type == kClassTypeObject; if(addViewHelper) { rdtype = (codeview_reftype*) (userTypes + cbUserTypes); @@ -2101,7 +2131,10 @@ bool CV2PDB::initGlobalTypes() ifaceBaseType = appendObjectType (kClassTypeIface, ifaceEnumType, IFACE_SYMBOL); cppIfaceBaseType = appendObjectType (kClassTypeCppIface, cppIfaceEnumType, CPPIFACE_SYMBOL); } - classBaseType = appendObjectType (kClassTypeObject, classEnumType, OBJECT_SYMBOL); + if (auto sym = findUdtSymbol(OBJECT_SYMBOL)) + classBaseType = sym->udt_v1.type; + else + classBaseType = appendObjectType (kClassTypeObject, classEnumType, OBJECT_SYMBOL); } for (unsigned int t = 0; t < globalTypeHeader->cTypes && !hadError(); t++) @@ -2332,20 +2365,29 @@ bool CV2PDB::initGlobalTypes() case LF_METHODLIST_V1: { + if (methodListToOneMethod || removeMethodLists) + { + dtype->generic.id = LF_NULL_V1; + len = 4; + break; + } dtype->generic.id = LF_METHODLIST_V2; const unsigned short* pattr = (const unsigned short*)((const char*)type + 4); unsigned* dpattr = (unsigned*)((char*)dtype + 4); while ((const char*)pattr + 4 <= (const char*)type + type->generic.len + 2) { - // type translation? switch ((*pattr >> 2) & 7) { case 4: case 6: - *dpattr++ = *pattr++; + *dpattr++ = *pattr++; // attribute + *dpattr++ = translateType(*pattr++); // type + *dpattr++ = *(unsigned*)pattr; // vbaseoff + pattr += 2; + break; default: - *dpattr++ = *pattr++; - *dpattr++ = *pattr++; + *dpattr++ = *pattr++; // attribute + *dpattr++ = translateType(*pattr++); // type break; } } diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 91dd165..a7883a4 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -245,6 +245,9 @@ public: bool addClassTypeEnum; bool addStringViewHelper; + bool addObjectViewHelper; + bool methodListToOneMethod; + bool removeMethodLists; bool useGlobalMod; bool thisIsNotRef; bool v3; diff --git a/src/cvutil.h b/src/cvutil.h index 3467ca3..669a476 100644 --- a/src/cvutil.h +++ b/src/cvutil.h @@ -10,7 +10,7 @@ #include "cv2pdb.h" #include "symutil.h" -#define OBJECT_SYMBOL "object@Object" +#define OBJECT_SYMBOL "object.Object" #define IFACE_SYMBOL "DInterface" #define CPPIFACE_SYMBOL "CppInterface" diff --git a/src/mscvpdb.h b/src/mscvpdb.h index 6a699c4..b377a64 100644 --- a/src/mscvpdb.h +++ b/src/mscvpdb.h @@ -352,6 +352,26 @@ union codeview_type unsigned int arglist; unsigned int this_adjust; } mfunction_v2; + + struct + { + unsigned short int len; + short int id; + unsigned short int attr; + unsigned short int fntype; + unsigned int vbaseoff[1]; // vtbl offset if introducing virtual + } methodlist_v1; + + struct + { + unsigned short int len; + short int id; + unsigned short int attr; + unsigned short int pad0; + unsigned int fntype; + unsigned int vbaseoff[1]; // vtbl offset if introducing virtual + } methodlist_v2; + }; union codeview_reftype -- cgit v0.12