summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRainer Schuetze <r.sagitario@gmx.de>2017-09-02 16:11:47 (GMT)
committerRainer Schuetze <r.sagitario@gmx.de>2017-09-02 16:11:47 (GMT)
commit14eef861769f85b6f32c68ff1898c41d8ac65ef5 (patch)
tree7cad0d93a48238a737d9cd9dae984b82110d25af /src
parentbb0e25a41af88c9bf76e5cda02a6fd45f9d09778 (diff)
downloadcv2pdb-14eef861769f85b6f32c68ff1898c41d8ac65ef5.zip
cv2pdb-14eef861769f85b6f32c68ff1898c41d8ac65ef5.tar.gz
cv2pdb-14eef861769f85b6f32c68ff1898c41d8ac65ef5.tar.bz2
* search VS2017 registry entries to find mspdb140.dll
* when using mspdb140.dll (VS2015) or later, use symbols to emit line numbers * translate S_UDT_V1 to V3 version * translate S_BLOCK_V1 to V3 version * remove "this" from delegate parameter list if inconsistent with procedure type
Diffstat (limited to 'src')
-rw-r--r--src/cv2pdb.cpp282
-rw-r--r--src/cv2pdb.h2
-rw-r--r--src/mspdb.cpp24
-rw-r--r--src/mspdb.h62
4 files changed, 334 insertions, 36 deletions
diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp
index 5fc8f12..34421b3 100644
--- a/src/cv2pdb.cpp
+++ b/src/cv2pdb.cpp
@@ -15,8 +15,10 @@
#define REMOVE_LF_DERIVED 1 // types wrong by DMD
#define PRINT_INTERFACEVERSON 0
+static const int typePrefix = 4;
+
CV2PDB::CV2PDB(PEImage& image)
-: img(image), pdb(0), dbi(0), libraries(0), rsds(0), modules(0), globmod(0)
+: img(image), pdb(0), dbi(0), tpi(0), ipi(0), libraries(0), rsds(0), modules(0), globmod(0)
, segMap(0), segMapDesc(0), segFrame2Index(0), globalTypeHeader(0)
, globalTypes(0), cbGlobalTypes(0), allocGlobalTypes(0)
, userTypes(0), cbUserTypes(0), allocUserTypes(0)
@@ -71,6 +73,8 @@ bool CV2PDB::cleanup(bool commit)
dbi->Close();
if (tpi)
tpi->Close();
+ if (ipi)
+ ipi->Close();
if (pdb)
pdb->Commit();
if (pdb)
@@ -180,6 +184,15 @@ bool CV2PDB::openPDB(const TCHAR* pdbname, const TCHAR* pdbref)
if (rc <= 0 || !tpi)
return setError("cannot create TPI");
+#if 0
+ if (mspdb::vsVersion >= 14)
+ {
+ rc = pdb->OpenIpi("", &ipi);
+ if (rc <= 0 || !ipi)
+ return setError("cannot create IPI");
+ }
+#endif
+
#if PRINT_INTERFACEVERSON
printf("TPI::QueryInterfaceVersion() = %d\n", tpi->QueryInterfaceVersion());
printf("TPI::QueryImplementationVersion() = %d\n", tpi->QueryImplementationVersion());
@@ -908,7 +921,7 @@ const codeview_type* CV2PDB::getConvertedTypeData(int type)
if (type < 0 || type >= nextUserType - 0x1000)
return 0;
- int pos = 4;
+ int pos = typePrefix;
while(type > 0 && pos < cbGlobalTypes)
{
const codeview_type* ptype = (codeview_type*)(globalTypes + pos);
@@ -2109,12 +2122,12 @@ bool CV2PDB::initGlobalTypes()
pointerTypes = new int[globalTypeHeader->cTypes];
memset(pointerTypes, 0, globalTypeHeader->cTypes * sizeof(*pointerTypes));
- globalTypes = (unsigned char*) malloc(entry->cb + 4);
- allocGlobalTypes = entry->cb + 4;
+ globalTypes = (unsigned char*) malloc(entry->cb + typePrefix);
+ allocGlobalTypes = entry->cb + typePrefix;
if (!globalTypes)
return setError("Out of memory");
*(DWORD*) globalTypes = 4;
- cbGlobalTypes = 4;
+ cbGlobalTypes = typePrefix;
nextUserType = globalTypeHeader->cTypes + 0x1000;
@@ -2132,7 +2145,7 @@ bool CV2PDB::initGlobalTypes()
cppIfaceBaseType = appendObjectType (kClassTypeCppIface, cppIfaceEnumType, CPPIFACE_SYMBOL);
}
if (auto sym = findUdtSymbol(OBJECT_SYMBOL))
- classBaseType = sym->udt_v1.type;
+ classBaseType = sym->generic.id == S_UDT_V1 ? sym->udt_v1.type : sym->udt_v2.type;
else
classBaseType = appendObjectType (kClassTypeObject, classEnumType, OBJECT_SYMBOL);
}
@@ -2479,7 +2492,7 @@ int CV2PDB::insertBaseClass(const codeview_type* fieldlist, int type)
int off = (unsigned char*) fieldlist - globalTypes;
checkGlobalTypeAlloc(len);
- int copyoff = off + 4;
+ int copyoff = off + 4; // insert at beginning of field list
memmove(globalTypes + copyoff + len, globalTypes + copyoff, cbGlobalTypes - copyoff);
memcpy(globalTypes + copyoff, &cvtype, len);
cbGlobalTypes += len;
@@ -2491,7 +2504,7 @@ int CV2PDB::insertBaseClass(const codeview_type* fieldlist, int type)
bool CV2PDB::insertClassTypeEnums()
{
- int pos = 4; // skip prefix
+ int pos = typePrefix; // skip prefix
for (unsigned int t = 0; pos < cbGlobalTypes && t < globalTypeHeader->cTypes; t++)
{
codeview_type* type = (codeview_type*)(globalTypes + pos);
@@ -2703,6 +2716,9 @@ int CV2PDB::getNextSrcLine(int seg, unsigned int off)
bool CV2PDB::addSrcLines()
{
+ if(mspdb::vsVersion >= 14)
+ return addSrcLines14();
+
for (int m = 0; m < countEntries; m++)
{
OMFDirEntry* entry = img.getCVEntry(m);
@@ -2739,7 +2755,7 @@ bool CV2PDB::addSrcLines()
int segend = getNextSrcLine(seg, sourceLine->offset[cnt-1]);
int seglength = (segend >= 0 ? segend - 1 - segoff : lnSegStartEnd[2*s + 1] - segoff);
- int lineMin = lineNo[0];
+ int lineMin = max(1, lineNo[0]);
for (int ln = 1; ln < cnt; ln++)
if (lineMin > lineNo[ln])
lineMin = lineNo[ln];
@@ -2747,7 +2763,7 @@ bool CV2PDB::addSrcLines()
for (int ln = 0; ln < cnt; ln++)
{
lineInfo[ln].offset = sourceLine->offset[ln] - segoff;
- lineInfo[ln].line = lineNo[ln] - lineMin;
+ lineInfo[ln].line = max(0, lineNo[ln] - lineMin); // | 0x80000000; // mark as statement
}
int rc = mod->AddLines(name, seg, segoff, seglength, segoff, lineMin,
(unsigned char*) lineInfo, cnt * sizeof(*lineInfo));
@@ -2761,6 +2777,158 @@ bool CV2PDB::addSrcLines()
return true;
}
+////////////////////////////////////////
+template<typename T>
+void append(std::vector<char>& v, const T& x)
+{
+ size_t sz = v.size();
+ v.resize(sz + sizeof(T));
+ memcpy(v.data() + sz, &x, sizeof(T));
+}
+
+void append(std::vector<char>& v, const void* data, size_t len)
+{
+ size_t sz = v.size();
+ v.resize(sz + len);
+ memcpy(v.data() + sz, data, len);
+}
+
+void align(std::vector<char>& v, int algn)
+{
+ while(v.size() & (algn - 1))
+ v.push_back(0);
+}
+
+int addfile(std::vector<char>& f3, std::vector<char>& f4, const char* s)
+{
+ size_t slen = strlen(s);
+ const char* p = f3.data();
+ size_t plen = strlen(p);
+ int fileno = -1; // don't count initial 0
+ while(plen != slen || strncmp(p, s, slen) != 0)
+ {
+ p += plen + 1;
+ fileno++;
+ if (p - f3.data() >= (ptrdiff_t)f3.size())
+ {
+ size_t pos = f3.size();
+ append(f3, s, slen + 1);
+
+ append(f4, (int)pos);
+ append(f4, (int)0); // checksum
+ return fileno * 8;
+ }
+ plen = strlen(p);
+ }
+ return fileno * 8; // offset in source list
+}
+
+////////////////////////////////////////
+bool CV2PDB::addSrcLines14()
+{
+ if (!useGlobalMod)
+ return setError("unexpected call of addSrcLines14()");
+
+ std::vector<char> F2_buf; // lines
+ std::vector<char> F2_all; // multiple f2 blocks
+ std::vector<char> F3_buf; // filenames
+ std::vector<char> F4_buf; // file checksums
+
+ append(F3_buf, (char)0); // empty string
+
+ for (int m = 0; m < countEntries; m++)
+ {
+ OMFDirEntry* entry = img.getCVEntry(m);
+ if(entry->SubSection == sstSrcModule)
+ {
+ mspdb::Mod* mod = useGlobalMod ? globalMod() : modules[entry->iMod];
+ if (!mod)
+ return setError("sstSrcModule for non-existing module");
+
+ OMFSourceModule* sourceModule = img.CVP<OMFSourceModule>(entry->lfo);
+ int* segStartEnd = img.CVP<int>(entry->lfo + 4 + 4 * sourceModule->cFile);
+ short* seg = img.CVP<short>(entry->lfo + 4 + 4 * sourceModule->cFile + 8 * sourceModule->cSeg);
+
+ for (int f = 0; f < sourceModule->cFile; f++)
+ {
+ int cvoff = entry->lfo + sourceModule->baseSrcFile[f];
+ OMFSourceFile* sourceFile = img.CVP<OMFSourceFile> (cvoff);
+ int* lnSegStartEnd = img.CVP<int>(cvoff + 4 + 4 * sourceFile->cSeg);
+ BYTE* pname = (BYTE*)(lnSegStartEnd + 2 * sourceFile->cSeg);
+ char* name = p2c (pname);
+
+ int fileid = addfile(F3_buf, F4_buf, name);
+
+ for (int s = 0; s < sourceFile->cSeg; s++)
+ {
+ int lnoff = entry->lfo + sourceFile->baseSrcLn[s];
+ OMFSourceLine* sourceLine = img.CVP<OMFSourceLine> (lnoff);
+ unsigned short* lineNo = img.CVP<unsigned short> (lnoff + 4 + 4 * sourceLine->cLnOff);
+
+ int seg = sourceLine->Seg;
+ int cnt = sourceLine->cLnOff;
+ if(cnt <= 0)
+ continue;
+
+ int segoff = lnSegStartEnd[2*s];
+ // lnSegStartEnd[2*s + 1] only spans until the first byte of the last source line
+ int segend = getNextSrcLine(seg, sourceLine->offset[cnt-1]);
+ int seglength = (segend >= 0 ? segend - 1 - segoff : lnSegStartEnd[2*s + 1] - segoff);
+
+ append(F2_buf, segoff);
+ append(F2_buf, (short)seg);
+ append(F2_buf, (short)0); // flags (no columns)
+ append(F2_buf, seglength);
+
+ append(F2_buf, fileid);
+ append(F2_buf, cnt);
+ append(F2_buf, cnt * 8 + 12); // size of block
+
+ for (int ln = 0; ln < cnt; ln++)
+ {
+ append(F2_buf, (int)sourceLine->offset[ln] - segoff);
+ append(F2_buf, (int)lineNo[ln] | 0x80000000); // mark as statement
+ }
+#if 1
+ append(F2_all, (int)0xf2);
+ append(F2_all, (int)F2_buf.size());
+ append(F2_all, F2_buf.data(), F2_buf.size());
+ align(F2_all, 4);
+#endif
+ F2_buf.resize(0);
+ }
+ }
+ }
+ }
+
+ std::vector<char> buf;
+ append(buf, (int)4);
+ if (F3_buf.size() > 0)
+ {
+ append(buf, (int)0xf3);
+ append(buf, (int)F3_buf.size());
+ append(buf, F3_buf.data(), F3_buf.size());
+ align(buf, 4);
+ }
+ if (F4_buf.size() > 0)
+ {
+ append(buf, (int)0xf4);
+ append(buf, (int)F4_buf.size());
+ append(buf, F4_buf.data(), F4_buf.size());
+ align(buf, 4);
+ }
+ if (F2_all.size() > 0)
+ {
+ append(buf, F2_all.data(), F2_all.size());
+ align(buf, 4);
+ }
+ int rc = globalMod()->AddSymbols((unsigned char *)buf.data(), buf.size());
+ if (rc <= 0)
+ return setError("cannot add line number info to module");
+
+ return true;
+}
+
bool CV2PDB::addPublics()
{
for (int m = 0; m < countEntries; m++)
@@ -2848,11 +3016,11 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
switch (sym->generic.id)
{
case S_UDT_V1:
- dsym->udt_v1.type = translateType(sym->udt_v1.type);
- for(int p = 0; p < dsym->udt_v1.p_name.namelen; p++)
- if(dsym->udt_v1.p_name.name[p] == '.')
- dsym->udt_v1.p_name.name[p] = '@';
- //sym->udt_v1.type = 0x101e;
+ dsym->udt_v2.id = v3 ? S_UDT_V3 : S_UDT_V2;
+ dsym->udt_v2.type = translateType(sym->udt_v1.type);
+ destlength = pstrcpy_v (v3, (BYTE*) &dsym->udt_v2.p_name, (BYTE*) &sym->udt_v1.p_name);
+ destlength += (BYTE*) &dsym->udt_v2.p_name - (BYTE*) dsym;
+ dsym->udt_v2.len = destlength - 2;
break;
case S_LDATA_V1:
@@ -2892,6 +3060,25 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
dsym->data_v2.len = destlength - 2;
lastGProcSym = dsym;
+ if(const codeview_type* cvtype = getTypeData(dsym->proc_v2.proctype))
+ {
+ // closure parameter "this" not part of type, remove it to make symbol and type consistent
+ int params = 0;
+ codeview_symbol* bpsym;
+ for(int j = i + length; i < srcSize; j += bpsym->generic.len + 2, params++)
+ {
+ bpsym = (codeview_symbol*)(srcSymbols + j);
+ if (bpsym->generic.id != S_BPREL_V1 && bpsym->generic.id != S_BPREL_V2 && bpsym->generic.id != S_BPREL_V3)
+ break;
+ }
+ int typeparams = cvtype->generic.id == LF_PROCEDURE_V1 ? cvtype->procedure_v1.params : cvtype->procedure_v2.params;
+ while (params > typeparams)
+ {
+ // skip the first parameters
+ length += ((codeview_symbol*)(srcSymbols + i + length))->generic.len + 2;
+ params--;
+ }
+ }
break;
case S_BPREL_V1:
@@ -2978,8 +3165,9 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
}
//sym->stack_v1.symtype = 0x1012;
break;
- case S_ENDARG_V1:
case S_RETURN_V1:
+ continue; // not understood by cvdump
+ case S_ENDARG_V1:
case S_SSEARCH_V1:
break;
case S_END_V1:
@@ -2992,6 +3180,7 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
case S_PROCREF_V1:
case S_DATAREF_V1:
case S_LPROCREF_V1:
+#if 0
if(Dversion > 0)
{
// dmd does not add a string, but it's not obvious to detect whether it exists or not
@@ -3003,6 +3192,7 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
destlength += 4;
}
else
+#endif
// throw entry away, it's use is unknown anyway, and it causes a lot of trouble
destlength = 0;
break;
@@ -3018,10 +3208,29 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
dsym->constant_v2.len = destlength - 2;
break;
+ case S_BLOCK_V1:
+ if(v3)
+ {
+ dsym->block_v3.id = S_BLOCK_V3;
+ dsym->block_v3.parent = sym->block_v1.parent;
+ dsym->block_v3.end = sym->block_v1.end;
+ dsym->block_v3.length = sym->block_v1.length;
+ dsym->block_v3.offset = sym->block_v1.offset;
+ dsym->block_v3.segment = sym->block_v1.segment;
+ destlength = pstrcpy_v (v3, (BYTE*) &dsym->block_v3.name, (BYTE*) &sym->block_v1.p_name);
+ destlength += sizeof(dsym->block_v3) - sizeof(dsym->block_v3.name);
+ dsym->block_v3.len = destlength - 2;
+ }
+ break;
+
case S_ALIGN_V1:
continue; // throw away
break;
+ case S_UDT_V2:
+ case S_UDT_V3:
+ break; // already converted or added explicitly
+
default:
sym = sym;
break;
@@ -3032,53 +3241,65 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
return destSize;
}
+bool isUDTid(int id)
+{
+ return id == S_UDT_V1 || id == S_UDT_V2 || id == S_UDT_V3;
+}
+
codeview_symbol* CV2PDB::findUdtSymbol(int type)
{
type = translateType(type);
for(int p = 0; p < cbGlobalSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (globalSymbols + p);
- if(sym->generic.id == S_UDT_V1 && sym->udt_v1.type == type)
+ if(isUDTid(sym->generic.id) && sym->udt_v1.type == type)
return sym;
p += sym->generic.len + 2;
}
for(int p = 0; p < cbStaticSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (staticSymbols + p);
- if(sym->generic.id == S_UDT_V1 && sym->udt_v1.type == type)
+ if(isUDTid(sym->generic.id) && sym->udt_v1.type == type)
return sym;
p += sym->generic.len + 2;
}
for(int p = 0; p < cbUdtSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (udtSymbols + p);
- if(sym->generic.id == S_UDT_V1 && sym->udt_v1.type == type)
+ if(isUDTid(sym->generic.id) && sym->udt_v1.type == type)
return sym;
p += sym->generic.len + 2;
}
return 0;
}
+bool isUDT(codeview_symbol* sym, const char* name)
+{
+ return (sym->generic.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name) ||
+ sym->generic.id == S_UDT_V2 && p2ccmp(sym->udt_v2.p_name, name) ||
+ sym->generic.id == S_UDT_V3 && strcmp(sym->udt_v3.name, name) == 0);
+}
+
codeview_symbol* CV2PDB::findUdtSymbol(const char* name)
{
for(int p = 0; p < cbGlobalSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (globalSymbols + p);
- if(sym->generic.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name))
+ if(isUDT(sym, name))
return sym;
p += sym->generic.len + 2;
}
for(int p = 0; p < cbStaticSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (staticSymbols + p);
- if(sym->generic.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name))
+ if(isUDT(sym, name))
return sym;
p += sym->generic.len + 2;
}
for(int p = 0; p < cbUdtSymbols; )
{
codeview_symbol* sym = (codeview_symbol*) (udtSymbols + p);
- if(sym->generic.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name))
+ if(isUDT(sym, name))
return sym;
p += sym->generic.len + 2;
}
@@ -3100,19 +3321,18 @@ bool CV2PDB::addUdtSymbol(int type, const char* name)
// no need to convert to udt_v2/udt_v3, the debugger is fine with it.
codeview_symbol* sym = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
- sym->udt_v1.id = S_UDT_V1;
- sym->udt_v1.type = translateType(type);
- cstrcpy_v (true, (BYTE*)sym->udt_v1.p_name.name, name ? name : ""); // allow anonymous typedefs
- sym->udt_v1.p_name.namelen = strlen(sym->udt_v1.p_name.name);
- sym->udt_v1.len = sizeof(sym->udt_v1) + sym->udt_v1.p_name.namelen - 1 - 2;
- cbUdtSymbols += sym->udt_v1.len + 2;
+ sym->udt_v2.id = v3 ? S_UDT_V3 : S_UDT_V2;
+ sym->udt_v2.type = translateType(type);
+ int len = cstrcpy_v (v3, (BYTE*)&sym->udt_v2.p_name, name ? name : ""); // allow anonymous typedefs
+ sym->udt_v2.len = sizeof(sym->udt_v2) - sizeof(sym->udt_v2.p_name) + len - 2;
+ cbUdtSymbols += sym->udt_v2.len + 2;
return true;
}
bool CV2PDB::addSymbols(mspdb::Mod* mod, BYTE* symbols, int cb, bool addGlobals)
{
- int prefix = 4; // mod == globmod ? 3 : 4;
+ int prefix = mspdb::vsVersion >= 14 ? 3 : 4; // mod == globmod ? 3 : 4;
int words = (cb + cbGlobalSymbols + cbStaticSymbols + cbUdtSymbols + 3) / 4 + prefix;
DWORD* data = new DWORD[2 * words + 1000];
@@ -3165,7 +3385,7 @@ bool CV2PDB::addSymbols(int iMod, BYTE* symbols, int cb, bool addGlobals)
bool CV2PDB::addSymbols()
{
- int prefix = 4;
+ int prefix = mspdb::vsVersion >= 14 ? 3 : 4;
DWORD* data = 0;
int databytes = 0;
if (useGlobalMod)
@@ -3195,7 +3415,7 @@ bool CV2PDB::addSymbols()
}
bool rc = true;
if (useGlobalMod)
- rc = writeSymbols (globalMod(), data, databytes, prefix, true);
+ rc = writeSymbols(globalMod(), data, databytes, prefix, true);
delete [] data;
return rc;
diff --git a/src/cv2pdb.h b/src/cv2pdb.h
index a7883a4..b1e84a1 100644
--- a/src/cv2pdb.h
+++ b/src/cv2pdb.h
@@ -137,6 +137,7 @@ public:
bool addTypes();
bool addSrcLines();
+ bool addSrcLines14();
bool addPublics();
codeview_symbol* findUdtSymbol(int type);
@@ -187,6 +188,7 @@ public:
mspdb::PDB* pdb;
mspdb::DBI *dbi;
mspdb::TPI *tpi;
+ mspdb::TPI *ipi;
mspdb::Mod** modules;
mspdb::Mod* globmod;
diff --git a/src/mspdb.cpp b/src/mspdb.cpp
index fbb9434..cb3e812 100644
--- a/src/mspdb.cpp
+++ b/src/mspdb.cpp
@@ -81,6 +81,28 @@ bool tryLoadMsPdb(const char* version, const char* mspdb, const char* path = 0)
return modMsPdb != 0;
}
+bool tryLoadMsPdbVS2017(const char* mspdb, const char* path = 0)
+{
+ const char* key = "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7";
+
+ HKEY hkey;
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_OPEN_FLAGS, &hkey) != ERROR_SUCCESS)
+ return false;
+
+ char installDir[260];
+ DWORD size = sizeof(installDir);
+ bool rc = RegQueryValueExA(hkey, "15.0", 0, 0, (LPBYTE)installDir, &size) == ERROR_SUCCESS;
+ RegCloseKey(hkey);
+ if(!rc)
+ return false;
+
+ strncat(installDir, "Common7\\IDE\\", 260);
+ strncat(installDir, mspdb, 260);
+
+ tryLoadLibrary(installDir);
+ return modMsPdb != 0;
+}
+
#ifdef _M_X64
#define BIN_DIR_GE_VS12 "..\\..\\VC\\bin\\amd64\\"
#define BIN_DIR_LT_VS12 BIN_DIR_GE_VS12
@@ -155,6 +177,8 @@ void tryLoadMsPdb140(bool throughPath)
{
if(throughPath)
modMsPdb = LoadLibraryA(mspdb140_dll);
+ if(!modMsPdb && !throughPath)
+ tryLoadMsPdbVS2017(mspdb140_dll);
if (!modMsPdb && !throughPath)
tryLoadMsPdb("VisualStudio\\14.0", mspdb140_dll, BIN_DIR_GE_VS12);
if (!modMsPdb && !throughPath)
diff --git a/src/mspdb.h b/src/mspdb.h
index a8883e0..410c148 100644
--- a/src/mspdb.h
+++ b/src/mspdb.h
@@ -33,7 +33,6 @@ struct Mod;
struct StreamCached;
struct GSI;
struct TPI;
-struct IPI;
struct NameMap;
struct EnumNameMap;
@@ -215,7 +214,7 @@ public: virtual int OpenTpi(char const *,struct TPI * *);
};
struct PDB_part_vs11 : public PDB_part1 {
-public: virtual int OpenIpi(char const *,struct IPI * *); // VS11
+public: virtual int OpenIpi(char const *,struct TPI * *); // VS11
};
template<class BASE>
@@ -235,8 +234,17 @@ public: virtual int QuerySignature2(struct _GUID *);
public: virtual int CopyToW(unsigned short const *,unsigned long,unsigned long);
public: virtual int fIsSZPDB(void)const ;
public: virtual int containsW(unsigned short const *,unsigned long *);
+// mspdb140.dll!PDBCommon::OpenStreamW(unsigned short const *,struct Stream * *)
public: virtual int CopyToW2(unsigned short const *,unsigned long,int (__cdecl*(__cdecl*)(void *,enum PCC))(void),void *);
public: virtual int OpenStreamEx(char const *,char const *,struct Stream * *);
+// mspdb140.dll!PDB_Proxy::RegisterPDBMapping(unsigned short const *,unsigned short const *)
+// mspdb140.dll!PDB_Proxy::EnablePrefetching(void)
+// mspdb140.dll!PDB_Proxy::FLazy(void)
+// mspdb140.dll!PDB_Proxy::FMinimal(void)
+// mspdb140.dll!PDB_Proxy::ResetGUID(unsigned char *,unsigned long)
+// mspdb140.dll!PDB_Proxy::FReleaseGlobalSymbolBuffer(void)
+// mspdb140.dll!PDB_Proxy::UpdateSignature(unsigned long,struct _GUID,unsigned long)
+// mspdb140.dll!PDB_Proxy::`vector deleting destructor'(unsigned int)
};
struct PDB_VS10 : public PDB_part2<PDB_part1> {};
@@ -246,7 +254,7 @@ struct PDB
{
PDB_VS10 vs10;
-public:
+public:
static int __cdecl Open2W(unsigned short const *path,char const *mode,long *p,unsigned short *ext,unsigned int flags,struct PDB **pPDB);
unsigned long QueryAge() { return vs10.QueryAge(); }
@@ -272,6 +280,12 @@ public:
return ((PDB_VS11*)&vs10)->QuerySignature2(guid);
return vs10.QuerySignature2(guid);
}
+ int OpenIpi(char const *name,struct TPI * *ipi)
+ {
+ if(vsVersion >= 11)
+ return ((PDB_VS11*)&vs10)->OpenIpi(name, ipi);
+ return 0;
+ }
};
struct Src {
@@ -383,6 +397,33 @@ public: virtual int Mod::QueryPdbFileW(unsigned short * const,long *);
public: virtual int Mod2::AddPublic2(char const *name,unsigned short sec,long off,unsigned long type);
public: virtual int Mod::InsertLines(unsigned char *,long);
public: virtual int Mod::QueryLines2(long,unsigned char *,long *);
+// mspdb140.dll:
+public: virtual int QueryCrossScopeExports(unsigned long,unsigned char *,unsigned long *);
+public: virtual int QueryCrossScopeImports(unsigned long,unsigned char *,unsigned long *);
+public: virtual int QueryInlineeLines(unsigned long,unsigned char *,unsigned long *);
+public: virtual int EnCReleaseCompilerGeneratedPDB(unsigned char *,unsigned long);
+public: virtual int QueryFuncMDTokenMap(unsigned long,unsigned char *,unsigned long *);
+public: virtual int QueryTypeMDTokenMap(unsigned long,unsigned char *,unsigned long *);
+public: virtual int QueryMergedAssemblyInput(unsigned long,unsigned char *,unsigned long *);
+public: virtual int QueryILLines(unsigned long,unsigned char *,unsigned long *);
+public: virtual int GetEnumILLines(struct EnumLines * *);
+public: virtual int QueryILLineFlags(unsigned long *);
+public: virtual int MergeTypes(unsigned char *,unsigned long);
+public: virtual int IsTypeServed(unsigned long,int);
+public: virtual int QueryTypes(unsigned char *,unsigned long *);
+public: virtual int QueryIDs(unsigned char *,unsigned long *);
+public: virtual int QueryCVRecordForTi(unsigned long,int,unsigned char *,unsigned long *);
+public: virtual int QueryPbCVRecordForTi(unsigned long,int,unsigned char * *);
+public: virtual int QueryTiForUDT(char const *,int,unsigned long *);
+public: virtual int QueryCoffSymRVAs(unsigned char *,unsigned long *);
+public: virtual int AddSecContrib2(unsigned short,unsigned long,unsigned long,unsigned long,unsigned long);
+public: virtual int AddSecContrib2Ex(unsigned short,unsigned long,unsigned long,unsigned long,unsigned long,unsigned long,unsigned long);
+public: virtual int AddSymbols2(unsigned char *,unsigned long,unsigned long);
+public: virtual int RemoveGlobalRefs(void);
+public: virtual int QueryPbCVRecordForTi_alias(unsigned long,int,unsigned char * *);
+public: virtual int FReleaseGlobalSymbolBuffer(void);
+public: virtual int EnCReleaseCompilerGeneratedPDB_alias(unsigned char *,unsigned long);
+// mspdb140.dll!Mod_Proxy2::`vector deleting destructor'(unsigned int)
};
@@ -411,7 +452,7 @@ public: virtual int QueryNextItsm(unsigned char,unsigned char *);
public: virtual int reinitialize(void); // returns 0 (QueryLazyTypes in 10.0)
public: virtual int SetLazyTypes(int);
public: virtual int FindTypeServers(long *,char *);
-public: virtual void noop(void); // noop (_Reserved_was_QueryMreLog in 10.0)
+public: virtual void noop(void); // noop (_Reserved_was_QueryMreLog in 10.0, (mspdb140.dll: DumpTypeServers(void))
public: virtual int OpenDbg(enum DBGTYPE,struct Dbg * *);
public: virtual int QueryDbgTypes(enum DBGTYPE *,long *);
public: virtual int QueryAddrForSec(unsigned short *,long *,unsigned short,long,unsigned long,unsigned long);
@@ -421,7 +462,7 @@ struct DBI_part2 : public DBI_part1 {
public: virtual int QueryAddrForSecEx(unsigned short *,long *,unsigned short,long,unsigned long,unsigned long);
};
-template<class BASE>
+template<class BASE>
struct DBI_BASE : public BASE {
public: virtual int QuerySupportsEC(void);
public: virtual int QueryPdb(struct PDB * *);
@@ -452,6 +493,14 @@ public: virtual int FSetPfnNotePdbUsed(void *,void (__cdecl*)(void *,unsigned sh
public: virtual int FCTypes(void);
public: virtual int QueryFileInfo2(unsigned char *,long *);
public: virtual int FSetPfnQueryCallback(void *,int (__cdecl*(__cdecl*)(void *,enum DOVC))(void));
+// mspdb140.dll!DBI_Proxy::FSetPfnNoteTypeMismatch(void *,void (*)(void *,unsigned short const *,unsigned short const *))
+// mspdb140.dll!DBI_Proxy::FSetPfnTmdTypeFilter(void *,int (*)(void *,unsigned short const *))
+// mspdb140.dll!DBI_Proxy::RemovePublic(char const *)
+// mspdb140.dll!DBI_Proxy2::getEnumContrib2(struct Enum * *)
+// mspdb140.dll!DBI_Proxy2::QueryModFromAddrEx(unsigned short,unsigned long,struct Mod * *,unsigned short *,unsigned long *,unsigned long *,unsigned long *,unsigned long *)
+// mspdb140.dll!DBI_Proxy2::QueryImodFromAddrEx(unsigned short,unsigned long,unsigned short *,unsigned short *,unsigned long *,unsigned long *,unsigned long *,unsigned long *)
+// mspdb140.dll!DBI_Proxy::UpdateGlobalDataAddr(char const *,unsigned short,unsigned long)
+// mspdb140.dll!DBI_Proxy2::`vector deleting destructor'(unsigned int)
};
struct DBI_VS9 : public DBI_BASE<DBI_part1> {};
@@ -530,6 +579,9 @@ public: virtual unsigned long TPI::QueryTiMac(void);
public: virtual int TPI::AreTypesEqual(unsigned long,unsigned long);
public: virtual int TPI2::IsTypeServed(unsigned long);
public: virtual int TPI::QueryTiForUDTW(unsigned short const *,int,unsigned long *);
+// mspdb140.dll!TPI_Proxy::QueryModSrcLineForUDTDefn(unsigned long,unsigned short *,unsigned long *,unsigned long *)
+// mspdb140.dll!TPI_Proxy2::QueryTIsForCVRecords(unsigned char *,unsigned long,unsigned long,unsigned long,unsigned long *)
+// mspdb140.dll!TPI_Proxy2::`vector deleting destructor'(unsigned int)
};