From 75930c8588ebf9f5eb77d5e49b7b7e6e33c2c15a Mon Sep 17 00:00:00 2001 From: sagitario Date: Sat, 6 Jun 2009 15:16:25 +0000 Subject: v0.5: * fixed error in __viewhelper field of string type, that could screw up type info * added support for wstring and dstring * fixed problems with debug info inside library by combining debug info of different modules into a single pseudo-module * now also replaces '.' by '@' in enumerator types for more consistent debug info --- CHANGES | 8 ++ Makefile | 11 ++- TODO | 3 + VERSION | 2 +- autoexp.snippet | 46 ++++++++++-- src/PEImage.h | 4 +- src/cv2pdb.cpp | 161 ++++++++++++++++++++++++++++------------ src/cv2pdb.h | 10 ++- src/cv2pdb.sln | 9 +++ src/dviewhelper/dviewhelper.cpp | 72 +++++++++++++++--- src/main.cpp | 2 +- test/Makefile | 40 ++++++++++ test/cvtest.d | 50 ++++++++++--- test/cvtest.vcproj | 74 ++++++++++++++++++ 14 files changed, 405 insertions(+), 87 deletions(-) create mode 100644 test/Makefile create mode 100644 test/cvtest.vcproj diff --git a/CHANGES b/CHANGES index 2a729a9..9488922 100644 --- a/CHANGES +++ b/CHANGES @@ -33,3 +33,11 @@ Version history * fixed crash when long is used as index or element type of dynamic or associative arrays + +2009-06-06 Version 0.5 + + * fixed error in __viewhelper field of string type, that could screw up type info + * added support for wstring and dstring + * fixed problems with debug info inside library by combining debug info of different modules + into a single pseudo-module + * now also replaces '.' by '@' in enumerator types for more consistent debug info diff --git a/Makefile b/Makefile index 3d1be76..ef11080 100644 --- a/Makefile +++ b/Makefile @@ -32,13 +32,18 @@ SRC = src\cv2pdb.cpp \ src\symutil.h \ src\dviewhelper\dviewhelper.cpp -ADD = Makefile src\cv2pdb.vcproj src\dviewhelper\dviewhelper.vcproj src\cv2pdb.sln +ADD = Makefile \ + src\cv2pdb.vcproj \ + src\dviewhelper\dviewhelper.vcproj \ + src\cv2pdb.sln DOC = VERSION README INSTALL LICENSE CHANGES TODO autoexp.snippet BIN = bin\Release\cv2pdb.exe bin\Release\dviewhelper.dll -TEST = test\cvtest.d +TEST = test\cvtest.d \ + test\cvtest.vcproj \ + test\Makefile \ all: bin src @@ -70,6 +75,6 @@ $(BIN_ZIP): $(BIN) $(DOC) Makefile IDEDIR = $(VSINSTALLDIR)\Common7\IDE -$(BIN): $(SRC) $(ADD) VERSION +$(BIN): $(SRC) $(ADD) $(TEST) VERSION if exist "$(IDEDIR)\VCExpress.exe" "$(IDEDIR)\VCExpress.exe" /Build Release src\cv2pdb.sln if not exist "$(IDEDIR)\VCExpress.exe" "$(IDEDIR)\devenv.exe" /Build Release src\cv2pdb.sln diff --git a/TODO b/TODO index 341b1b6..e217f00 100644 --- a/TODO +++ b/TODO @@ -22,3 +22,6 @@ in the future, but not all have a known solution. * assoc_array.length cannot be displayed (it is assoc_array.a->nodes) * enum values not displayed * does not work with debug version of phobos +* map dchar to something displayable +* workaround for ulong (written by DMD as int[]) +* last code bytes in module not included in last source line diff --git a/VERSION b/VERSION index ef5fa03..f264463 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.4 +VERSION = 0.5 diff --git a/autoexp.snippet b/autoexp.snippet index 6dd1a3b..45dd5c8 100644 --- a/autoexp.snippet +++ b/autoexp.snippet @@ -19,8 +19,12 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; [AutoExpand] -string_viewhelper=$ADDIN(dviewhelper.dll,_DStringView@28) 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 @@ -30,20 +34,45 @@ object_viewhelper=$ADDIN(dviewhelper.dll,_DObjectView@28) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; [Visualizer] -; string: dynamic array of char -const char[]|char[]|string { +; string, wstring and dstring use __viewhelper +string|wstring|dstring { preview ( - #if ($e.data == 0) ( "null" ) - #else ( + #if ($e.data == 0) ( "null" ) + #else ( #( "[", $e.length, "] ", [$e.__viewhelper] - ;; "[", $e.length, "] ", [$e.data,s] ) ) ) stringview ( - #if ($e.data == 0) ( "null" ) - #else ( + #if ($e.data == 0) ( "null" ) + #else ( + #( + [$e.data, s] + ) + ) + ) + children ( + #( + length: [$e.length, i], + data: [$e.data] + ) + ) +} + +; 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.data == 0) ( "null" ) + #else ( + #( + "[", $e.length, "] ", [$e.data] + ) + ) + ) + stringview ( + #if ($e.data == 0) ( "null" ) + #else ( #( [$e.data, s] ) @@ -126,3 +155,4 @@ internal@aaA<*,*> { ) } +;; eo section Visualizer for D variables ;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/PEImage.h b/src/PEImage.h index df50395..039d2a1 100644 --- a/src/PEImage.h +++ b/src/PEImage.h @@ -48,7 +48,7 @@ public: for (int i = 0; i < hdr->FileHeader.NumberOfSections; i++) { if (rva >= sec[i].VirtualAddress && - rva + len <= sec[i].VirtualAddress + sec[i].SizeOfRawData) + rva + len <= sec[i].VirtualAddress + sec[i].SizeOfRawData) return DPV

(sec[i].PointerToRawData + rva - sec[i].VirtualAddress, len); } return 0; @@ -63,6 +63,8 @@ public: int countCVEntries() const; OMFDirEntry* getCVEntry(int i) const; + int getCVSize() const { return dbgDir->SizeOfData; } + // utilities static void* alloc_aligned(unsigned int size, unsigned int align, unsigned int alignoff = 0); static void free_aligned(void* p); diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index 49cb158..a8da38d 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -23,6 +23,7 @@ CV2PDB::CV2PDB(PEImage& image) , pointerTypes(0) , Dversion(2) { + useGlobalMod = true; thisIsNotRef = true; v3 = true; countEntries = img.countCVEntries(); @@ -152,14 +153,25 @@ bool CV2PDB::createModules() const BYTE* plib = getLibrary (module->iLib); const char* lib = (!plib || !*plib ? name : p2c(plib, 1)); - if (modules[entry->iMod]) + mspdb::Mod* mod; + if (useGlobalMod) { - modules[entry->iMod]->Close(); - modules[entry->iMod] = 0; + mod = globalMod(); + if(!mod) + return false; } - int rc = dbi->OpenMod(name, lib, &modules[entry->iMod]); - if (rc <= 0 || !modules[entry->iMod]) - return setError("cannot create mod"); + else + { + if (modules[entry->iMod]) + { + modules[entry->iMod]->Close(); + modules[entry->iMod] = 0; + } + int rc = dbi->OpenMod(name, lib, &modules[entry->iMod]); + if (rc <= 0 || !modules[entry->iMod]) + return setError("cannot create mod"); + mod = modules[entry->iMod]; + } for (int s = 0; s < module->cSeg; s++) { @@ -168,7 +180,7 @@ bool CV2PDB::createModules() if (segMap && segIndex < segMap->cSeg) segFlags = segMapDesc[segIndex].flags; segFlags = 0x60101020; // 0x40401040, 0x60500020; // TODO - rc = modules[entry->iMod]->AddSecContrib(segIndex, segDesc[s].Off, segDesc[s].cbSeg, segFlags); + int rc = mod->AddSecContrib(segIndex, segDesc[s].Off, segDesc[s].cbSeg, segFlags); if (rc <= 0) return setError("cannot add section contribution to module"); } @@ -177,6 +189,17 @@ bool CV2PDB::createModules() return true; } +mspdb::Mod* CV2PDB::globalMod() +{ + if (!globmod) + { + int rc = dbi->OpenMod("__Globals", "__Globals", &globmod); + if (rc <= 0 || !globmod) + setError("cannot create global module"); + } + return globmod; +} + bool CV2PDB::initLibraries() { libraries = 0; @@ -825,7 +848,7 @@ int CV2PDB::translateType(int type) bool CV2PDB::nameOfBasicType(int type, char* name, int maxlen) { - int size = type & 7; + int size = type & 0xf; int typ = (type & 0xf0) >> 4; int mode = (type & 0x700) >> 8; @@ -897,6 +920,9 @@ bool CV2PDB::nameOfBasicType(int type, char* name, int maxlen) case 5: strcpy(name, "uint"); break; case 6: strcpy(name, "long"); break; case 7: strcpy(name, "ulong"); break; + case 8: strcpy(name, "dchar"); break; + default: + return setError("nameOfBasicType: unsupported size real int type"); } } if (mode != 0 && mode != 7) @@ -1051,10 +1077,20 @@ bool CV2PDB::nameOfDynamicArray(int indexType, int elemType, char* name, int max { if (!nameOfType(elemType, name, maxlen)) return false; + if (Dversion >= 2 && strcmp(name, "const char") == 0) strcpy(name, "string"); + else if (Dversion >= 2 && strcmp(name, "const wchar") == 0) + strcpy(name, "wstring"); + else if (Dversion >= 2 && strcmp(name, "const dchar") == 0) + strcpy(name, "dstring"); + else if (Dversion < 2 && strcmp(name, "char") == 0) strcpy(name, "string"); + else if (Dversion < 2 && strcmp(name, "wchar") == 0) + strcpy(name, "wstring"); + else if (Dversion < 2 && strcmp(name, "dchar") == 0) + strcpy(name, "dstring"); else strcat (name, "[]"); // sprintf(name, "dyn_array<%X,%X>", indexType, elemType); @@ -1117,7 +1153,7 @@ const char* CV2PDB::appendDynamicArray(int indexType, int elemType) int dataptrType = nextUserType++; int dstringType = 0; - if(strcmp(name, "string") == 0) + if(strcmp(name, "string") == 0 || strcmp(name, "wstring") == 0 || strcmp(name, "dstring") == 0) { // nextUserType + 1: field list (size, array) rdtype = (codeview_reftype*) (userTypes + cbUserTypes); @@ -1127,10 +1163,12 @@ const char* CV2PDB::appendDynamicArray(int indexType, int elemType) rdtype->fieldlist.len = 2; cbUserTypes += rdtype->fieldlist.len + 2; + char helpertype[64]; + strcat(strcpy(helpertype, name), "_viewhelper"); dtype = (codeview_type*) (userTypes + cbUserTypes); - cbUserTypes += addClass(dtype, 2, helpfieldlistType, 0, 0, 0, 0, "string_viewhelper"); + cbUserTypes += addClass(dtype, 0, helpfieldlistType, 0, 0, 0, 0, helpertype); dstringType = nextUserType++; - addUdtSymbol(dstringType, "string_viewhelper"); + addUdtSymbol(dstringType, helpertype); } // nextUserType + 1: field list (size, array) @@ -1149,10 +1187,10 @@ const char* CV2PDB::appendDynamicArray(int indexType, int elemType) int numElem = 2; rdtype->fieldlist.len = len1 + len2 + 2; - if(strcmp(name, "string") == 0) + if(dstringType > 0) { dfieldtype = (codeview_fieldtype*)(rdtype->fieldlist.list + rdtype->fieldlist.len - 2); - rdtype->fieldlist.len = addFieldMember(dfieldtype, 1, 0, dstringType, "__viewhelper"); + rdtype->fieldlist.len += addFieldMember(dfieldtype, 1, 0, dstringType, "__viewhelper"); numElem++; } @@ -1368,7 +1406,7 @@ int CV2PDB::appendObjectType (int object_derived_type) cbUserTypes += rdtype->fieldlist.len + 2; dtype = (codeview_type*) (userTypes + cbUserTypes); - cbUserTypes += addClass(dtype, 2, helpfieldlistType, 0, 0, 0, 0, "object_viewhelper"); + cbUserTypes += addClass(dtype, 0, helpfieldlistType, 0, 0, 0, 0, "object_viewhelper"); viewHelperType = nextUserType++; addUdtSymbol(viewHelperType, "object_viewhelper"); } @@ -1731,6 +1769,14 @@ bool CV2PDB::addTypes() if (!globalTypes) return true; + if (useGlobalMod) + { + int rc = globalMod()->AddTypes(globalTypes, cbGlobalTypes); + if (rc <= 0) + return setError("cannot add type info to module"); + return true; + } + for (int m = 0; m < countEntries; m++) { OMFDirEntry* entry = img.getCVEntry(m); @@ -1740,12 +1786,9 @@ bool CV2PDB::addTypes() if (!mod) return setError("sstSrcModule for non-existing module"); - int cb = cbGlobalTypes; - int rc = mod->AddTypes(globalTypes, cb); + int rc = mod->AddTypes(globalTypes, cbGlobalTypes); if (rc <= 0) return setError("cannot add type info to module"); - // does it make sense to add symbols more than once? - // break; } } return true; @@ -1758,7 +1801,7 @@ bool CV2PDB::addSrcLines() OMFDirEntry* entry = img.getCVEntry(m); if(entry->SubSection == sstSrcModule) { - mspdb::Mod* mod = modules[entry->iMod]; + mspdb::Mod* mod = useGlobalMod ? globalMod() : modules[entry->iMod]; if (!mod) return setError("sstSrcModule for non-existing module"); @@ -1811,7 +1854,7 @@ bool CV2PDB::addPublics() { mspdb::Mod* mod = 0; if (entry->iMod < countEntries) - mod = modules[entry->iMod]; + mod = useGlobalMod ? globalMod() : modules[entry->iMod]; OMFSymHash* header = img.CVP(entry->lfo); BYTE* symbols = img.CVP(entry->lfo + sizeof(OMFSymHash)); @@ -1890,6 +1933,9 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de { 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; break; @@ -2054,36 +2100,26 @@ bool CV2PDB::addUdtSymbol(int type, const char* name) return true; } -bool CV2PDB::addSymbols(int iMod, BYTE* symbols, int cb) -{ - mspdb::Mod* mod = 0; - if (iMod < countEntries) - mod = modules[iMod]; - for (int i = 0; !mod && i < countEntries; i++) - mod = modules[i]; // add global symbols to first module - if (!mod) - { - if (!globmod) - { - int rc = dbi->OpenMod("", "", &globmod); - if (rc <= 0 || !globmod) - return setError("cannot create global module"); - } - mod = globmod; - } - if (!mod) - return setError("no module to set symbols"); - - int prefix = mod == globmod ? 3 : 4; +bool CV2PDB::addSymbols(mspdb::Mod* mod, BYTE* symbols, int cb, bool addGlobals) +{ + int prefix = 4; // mod == globmod ? 3 : 4; int words = (cb + cbGlobalSymbols + cbStaticSymbols + cbUdtSymbols + 3) / 4 + prefix; - DWORD* data = new DWORD[2 * words]; + DWORD* data = new DWORD[2 * words + 1000]; int databytes = copySymbols(symbols, cb, (BYTE*) (data + prefix), 0); - if (staticSymbols) + + bool rc = writeSymbols(mod, data, databytes, prefix, addGlobals); + delete [] data; + return rc; +} + +bool CV2PDB::writeSymbols(mspdb::Mod* mod, DWORD* data, int databytes, int prefix, bool addGlobals) +{ + if (addGlobals && staticSymbols) databytes = copySymbols(staticSymbols, cbStaticSymbols, (BYTE*) (data + prefix), databytes); - if (globalSymbols) + if (addGlobals && globalSymbols) databytes = copySymbols(globalSymbols, cbGlobalSymbols, (BYTE*) (data + prefix), databytes); - if (udtSymbols) + if (addGlobals && udtSymbols) databytes = copySymbols(udtSymbols, cbUdtSymbols, (BYTE*) (data + prefix), databytes); data[0] = 4; @@ -2094,15 +2130,36 @@ bool CV2PDB::addSymbols(int iMod, BYTE* symbols, int cb) int rc = mod->AddSymbols((BYTE*) data, ((databytes + 3) / 4 + prefix) * 4); if (rc <= 0) return setError("cannot add symbols to module"); - delete [] data; return true; } +bool CV2PDB::addSymbols(int iMod, BYTE* symbols, int cb, bool addGlobals) +{ + mspdb::Mod* mod = 0; + if (iMod < countEntries) + mod = modules[iMod]; + for (int i = 0; !mod && i < countEntries; i++) + mod = modules[i]; // add global symbols to first module + if (!mod) + mod = globalMod(); + if (!mod) + return setError("no module to set symbols"); + + return addSymbols(mod, symbols, cb, addGlobals); +} + bool CV2PDB::addSymbols() { if (!initGlobalSymbols()) return false; + int prefix = 4; + DWORD* data = 0; + int databytes = 0; + if (useGlobalMod) + data = new DWORD[2 * img.getCVSize() + 1000]; // enough for all symbols + + bool addGlobals = true; for (int m = 0; m < countEntries; m++) { OMFDirEntry* entry = img.getCVEntry(m); @@ -2112,8 +2169,11 @@ bool CV2PDB::addSymbols() switch(entry->SubSection) { case sstAlignSym: - if (!addSymbols (entry->iMod, symbols + 4, entry->cb - 4)) + if (useGlobalMod) + databytes = copySymbols(symbols + 4, entry->cb - 4, (BYTE*) (data + prefix), databytes); + else if (!addSymbols (entry->iMod, symbols + 4, entry->cb - 4, addGlobals)) return false; + addGlobals = false; break; case sstStaticSym: @@ -2121,7 +2181,12 @@ bool CV2PDB::addSymbols() break; // handled in initGlobalSymbols } } - return true; + bool rc = true; + if (useGlobalMod) + rc = writeSymbols (globalMod(), data, databytes, prefix, true); + + delete [] data; + return rc; } bool CV2PDB::writeImage(const char* opath) diff --git a/src/cv2pdb.h b/src/cv2pdb.h index fec2dff..e132e95 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -89,15 +89,20 @@ public: bool addSrcLines(); bool addPublics(); + bool addUdtSymbol(int type, const char* name); + // returns new destSize int copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int destSize); - bool addUdtSymbol(int type, const char* name); - bool addSymbols(int iMod, BYTE* symbols, int cb); + bool writeSymbols(mspdb::Mod* mod, DWORD* data, int databytes, int prefix, bool addGlobals); + bool addSymbols(mspdb::Mod* mod, BYTE* symbols, int cb, bool addGlobals); + bool addSymbols(int iMod, BYTE* symbols, int cb, bool addGlobals); bool addSymbols(); bool writeImage(const char* opath); + mspdb::Mod* globalMod(); + // private: BYTE* libraries; @@ -139,6 +144,7 @@ public: int nextUserType; int objectType; + bool useGlobalMod; bool thisIsNotRef; bool v3; const char* lastError; diff --git a/src/cv2pdb.sln b/src/cv2pdb.sln index e83abbb..18f285d 100644 --- a/src/cv2pdb.sln +++ b/src/cv2pdb.sln @@ -17,6 +17,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\VERSION = ..\VERSION EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cvtest", "..\test\cvtest.vcproj", "{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}" + ProjectSection(ProjectDependencies) = postProject + {5E2BD27D-446A-4C99-9829-135F7C000D90} = {5E2BD27D-446A-4C99-9829-135F7C000D90} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -31,6 +36,10 @@ Global {E4424774-A7A0-4502-8626-2723904D70EA}.Debug|Win32.Build.0 = Debug|Win32 {E4424774-A7A0-4502-8626-2723904D70EA}.Release|Win32.ActiveCfg = Release|Win32 {E4424774-A7A0-4502-8626-2723904D70EA}.Release|Win32.Build.0 = Release|Win32 + {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug|Win32.Build.0 = Debug|Win32 + {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Release|Win32.ActiveCfg = Release|Win32 + {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/dviewhelper/dviewhelper.cpp b/src/dviewhelper/dviewhelper.cpp index 594c231..110cc09 100644 --- a/src/dviewhelper/dviewhelper.cpp +++ b/src/dviewhelper/dviewhelper.cpp @@ -6,8 +6,11 @@ // License for redistribution is given by the Artistic License 2.0 // see file LICENSE for further details // -// Compile the DLL and add this to AUTOEXP.DAT in section [AutoExpand] -// string=$ADDIN(\dviewhelper.dll,_DStringView@28) +// Compile the DLL and add the following lines to AUTOEXP.DAT in section [AutoExpand] +// string_viewhelper=$ADDIN(\dviewhelper.dll,_DStringView@28) +// wstring_viewhelper=$ADDIN(\dviewhelper.dll,_DWStringView@28) +// dstring_viewhelper=$ADDIN(\dviewhelper.dll,_DDStringView@28) +// object_viewhelper=$ADDIN(\dviewhelper.dll,_DObjectView@28) // /////////////////////////////////////////////////////////////////////////////// @@ -35,9 +38,10 @@ struct DString DWORD data; }; -__declspec(dllexport) -HRESULT WINAPI DStringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, - char *pResult, size_t max, DWORD reserved) +/////////////////////////////////////////////////////////////////////////////// + +HRESULT WINAPI StringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, + char *pResult, size_t max, DWORD sizePerChar) { // Get the string struct DString dstr; @@ -53,19 +57,65 @@ HRESULT WINAPI DStringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOO return S_OK; } + char* pData = pResult + 1; DWORD cnt = (dstr.length < max - 3 ? dstr.length : max - 3); - if (pHelper->ReadDebuggeeMemory(pHelper, dstr.data, cnt, pResult + 1, &read) != S_OK) + if (sizePerChar * cnt > max) + pData = new char[sizePerChar * cnt]; + + if (pHelper->ReadDebuggeeMemory(pHelper, dstr.data, sizePerChar * cnt, pData, &read) != S_OK) { strncpy(pResult,"Cannot access data", max); - return S_OK; + } + else + { + //! @todo: proper utf8/16/32 translation + for (DWORD p = 0; p < cnt; p++) + { + int ch; + if (sizePerChar == 4) + ch = ((long*) pData) [p]; + else if (sizePerChar == 2) + ch = ((short*) pData) [p]; + else + ch = pData [p]; + + if (ch >= 128 && ch < -128) + pResult[p + 1] = -1; + else + pResult[p + 1] = (char) ch; + } + pResult[0] = '\"'; + pResult[cnt+1] = '\"'; + pResult[cnt+2] = 0; } - pResult[0] = '\"'; - pResult[cnt+1] = '\"'; - pResult[cnt+2] = 0; + if(pData != pResult + 1) + delete [] pData; return S_OK; } + +__declspec(dllexport) +HRESULT WINAPI DStringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, + char *pResult, size_t max, DWORD reserved) +{ + return StringView(dwAddress, pHelper, nBase, bUniStrings, pResult, max, 1); +} + +__declspec(dllexport) +HRESULT WINAPI DWStringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, + char *pResult, size_t max, DWORD reserved) +{ + return StringView(dwAddress, pHelper, nBase, bUniStrings, pResult, max, 2); +} + +__declspec(dllexport) +HRESULT WINAPI DDStringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, + char *pResult, size_t max, DWORD reserved) +{ + return StringView(dwAddress, pHelper, nBase, bUniStrings, pResult, max, 4); +} + __declspec(dllexport) HRESULT WINAPI DObjectView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved) @@ -107,4 +157,4 @@ HRESULT WINAPI DObjectView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOO return S_OK; } -} // extern "C" \ No newline at end of file +} // extern "C" diff --git a/src/main.cpp b/src/main.cpp index fb80f30..98c6d7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,7 +86,7 @@ int main(int argc, char** argv) printf("License for redistribution is given by the Artistic License 2.0\n"); printf("see file LICENSE for further details\n"); printf("\n"); - printf("usage: %s [-Dversion] [new-exe-file] [pdb-file]\n", argv[0]); + printf("usage: %s [-Dversion|-C] [new-exe-file] [pdb-file]\n", argv[0]); return -1; } diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..6bed715 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,40 @@ + +PROJECT = cvtest + +SRC = cvtest.d + +DBGDIR = ..\bin\Debug +RELDIR = ..\bin\Release + +DMD = c:\l\dmd-2.030\windows\bin\dmd.exe +# DMD = c:\l\dmd-1.045\windows\bin\dmd.exe + +CV2PDB_DBG = $(DBGDIR)\cv2pdb.exe +CV2PDB_REL = $(RELDIR)\cv2pdb.exe + +DFLAGS = -L/DELEXECUTABLE +LIBS = phobos.lib + +default: dbg_exe +release: rel_exe + +dbg_exe: $(DBGDIR)\$(PROJECT).exe +rel_exe: $(RELDIR)\$(PROJECT).exe + +###################### +$(DBGDIR)\$(PROJECT).exe : $(DBGDIR)\$(PROJECT)_cv.exe $(CV2PDB_DBG) + $(CV2PDB_DBG) $(DBGDIR)\$(PROJECT)_cv.exe $@ + +$(DBGDIR)\$(PROJECT)_cv.exe : $(SRC) Makefile + $(DMD) -of$@ -g -unittest $(DFLAGS) @<< + $(SRC) $(LIBS) +< + ulong quirk_ulong; // written as int[] +} diff --git a/test/cvtest.vcproj b/test/cvtest.vcproj new file mode 100644 index 0000000..f769bce --- /dev/null +++ b/test/cvtest.vcproj @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v0.12