From 259c6e72e8ed783d224648e9d0012adb6398e5b0 Mon Sep 17 00:00:00 2001 From: sagitario Date: Fri, 4 Jun 2010 07:26:26 +0000 Subject: Version 0.13 * adapted to mspdb100.dll which comes with VS2010 * tweaked autoexp.dat modifications to be more stable with uninitialized data * autoexp.snippet now split into two files --- CHANGES | 6 ++ INSTALL | 26 ++++-- Makefile | 2 +- VERSION | 2 +- autoexp.expand | 17 ++++ autoexp.snippet | 217 ------------------------------------------------- autoexp.visualizer | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cv2pdb.cpp | 32 +++++++- src/cv2pdb.h | 2 +- src/demangle.cpp | 9 ++- src/mspdb.cpp | 29 +++++-- src/mspdb.h | 161 ++++++++++++++++++++++-------------- src/symutil.cpp | 1 - test/Makefile | 4 +- test/cvtest.d | 39 +++++++++ 15 files changed, 477 insertions(+), 303 deletions(-) create mode 100644 autoexp.expand delete mode 100644 autoexp.snippet create mode 100644 autoexp.visualizer diff --git a/CHANGES b/CHANGES index 12f6653..528bc89 100644 --- a/CHANGES +++ b/CHANGES @@ -90,3 +90,9 @@ Version history * added managed C++ project to integrate cv2pdb with CLR (thanks to Alexander Bothe) * dmd 2.043 uses different implementation of associative arrays, use command line option -D 2.043 or above to produce the respective debug info + +2010-06-03 Version 0.13 + + * adapted to mspdb100.dll which comes with VS2010 + * tweaked autoexp.dat modifications to be more stable with uninitialized data + * autoexp.snippet now split into two files: autoexp.expand and autoexp.visualizer diff --git a/INSTALL b/INSTALL index 76bafeb..856b73a 100644 --- a/INSTALL +++ b/INSTALL @@ -9,22 +9,33 @@ Prerequisites For this program to be useful, you should have you should have the Digital Mars D Compiler (http://www.digitalmars.com/d/2.0/dmd-windows.html) -and either Microsoft Visual Studio 2005 or 2008 or one of the Express +and either Microsoft Visual Studio 2005, 2008 or 2010 or one of the Express versions installed. cv2pdb uses one of the Microsoft DLLs to actually write the PDB file. +If you are using some other program, you'll still need some +files from one of the distributions. These are mspdb80.dll, mspdbsrv.exe, +msobj80.dll, mspdbcore.dll and msvcr90.dll from the VS2008 installation or +mspdb100.dll, mspdbsrv.exe, msobj100.dll, mspdbcore.dll and msvcr100.dll +from VS2010. They should be accessible through the PATH environment variable. +(The VS Shell is missing the msobj80.dll/msobj100.dll only). + Installation ------------ -Sorry, there is no full featured installer available yet, you'll have +You might want to consider installing Visual D (www.dsource.org/project/visuald) +instead of cv2pdb. Visual D provides both project and language integration +into Visual Studio and comes with an installer that includes cv2pdb. + +There is no full featured installer available for cv2pdb, you'll have to do some simple manual steps to use cv2pdb. 1. The binary package of cv2pdb contains an executable cv2pdb.exe, which should be copied somewhere accessible through your PATH environment variable. -2. cv2pdb.exe must be able to locate the DLL mspdb80.dll from the Visual -Studio installation. It reads out the installation path of the latter, but -if this fails, mspdb80.dll should also be accessible through your PATH +2. cv2pdb.exe must be able to locate the DLL mspdb80.dll/mspdb100.dll from the Visual +Studio installation. It tries to read the installation path of the latter from the registry, but +if this fails, mspdb80.dll/mspdb100.dll should also be accessible through your PATH environment variable. 3. For best debugging experience, you should configure Visual Studio @@ -34,8 +45,9 @@ navigating to the file extensions option page (found in Tools -> Options with editor "Microsoft Visual C++". This will also enable display of variables in the "Auto" watch window. -4. You should also add the contents of the file autoexp.snippet to the -[AutoExpand] and [Visualizer] sections of the file autoexp.dat found in +4. You should also add the contents of the files autoexp.expand and +autoexp.visualizer to the respective [AutoExpand] and [Visualizer] +sections of the file autoexp.dat found in \Common7\Packages\Debugger. Please note that in a standard installation of Visual Studio, the section [AutoExpand] is at the beginning of that file, followed by diff --git a/Makefile b/Makefile index a7230f8..c246003 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ ADD = Makefile \ src\dviewhelper\dviewhelper.vcproj \ src\cv2pdb.sln -DOC = VERSION README INSTALL LICENSE CHANGES TODO FEATURES autoexp.snippet +DOC = VERSION README INSTALL LICENSE CHANGES TODO FEATURES autoexp.expand autoexp.visualizer BIN = bin\Release\cv2pdb.exe bin\Release\dviewhelper.dll diff --git a/VERSION b/VERSION index b8eae15..dc33958 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.12 +VERSION = 0.13 diff --git a/autoexp.expand b/autoexp.expand new file mode 100644 index 0000000..25cc23b --- /dev/null +++ b/autoexp.expand @@ -0,0 +1,17 @@ +;; added to [AutoExpand] for cv2pdb - keep this line for uninstaller +;; add DO NOT REMOVE to the line above after the '-' to not remove/update +;; this section by the installer/uninstaller +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; load helper dll dviewhelper.dll to display D strings +;; +;; add the following lines to the [AutoExpand] section +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +object_viewhelper=$ADDIN(dviewhelper.dll,_DObjectView@28) +string_viewhelper=$ADDIN(dviewhelper.dll,_DStringView@28) +wstring_viewhelper=$ADDIN(dviewhelper.dll,_DWStringView@28) +dstring_viewhelper=$ADDIN(dviewhelper.dll,_DDStringView@28) + +;; eo section AutoExpand for D variables ;;;;;;;;;;;;;;;;;;;;;; +;; eo added for cv2pdb - keep this line for uninstaller diff --git a/autoexp.snippet b/autoexp.snippet deleted file mode 100644 index 5917595..0000000 --- a/autoexp.snippet +++ /dev/null @@ -1,217 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; This file is part cv2pdb, a -;; converter of DMD CodeView debug information to PDB files -;; -;; written by Rainer Schuetze, placed into the Public Domain -;; -;; D types -;; -;; add the content of this file to -;; \Common7\Package\Debugger\autoexp.dat -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; load helper dll dviewhelper.dll to display strings -;; -;; add the following 2 lines to the [AutoExpand] section -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; [AutoExpand] - -object_viewhelper=$ADDIN(dviewhelper.dll,_DObjectView@28) -string_viewhelper=$ADDIN(dviewhelper.dll,_DStringView@28) -wstring_viewhelper=$ADDIN(dviewhelper.dll,_DWStringView@28) -dstring_viewhelper=$ADDIN(dviewhelper.dll,_DDStringView@28) - -;; eo section AutoExpand for D variables ;;;;;;;;;;;;;;;;;;;;;; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; D types visualizer -;; -;; add the remainder of this file to the [Visualizer] section -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; [Visualizer] - -; string, wstring and dstring use __viewhelper -string|wstring|dstring { - - preview ( - #if ($e.ptr == 0) ( "null" ) - #else ( - #( "[", $e.length, "] ", [$e.__viewhelper] ) - ) - ) - stringview ( - #if ($e.ptr == 0) ( "null" ) - #else ( - #( [$e.ptr, s] ) - ) - ) - children ( - #( - length: [$e.length, i], - data: [$e.ptr] - ) - ) -} - -; strings as dynamic arrays of char (no __viewhelper, check -D option for cv2pdb!) -const char[]|char[]|const wchar[]|wchar[]|const dchar[]|dchar[] { - - preview ( - #if ($e.ptr == 0) ( "null" ) - #else ( - #( "[", $e.length, "] ", [$e.ptr] ) - ) - ) - stringview ( - #if ($e.ptr == 0) ( "null" ) - #else ( - #( [$e.ptr, s] ) - ) - ) - children ( - #( - length: [$e.length, i], - data: [$e.ptr] - ) - ) -} - -; dynamic array -*[] { - preview ( - #if ($e.ptr == 0) ( "null" ) - #else ( - #( - "[", $e.length, "](", - #array ( - expr : ($e.ptr)[$i], - size : $e.length - ), - ")" - ) - ) - ) - children ( - #( - length: [$e.length, i], - #array ( - expr: $e.ptr[$i], - size: $e.length - ) - ) - ) -} - -;; display associative array -;; -;; the "magic" sizes of the basic dynamic array are used to check for uninitialized -;; arrays -;; 97UL, 389UL, -;; 1_543UL, 6_151UL, -;; 24_593UL, 98_317UL, -;; 393_241UL, 1_572_869UL, -;; 6_291_469UL, 25_165_843UL, -;; 100_663_319UL, 402_653_189UL, -;; 1_610_612_741UL, 4_294_967_291UL, -aa<*> { - preview( - #if($e.a == 0 || $e.a->b.ptr == 0) ( "null" ) - ; expressions must be in a sinlge line (sigh) - #elif($e.a->b.length == 97 || $e.a->b.length == 389 || $e.a->b.length == 1543 || $e.a->b.length == 6151 || $e.a->b.length == 24593 || $e.a->b.length == 98317 || $e.a->b.length == 393241 || $e.a->b.length == 1572869 || $e.a->b.length == 6291469 || $e.a->b.length == 25165843) - ( - #if($e.a->nodes > 1024) ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a], " too large for expansion" ) - ) - #else ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a] ) - ) - ) - #elif (1) ; no #else in a series of #elif !? - ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a], " uninitialized" ) - ) - ) - children( - #if($e.a == 0 || $e.a->b.ptr == 0 || $e.a->nodes > 1024) - ( #array( expr: 0, size: 0 ) ) - #else ( - #( - #array ( - expr: &$e.a->b.ptr[$i], - size: $e.a->b.length - ) : - #tree ( - head : $e, - left : left, - right : right, - ) : $e - ) - ) - ) -} - -;; display associative array (starting with with dmd2.043, new sizes 4 and 31 were added, and -;; a list is used per hash entry instead of a tree -;; remember to pass -D 2.043 to cv2pdb to produce suitable debug info -;; -aa2<*> { - preview( - #if($e.a == 0 || $e.a->b.ptr == 0) ( "null" ) - ; expressions must be in a single line (sigh) - #elif($e.a->b.length == 4 || $e.a->b.length == 31 || $e.a->b.length == 97 || $e.a->b.length == 389 || $e.a->b.length == 1543 || $e.a->b.length == 6151 || $e.a->b.length == 24593 || $e.a->b.length == 98317 || $e.a->b.length == 393241 || $e.a->b.length == 1572869 || $e.a->b.length == 6291469 || $e.a->b.length == 25165843) - ( - #if($e.a->nodes > 1024) ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a], " too large for expansion" ) - ) - #else ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a] ) - ) - ) - #elif (1) ; no #else in a series of #elif !? - ( - #( "[", $e.a->nodes, "] ", [(void*) $e.a], " uninitialized" ) - ) - ) - children( - #if($e.a == 0 || $e.a->b.ptr == 0 || $e.a->nodes > 1024) - ( #array( expr: 0, size: 0 ) ) - #else ( - #( - #array ( - expr: &$e.a->b.ptr[$i], - size: $e.a->b.length - ) : - ; DMD 2.043+ - #list ( - head : $e, - next : next - ) : $e - ) - ) - ) -} - -; display tree -internal@aaA<*,*> { - preview( - #( "<", $e.key, ", ", $e.value, ">" ) - ) -} - -; display null references for class objects -*@* { - preview( - #( - #if (&$e == 0) ( "null" ) - #else ( - #( "[", [$e.__viewhelper], "] ", [$e,!] ) - ) - ) - ) -} - -;; eo section Visualizer for D variables ;;;;;;;;;;;;;;;;;;;;;; diff --git a/autoexp.visualizer b/autoexp.visualizer new file mode 100644 index 0000000..ea62187 --- /dev/null +++ b/autoexp.visualizer @@ -0,0 +1,233 @@ +;; added to [Visualizer] for cv2pdb - keep this line for uninstaller +;; add DO NOT REMOVE to the line above after the '-' to not remove/update +;; this section by the installer/uninstaller + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; D types visualizer +;; +;; add the remainder of this file to the [Visualizer] section +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; string, wstring and dstring use __viewhelper +string|wstring|dstring { + + preview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #( "[", $e.length, "] ", [$e.__viewhelper] ) + ) + ) + stringview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #( [$e.ptr, s] ) + ) + ) + children ( + #( + length: [$e.length, i], + data: [$e.ptr] + ) + ) +} + +; strings as dynamic arrays of char (no __viewhelper, check -D option for cv2pdb!) +const char[]|char[]|const wchar[]|wchar[]|const dchar[]|dchar[] { + + preview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #( "[", $e.length, "] ", [$e.ptr] ) + ) + ) + stringview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #( [$e.ptr, s] ) + ) + ) + children ( + #( + length: [$e.length, i], + data: [$e.ptr] + ) + ) +} + +const void[]|void[] { + preview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #( "[", $e.length, "] ", [(void*) $e.ptr] ) + ) + ) + children ( + #( + length: [$e.length], + ptr: [(void*) $e.ptr] + ) + ) +} + +; dynamic array +*[] { + preview ( + #if ($e.ptr == 0) ( "null" ) + #else ( + #if($e.length > 1024) ( + #( "[", $e.length, "] ", (void*) $e.ptr, " too large for expansion" ) + ) + #else ( + #( + "[", $e.length, "](", + #array ( + expr : ($e.ptr)[$i], + size : $e.length + ), + ")" + ) + ) + ) + ) + children ( + #if($e.length > 4096) ( + #( + length: [$e.length], + ptr: [$e.ptr] + ) + ) + #else ( + #( + length: [$e.length], + #array ( + expr: $e.ptr[$i], + size: $e.length + ) + ) + ) + ) +} + +;; display associative array +;; +;; the "magic" sizes of the basic dynamic array are used to check for uninitialized +;; arrays +;; 97UL, 389UL, +;; 1_543UL, 6_151UL, +;; 24_593UL, 98_317UL, +;; 393_241UL, 1_572_869UL, +;; 6_291_469UL, 25_165_843UL, +;; 100_663_319UL, 402_653_189UL, +;; 1_610_612_741UL, 4_294_967_291UL, +aa<*> { + preview( + #if($e.a == 0 || $e.a->b.ptr == 0) ( "null" ) + ; expressions must be in a single line (sigh) + #elif($e.a->b.length == 97 || $e.a->b.length == 389 || $e.a->b.length == 1543 || $e.a->b.length == 6151 || $e.a->b.length == 24593 || $e.a->b.length == 98317 || $e.a->b.length == 393241 || $e.a->b.length == 1572869 || $e.a->b.length == 6291469 || $e.a->b.length == 25165843) + ( + #if($e.a->nodes > 1024) ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a], " too large for expansion" ) + ) + #else ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a] ) + ) + ) + #elif (1) ; no #else in a series of #elif !? + ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a], " uninitialized" ) + ) + ) + children( + #if($e.a == 0 || $e.a->b.ptr == 0 || $e.a->nodes > 1024) + ( #array( expr: 0, size: 0 ) ) + #else ( + #( + #array ( + expr: &$e.a->b.ptr[$i], + size: $e.a->b.length + ) : + #tree ( + head : $e, + left : left, + right : right +; limit size for sanity, hope rehashing takes care of not long lists +; limiting the number does not work, it will try to show the given number of elements +; size : 32 + ) : $e + ) + ) + ) +} + +;; display associative array (starting with with dmd2.043, new sizes 4 and 31 were added, and +;; a list is used per hash entry instead of a tree +;; remember to pass -D 2.043 to cv2pdb to produce suitable debug info +;; +aa2<*> { + preview( + #if($e.a == 0 || $e.a->b.ptr == 0) ( "null" ) + ; expressions must be in a single line (sigh) + #elif($e.a->b.length == 4 || $e.a->b.length == 31 || $e.a->b.length == 97 || $e.a->b.length == 389 || $e.a->b.length == 1543 || $e.a->b.length == 6151 || $e.a->b.length == 24593 || $e.a->b.length == 98317 || $e.a->b.length == 393241 || $e.a->b.length == 1572869 || $e.a->b.length == 6291469 || $e.a->b.length == 25165843) + ( + #if($e.a->nodes > 1024) ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a], " too large for expansion" ) + ) + #else ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a] ) + ) + ) + #elif (1) ; no #else in a series of #elif !? + ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a], " uninitialized" ) + ) + ) + children( + #if($e.a == 0 || $e.a->b.ptr == 0) + ( #array( expr: 0, size: 0 ) ) + ; expressions must be in a single line (sigh) + #elif($e.a->b.length == 4 || $e.a->b.length == 31 || $e.a->b.length == 97 || $e.a->b.length == 389 || $e.a->b.length == 1543 || $e.a->b.length == 6151 || $e.a->b.length == 24593 || $e.a->b.length == 98317 || $e.a->b.length == 393241 || $e.a->b.length == 1572869 || $e.a->b.length == 6291469 || $e.a->b.length == 25165843) + ( + #( + #array ( + expr: &$e.a->b.ptr[$i], + size: $e.a->b.length + ) : + ; DMD 2.043+ + #list ( + head : $e, + next : next +; limit size for sanity, hope rehashing takes care of not long lists +; limiting the number does not work, it will try to show the given number of elements +; size : 32 + ) : $e + ) + ) + #elif (1) ; no #else in a series of #elif !? + ( + #( "[", $e.a->nodes, "] ", [(void*) $e.a], " uninitialized" ) + ) + ) +} + +; display tree +internal@aaA<*,*> { + preview( + #( "<", $e.key, ", ", $e.value, ">" ) + ) +} + +; display null references for class objects +*@* { + preview( + #( + #if (&$e == 0) ( "null" ) + #else ( + #( "[", [$e.__viewhelper], "] ", [$e,!] ) + ) + ) + ) +} + +;; eo section Visualizer for D variables ;;;;;;;;;;;;;;;;;;;;;; +;; eo added for cv2pdb - keep this line for uninstaller diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index 0a66e8e..a934d2f 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -12,6 +12,7 @@ #include #define REMOVE_LF_DERIVED 1 // types wrong by DMD +#define PRINT_INTERFACEVERSON 0 static const int kIncomplete = 0x80; @@ -125,9 +126,11 @@ bool CV2PDB::openPDB(const char* pdbname) if (!pdb) return setError("cannot create PDB file"); - //printf("PDB::QueryInterfaceVersion() = %d\n", pdb->QueryInterfaceVersion()); - //printf("PDB::QueryImplementationVersion() = %d\n", pdb->QueryImplementationVersion()); - //printf("PDB::QueryPdbImplementationVersion() = %d\n", pdb->QueryPdbImplementationVersion()); +#if PRINT_INTERFACEVERSON + printf("PDB::QueryInterfaceVersion() = %d\n", pdb->QueryInterfaceVersion()); + printf("PDB::QueryImplementationVersion() = %d\n", pdb->QueryImplementationVersion()); + printf("PDB::QueryPdbImplementationVersion() = %d\n", pdb->QueryPdbImplementationVersion()); +#endif rsds = (OMFSignatureRSDS *) new char[24 + strlen(pdbname) + 1]; // sizeof(OMFSignatureRSDS) without name memcpy (rsds->Signature, "RSDS", 4); @@ -139,10 +142,20 @@ bool CV2PDB::openPDB(const char* pdbname) if (rc <= 0 || !dbi) return setError("cannot create DBI"); +#if PRINT_INTERFACEVERSON + printf("DBI::QueryInterfaceVersion() = %d\n", dbi->QueryInterfaceVersion()); + printf("DBI::QueryImplementationVersion() = %d\n", dbi->QueryImplementationVersion()); +#endif + rc = pdb->OpenTpi("", &tpi); if (rc <= 0 || !tpi) return setError("cannot create TPI"); +#if PRINT_INTERFACEVERSON + printf("TPI::QueryInterfaceVersion() = %d\n", tpi->QueryInterfaceVersion()); + printf("TPI::QueryImplementationVersion() = %d\n", tpi->QueryImplementationVersion()); +#endif + return true; } @@ -192,6 +205,15 @@ bool CV2PDB::createModules() return setError("cannot create mod"); mod = modules[entry->iMod]; } +#if PRINT_INTERFACEVERSON + static bool once; + if(!once) + { + printf("Mod::QueryInterfaceVersion() = %d\n", mod->QueryInterfaceVersion()); + printf("Mod::QueryImplementationVersion() = %d\n", mod->QueryImplementationVersion()); + once = true; + } +#endif for (int s = 0; s < module->cSeg; s++) { @@ -2501,7 +2523,9 @@ bool CV2PDB::writeSymbols(mspdb::Mod* mod, DWORD* data, int databytes, int prefi data[3] = 1; int rc = mod->AddSymbols((BYTE*) data, ((databytes + 3) / 4 + prefix) * 4); if (rc <= 0) - return setError("cannot add symbols to module"); + return setError(mspdb::DBI::isVS10 + ? "cannot add symbols to module, probably msobj100.dll missing" + : "cannot add symbols to module, probably msobj80.dll missing"); return true; } diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 48b67d5..c95fa52 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -49,7 +49,7 @@ public: int addFieldMember(codeview_fieldtype* dfieldtype, int attr, int offset, int type, const char* name); int addFieldStaticMember(codeview_fieldtype* dfieldtype, int attr, int type, const char* name); - int addFieldNestedType(codeview_fieldtype* dfieldtype, int type, const char* name); + int addFieldNestedType(codeview_fieldtype* dfieldtype, int type, const char* name); void checkUserTypeAlloc(int size = 1000, int add = 10000); diff --git a/src/demangle.cpp b/src/demangle.cpp index 87bef71..01ee4f2 100644 --- a/src/demangle.cpp +++ b/src/demangle.cpp @@ -16,6 +16,8 @@ #include #include +#include "symutil.h" + using namespace std; typedef unsigned char ubyte; @@ -493,13 +495,16 @@ void unittest() string r = d.demangle(table[i][0]); assert(r == table[i][1]); // "table entry #" + toString(i) + ": '" + name[0] + "' demangles as '" + r + "' but is expected to be '" + name[1] + "'"); - } + + const char s[] = "_D12intellisen\xd1" "11LibraryInfo14findDe\xeaitionMFKS\x80\x8f\xaf" "0SearchDataZA\x80\x91\x9d\x80\x8a\xbb" "8count\x80\x83\x90MFAyaP\x80\x8f\xaa" "9JSONscopeH\x80\x83\x93S3std4json\x80\x85\x98ValueZb"; + char buf[512]; + dsym2c((const BYTE*) s, sizeof(s) - 1, buf, sizeof(buf)); } bool d_demangle(const char* name, char* demangled, int maxlen, bool plain) { - // static bool once; if(!once) unittest(); once = true; + static bool once; if(!once) { once = true; unittest(); } Demangle d; string r = d.demangle(name, plain); diff --git a/src/mspdb.cpp b/src/mspdb.cpp index fe10243..76ec6d7 100644 --- a/src/mspdb.cpp +++ b/src/mspdb.cpp @@ -13,7 +13,10 @@ HMODULE modMsPdb; mspdb::fnPDBOpen2W *pPDBOpen2W; -char* mspdb_dll = "mspdb80.dll"; +char* mspdb80_dll = "mspdb80.dll"; +char* mspdb100_dll = "mspdb100.dll"; + +bool mspdb::DBI::isVS10 = false; bool getInstallDir(const char* version, char* installDir, DWORD size) { @@ -46,15 +49,29 @@ bool tryLoadMsPdb(const char* version, const char* mspdb) bool initMsPdb() { if (!modMsPdb) - modMsPdb = LoadLibraryA(mspdb_dll); + modMsPdb = LoadLibraryA(mspdb80_dll); + + if (!modMsPdb) + tryLoadMsPdb("VisualStudio\\9.0", mspdb80_dll); if (!modMsPdb) - tryLoadMsPdb("VisualStudio\\9.0", mspdb_dll); + tryLoadMsPdb("VisualStudio\\8.0", mspdb80_dll); if (!modMsPdb) - tryLoadMsPdb("VisualStudio\\8.0", mspdb_dll); + tryLoadMsPdb("VCExpress\\9.0", mspdb80_dll); if (!modMsPdb) - tryLoadMsPdb("VCExpress\\9.0", mspdb_dll); + tryLoadMsPdb("VCExpress\\8.0", mspdb80_dll); + +#if 1 if (!modMsPdb) - tryLoadMsPdb("VCExpress\\8.0", mspdb_dll); + { + modMsPdb = LoadLibraryA(mspdb100_dll); + if (!modMsPdb) + tryLoadMsPdb("VisualStudio\\10.0", mspdb100_dll); + if (!modMsPdb) + tryLoadMsPdb("VCExpress\\10.0", mspdb100_dll); + if (modMsPdb) + mspdb::DBI::isVS10 = true; + } +#endif if (!modMsPdb) return false; diff --git a/src/mspdb.h b/src/mspdb.h index 7104fc2..16209b4 100644 --- a/src/mspdb.h +++ b/src/mspdb.h @@ -30,7 +30,6 @@ struct MRECmp2; struct PDB; struct Src; struct Mod; -struct DBI; struct StreamCached; struct GSI; struct TPI; @@ -41,18 +40,22 @@ struct EnumNameMap; #define PDBCommon PDB #define SrcCommon Src #define ModCommon Mod -#define DBICommon DBI #define MREUtil2 MREUtil #define MREFile2 MREFile #define MREBag2 MREBag #define Mod2 Mod -#define DBI2 DBI #define GSI2 GSI #define TPI2 TPI #define NameMap2 NameMap #define EnumNameMap2 EnumNameMap +struct DBI; +/* +#define DBICommon DBI +#define DBI2 DBI +*/ + struct MREUtil { public: virtual int MREUtil::FRelease(void); public: virtual void MREUtil::EnumSrcFiles(int (__stdcall*)(struct MREUtil *,struct EnumFile &,enum EnumType),unsigned short const *,void *); @@ -338,64 +341,100 @@ public: virtual int Mod::QueryLines2(long,unsigned char *,long *); }; -struct DBI { -public: virtual unsigned long DBI::QueryImplementationVersion(void); -public: virtual unsigned long DBI::QueryInterfaceVersion(void); -public: virtual int DBICommon::OpenMod(char const *objName,char const *libName,struct Mod * *); -public: virtual int DBI::DeleteMod(char const *); -public: virtual int DBI2::QueryNextMod(struct Mod *,struct Mod * *); -public: virtual int DBI::OpenGlobals(struct GSI * *); -public: virtual int DBI::OpenPublics(struct GSI * *); -public: virtual int DBI::AddSec(unsigned short sec,unsigned short flags,long offset,long cbseg); -public: virtual int DBI2::QueryModFromAddr(unsigned short,long,struct Mod * *,unsigned short *,long *,long *); -public: virtual int DBI::QuerySecMap(unsigned char *,long *); -public: virtual int DBI::QueryFileInfo(unsigned char *,long *); -public: virtual void DBI::DumpMods(void); -public: virtual void DBI::DumpSecContribs(void); -public: virtual void DBI::DumpSecMap(void); -public: virtual int DBI2::Close(void); -public: virtual int DBI::AddThunkMap(long *,unsigned int,long,struct SO *,unsigned int,unsigned short,long); -public: virtual int DBI::AddPublic(char const *,unsigned short,long); -public: virtual int DBI2::getEnumContrib(struct Enum * *); -public: virtual int DBI::QueryTypeServer(unsigned char,struct TPI * *); -public: virtual int DBI::QueryItsmForTi(unsigned long,unsigned char *); -public: virtual int DBI::QueryNextItsm(unsigned char,unsigned char *); -public: virtual int DBI::reinitialize(void); // returns 0 -public: virtual int DBI::SetLazyTypes(int); -public: virtual int DBI::FindTypeServers(long *,char *); -public: virtual void DBI::noop(void); // noop -public: virtual int DBI::OpenDbg(enum DBGTYPE,struct Dbg * *); -public: virtual int DBI::QueryDbgTypes(enum DBGTYPE *,long *); -public: virtual int DBI::QueryAddrForSec(unsigned short *,long *,unsigned short,long,unsigned long,unsigned long); -public: virtual int DBI::QuerySupportsEC(void); -public: virtual int DBI2::QueryPdb(struct PDB * *); -public: virtual int DBI::AddLinkInfo(struct LinkInfo *); -public: virtual int DBI::QueryLinkInfo(struct LinkInfo *,long *); -public: virtual unsigned long DBI::QueryAge(void)const ; -public: virtual int DBI2::reinitialize2(void); // returns 0 -public: virtual void DBI::FlushTypeServers(void); -public: virtual int DBICommon::QueryTypeServerByPdb(char const *,unsigned char *); -public: virtual int DBI2::OpenModW(unsigned short const *objName,unsigned short const *libName,struct Mod * *); -public: virtual int DBI::DeleteModW(unsigned short const *); -public: virtual int DBI::AddPublicW(unsigned short const *name,unsigned short sec,long off,unsigned long type); -public: virtual int DBI::QueryTypeServerByPdbW(unsigned short const *,unsigned char *); -public: virtual int DBI::AddLinkInfoW(struct LinkInfoW *); -public: virtual int DBI::AddPublic2(char const *name,unsigned short sec,long off,unsigned long type); -public: virtual unsigned short DBI::QueryMachineType(void)const ; -public: virtual void DBI::SetMachineType(unsigned short); -public: virtual void DBI::RemoveDataForRva(unsigned long,unsigned long); -public: virtual int DBI::FStripped(void); -public: virtual int DBI2::QueryModFromAddr2(unsigned short,long,struct Mod * *,unsigned short *,long *,long *,unsigned long *); -public: virtual int DBI::QueryNoOfMods(long *); -public: virtual int DBI2::QueryMods(struct Mod * *,long); -public: virtual int DBI2::QueryImodFromAddr(unsigned short,long,unsigned short *,unsigned short *,long *,long *,unsigned long *); -public: virtual int DBI2::OpenModFromImod(unsigned short,struct Mod * *); -public: virtual int DBI::QueryHeader2(long,unsigned char *,long *); -public: virtual int DBI::FAddSourceMappingItem(unsigned short const *,unsigned short const *,unsigned long); -public: virtual int DBI::FSetPfnNotePdbUsed(void *,void (__cdecl*)(void *,unsigned short const *,int,int)); -public: virtual int DBI::FCTypes(void); -public: virtual int DBI::QueryFileInfo2(unsigned char *,long *); -public: virtual int DBI::FSetPfnQueryCallback(void *,int (__cdecl*(__cdecl*)(void *,enum DOVC))(void)); +struct DBI_part1 { +public: virtual unsigned long QueryImplementationVersion(void); +public: virtual unsigned long QueryInterfaceVersion(void); +public: virtual int OpenMod(char const *objName,char const *libName,struct Mod * *); +public: virtual int DeleteMod(char const *); +public: virtual int QueryNextMod(struct Mod *,struct Mod * *); +public: virtual int OpenGlobals(struct GSI * *); +public: virtual int OpenPublics(struct GSI * *); +public: virtual int AddSec(unsigned short sec,unsigned short flags,long offset,long cbseg); +public: virtual int QueryModFromAddr(unsigned short,long,struct Mod * *,unsigned short *,long *,long *); +public: virtual int QuerySecMap(unsigned char *,long *); +public: virtual int QueryFileInfo(unsigned char *,long *); +public: virtual void DumpMods(void); +public: virtual void DumpSecContribs(void); +public: virtual void DumpSecMap(void); +public: virtual int Close(void); +public: virtual int AddThunkMap(long *,unsigned int,long,struct SO *,unsigned int,unsigned short,long); +public: virtual int AddPublic(char const *,unsigned short,long); +public: virtual int getEnumContrib(struct Enum * *); +public: virtual int QueryTypeServer(unsigned char,struct TPI * *); +public: virtual int QueryItsmForTi(unsigned long,unsigned char *); +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 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); +}; +struct DBI_part2 : public DBI_part1 { +// in mspdb100.dll: +public: virtual int QueryAddrForSecEx(unsigned short *,long *,unsigned short,long,unsigned long,unsigned long); +}; + +template +struct DBI_BASE : public BASE { +public: virtual int QuerySupportsEC(void); +public: virtual int QueryPdb(struct PDB * *); +public: virtual int AddLinkInfo(struct LinkInfo *); +public: virtual int QueryLinkInfo(struct LinkInfo *,long *); +public: virtual unsigned long QueryAge(void)const ; +public: virtual int reinitialize2(void); // returns 0 (QueryLazyTypes in 10.0) +public: virtual void FlushTypeServers(void); +public: virtual int QueryTypeServerByPdb(char const *,unsigned char *); +public: virtual int OpenModW(unsigned short const *objName,unsigned short const *libName,struct Mod * *); +public: virtual int DeleteModW(unsigned short const *); +public: virtual int AddPublicW(unsigned short const *name,unsigned short sec,long off,unsigned long type); +public: virtual int QueryTypeServerByPdbW(unsigned short const *,unsigned char *); +public: virtual int AddLinkInfoW(struct LinkInfoW *); +public: virtual int AddPublic2(char const *name,unsigned short sec,long off,unsigned long type); +public: virtual unsigned short QueryMachineType(void)const ; +public: virtual void SetMachineType(unsigned short); +public: virtual void RemoveDataForRva(unsigned long,unsigned long); +public: virtual int FStripped(void); +public: virtual int QueryModFromAddr2(unsigned short,long,struct Mod * *,unsigned short *,long *,long *,unsigned long *); +public: virtual int QueryNoOfMods(long *); +public: virtual int QueryMods(struct Mod * *,long); +public: virtual int QueryImodFromAddr(unsigned short,long,unsigned short *,unsigned short *,long *,long *,unsigned long *); +public: virtual int OpenModFromImod(unsigned short,struct Mod * *); +public: virtual int QueryHeader2(long,unsigned char *,long *); +public: virtual int FAddSourceMappingItem(unsigned short const *,unsigned short const *,unsigned long); +public: virtual int FSetPfnNotePdbUsed(void *,void (__cdecl*)(void *,unsigned short const *,int,int)); +public: virtual int FCTypes(void); +public: virtual int QueryFileInfo2(unsigned char *,long *); +public: virtual int FSetPfnQueryCallback(void *,int (__cdecl*(__cdecl*)(void *,enum DOVC))(void)); +}; + +struct DBI_VS9 : public DBI_BASE {}; +struct DBI_VS10 : public DBI_BASE {}; + +struct DBI +{ + static bool isVS10; + DBI_VS9 vs9; + + unsigned long QueryImplementationVersion() { return vs9.QueryImplementationVersion(); } + unsigned long QueryInterfaceVersion() { return vs9.QueryInterfaceVersion(); } + int Close() { return vs9.Close(); } + int OpenMod(char const *objName,char const *libName,struct Mod * *pmod) { return vs9.OpenMod(objName,libName,pmod); } + int AddSec(unsigned short sec,unsigned short flags,long offset,long cbseg) { return vs9.AddSec(sec,flags,offset,cbseg); } + + int AddPublic2(char const *name,unsigned short sec,long off,unsigned long type) + { + if(isVS10) + return ((DBI_VS10*) &vs9)->AddPublic2(name, sec, off, type); + return vs9.AddPublic2(name, sec, off, type); + } + void SetMachineType(unsigned short type) + { + if(isVS10) + return ((DBI_VS10*) &vs9)->SetMachineType(type); + return vs9.SetMachineType(type); + } }; struct StreamCached { diff --git a/src/symutil.cpp b/src/symutil.cpp index fe8f3e6..0b761f2 100644 --- a/src/symutil.cpp +++ b/src/symutil.cpp @@ -36,7 +36,6 @@ int dsym2c(const BYTE* p, BYTE len, char* cname, int maxclen) for(int z = 0; z < zlen; z++) cname[cpos + z] = cname[cpos - zpos + z]; cpos += zlen; - break; } else if (ch > 0x80) { diff --git a/test/Makefile b/test/Makefile index 43e0f17..edba402 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,7 +6,7 @@ SRC = cvtest.d DBGDIR = ..\bin\Debug RELDIR = ..\bin\Release -DMD = c:\l\dmd-2.040\windows\bin\dmd.exe +DMD = c:\l\dmd2\windows\bin\dmd.exe # DMD = c:\l\dmd-1.045\windows\bin\dmd.exe CV2PDB_DBG = $(DBGDIR)\cv2pdb.exe @@ -23,7 +23,7 @@ rel_exe: $(RELDIR)\$(PROJECT).exe ###################### $(DBGDIR)\$(PROJECT).exe : $(DBGDIR)\$(PROJECT)_cv.exe $(CV2PDB_DBG) - $(CV2PDB_DBG) $(DBGDIR)\$(PROJECT)_cv.exe $@ + $(CV2PDB_DBG) -D2.043 $(DBGDIR)\$(PROJECT)_cv.exe $@ $(DBGDIR)\$(PROJECT)_cv.exe : $(SRC) Makefile $(DMD) -of$@ -g -unittest $(DFLAGS) @<< diff --git a/test/cvtest.d b/test/cvtest.d index f504500..5deae42 100644 --- a/test/cvtest.d +++ b/test/cvtest.d @@ -156,6 +156,41 @@ version(D2) } } +class A +{ + static int outer_func(int x) + { + int inner_func(int y) + { + return x * y; + } + return inner_func(2); + } +} + +A outer_func(int x) +{ + int inner_func(int y) + { + return x * y; + } + inner_func(3); + return new A; +} + +int arrays() +{ + int[] iarr; + iarr ~= 4; + + void[] varr; + varr = new char[102]; + + const void[] cvarr; + + return iarr.length; +} + int main2(char[][]argv) { enum_name inst_enum = enum_name.kEnum2; @@ -208,6 +243,10 @@ int main(char[][]argv) { long lng = 3; + arrays(); + outer_func(3); + A.outer_func(3); + main2(argv); writefln("Hello world"); -- cgit v0.12