From 1ebb42385c535860df1455656f39699bffb20937 Mon Sep 17 00:00:00 2001 From: sagitario Date: Sat, 16 May 2009 08:04:29 +0000 Subject: v0.2: some minor doc changes replace .debug section in executable rather than rename it, if it the last section. support for field type LF_VFUNCTAB and symbol type S_CONSTANT used by DMC. added stringview to autoexp.dat for full length text display. --- CHANGES | 8 +++++++ INSTALL | 10 +++++---- Makefile | 2 +- README | 16 +++++++++++++- TODO | 25 ++++++++++++++++++++++ VERSION | 2 +- autoexp.snippet | 8 +++++++ src/PEImage.cpp | 66 +++++++++++++++++++++++++++++++++++++-------------------- src/PEImage.h | 2 +- src/cv2pdb.cpp | 25 ++++++++++++++++++++++ 10 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 TODO diff --git a/CHANGES b/CHANGES index 8239f0c..6c51426 100644 --- a/CHANGES +++ b/CHANGES @@ -10,3 +10,11 @@ Version history 2009-05-08 Version 0.1 * initial release + +2009-05-16 Version 0.2 + + * replace .debug section in executable rather than rename it. (only works + if it is the last section). + * support for field type LF_VFUNCTAB and symbol type S_CONSTANT used by DMC. + * added stringview to autoexp.dat for full length text display. + diff --git a/INSTALL b/INSTALL index e525207..16a0a97 100644 --- a/INSTALL +++ b/INSTALL @@ -7,9 +7,11 @@ Copyright (c) 2009 by Rainer Schuetze, All Rights Reserved Prerequisites ------------- -For this program to be useful, you should have either Microsoft Visual -Studio 2005 or 2008 or one of the Express versions installed. cv2pdb -uses one of the Microsoft DLLs to actually write the PDB file. +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 +versions installed. cv2pdb uses one of the Microsoft DLLs to actually +write the PDB file. Installation ------------ @@ -45,5 +47,5 @@ Building from source -------------------- The source package comes with a Visual Studio 2008 project and solution that work with both the Standard and the Express version. These won't -work in VS2005, but rebuilding the project should be easy. +work in VS2005, but creating a VS2005 project should be easy. diff --git a/Makefile b/Makefile index fe69a9b..b6b1595 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ SRC = src\cv2pdb.cpp \ ADD = Makefile src\cv2pdb.vcproj src\cv2pdb.sln -DOC = VERSION README INSTALL LICENSE CHANGES autoexp.snippet +DOC = VERSION README INSTALL LICENSE CHANGES TODO autoexp.snippet BIN = bin\Release\cv2pdb.exe diff --git a/README b/README index 8433c99..f2df67b 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ converter of DMD CodeView debug information to PDB files Copyright (c) 2009 by Rainer Schuetze, All Rights Reserved The goal of this project is to make debugging of D applications that -were created with the Digital Mars DMD compiler, as painless as possible +were created with the Digital Mars DMD compiler, as seamless as possible in current versions of Visual Studio (i.e Visual Studio 2008 and VCExpress). As a side effect, other applications might also benefit from the @@ -46,6 +46,20 @@ See the file INSTALL for further details. Usage ----- +Quick start: + +Simply run + + cv2pdb debuggee.exe + +on your executable to debug and start the debugger, e.g. + + devenv debuggee.exe +or + vcexpress debuggee.exe + +Description: + cv2pdb.exe is a command line tool which outputs its usage information if run without arguments: diff --git a/TODO b/TODO new file mode 100644 index 0000000..f40c257 --- /dev/null +++ b/TODO @@ -0,0 +1,25 @@ + +This is the TODO file for cv2pdb, a +converter of DMD CodeView debug information to PDB files + +Copyright (c) 2009 by Rainer Schuetze, All Rights Reserved + +There are some quirks that you might run into when using +Visual Studio to debug D programs. These will hopefully be removed +in the future, but not all have a known solution. + +* has to use '@' instead of '.' in class names to avoid confusing debugger, + but it looks ugly +* "this.var" is not a valid debugger expression, you have to use + "var" or "this->var" +* strings are displayed zero-terminated, not D style (though display + is often ok) +* global/static vars have to be watched with full module and class name + specified (e.g. module@globvar) +* type of associative arrays is displayed as aa<*> to allow overload + in autoexp.dat +* DMD does not emit different debug information for const and invariant, + type info is the same +* type display of delegate does not have arguments +* assoc_array.length cannot be displayed (it is assoc_array.a->length) +* support DMC debug info? diff --git a/VERSION b/VERSION index b37d68d..ec3d324 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.1 +VERSION = 0.2 diff --git a/autoexp.snippet b/autoexp.snippet index a430e23..0d9c132 100644 --- a/autoexp.snippet +++ b/autoexp.snippet @@ -22,6 +22,14 @@ const char[]|char[]|string { ) ) ) + stringview ( + #if ($e.data == 0) ( "null" ) + #else ( + #( + [$e.data, s] + ) + ) + ) children ( #( length: [$e.length, i], diff --git a/src/PEImage.cpp b/src/PEImage.cpp index ec826a8..d926078 100644 --- a/src/PEImage.cpp +++ b/src/PEImage.cpp @@ -10,6 +10,7 @@ extern "C" { #include "mscvpdb.h" } +#include #include #include #include @@ -59,7 +60,7 @@ bool PEImage::load(const char* iname) close(fd); fd = -1; - return initPtr(); + return initPtr(true); } /////////////////////////////////////////////////////////////////////// @@ -86,17 +87,9 @@ bool PEImage::save(const char* oname) /////////////////////////////////////////////////////////////////////// bool PEImage::replaceDebugSection (const void* data, int datalen) { - int align = hdr->OptionalHeader.FileAlignment; - int align_len = datalen; - int fill = 0; - if (align > 0) - { - fill = (align - (dump_total_len % align)) % align; - align_len = ((datalen + align - 1) / align) * align; - } - char* newdata = (char*) alloc_aligned(dump_total_len + fill + datalen, 0x1000); - if(!newdata) - return setError("cannot alloc new image"); + // append new debug directory to data + IMAGE_DEBUG_DIRECTORY debugdir = *dbgDir; + int xdatalen = datalen + sizeof(debugdir); // assume there is place for another section because of section alignment int s; @@ -104,22 +97,43 @@ bool PEImage::replaceDebugSection (const void* data, int datalen) for(s = 0; s < hdr->FileHeader.NumberOfSections; s++) { if (strcmp ((char*) sec [s].Name, ".debug") == 0) + { + if (s == hdr->FileHeader.NumberOfSections - 1) + { + dump_total_len = sec[s].PointerToRawData; + break; + } strcpy ((char*) sec [s].Name, ".ddebug"); + printf("warning: .debug not last section, cannot remove section\n"); + } lastVirtualAddress = sec [s].VirtualAddress + sec[s].Misc.VirtualSize; } - int salign_len = datalen; + int align = hdr->OptionalHeader.FileAlignment; + int align_len = xdatalen; + int fill = 0; + + if (align > 0) + { + fill = (align - (dump_total_len % align)) % align; + align_len = ((xdatalen + align - 1) / align) * align; + } + char* newdata = (char*) alloc_aligned(dump_total_len + fill + xdatalen, 0x1000); + if(!newdata) + return setError("cannot alloc new image"); + + int salign_len = xdatalen; align = hdr->OptionalHeader.SectionAlignment; if (align > 0) { lastVirtualAddress = ((lastVirtualAddress + align - 1) / align) * align; - salign_len = ((datalen + align - 1) / align) * align; + salign_len = ((xdatalen + align - 1) / align) * align; } strcpy((char*) sec[s].Name, ".debug"); sec[s].Misc.VirtualSize = align_len; // union with PhysicalAddress; sec[s].VirtualAddress = lastVirtualAddress; - sec[s].SizeOfRawData = datalen; + sec[s].SizeOfRawData = xdatalen; sec[s].PointerToRawData = dump_total_len + fill; sec[s].PointerToRelocations = 0; sec[s].PointerToLinenumbers = 0; @@ -127,27 +141,33 @@ bool PEImage::replaceDebugSection (const void* data, int datalen) sec[s].NumberOfLinenumbers = 0; sec[s].Characteristics = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA; - hdr->FileHeader.NumberOfSections++; - hdr->OptionalHeader.SizeOfImage += salign_len; + hdr->FileHeader.NumberOfSections = s + 1; + // hdr->OptionalHeader.SizeOfImage += salign_len; + hdr->OptionalHeader.SizeOfImage = sec[s].VirtualAddress + salign_len; - dbgDir->PointerToRawData = sec[s].PointerToRawData; - dbgDir->AddressOfRawData = sec[s].PointerToRawData; - dbgDir->SizeOfData = sec[s].SizeOfRawData; + hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = lastVirtualAddress + datalen; // append debug data chunk to existing file image memcpy(newdata, dump_base, dump_total_len); memset(newdata + dump_total_len, 0, fill); memcpy(newdata + dump_total_len + fill, data, datalen); + dbgDir = (IMAGE_DEBUG_DIRECTORY*) (newdata + dump_total_len + fill + datalen); + memcpy(dbgDir, &debugdir, sizeof(debugdir)); + + dbgDir->PointerToRawData = sec[s].PointerToRawData; + dbgDir->AddressOfRawData = sec[s].PointerToRawData; + dbgDir->SizeOfData = sec[s].SizeOfRawData; + free_aligned(dump_base); dump_base = newdata; - dump_total_len += fill + datalen; + dump_total_len += fill + xdatalen; - return initPtr(); + return initPtr(false); } /////////////////////////////////////////////////////////////////////// -bool PEImage::initPtr() +bool PEImage::initPtr(bool initDbgDir) { dos = DPV (0); if(!dos) diff --git a/src/PEImage.h b/src/PEImage.h index bbc2eb9..df50395 100644 --- a/src/PEImage.h +++ b/src/PEImage.h @@ -58,7 +58,7 @@ public: bool save(const char* oname); bool replaceDebugSection (const void* data, int datalen); - bool initPtr(); + bool initPtr(bool initDbgDir); int countCVEntries() const; OMFDirEntry* getCVEntry(int i) const; diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index b1a932d..bb91af7 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -489,6 +489,18 @@ int CV2PDB::addFields(codeview_reftype* dfieldlist, const codeview_reftype* fiel copylen += strlen(fieldtype->nesttype_v3.name) + 1; break; + case LF_VFUNCTAB_V1: + dfieldtype->vfunctab_v2.id = LF_VFUNCTAB_V2; + dfieldtype->vfunctab_v2.type = fieldtype->vfunctab_v1.type; + dfieldtype->vfunctab_v2._pad0 = 0; + pos += sizeof(fieldtype->vfunctab_v1); + dpos += sizeof(dfieldtype->vfunctab_v2); + break; + + case LF_VFUNCTAB_V2: + copylen = sizeof(dfieldtype->vfunctab_v2); + break; + default: setError("unsupported field entry"); break; @@ -1773,6 +1785,7 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de { codeview_symbol* lastGProcSym = 0; int type, length, destlength; + int leaf_len, value; for (int i = 0; i < srcSize; i += length) { codeview_symbol* sym = (codeview_symbol*)(srcSymbols + i); @@ -1885,9 +1898,21 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de destSize += 4; break; + case S_CONSTANT_V1: + dsym->constant_v2.id = v3 ? S_CONSTANT_V3 : S_CONSTANT_V2; + dsym->constant_v2.type = sym->constant_v1.type; + leaf_len = numeric_leaf(&value, &sym->constant_v1.cvalue); + memcpy(&dsym->constant_v2.cvalue, &sym->constant_v1.cvalue, leaf_len); + destlength = pstrcpy_v (v3, (BYTE*) &dsym->constant_v2.cvalue + leaf_len, + (BYTE*) &sym->constant_v1.cvalue + leaf_len); + destlength += sizeof(dsym->constant_v2) - sizeof(dsym->constant_v2.cvalue) + leaf_len; + dsym->constant_v2.len = destlength - 2; + break; + case S_ALIGN_V1: continue; // throw away break; + default: sym = sym; break; -- cgit v0.12