summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsagitario <sagitario@fc51e93f-b9fe-4711-8d8d-3ae870c5f7d8>2009-12-29 17:24:15 (GMT)
committersagitario <sagitario@fc51e93f-b9fe-4711-8d8d-3ae870c5f7d8>2009-12-29 17:24:15 (GMT)
commit68e0196f31f8d6fef0d7ccaa21c0f33d5fa5504e (patch)
treedc6d82c48eeccea5fac84a98a909b3bef5f0fad8
parent8e8aded10e47e71e46f147c70c05682530abd9a9 (diff)
downloadcv2pdb-68e0196f31f8d6fef0d7ccaa21c0f33d5fa5504e.zip
cv2pdb-68e0196f31f8d6fef0d7ccaa21c0f33d5fa5504e.tar.gz
cv2pdb-68e0196f31f8d6fef0d7ccaa21c0f33d5fa5504e.tar.bz2
Version 0.11
* basic types now show with their D names, not as C types * "enum" prefix removed from type names of enumerator types * added type information for complex data types * dmd-patch needed for long/ulong support * experimental hack to add lexical scope to local variables
-rw-r--r--CHANGES9
-rw-r--r--FEATURES33
-rw-r--r--Makefile2
-rw-r--r--TODO4
-rw-r--r--VERSION2
-rw-r--r--src/cv2pdb.cpp142
-rw-r--r--src/cv2pdb.h8
-rw-r--r--src/cv2pdb.sln1
8 files changed, 190 insertions, 11 deletions
diff --git a/CHANGES b/CHANGES
index e4f5650..8060c7d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -71,3 +71,12 @@ Version history
- entries LF_FRIENDCLS, LF_VBCLASS and LF_IVBCLASS converted
thanks to Andrew.
* derived-classes info in class entry now cleared to be consistent with removal of LF_DERIVED
+
+2009-12-29 Version 0.11
+
+ * basic types now show with their D names, not as C types
+ * "enum" prefix removed from type names of enumerator types
+ * added type information for complex data types
+ * dmd-patch needed for long/ulong support (http://d.puremagic.com/issues/show_bug.cgi?id=3373)
+ * experimental hack to add lexical scope to local variables (dmd patch in
+ http://d.puremagic.com/issues/show_bug.cgi?id=3657 needed)
diff --git a/FEATURES b/FEATURES
new file mode 100644
index 0000000..e394ddb
--- /dev/null
+++ b/FEATURES
@@ -0,0 +1,33 @@
+Main Features
+
+* conversion of DMD/DMC CodeView information to PDB file
+* converted line number info allows setting breakpoints
+* display of variables, fields and objects in watch, local and auto
+ window and in data tooltips
+* convenient display of dynamic and associative arrays in watch windows
+* demangled function names for convenient display of callstack
+
+More features
+
+This list is a bit more technical and shows what is actually done to
+achieve the desired functionality:
+
+* replaces '.' in class names with '@' to avoid confusing debugger
+* converts class pointers to reference for "clss.field" syntax
+* converts the type of member function, so that "this" is an object
+ pointer, allowing the debugger to display fields without "this."
+* generates generic debug info for dynamic arrays, associative arrays
+ and delegates
+* creates readable type names for display of D specific types
+* autoexp.dat formats output for dynamic and associative arrays in
+ watch windows
+* autoexp.dat filters display of null references
+* adds object class debug info
+* "char[]", "wchar[]" and "dchar[]" (D1) or "const char[]",
+ "const wchar[]" and "const dchar[]" (D2) translated to "string",
+ "wstring" and "dstring", respectively
+* converts type delegate<void*,int> to __int64
+* addin dviewhelper.dll allows correct display of D style strings
+ and derived object type
+* maps D basic types to enumerators to overload C style names
+* add struct definitions for complex data types
diff --git a/Makefile b/Makefile
index ef11080..a7230f8 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 autoexp.snippet
+DOC = VERSION README INSTALL LICENSE CHANGES TODO FEATURES autoexp.snippet
BIN = bin\Release\cv2pdb.exe bin\Release\dviewhelper.dll
diff --git a/TODO b/TODO
index 94431ef..ae2c7c8 100644
--- a/TODO
+++ b/TODO
@@ -18,11 +18,11 @@ in the future, but not all have a known solution.
in autoexp.dat
* DMD does not emit different debug information for const and invariant,
type info is the same
+* DMD does not emit different debug information for float and ifloat,
+ type info is the same
* type display of delegate does not have arguments
* assoc_array.length cannot be displayed (it is assoc_array.a->nodes)
* enum values not displayed
-* map dchar to something displayable
-* workaround for ulong (written by DMD as int[])
* watch incorrect if same variable name used in different parts of a function
* rtti display: disable for structs
* line number in templates sometimes off by 1 or 2
diff --git a/VERSION b/VERSION
index e7544c4..2a01178 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-VERSION = 0.10
+VERSION = 0.11
diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp
index f8621c1..00ff969 100644
--- a/src/cv2pdb.cpp
+++ b/src/cv2pdb.cpp
@@ -23,9 +23,13 @@ CV2PDB::CV2PDB(PEImage& image)
, globalSymbols(0), cbGlobalSymbols(0), staticSymbols(0), cbStaticSymbols(0)
, udtSymbols(0), cbUdtSymbols(0), allocUdtSymbols(0)
, srcLineStart(0), srcLineSections(0)
-, pointerTypes(0)
+, pointerTypes(0), objectType(0)
, Dversion(2)
{
+ memset(typedefs, 0, sizeof(typedefs));
+ memset(translatedTypedefs, 0, sizeof(translatedTypedefs));
+ cntTypedefs = 0;
+
useGlobalMod = true;
thisIsNotRef = true;
v3 = true;
@@ -102,6 +106,10 @@ bool CV2PDB::cleanup(bool commit)
globalTypeHeader = 0;
objectType = 0;
pointerTypes = 0;
+ objectType = 0;
+ memset(typedefs, 0, sizeof(typedefs));
+ memset(translatedTypedefs, 0, sizeof(translatedTypedefs));
+ cntTypedefs = 0;
return true;
}
@@ -926,7 +934,13 @@ int CV2PDB::sizeofType(int type)
int CV2PDB::translateType(int type)
{
if (type < 0x1000)
+ {
+ for(int i = 0; i < cntTypedefs; i++)
+ if(type == typedefs[i])
+ return translatedTypedefs[i];
return type;
+ }
+
const codeview_type* cvtype = getTypeData(type);
if (!cvtype)
return type;
@@ -1118,16 +1132,16 @@ bool CV2PDB::nameOfType(int type, char* name, int maxlen)
break;
case LF_ENUM_V1:
- strcpy(name, "enum ");
- p2ccpy(name + 5, (const BYTE*) &ptype->enumeration_v1.p_name);
+ //strcpy(name, "enum ");
+ p2ccpy(name, (const BYTE*) &ptype->enumeration_v1.p_name);
break;
case LF_ENUM_V2:
- strcpy(name, "enum ");
- p2ccpy(name + 5, (const BYTE*) &ptype->enumeration_v2.p_name);
+ //strcpy(name, "enum ");
+ p2ccpy(name, (const BYTE*) &ptype->enumeration_v2.p_name);
break;
case LF_ENUM_V3:
- strcpy(name, "enum ");
- strcpy(name + 5, ptype->enumeration_v3.name);
+ //strcpy(name, "enum ");
+ strcpy(name, ptype->enumeration_v3.name);
break;
case LF_MODIFIER_V1:
@@ -1564,6 +1578,96 @@ int CV2PDB::appendPointerType(int pointedType, int attr)
return nextUserType - 1;
}
+int CV2PDB::appendComplex(int cplxtype, int basetype, int elemsize, const char* name)
+{
+ basetype = translateType(basetype);
+
+ codeview_reftype* rdtype;
+ codeview_type* dtype;
+
+ checkUserTypeAlloc();
+
+ // nextUserType: field list (size, array)
+ rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
+ rdtype->fieldlist.id = LF_FIELDLIST_V2;
+
+ // member type re
+ codeview_fieldtype* dfieldtype = (codeview_fieldtype*)rdtype->fieldlist.list;
+ int len1 = addFieldMember(dfieldtype, 1, 0, basetype, "re");
+
+ // member funcType* funcptr
+ dfieldtype = (codeview_fieldtype*)(rdtype->fieldlist.list + len1);
+ int len2 = addFieldMember(dfieldtype, 1, elemsize, basetype, "im");
+
+ rdtype->fieldlist.len = len1 + len2 + 2;
+ cbUserTypes += rdtype->fieldlist.len + 2;
+ int fieldlistType = nextUserType++;
+
+ // nextUserType + 3: struct delegate<>
+ dtype = (codeview_type*) (userTypes + cbUserTypes);
+ cbUserTypes += addClass(dtype, 2, fieldlistType, 0, 0, 0, 2*elemsize, name);
+
+ int classType = nextUserType++;
+ addUdtSymbol(classType, name);
+
+ typedefs[cntTypedefs] = cplxtype;
+ translatedTypedefs[cntTypedefs] = classType;
+ cntTypedefs++;
+
+ return classType;
+}
+
+int CV2PDB::appendTypedef(int type, const char* name)
+{
+ checkUserTypeAlloc();
+
+ int basetype = type;
+ if(type == 0x78)
+ basetype = 0x75; // dchar type not understood by debugger, use uint instead
+
+ codeview_reftype* rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
+ rdtype->fieldlist.id = LF_FIELDLIST_V2;
+ rdtype->fieldlist.len = 2;
+ cbUserTypes += rdtype->fieldlist.len + 2;
+ int fieldlistType = nextUserType++;
+
+ codeview_type* dtype = (codeview_type*) (userTypes + cbUserTypes);
+ dtype->enumeration_v2.id = (v3 ? LF_ENUM_V3 : LF_ENUM_V2);
+ dtype->enumeration_v2.type = basetype;
+ dtype->enumeration_v2.fieldlist = fieldlistType;
+ dtype->enumeration_v2.count = 0;
+ dtype->enumeration_v2.property = 0x200;
+ int len = cstrcpy_v (v3, (BYTE*) &dtype->enumeration_v2.p_name, name);
+ len += sizeof(dtype->enumeration_v2) - sizeof(dtype->enumeration_v2.p_name);
+ dtype->enumeration_v2.len = len - 2;
+ cbUserTypes += len;
+
+ typedefs[cntTypedefs] = type;
+ translatedTypedefs[cntTypedefs] = nextUserType;
+ cntTypedefs++;
+
+ nextUserType++;
+ return nextUserType - 1;
+}
+
+void CV2PDB::appendTypedefs()
+{
+ appendTypedef(0x10, "byte");
+ appendTypedef(0x20, "ubyte");
+ appendTypedef(0x21, "ushort");
+ appendTypedef(0x75, "uint");
+ appendTypedef(0x1002, "dlong"); // instead of "long"
+ appendTypedef(0x1003, "ulong");
+ appendTypedef(0x42, "real");
+ // no imaginary types
+ appendTypedef(0x71, "wchar");
+ appendTypedef(0x78, "dchar");
+
+ appendComplex(0x50, 0x40, 4, "cfloat");
+ appendComplex(0x51, 0x41, 8, "cdouble");
+ appendComplex(0x52, 0x42, 10, "creal");
+}
+
bool CV2PDB::initGlobalTypes()
{
int object_derived_type = 0;
@@ -1591,6 +1695,8 @@ bool CV2PDB::initGlobalTypes()
nextUserType = globalTypeHeader->cTypes + 0x1000;
+ appendTypedefs();
+
for (unsigned int t = 0; t < globalTypeHeader->cTypes && !hadError(); t++)
{
const codeview_type* type = (codeview_type*)(typeData + offset[t]);
@@ -2200,6 +2306,28 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de
case S_BPREL_V1:
type = dsym->stack_v1.symtype;
+#if 1
+ if (type == 0 && p2ccmp(dsym->stack_v1.p_name, "@sblk"))
+ {
+ unsigned offset = dsym->stack_v1.offset & 0xffff;
+ unsigned length = dsym->stack_v1.offset >> 16;
+ dsym->block_v3.id = S_BLOCK_V3;
+ dsym->block_v3.parent = 0;
+ dsym->block_v3.end = 0; // destSize + sizeof(dsym->block_v3) + 12;
+ dsym->block_v3.length = length;
+ dsym->block_v3.offset = offset + (lastGProcSym ? lastGProcSym->proc_v2.offset : 0);
+ dsym->block_v3.segment = (lastGProcSym ? lastGProcSym->proc_v2.segment : 0);
+ dsym->block_v3.name[0] = 0;
+ destlength = sizeof(dsym->block_v3);
+ dsym->data_v2.len = destlength - 2;
+ }
+ else if (type == 0 && p2ccmp(dsym->stack_v1.p_name, "@send"))
+ {
+ destlength = 4;
+ dsym->generic.id = S_END_V1;
+ dsym->generic.len = destlength - 2;
+ }
+#endif
if (p2ccmp(dsym->stack_v1.p_name, "this"))
{
if (lastGProcSym)
diff --git a/src/cv2pdb.h b/src/cv2pdb.h
index 06f953a..03271d5 100644
--- a/src/cv2pdb.h
+++ b/src/cv2pdb.h
@@ -82,6 +82,9 @@ public:
const char* appendDelegate(int thisType, int funcType);
int appendObjectType (int object_derived_type);
int appendPointerType(int pointedType, int attr);
+ int appendTypedef(int type, const char* name);
+ int appendComplex(int cplxtype, int basetype, int elemsize, const char* name);
+ void appendTypedefs();
bool initGlobalTypes();
bool initGlobalSymbols();
@@ -151,6 +154,11 @@ public:
int nextUserType;
int objectType;
+ // D named types
+ int typedefs[20];
+ int translatedTypedefs[20];
+ int cntTypedefs;
+
bool useGlobalMod;
bool thisIsNotRef;
bool v3;
diff --git a/src/cv2pdb.sln b/src/cv2pdb.sln
index 18f285d..53eb722 100644
--- a/src/cv2pdb.sln
+++ b/src/cv2pdb.sln
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
..\autoexp.snippet = ..\autoexp.snippet
..\CHANGES = ..\CHANGES
+ ..\FEATURES = ..\FEATURES
..\INSTALL = ..\INSTALL
..\LICENSE = ..\LICENSE
..\Makefile = ..\Makefile