summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES8
-rw-r--r--INSTALL10
-rw-r--r--Makefile2
-rw-r--r--README16
-rw-r--r--TODO25
-rw-r--r--VERSION2
-rw-r--r--autoexp.snippet8
-rw-r--r--src/PEImage.cpp66
-rw-r--r--src/PEImage.h2
-rw-r--r--src/cv2pdb.cpp25
10 files changed, 133 insertions, 31 deletions
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 <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <ctype.h>
@@ -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<IMAGE_DOS_HEADER> (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;