From 0fb1fd5b60c996ed16affcefd37603fb620f107e Mon Sep 17 00:00:00 2001 From: sagitario Date: Sat, 25 May 2013 17:40:23 +0000 Subject: 2012-11-09 Version 0.26 * new option -p allows to specify the embedded PDB reference in the binary * added support for VS2012 2013-05-11 Version 0.27 * fixed crash when converting DWARF locations using 8 bytes or more --- CHANGES | 9 +++++++ VERSION | 2 +- autoexp.expand | 1 + autoexp.visualizer | 2 +- src/PEImage.cpp | 57 ++++++++++++++++++++--------------------- src/cv2pdb.sln | 41 +++++++++++++++++------------ src/cv2pdb.vcproj | 3 ++- src/dviewhelper/dviewhelper.cpp | 38 ++++++++++++++++++++------- src/dwarf2pdb.cpp | 37 +++++++++++++++----------- src/mspdb.cpp | 34 +++++++++++++++++++----- test/cvtest.d | 10 +++++++- 11 files changed, 153 insertions(+), 81 deletions(-) diff --git a/CHANGES b/CHANGES index c5ee8ce..e947bcf 100644 --- a/CHANGES +++ b/CHANGES @@ -173,3 +173,12 @@ unreleased Version 0.22 * new option -p allows to specify the embedded PDB reference in the binary * added support for VS2012 + +2012-11-09 Version 0.26 + + * new option -p allows to specify the embedded PDB reference in the binary + * added support for VS2012 + +2013-05-11 Version 0.27 + + * fixed crash when converting DWARF locations using 8 bytes or more diff --git a/VERSION b/VERSION index d4e76c1..c8782cb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.25 +VERSION = 0.27 diff --git a/autoexp.expand b/autoexp.expand index cdaf324..a1f1909 100644 --- a/autoexp.expand +++ b/autoexp.expand @@ -9,6 +9,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; object_viewhelper=$ADDIN(dviewhelper.dll,_DObjectView@28) +object@Object=$ADDIN(dviewhelper.dll,_DObjectView@28) string=$ADDIN(dviewhelper.dll,_DStringView@28) wstring=$ADDIN(dviewhelper.dll,_DWStringView@28) dstring=$ADDIN(dviewhelper.dll,_DDStringView@28) diff --git a/autoexp.visualizer b/autoexp.visualizer index 6fb3bb5..f5c664c 100644 --- a/autoexp.visualizer +++ b/autoexp.visualizer @@ -38,7 +38,7 @@ const void[]|void[] { } ; dynamic array -*[] { +*[]|dArray* { preview ( #if ($e.ptr == 0) ( "null" ) #else ( diff --git a/src/PEImage.cpp b/src/PEImage.cpp index c2c01c5..5f3a79b 100644 --- a/src/PEImage.cpp +++ b/src/PEImage.cpp @@ -232,38 +232,37 @@ bool PEImage::initCVPtr(bool initDbgDir) if(IMGHDR(OptionalHeader.NumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_DEBUG) return setError("too few entries in data directory"); - if(IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size) != 0x1c) - return setError("unexpected size of DEBUG data directory entry"); - - int off = IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress); - dbgDir = RVA(off, 0x1c); - if (!dbgDir) - return setError("debug directory not placed in image"); - if (dbgDir->Type != IMAGE_DEBUG_TYPE_CODEVIEW) - return setError("debug directory not of type CodeView"); - - cv_base = dbgDir->PointerToRawData; - OMFSignature* sig = DPV(cv_base, dbgDir->SizeOfData); - if (!sig) - return setError("invalid debug data base address and size"); - if (memcmp(sig->Signature, "NB09", 4) != 0 && memcmp(sig->Signature, "NB11", 4) != 0) + unsigned int i; + int found = false; + for(i = 0; i < IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size)/sizeof(IMAGE_DEBUG_DIRECTORY); i++) { - // return setError("can only handle debug info of type NB09 and NB11"); - dirHeader = 0; - dirEntry = 0; + int off = IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) + i*sizeof(IMAGE_DEBUG_DIRECTORY); + dbgDir = RVA(off, sizeof(IMAGE_DEBUG_DIRECTORY)); + if (!dbgDir) + continue; //return setError("debug directory not placed in image"); + if (dbgDir->Type != IMAGE_DEBUG_TYPE_CODEVIEW) + continue; //return setError("debug directory not of type CodeView"); + + cv_base = dbgDir->PointerToRawData; + OMFSignature* sig = DPV(cv_base, dbgDir->SizeOfData); + if (!sig) + return setError("invalid debug data base address and size"); + if (memcmp(sig->Signature, "NB09", 4) != 0 && memcmp(sig->Signature, "NB11", 4) != 0) + { + // return setError("can only handle debug info of type NB09 and NB11"); + dirHeader = 0; + dirEntry = 0; + return true; + } + dirHeader = CVP(sig->filepos); + if (!dirHeader) + return setError("invalid CodeView dir header data base address"); + dirEntry = CVP(sig->filepos + dirHeader->cbDirHeader); + if (!dirEntry) + return setError("CodeView debug dir entries invalid"); return true; } - dirHeader = CVP(sig->filepos); - if (!dirHeader) - return setError("invalid cv dir header data base address"); - dirEntry = CVP(sig->filepos + dirHeader->cbDirHeader); - if (!dirEntry) - return setError("cv debug dir entries invalid"); - - //if (dirHeader->cDir == 0) - // return setError("cv debug dir has no entries"); - - return true; + return setError("no CodeView debug info data found"); } /////////////////////////////////////////////////////////////////////// diff --git a/src/cv2pdb.sln b/src/cv2pdb.sln index 6252819..d02d6a2 100644 --- a/src/cv2pdb.sln +++ b/src/cv2pdb.sln @@ -1,10 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cv2pdb", "cv2pdb.vcproj", "{5E2BD27D-446A-4C99-9829-135F7C000D90}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dviewhelper", "dviewhelper\dviewhelper.vcproj", "{E4424774-A7A0-4502-8626-2723904D70EA}" -EndProject +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7F4A9B6A-05A2-45D0-AFC3-3754B7FB77B9}" ProjectSection(SolutionItems) = preProject ..\autoexp.expand = ..\autoexp.expand @@ -19,14 +15,25 @@ 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 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cv2pdb", "cv2pdb.vcxproj", "{5E2BD27D-446A-4C99-9829-135F7C000D90}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dviewhelper", "dviewhelper\dviewhelper.vcxproj", "{E4424774-A7A0-4502-8626-2723904D70EA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cvtest", "..\test\cvtest.vcxproj", "{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}" EndProject Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "test", "..\test\test.visualdproj", "{370E7494-D0CB-450F-B74A-4CEEDB19FBAE}" EndProject -Project("{8BC9CEB9-8B4A-11D0-8D11-00A0C91BC942}") = "test64.exe", "..\bin\Debug GDCWin32\test64.exe", "{022545C9-DE2E-44F0-B87C-74CEAC3202F6}" +Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "test64", "..\bin\Debug GDCWin32\test64.exe", "{022545C9-DE2E-44F0-B87C-74CEAC3202F6}" + ProjectSection(DebuggerProjectSystem) = preProject + PortSupplier = 00000000-0000-0000-0000-000000000000 + Executable = M:\s\d\cv2pdb\trunk\bin\Debug GDCWin32\test64.exe + RemoteMachine = TENGEN-MOBIL + StartingDirectory = M:\s\d\cv2pdb\trunk\bin\Debug GDCWin32 + Environment = Default + LaunchingEngine = 00000000-0000-0000-0000-000000000000 + LaunchSQLEngine = No + AttachLaunchAction = No + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -77,12 +84,12 @@ Global {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|Win32.Build.0 = Release|Win32 {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|x64.ActiveCfg = Release|x64 {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|x64.Build.0 = Release|x64 - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|Win32.ActiveCfg = Debug - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|x64.ActiveCfg = Debug - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|Win32.ActiveCfg = Debug - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|x64.ActiveCfg = Debug - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|Win32.ActiveCfg = Debug - {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|x64.ActiveCfg = Debug + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|Win32.ActiveCfg = Debug|x64 + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|x64.ActiveCfg = Debug|x64 + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|Win32.ActiveCfg = Debug|x64 + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|x64.ActiveCfg = Debug|x64 + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|Win32.ActiveCfg = Debug|x64 + {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|x64.ActiveCfg = Debug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/cv2pdb.vcproj b/src/cv2pdb.vcproj index ea09f64..fbf1e9a 100644 --- a/src/cv2pdb.vcproj +++ b/src/cv2pdb.vcproj @@ -1,7 +1,7 @@ dwVersion >= 0x20000) + qwAddress = pHelper->GetRealAddress(pHelper); + + if(qwAddress == 0) { strncpy(pResult,"null", max); return S_OK; } + int proc = 0; + if(pHelper->dwVersion >= 0x20000) + proc = pHelper->GetProcessorType(pHelper); + int sizeOfPtr = proc == 0 ? 4 : 8; + DWORD read; - DWORD vtablePtr; - if (pHelper->ReadDebuggeeMemory(pHelper, dwAddress, sizeof(vtablePtr), &vtablePtr, &read) != S_OK) + DWORDLONG vtablePtr = 0; + if (readMem(pHelper, qwAddress, sizeOfPtr, &vtablePtr, &read) != S_OK) { strncpy(pResult,"Cannot access object", max); return S_OK; } - DWORD classinfoPtr; - if (pHelper->ReadDebuggeeMemory(pHelper, vtablePtr, sizeof(vtablePtr), &classinfoPtr, &read) != S_OK) + DWORDLONG classinfoPtr = 0; + if (readMem(pHelper, vtablePtr, sizeOfPtr, &classinfoPtr, &read) != S_OK) { strncpy(pResult,"Cannot access vtable", max); return S_OK; } - DString dstr; - if (pHelper->ReadDebuggeeMemory(pHelper, classinfoPtr + 16, sizeof(dstr), &dstr, &read) != S_OK) + char strdata[16]; + if (readMem(pHelper, classinfoPtr + 4*sizeOfPtr, 2*sizeOfPtr, strdata, &read) != S_OK) { strncpy(pResult,"Cannot access class info", max); return S_OK; } - DWORD cnt = (dstr.length < max - 1 ? dstr.length : max - 1); - if (pHelper->ReadDebuggeeMemory(pHelper, dstr.data, cnt, pResult, &read) != S_OK) + DWORDLONG length, data; + if(sizeOfPtr > 4) + { + length = *(DWORDLONG*) strdata; + data = *(DWORDLONG*) (strdata + sizeOfPtr); + } + else + { + length = *(DWORD*) strdata; + data = *(DWORD*) (strdata + sizeOfPtr); + } + DWORD cnt = (DWORD)(length < max - 1 ? length : max - 1); + if (readMem(pHelper, data, cnt, pResult, &read) != S_OK) { strncpy(pResult,"Cannot access name data", max); return S_OK; diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 8240627..fd2ea37 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -151,8 +151,10 @@ struct DWARF_InfoData unsigned long specification; unsigned long inlined; unsigned long external; - unsigned long long location; // first 8 bytes - unsigned long long member_location; // first 8 bytes + unsigned char*location_ptr; + unsigned long location_len; + unsigned char*member_location_ptr; + unsigned long member_location_len; unsigned long locationlist; // offset into debug_loc long frame_base; long upper_bound; @@ -250,7 +252,7 @@ struct DWARF_LineState /////////////////////////////////////////////////////////////////////////////// -long decodeLocation(unsigned char* loc, bool push0, int &id, int& size) +long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size) { unsigned char* p = loc; long stack[8] = {0}; @@ -259,6 +261,9 @@ long decodeLocation(unsigned char* loc, bool push0, int &id, int& size) id = push0 ? S_CONSTANT_V2 : -1; do { + if(p - loc >= len) + break; + int op = *p++; if(op == 0) break; @@ -380,10 +385,10 @@ long decodeLocation(unsigned char* loc, bool push0, int &id, int& size) } -long decodeLocation(unsigned long long loc, bool push0, int &id) +long decodeLocation(unsigned char*loc, long len, bool push0, int &id) { int size; - return decodeLocation((unsigned char*) &loc, push0, id, size); + return decodeLocation(loc, len, push0, id, size); } unsigned char* CV2PDB::getDWARFAbbrev(int off, int findcode) @@ -449,8 +454,10 @@ bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, un id.specification = 0; id.inlined = 0; id.external = 0; - id.member_location = 0; - id.location = 0; + id.member_location_ptr = 0; + id.member_location_len = 0; + id.location_ptr = 0; + id.location_len = 0; id.locationlist = 0; id.frame_base = -1; id.upper_bound = 0; @@ -518,10 +525,10 @@ bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, un case DW_AT_lower_bound: id.lower_bound = data; break; case DW_AT_containing_type: id.containing_type = data; break; case DW_AT_specification: id.specification = data; break; - case DW_AT_data_member_location: id.member_location = lldata; break; + case DW_AT_data_member_location: id.member_location_ptr = p; id.member_location_len = size; break; case DW_AT_location: if(form == DW_FORM_block1) - id.location = lldata; + id.location_ptr = p, id.location_len = size; else id.locationlist = data; break; @@ -729,7 +736,7 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, { if(id.name) { - off = decodeLocation(id.location, false, cvid); + off = decodeLocation(id.location_ptr, id.location_len, false, cvid); if(cvid == S_BPREL_V2) appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff); } @@ -743,7 +750,7 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, case DW_TAG_variable: if(id.name) { - off = decodeLocation(id.location, false, cvid); + off = decodeLocation(id.location_ptr, id.location_len, false, cvid); if(cvid == S_BPREL_V2) appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff); } @@ -818,7 +825,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c int cvid = -1; if (id.tag == DW_TAG_member && id.name) { - int off = isunion ? 0 : decodeLocation(id.member_location, true, cvid); + int off = isunion ? 0 : decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid); if(isunion || cvid == S_CONSTANT_V2) { checkDWARFTypeAlloc(kMaxNameLen + 100); @@ -829,7 +836,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c } else if(id.tag == DW_TAG_inheritance) { - int off = decodeLocation(id.member_location, true, cvid); + int off = decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid); if(cvid == S_CONSTANT_V2) { codeview_fieldtype* bc = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes); @@ -1249,14 +1256,14 @@ bool CV2PDB::iterateDWARFDebugInfo(int op) { int seg = -1; unsigned long segOff; - if(id.location == 0 && id.external && id.linkage_name) + if(id.location_ptr == 0 && id.external && id.linkage_name) { seg = img.findSymbol(id.linkage_name, segOff); } else { int cvid; - segOff = decodeLocation(id.location, false, cvid); + segOff = decodeLocation(id.location_ptr, id.location_len, false, cvid); if(cvid == S_GDATA_V2) seg = img.findSection(segOff); if(seg >= 0) diff --git a/src/mspdb.cpp b/src/mspdb.cpp index 3602ccd..fc1cdec 100644 --- a/src/mspdb.cpp +++ b/src/mspdb.cpp @@ -16,6 +16,7 @@ mspdb::fnPDBOpen2W *pPDBOpen2W; char* mspdb80_dll = "mspdb80.dll"; char* mspdb100_dll = "mspdb100.dll"; char* mspdb110_dll = "mspdb110.dll"; +// char* mspdb110shell_dll = "mspdbst.dll"; // the VS 2012 Shell uses this file instead of mspdb110.dll, but is missing mspdbsrv.exe int mspdb::vsVersion = 8; @@ -47,12 +48,11 @@ bool tryLoadMsPdb(const char* version, const char* mspdb) return modMsPdb != 0; } -bool initMsPdb() +void tryLoadMsPdb80() { if (!modMsPdb) modMsPdb = LoadLibraryA(mspdb80_dll); -#if 1 if (!modMsPdb) tryLoadMsPdb("VisualStudio\\9.0", mspdb80_dll); if (!modMsPdb) @@ -61,9 +61,10 @@ bool initMsPdb() tryLoadMsPdb("VCExpress\\9.0", mspdb80_dll); if (!modMsPdb) tryLoadMsPdb("VCExpress\\8.0", mspdb80_dll); -#endif +} -#if 1 +void tryLoadMsPdb100() +{ if (!modMsPdb) { modMsPdb = LoadLibraryA(mspdb100_dll); @@ -74,21 +75,40 @@ bool initMsPdb() if (modMsPdb) mspdb::vsVersion = 10; } -#endif +} -#if 1 +void tryLoadMsPdb110() +{ if (!modMsPdb) { modMsPdb = LoadLibraryA(mspdb110_dll); if (!modMsPdb) tryLoadMsPdb("VisualStudio\\11.0", mspdb110_dll); if (!modMsPdb) - tryLoadMsPdb("VCExpress\\11.0", mspdb110_dll); + tryLoadMsPdb("VSWinExpress\\11.0", mspdb110_dll); if (modMsPdb) mspdb::vsVersion = 11; } +} + +bool initMsPdb() +{ +#if 0 // might cause problems when combining VS Shell 2010 with VS 2008 or similar + if(const char* p = getenv("VisualStudioDir")) + { + // guess from environment variable from which version of VS we are invoked and prefer a correspondig mspdb DLL + if (strstr(p, "2010")) + tryLoadMsPdb100(); + if (strstr(p, "2012")) + tryLoadMsPdb110(); + // VS2008 tried next anyway + } #endif + tryLoadMsPdb80(); + tryLoadMsPdb100(); + tryLoadMsPdb110(); + if (!modMsPdb) return false; diff --git a/test/cvtest.d b/test/cvtest.d index 73394ee..1b1e587 100644 --- a/test/cvtest.d +++ b/test/cvtest.d @@ -128,6 +128,11 @@ struct struct_name { int member; static int static_member; + + int method() + { + return member + static_member + this.member; + } } union union_name @@ -352,7 +357,10 @@ int main2(char[][]argv) // delegate int delegate() dg = &inst_method.method; int res = dg(); - + + int delegate() dg2 = &inst_struct.method; + int res2 = dg2(); + class_with_struct_member cwsm = new class_with_struct_member; return 0; -- cgit v0.12