diff options
-rw-r--r-- | CHANGES | 9 | ||||
-rw-r--r-- | FEATURES | 33 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | src/cv2pdb.cpp | 142 | ||||
-rw-r--r-- | src/cv2pdb.h | 8 | ||||
-rw-r--r-- | src/cv2pdb.sln | 1 |
8 files changed, 190 insertions, 11 deletions
@@ -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
@@ -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
@@ -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
@@ -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
|