diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/PEImage.cpp | 10 | ||||
-rw-r--r-- | src/cv2pdb.cpp | 568 | ||||
-rw-r--r-- | src/cv2pdb.h | 49 | ||||
-rw-r--r-- | src/cv2pdb.sln | 3 | ||||
-rw-r--r-- | src/cv2pdb.vcproj | 8 | ||||
-rw-r--r-- | src/cvutil.cpp | 169 | ||||
-rw-r--r-- | src/cvutil.h | 51 | ||||
-rw-r--r-- | src/demangle.cpp | 26 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/symutil.cpp | 91 | ||||
-rw-r--r-- | src/symutil.h | 5 |
11 files changed, 824 insertions, 159 deletions
diff --git a/src/PEImage.cpp b/src/PEImage.cpp index 2a3cbc0..bc996a7 100644 --- a/src/PEImage.cpp +++ b/src/PEImage.cpp @@ -15,6 +15,7 @@ extern "C" { #include <fcntl.h>
#include <ctype.h>
#include <direct.h>
+#include <share.h>
#include <sys/stat.h>
///////////////////////////////////////////////////////////////////////
@@ -42,7 +43,7 @@ bool PEImage::load(const char* iname) if (fd != -1)
return setError("file already open");
- fd = open(iname, O_RDONLY | O_BINARY);
+ fd = sopen(iname, O_RDONLY | O_BINARY, SH_DENYWR);
if (fd == -1)
return setError("Can't open file");
@@ -156,9 +157,14 @@ bool PEImage::replaceDebugSection (const void* data, int datalen) memcpy(dbgDir, &debugdir, sizeof(debugdir));
dbgDir->PointerToRawData = sec[s].PointerToRawData;
+#if 0
dbgDir->AddressOfRawData = sec[s].PointerToRawData;
dbgDir->SizeOfData = sec[s].SizeOfRawData;
-
+#else // suggested by Z3N
+ dbgDir->AddressOfRawData = sec[s].VirtualAddress;
+ dbgDir->SizeOfData = sec[s].SizeOfRawData - sizeof(IMAGE_DEBUG_DIRECTORY);
+#endif
+
free_aligned(dump_base);
dump_base = newdata;
dump_total_len += fill + xdatalen;
diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index 3d50c93..27fbb28 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -7,6 +7,7 @@ #include "cv2pdb.h"
#include "PEImage.h"
#include "symutil.h"
+#include "cvutil.h"
#include <stdio.h>
#include <direct.h>
@@ -14,17 +15,6 @@ #define REMOVE_LF_DERIVED 1 // types wrong by DMD
#define PRINT_INTERFACEVERSON 0
-// class properties (also apply to struct,union and enum)
-static const int kPropPacked = 0x01;
-static const int kPropHasCtorDtor = 0x02;
-static const int kPropHasOverOps = 0x04;
-static const int kPropIsNested = 0x08;
-static const int kPropHasNested = 0x10;
-static const int kPropHasOverAsgn = 0x20;
-static const int kPropHasCasting = 0x40;
-static const int kPropIncomplete = 0x80;
-static const int kPropScoped = 0x100;
-
CV2PDB::CV2PDB(PEImage& image)
: img(image), pdb(0), dbi(0), libraries(0), rsds(0), modules(0), globmod(0)
, segMap(0), segMapDesc(0), segFrame2Index(0), globalTypeHeader(0)
@@ -33,13 +23,16 @@ CV2PDB::CV2PDB(PEImage& image) , globalSymbols(0), cbGlobalSymbols(0), staticSymbols(0), cbStaticSymbols(0)
, udtSymbols(0), cbUdtSymbols(0), allocUdtSymbols(0)
, srcLineStart(0), srcLineSections(0)
-, pointerTypes(0), objectType(0)
+, pointerTypes(0)
, Dversion(2)
+, classEnumType(0), ifaceEnumType(0), cppIfaceEnumType(0), structEnumType(0)
+, classBaseType(0), ifaceBaseType(0), cppIfaceBaseType(0), structBaseType(0)
{
memset(typedefs, 0, sizeof(typedefs));
memset(translatedTypedefs, 0, sizeof(translatedTypedefs));
cntTypedefs = 0;
+ addClassTypeEnum = true;
useGlobalMod = true;
thisIsNotRef = true;
v3 = true;
@@ -114,9 +107,7 @@ bool CV2PDB::cleanup(bool commit) segMap = 0;
segMapDesc = 0;
globalTypeHeader = 0;
- objectType = 0;
pointerTypes = 0;
- objectType = 0;
memset(typedefs, 0, sizeof(typedefs));
memset(translatedTypedefs, 0, sizeof(translatedTypedefs));
cntTypedefs = 0;
@@ -303,74 +294,9 @@ bool CV2PDB::initSegMap() int CV2PDB::numeric_leaf(int* value, const void* leaf)
{
- unsigned short int type = *(const unsigned short int*) leaf;
- leaf = (const unsigned short int*) leaf + 2;
- int length = 2;
-
- *value = 0;
- switch (type)
- {
- case LF_CHAR:
- length += 1;
- *value = *(const char*)leaf;
- break;
-
- case LF_SHORT:
- length += 2;
- *value = *(const short*)leaf;
- break;
-
- case LF_USHORT:
- length += 2;
- *value = *(const unsigned short*)leaf;
- break;
-
- case LF_LONG:
- case LF_ULONG:
- length += 4;
- *value = *(const int*)leaf;
- break;
-
- case LF_COMPLEX64:
- case LF_QUADWORD:
- case LF_UQUADWORD:
- case LF_REAL64:
- length += 8;
- break;
-
- case LF_COMPLEX32:
- case LF_REAL32:
- length += 4;
- break;
-
- case LF_REAL48:
- length += 6;
- break;
-
- case LF_COMPLEX80:
- case LF_REAL80:
- length += 10;
- break;
-
- case LF_COMPLEX128:
- case LF_REAL128:
- length += 16;
- break;
-
- case LF_VARSTRING:
- length += 2 + *(const unsigned short*)leaf;
- break;
-
- default:
- if (type < LF_NUMERIC)
- *value = type;
- else
- {
- setError("unsupported numeric leaf");
- length = 0;
- }
- break;
- }
+ int length = ::numeric_leaf(value, leaf);
+ if(length == 0)
+ setError("unsupported numeric leaf");
return length;
}
@@ -402,6 +328,7 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft int pos = 0, dpos = 0;
int leaf_len, value;
int nested_types = 0;
+ int base_classes = 0;
int test_nested_type = (cmd == kCmdNestedTypes ? arg : 0);
int cntFields = 0;
@@ -482,6 +409,7 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft break;
case LF_BCLASS_V1:
+ base_classes++;
if (dp)
{
dfieldtype->bclass_v2.id = LF_BCLASS_V2;
@@ -515,6 +443,7 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft break;
case LF_BCLASS_V2:
+ base_classes++;
leaf_len = numeric_leaf(&value, &fieldtype->bclass_v2.offset);
copylen = sizeof(dfieldtype->bclass_v2) - 2 + leaf_len;
break;
@@ -532,6 +461,17 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft copy_p2dsym(dp, dpos, p, pos, maxdlen);
else
copylen = fieldtype->method_v1.p_name.namelen + 1;
+
+ if(cmd == kCmdOffsetFirstVirtualMethod)
+ if(const codeview_type* cvtype = getTypeData(fieldtype->method_v1.mlist))
+ if(cvtype->common.id == LF_METHODLIST_V1 && cvtype->common.len > 2)
+ {
+ // just check the first entry
+ const unsigned short *pattr = (const unsigned short*)(&cvtype->common + 1);
+ int mode =(*pattr >> 2) & 7;
+ if(mode == 4 || mode == 6)
+ return *(const unsigned*)(&pattr[2]);
+ }
break;
case LF_METHOD_V2:
@@ -584,6 +524,8 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft copylen = fieldtype->nesttype_v1.p_name.namelen + 1;
if(test_nested_type == 0 || test_nested_type == fieldtype->nesttype_v1.type)
nested_types++;
+ if(cmd == kCmdHasClassTypeEnum && p2ccmp(fieldtype->nesttype_v1.p_name, CLASSTYPEENUM_TYPE))
+ return true;
break;
case LF_NESTTYPE_V2:
@@ -591,6 +533,8 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft copylen += fieldtype->nesttype_v2.p_name.namelen + 1;
if(test_nested_type == 0 || test_nested_type == fieldtype->nesttype_v1.type)
nested_types++;
+ if(cmd == kCmdHasClassTypeEnum && p2ccmp(fieldtype->nesttype_v2.p_name, CLASSTYPEENUM_TYPE))
+ return true;
break;
case LF_NESTTYPE_V3:
@@ -598,6 +542,8 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft copylen += strlen(fieldtype->nesttype_v3.name) + 1;
if(test_nested_type == 0 || test_nested_type == fieldtype->nesttype_v1.type)
nested_types++;
+ if(cmd == kCmdHasClassTypeEnum && strcmp(fieldtype->nesttype_v3.name, CLASSTYPEENUM_TYPE) == 0)
+ return true;
break;
case LF_VFUNCTAB_V1:
@@ -640,6 +586,7 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft // necessary to convert this info? no data associated with it, so it might not be used
case LF_VBCLASS_V1:
case LF_IVBCLASS_V1:
+ base_classes++;
if (dp)
{
dfieldtype->vbclass_v2.id = fieldtype->common.id == LF_VBCLASS_V1 ? LF_VBCLASS_V2 : LF_IVBCLASS_V2;
@@ -656,6 +603,7 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft case LF_VBCLASS_V2:
case LF_IVBCLASS_V2:
+ base_classes++;
leaf_len = numeric_leaf(&value, &fieldtype->vbclass_v2.vbpoff);
leaf_len += numeric_leaf(&value, (char*) &fieldtype->vbclass_v2.vbpoff + leaf_len);
copylen = sizeof(fieldtype->vbclass_v2) - sizeof(fieldtype->vbclass_v2.vbpoff) + leaf_len;
@@ -685,6 +633,12 @@ int CV2PDB::_doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reft return cntFields;
case kCmdNestedTypes:
return nested_types;
+ case kCmdCountBaseClasses:
+ return base_classes;
+ case kCmdOffsetFirstVirtualMethod:
+ return -1;
+ case kCmdHasClassTypeEnum:
+ return false;
}
return setError("_doFields: unknown command");
@@ -737,6 +691,24 @@ int CV2PDB::addStruct(codeview_type* dtype, int n_element, int fieldlist, int pr return addAggregate(dtype, false, n_element, fieldlist, property, derived, vshape, structlen, name);
}
+int CV2PDB::addEnum(codeview_type* dtype, int count, int fieldlist, int property,
+ int type, const char*name)
+{
+ dtype->enumeration_v2.id = (v3 ? LF_ENUM_V3 : LF_ENUM_V2);
+ dtype->enumeration_v2.count = count;
+ dtype->enumeration_v2.fieldlist = fieldlist;
+ dtype->enumeration_v2.property = property;
+ dtype->enumeration_v2.type = type;
+ int len = cstrcpy_v(v3, (BYTE*)(&dtype->enumeration_v2.p_name), name);
+ len += sizeof (dtype->enumeration_v2) - sizeof(dtype->enumeration_v2.p_name);
+
+ unsigned char* p = (unsigned char*) dtype;
+ for (; len & 3; len++)
+ p[len] = 0xf4 - (len & 3);
+ dtype->enumeration_v2.len = len - 2;
+ return len;
+}
+
int CV2PDB::addPointerType(codeview_type* dtype, int type, int attr)
{
dtype->pointer_v2.id = LF_POINTER_V2;
@@ -793,6 +765,21 @@ int CV2PDB::addFieldNestedType(codeview_fieldtype* dfieldtype, int type, const c return len;
}
+int CV2PDB::addFieldEnumerate(codeview_fieldtype* dfieldtype, const char* name, int val)
+{
+ dfieldtype->enumerate_v1.id = v3 ? LF_ENUMERATE_V3 : LF_ENUMERATE_V1;
+ dfieldtype->enumerate_v1.attribute = 0;
+ //assert(val < LF_NUMERIC);
+ dfieldtype->enumerate_v1.value = val;
+ int len = cstrcpy_v(v3, (BYTE*)(&dfieldtype->enumerate_v1 + 1), name);
+ len += sizeof (dfieldtype->enumerate_v1);
+
+ unsigned char* p = (unsigned char*) dfieldtype;
+ for (; len & 3; len++)
+ p[len] = 0xf4 - (len & 3);
+ return len;
+}
+
void CV2PDB::checkUserTypeAlloc(int size, int add)
{
if (cbUserTypes + size >= allocUserTypes)
@@ -802,6 +789,25 @@ void CV2PDB::checkUserTypeAlloc(int size, int add) }
}
+void CV2PDB::writeUserTypeLen(codeview_type* type, int len)
+{
+ unsigned char* p = (unsigned char*) type;
+ for (; len & 3; len++)
+ p[len] = 0xf4 - (len & 3);
+
+ type->common.len = len - 2;
+ cbUserTypes += len;
+}
+
+void CV2PDB::checkGlobalTypeAlloc(int size, int add)
+{
+ if (cbGlobalTypes + size > allocGlobalTypes)
+ {
+ allocGlobalTypes += size + add;
+ globalTypes = (unsigned char*) realloc(globalTypes, allocGlobalTypes);
+ }
+}
+
const codeview_type* CV2PDB::getTypeData(int type)
{
if (!globalTypeHeader)
@@ -824,7 +830,7 @@ const codeview_type* CV2PDB::getUserTypeData(int type) return 0;
int pos = 0;
- while(type > 0)
+ while(type > 0 && pos < cbUserTypes)
{
const codeview_type* ptype = (codeview_type*)(userTypes + pos);
int len = ptype->common.len + 2;
@@ -834,30 +840,60 @@ const codeview_type* CV2PDB::getUserTypeData(int type) return (codeview_type*)(userTypes + pos);
}
-const codeview_type* CV2PDB::findCompleteClassType(const codeview_type* cvtype)
+const codeview_type* CV2PDB::getConvertedTypeData(int type)
{
- if (!globalTypeHeader)
+ type -= 0x1000;
+ if (type < 0 || type >= nextUserType - 0x1000)
return 0;
- int value;
- int cvleaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen);
+ int pos = 4;
+ while(type > 0 && pos < cbGlobalTypes)
+ {
+ const codeview_type* ptype = (codeview_type*)(globalTypes + pos);
+ int len = ptype->common.len + 2;
+ pos += len;
+ type--;
+ }
+ return (codeview_type*)(globalTypes + pos);
+}
- DWORD* offset = (DWORD*)(globalTypeHeader + 1);
- BYTE* typeData = (BYTE*)(offset + globalTypeHeader->cTypes);
- for (unsigned int t = 0; t < globalTypeHeader->cTypes; t++)
+const codeview_type* CV2PDB::findCompleteClassType(const codeview_type* cvtype, int* ptype)
+{
+ bool cstr;
+ const BYTE* pname = getStructName(cvtype, cstr);
+ if(!pname)
+ return 0;
+
+ if(globalTypeHeader)
{
- const codeview_type* type = (const codeview_type*)(typeData + offset[t]);
- if (type->common.id == LF_CLASS_V1 || type->common.id == LF_STRUCTURE_V1)
+ DWORD* offset = (DWORD*)(globalTypeHeader + 1);
+ BYTE* typeData = (BYTE*)(offset + globalTypeHeader->cTypes);
+ for (unsigned int t = 0; t < globalTypeHeader->cTypes; t++)
{
- if (!(type->struct_v1.property & kPropIncomplete))
+ const codeview_type* type = (const codeview_type*)(typeData + offset[t]);
+ if (isCompleteStruct(type, pname, cstr))
{
- int leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
- if (pstrcmp((const BYTE*) &cvtype->struct_v1.structlen + cvleaf_len,
- (const BYTE*) &type->struct_v1.structlen + leaf_len) == 0)
- return type;
+ if(ptype)
+ *ptype = t;
+ return type;
}
}
}
+ if(userTypes)
+ {
+ int t = globalTypeHeader->cTypes;
+ for(int pos = 0; pos < cbUserTypes; t++)
+ {
+ const codeview_type* type = (codeview_type*)(userTypes + pos);
+ if (isCompleteStruct(type, pname, cstr))
+ {
+ if(ptype)
+ *ptype = t;
+ return type;
+ }
+ pos += type->common.len + 2;
+ }
+ }
return cvtype;
}
@@ -919,7 +955,7 @@ int CV2PDB::fixProperty(int type, int prop, int fieldType) int CV2PDB::sizeofClassType(const codeview_type* cvtype)
{
- if (cvtype->struct_v1.property & kPropIncomplete)
+ if (getStructProperty(cvtype) & kPropIncomplete)
cvtype = findCompleteClassType(cvtype);
int value;
@@ -1371,7 +1407,7 @@ const char* CV2PDB::appendDynamicArray(int indexType, int elemType) char helpertype[64];
strcat(strcpy(helpertype, name), "_viewhelper");
dtype = (codeview_type*) (userTypes + cbUserTypes);
- cbUserTypes += addClass(dtype, 0, helpfieldlistType, 0, 0, 0, 0, helpertype);
+ cbUserTypes += addClass(dtype, 0, helpfieldlistType, 0, 0, 0, 4, helpertype);
dstringType = nextUserType++;
addUdtSymbol(dstringType, helpertype);
}
@@ -1609,7 +1645,7 @@ const char* CV2PDB::appendDelegate(int thisType, int funcType) return name;
}
-int CV2PDB::appendObjectType (int object_derived_type)
+int CV2PDB::appendObjectType (int object_type, int enumType, const char* classSymbol)
{
checkUserTypeAlloc();
@@ -1618,7 +1654,7 @@ int CV2PDB::appendObjectType (int object_derived_type) codeview_type* dtype;
int viewHelperType = 0;
- bool addViewHelper = true;
+ bool addViewHelper = object_type == kClassTypeObject;
if(addViewHelper)
{
rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
@@ -1664,18 +1700,23 @@ int CV2PDB::appendObjectType (int object_derived_type) rdtype->fieldlist.len += addFieldMember(dfieldtype, 1, 0, viewHelperType, "__viewhelper");
numElem++;
}
+ if(addClassTypeEnum)
+ {
+ dfieldtype = (codeview_fieldtype*)(rdtype->fieldlist.list + rdtype->fieldlist.len - 2);
+ rdtype->fieldlist.len += addFieldNestedType(dfieldtype, enumType, CLASSTYPEENUM_TYPE);
+ numElem++;
+ }
cbUserTypes += rdtype->common.len + 2;
int fieldListType = nextUserType++;
-#define OBJECT_SYMBOL "object@Object"
-
dtype = (codeview_type*) (userTypes + cbUserTypes);
- cbUserTypes += addClass(dtype, numElem, fieldListType, 0, object_derived_type, vtableType, 4, OBJECT_SYMBOL);
- objectType = nextUserType++;
+ int prop = addClassTypeEnum ? kPropHasNested : 0;
+ cbUserTypes += addClass(dtype, numElem, fieldListType, prop, 0, vtableType, 4, classSymbol);
+ int objType = nextUserType++;
- addUdtSymbol(objectType, OBJECT_SYMBOL);
- return objectType;
+ addUdtSymbol(objType, classSymbol);
+ return objType;
}
int CV2PDB::appendPointerType(int pointedType, int attr)
@@ -1727,6 +1768,124 @@ int CV2PDB::appendComplex(int cplxtype, int basetype, int elemsize, const char* return classType;
}
+int CV2PDB::appendEnumerator(const char* typeName, const char* enumName, int enumValue, int prop)
+{
+ 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 = addFieldEnumerate(dfieldtype, enumName, enumValue);
+
+ rdtype->fieldlist.len = len1 + 2;
+ cbUserTypes += rdtype->fieldlist.len + 2;
+ int fieldlistType = nextUserType++;
+
+ dtype = (codeview_type*) (userTypes + cbUserTypes);
+ cbUserTypes += addEnum(dtype, 1, fieldlistType, prop, 0x74, typeName);
+ int enumType = nextUserType++;
+
+ addUdtSymbol(enumType, typeName);
+ return enumType;
+}
+
+int CV2PDB::getBaseClass(const codeview_type* cvtype)
+{
+ if (getStructProperty(cvtype) & kPropIncomplete)
+ cvtype = findCompleteClassType(cvtype);
+
+ const codeview_reftype* fieldlist = (const codeview_reftype*) getConvertedTypeData(getStructFieldlist(cvtype));
+ if(!fieldlist || (fieldlist->common.id != LF_FIELDLIST_V1 && fieldlist->common.id != LF_FIELDLIST_V2))
+ return 0;
+
+ codeview_fieldtype* fieldtype = (codeview_fieldtype*)(fieldlist->fieldlist.list);
+ if(fieldtype->common.id == LF_BCLASS_V1)
+ return fieldtype->bclass_v1.type;
+ if(fieldtype->common.id == LF_BCLASS_V2)
+ return fieldtype->bclass_v2.type;
+ return 0;
+}
+
+int CV2PDB::countBaseClasses(const codeview_type* cvtype)
+{
+ if (getStructProperty(cvtype) & kPropIncomplete)
+ cvtype = findCompleteClassType(cvtype);
+
+ const codeview_reftype* fieldlist = (const codeview_reftype*) getConvertedTypeData(getStructFieldlist(cvtype));
+ if(!fieldlist || (fieldlist->common.id != LF_FIELDLIST_V1 && fieldlist->common.id != LF_FIELDLIST_V2))
+ return 0;
+
+ return _doFields(kCmdCountBaseClasses, 0, fieldlist, 0);
+}
+
+bool CV2PDB::derivesFromObject(const codeview_type* cvtype)
+{
+ if(cmpStructName(cvtype, (const BYTE*) OBJECT_SYMBOL, true))
+ return true;
+
+ int baseType = getBaseClass(cvtype);
+ const codeview_type* basetype = getTypeData(baseType);
+ if(!basetype)
+ return false;
+
+ return derivesFromObject(basetype);
+}
+
+bool CV2PDB::isCppInterface(const codeview_type* cvtype)
+{
+ // check whether the first virtual function is at offset 0 (C++) or 4 (D)
+
+ if (getStructProperty(cvtype) & kPropIncomplete)
+ cvtype = findCompleteClassType(cvtype);
+
+ const codeview_reftype* fieldlist = (const codeview_reftype*) getTypeData(getStructFieldlist(cvtype));
+ if(!fieldlist || (fieldlist->common.id != LF_FIELDLIST_V1 && fieldlist->common.id != LF_FIELDLIST_V2))
+ return false;
+
+ codeview_fieldtype* fieldtype = (codeview_fieldtype*)(fieldlist->fieldlist.list);
+ const codeview_type* basetype = 0;
+ if(fieldtype->common.id == LF_BCLASS_V1)
+ basetype = getTypeData(fieldtype->bclass_v1.type);
+ if(fieldtype->common.id == LF_BCLASS_V2)
+ basetype = getTypeData(fieldtype->bclass_v2.type);
+ if(basetype)
+ return isCppInterface(basetype);
+
+ int off = _doFields(kCmdOffsetFirstVirtualMethod, 0, fieldlist, 0);
+ return off == 0;
+}
+
+void CV2PDB::ensureUDT(int type, const codeview_type* cvtype)
+{
+ if (getStructProperty(cvtype) & kPropIncomplete)
+ cvtype = findCompleteClassType(cvtype, &type);
+
+ if(!findUdtSymbol(type + 0x1000))
+ {
+ char name[300];
+ int value, leaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen);
+ pstrcpy_v(true, (BYTE*) name, (const BYTE*) &cvtype->struct_v1.structlen + leaf_len);
+
+ codeview_reftype* rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
+ rdtype->fieldlist.id = LF_FIELDLIST_V2;
+ int helpfieldlistType = nextUserType++;
+ rdtype->fieldlist.len = 2;
+ cbUserTypes += rdtype->fieldlist.len + 2;
+
+ codeview_type*dtype = (codeview_type*) (userTypes + cbUserTypes);
+ cbUserTypes += addClass(dtype, 0, helpfieldlistType, 0, 0, 0, 4, name);
+ int viewHelperType = nextUserType++;
+ // addUdtSymbol(viewHelperType, "object_viewhelper");
+ addUdtSymbol(viewHelperType, name);
+ }
+}
+
int CV2PDB::appendTypedef(int type, const char* name)
{
checkUserTypeAlloc();
@@ -1749,8 +1908,7 @@ int CV2PDB::appendTypedef(int type, const char* name) 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;
+ writeUserTypeLen(dtype, len);
typedefs[cntTypedefs] = type;
translatedTypedefs[cntTypedefs] = nextUserType;
@@ -1809,6 +1967,20 @@ bool CV2PDB::initGlobalTypes() nextUserType = globalTypeHeader->cTypes + 0x1000;
appendTypedefs();
+ if(Dversion > 0)
+ {
+ if(addClassTypeEnum)
+ {
+ classEnumType = appendEnumerator("__ClassType", CLASSTYPEENUM_NAME, kClassTypeObject, kPropIsNested);
+ ifaceEnumType = appendEnumerator("__IfaceType", CLASSTYPEENUM_NAME, kClassTypeIface, kPropIsNested);
+ cppIfaceEnumType = appendEnumerator("__CppIfaceType", CLASSTYPEENUM_NAME, kClassTypeCppIface, kPropIsNested);
+ structEnumType = appendEnumerator("__StructType", CLASSTYPEENUM_NAME, kClassTypeStruct, kPropIsNested);
+
+ ifaceBaseType = appendObjectType (kClassTypeIface, ifaceEnumType, IFACE_SYMBOL);
+ cppIfaceBaseType = appendObjectType (kClassTypeCppIface, cppIfaceEnumType, CPPIFACE_SYMBOL);
+ }
+ classBaseType = appendObjectType (kClassTypeObject, classEnumType, OBJECT_SYMBOL);
+ }
for (unsigned int t = 0; t < globalTypeHeader->cTypes && !hadError(); t++)
{
@@ -1817,11 +1989,7 @@ bool CV2PDB::initGlobalTypes() int leaf_len, value;
int len = type->common.len + 2;
- if (cbGlobalTypes + len + 1000 > allocGlobalTypes)
- {
- allocGlobalTypes += len + 1000;
- globalTypes = (unsigned char*) realloc(globalTypes, allocGlobalTypes);
- }
+ checkGlobalTypeAlloc(len + 1000);
unsigned int clsstype;
codeview_type* dtype = (codeview_type*) (globalTypes + cbGlobalTypes);
@@ -1931,6 +2099,7 @@ bool CV2PDB::initGlobalTypes() #endif
len += leaf_len + sizeof(dtype->struct_v2) - sizeof(type->struct_v2.structlen);
+ ensureUDT(t, type);
// remember type index of derived list for object.Object
if (Dversion > 0 && dtype->struct_v2.derived)
if (memcmp((char*) &type->struct_v1.structlen + leaf_len, "\x0dobject.Object", 14) == 0)
@@ -2089,25 +2258,148 @@ bool CV2PDB::initGlobalTypes() cbGlobalTypes += len;
}
-#if 1
+#if 0
if(Dversion > 0)
- appendObjectType (object_derived_type);
+ appendObjectType (object_derived_type, 0, OBJECT_SYMBOL);
#endif
#if 1
- if (cbGlobalTypes + cbUserTypes > allocGlobalTypes)
- {
- allocGlobalTypes += cbUserTypes + 1000;
- globalTypes = (unsigned char*) realloc(globalTypes, allocGlobalTypes);
- }
+ checkGlobalTypeAlloc(cbUserTypes);
memcpy (globalTypes + cbGlobalTypes, userTypes, cbUserTypes);
cbGlobalTypes += cbUserTypes;
#endif
+ if(addClassTypeEnum)
+ insertClassTypeEnums();
}
}
return !hadError();
}
+bool CV2PDB::hasClassTypeEnum(const codeview_type* fieldlist)
+{
+ const codeview_reftype* rfieldlist = (const codeview_reftype*) fieldlist;
+ return _doFields(kCmdHasClassTypeEnum, 0, rfieldlist, 0) != 0;
+}
+
+int CV2PDB::appendClassTypeEnum(const codeview_type* fieldlist, int type, const char* name)
+{
+ BYTE data[200];
+ int len = addFieldNestedType((codeview_fieldtype*) data, type, name);
+
+ int fieldlen = fieldlist->common.len + 2;
+ int off = (unsigned char*) fieldlist - globalTypes;
+ checkGlobalTypeAlloc(len);
+
+ int copyoff = off + fieldlen;
+ memmove(globalTypes + copyoff + len, globalTypes + copyoff, cbGlobalTypes - copyoff);
+ memcpy(globalTypes + copyoff, data, len);
+ cbGlobalTypes += len;
+
+ codeview_type* nfieldlist = (codeview_type*) (globalTypes + off);
+ nfieldlist->common.len = fieldlen + len - 2;
+ return len;
+}
+
+int CV2PDB::insertBaseClass(const codeview_type* fieldlist, int type)
+{
+ codeview_fieldtype cvtype;
+ cvtype.bclass_v2.id = LF_BCLASS_V2;
+ cvtype.bclass_v2.type = type;
+ cvtype.bclass_v2.attribute = 3; // public
+ cvtype.bclass_v2.offset = 0;
+ int len = sizeof(cvtype.bclass_v2);
+ unsigned char* p = (unsigned char*) &cvtype;
+ for (; len & 3; len++)
+ p[len] = 0xf4 - (len & 3);
+
+ int fieldlen = fieldlist->common.len + 2;
+ int off = (unsigned char*) fieldlist - globalTypes;
+ checkGlobalTypeAlloc(len);
+
+ int copyoff = off + 4;
+ memmove(globalTypes + copyoff + len, globalTypes + copyoff, cbGlobalTypes - copyoff);
+ memcpy(globalTypes + copyoff, &cvtype, len);
+ cbGlobalTypes += len;
+
+ codeview_type* nfieldlist = (codeview_type*) (globalTypes + off);
+ nfieldlist->common.len = fieldlen + len - 2;
+ return len;
+}
+
+bool CV2PDB::insertClassTypeEnums()
+{
+ int pos = 4; // skip prefix
+ for (unsigned int t = 0; pos < cbGlobalTypes && t < globalTypeHeader->cTypes; t++)
+ {
+ codeview_type* type = (codeview_type*)(globalTypes + pos);
+ int typelen = type->common.len + 2;
+
+ switch(type->common.id)
+ {
+ case LF_STRUCTURE_V3:
+ case LF_STRUCTURE_V2:
+ case LF_CLASS_V3:
+ case LF_CLASS_V2:
+ if(const codeview_type* fieldlist = getConvertedTypeData(type->struct_v2.fieldlist))
+ {
+ if(!hasClassTypeEnum(fieldlist))
+ {
+ int enumtype = 0;
+ int basetype = 0;
+ const char* name;
+
+ if(type->common.id == LF_STRUCTURE_V2 || type->common.id == LF_STRUCTURE_V3)
+ {
+ enumtype = structEnumType;
+ basetype = structBaseType;
+ name = "__StructType";
+ }
+ else if(derivesFromObject(type))
+ {
+ enumtype = classEnumType;
+ basetype = classBaseType;
+ name = "__ClassType";
+ }
+ else if(isCppInterface(type))
+ {
+ enumtype = cppIfaceEnumType;
+ basetype = cppIfaceBaseType;
+ name = "__CppIfaceType";
+ }
+ else
+ {
+ enumtype = ifaceEnumType;
+ basetype = ifaceBaseType;
+ name = "__IfaceType";
+ }
+ if(basetype && !getBaseClass(type))
+ {
+ type->struct_v2.n_element++;
+ // appending can realloc globalTypes, changing its address!
+ int flpos = (unsigned char*) fieldlist - globalTypes;
+ int len = insertBaseClass(fieldlist, basetype);
+ if(fieldlist < type)
+ pos += len;
+ type = (codeview_type*)(globalTypes + pos);
+ fieldlist = (codeview_type*)(globalTypes + flpos);
+ }
+ if(enumtype)
+ {
+ type->struct_v2.n_element++;
+ // appending can realloc globalTypes, changing its address!
+ int len = appendClassTypeEnum(fieldlist, enumtype, name);
+ if(fieldlist < type)
+ pos += len;
+ }
+ }
+ }
+ break;
+ }
+ pos += typelen;
+ }
+ return true;
+}
+
bool CV2PDB::addTypes()
{
if (!globalTypes)
@@ -2458,6 +2750,7 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de dsym->common.id = S_END_V1;
dsym->common.len = destlength - 2;
}
+ else
#endif
if (p2ccmp(dsym->stack_v1.p_name, "this"))
{
@@ -2485,9 +2778,11 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de if (type >= 0x1000 && pointerTypes[type - 0x1000])
type = pointerTypes[type - 0x1000];
}
+ dsym->stack_v1.symtype = translateType(type);
}
else if(Dversion == 0)
{
+ // remove function scope from variable name
int p = -1;
for(int i = 0; i < dsym->stack_v1.p_name.namelen; i++)
if(dsym->stack_v1.p_name.name[i] == ':')
@@ -2502,8 +2797,18 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de destSymbols[destSize + destlength] = 0;
dsym->stack_v1.len = destlength - 2;
}
+ dsym->stack_v1.symtype = translateType(type);
+ }
+ else
+ {
+ dsym->stack_v2.id = v3 ? S_BPREL_V3 : S_BPREL_V1;
+ dsym->stack_v2.offset = sym->stack_v1.offset;
+ dsym->stack_v2.symtype = translateType(type);
+ destlength = pstrcpy_v (v3, (BYTE*) &dsym->stack_v2.p_name,
+ (BYTE*) &sym->stack_v1.p_name);
+ destlength += sizeof(dsym->stack_v2) - sizeof(dsym->stack_v2.p_name);
+ dsym->stack_v2.len = destlength - 2;
}
- dsym->stack_v1.symtype = translateType(type);
//sym->stack_v1.symtype = 0x1012;
break;
case S_ENDARG_V1:
@@ -2563,9 +2868,23 @@ int CV2PDB::copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int de codeview_symbol* CV2PDB::findUdtSymbol(int type)
{
type = translateType(type);
+ for(int p = 0; p < cbGlobalSymbols; )
+ {
+ codeview_symbol* sym = (codeview_symbol*) (globalSymbols + p);
+ if(sym->common.id == S_UDT_V1 && sym->udt_v1.type == type)
+ return sym;
+ p += sym->common.len + 2;
+ }
+ for(int p = 0; p < cbStaticSymbols; )
+ {
+ codeview_symbol* sym = (codeview_symbol*) (staticSymbols + p);
+ if(sym->common.id == S_UDT_V1 && sym->udt_v1.type == type)
+ return sym;
+ p += sym->common.len + 2;
+ }
for(int p = 0; p < cbUdtSymbols; )
{
- codeview_symbol* sym = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ codeview_symbol* sym = (codeview_symbol*) (udtSymbols + p);
if(sym->common.id == S_UDT_V1 && sym->udt_v1.type == type)
return sym;
p += sym->common.len + 2;
@@ -2644,9 +2963,6 @@ bool CV2PDB::addSymbols(int iMod, BYTE* symbols, int cb, bool addGlobals) bool CV2PDB::addSymbols()
{
- if (!initGlobalSymbols())
- return false;
-
int prefix = 4;
DWORD* data = 0;
int databytes = 0;
diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 0dfa0f3..0b93b38 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -34,7 +34,15 @@ public: const BYTE* getLibrary(int i);
bool initSegMap();
- enum { kCmdAdd, kCmdCount, kCmdNestedTypes };
+ enum
+ {
+ kCmdAdd,
+ kCmdCount,
+ kCmdNestedTypes,
+ kCmdOffsetFirstVirtualMethod,
+ kCmdHasClassTypeEnum,
+ kCmdCountBaseClasses
+ };
int _doFields(int cmd, codeview_reftype* dfieldlist, const codeview_reftype* fieldlist, int arg);
int addFields(codeview_reftype* dfieldlist, const codeview_reftype* fieldlist, int maxdlen);
int countFields(const codeview_reftype* fieldlist);
@@ -46,6 +54,8 @@ public: int derived, int vshape, int structlen, const char*name);
int addStruct(codeview_type* dtype, int n_element, int fieldlist, int property,
int derived, int vshape, int structlen, const char*name);
+ int addEnum(codeview_type* dtype, int count, int fieldlist, int property,
+ int type, const char*name);
int addPointerType(codeview_type* dtype, int type, int attr = 0x800A);
int addPointerType(unsigned char* dtype, int type, int attr = 0x800A);
@@ -53,16 +63,22 @@ public: int addFieldMember(codeview_fieldtype* dfieldtype, int attr, int offset, int type, const char* name);
int addFieldStaticMember(codeview_fieldtype* dfieldtype, int attr, int type, const char* name);
int addFieldNestedType(codeview_fieldtype* dfieldtype, int type, const char* name);
+ int addFieldEnumerate(codeview_fieldtype* dfieldtype, const char* name, int val);
void checkUserTypeAlloc(int size = 1000, int add = 10000);
+ void checkGlobalTypeAlloc(int size, int add = 1000);
+ void writeUserTypeLen(codeview_type* type, int len);
const codeview_type* getTypeData(int type);
const codeview_type* getUserTypeData(int type);
- const codeview_type* findCompleteClassType(const codeview_type* cvtype);
+ const codeview_type* getConvertedTypeData(int type);
+ const codeview_type* findCompleteClassType(const codeview_type* cvtype, int* ptype = 0);
int findMemberFunctionType(codeview_symbol* lastGProcSym, int thisPtrType);
- int fixProperty(int type, int prop, int fieldType);
+ int fixProperty(int type, int prop, int fieldType);
+ bool derivesFromObject(const codeview_type* cvtype);
+ bool isCppInterface(const codeview_type* cvtype);
int sizeofClassType(const codeview_type* cvtype);
int sizeofBasicType(int type);
@@ -70,6 +86,8 @@ public: // to be used when writing new type only to avoid double translation
int translateType(int type);
+ int getBaseClass(const codeview_type* cvtype);
+ int countBaseClasses(const codeview_type* cvtype);
bool nameOfBasicType(int type, char* name, int maxlen);
bool nameOfType(int type, char* name, int maxlen);
@@ -85,11 +103,16 @@ public: const char* appendDynamicArray(int indexType, int elemType);
const char* appendAssocArray(int keyType, int elemType);
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);
+ int appendObjectType (int object_derived_type, int enumType, const char* classSymbol);
+ 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();
+ int appendEnumerator(const char* typeName, const char* enumName, int enumValue, int prop);
+ int appendClassTypeEnum(const codeview_type* fieldlist, int type, const char* name);
+ bool hasClassTypeEnum(const codeview_type* fieldlist);
+ bool insertClassTypeEnums();
+ int insertBaseClass(const codeview_type* fieldlist, int type);
bool initGlobalTypes();
bool initGlobalSymbols();
@@ -100,6 +123,7 @@ public: codeview_symbol* findUdtSymbol(int type);
bool addUdtSymbol(int type, const char* name);
+ void ensureUDT(int type, const codeview_type* cvtype);
// returns new destSize
int copySymbols(BYTE* srcSymbols, int srcSize, BYTE* destSymbols, int destSize);
@@ -160,11 +184,22 @@ public: int nextUserType;
int objectType;
+ int classEnumType;
+ int ifaceEnumType;
+ int cppIfaceEnumType;
+ int structEnumType;
+
+ int classBaseType;
+ int ifaceBaseType;
+ int cppIfaceBaseType;
+ int structBaseType;
+
// D named types
int typedefs[20];
int translatedTypedefs[20];
int cntTypedefs;
+ bool addClassTypeEnum;
bool useGlobalMod;
bool thisIsNotRef;
bool v3;
diff --git a/src/cv2pdb.sln b/src/cv2pdb.sln index 53eb722..ddb3df0 100644 --- a/src/cv2pdb.sln +++ b/src/cv2pdb.sln @@ -7,7 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dviewhelper", "dviewhelper\ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7F4A9B6A-05A2-45D0-AFC3-3754B7FB77B9}"
ProjectSection(SolutionItems) = preProject
- ..\autoexp.snippet = ..\autoexp.snippet
+ ..\autoexp.expand = ..\autoexp.expand
+ ..\autoexp.visualizer = ..\autoexp.visualizer
..\CHANGES = ..\CHANGES
..\FEATURES = ..\FEATURES
..\INSTALL = ..\INSTALL
diff --git a/src/cv2pdb.vcproj b/src/cv2pdb.vcproj index 71a7252..cc0a479 100644 --- a/src/cv2pdb.vcproj +++ b/src/cv2pdb.vcproj @@ -182,6 +182,14 @@ >
</File>
<File
+ RelativePath=".\cvutil.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\cvutil.h"
+ >
+ </File>
+ <File
RelativePath=".\demangle.cpp"
>
</File>
diff --git a/src/cvutil.cpp b/src/cvutil.cpp new file mode 100644 index 0000000..c125b41 --- /dev/null +++ b/src/cvutil.cpp @@ -0,0 +1,169 @@ +// Convert DMD CodeView debug information to PDB files
+// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
+//
+// License for redistribution is given by the Artistic License 2.0
+// see file LICENSE for further details
+
+#include "cvutil.h"
+
+bool isStruct(const codeview_type* cvtype)
+{
+ switch(cvtype->common.id)
+ {
+ case LF_STRUCTURE_V1:
+ case LF_CLASS_V1:
+ case LF_STRUCTURE_V2:
+ case LF_CLASS_V2:
+ case LF_STRUCTURE_V3:
+ case LF_CLASS_V3:
+ return true;
+ }
+ return false;
+}
+
+int getStructProperty(const codeview_type* cvtype)
+{
+ switch(cvtype->common.id)
+ {
+ case LF_STRUCTURE_V1:
+ case LF_CLASS_V1:
+ return cvtype->struct_v1.property;
+ case LF_STRUCTURE_V2:
+ case LF_CLASS_V2:
+ return cvtype->struct_v2.property;
+ case LF_STRUCTURE_V3:
+ case LF_CLASS_V3:
+ return cvtype->struct_v3.property;
+ }
+ return 0;
+}
+
+int getStructFieldlist(const codeview_type* cvtype)
+{
+ switch(cvtype->common.id)
+ {
+ case LF_STRUCTURE_V1:
+ case LF_CLASS_V1:
+ return cvtype->struct_v1.fieldlist;
+ case LF_STRUCTURE_V2:
+ case LF_CLASS_V2:
+ return cvtype->struct_v2.fieldlist;
+ case LF_STRUCTURE_V3:
+ case LF_CLASS_V3:
+ return cvtype->struct_v3.fieldlist;
+ }
+ return 0;
+}
+
+const BYTE* getStructName(const codeview_type* cvtype, bool &cstr)
+{
+ int value, leaf_len;
+ switch(cvtype->common.id)
+ {
+ case LF_STRUCTURE_V1:
+ case LF_CLASS_V1:
+ cstr = false;
+ leaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen);
+ return (const BYTE*) &cvtype->struct_v1.structlen + leaf_len;
+ case LF_STRUCTURE_V2:
+ case LF_CLASS_V2:
+ cstr = false;
+ leaf_len = numeric_leaf(&value, &cvtype->struct_v2.structlen);
+ return (const BYTE*) &cvtype->struct_v2.structlen + leaf_len;
+ case LF_STRUCTURE_V3:
+ case LF_CLASS_V3:
+ cstr = true;
+ leaf_len = numeric_leaf(&value, &cvtype->struct_v3.structlen);
+ return (const BYTE*) &cvtype->struct_v3.structlen + leaf_len;
+ }
+ return 0;
+}
+
+bool cmpStructName(const codeview_type* cvtype, const BYTE* name, bool cstr)
+{
+ bool cstr2;
+ const BYTE* name2 = getStructName(cvtype, cstr2);
+ if(!name || !name2)
+ return name == name2;
+ return dstrcmp(name, cstr, name2, cstr2);
+}
+
+bool isCompleteStruct(const codeview_type* type, const BYTE* name, bool cstr)
+{
+ return isStruct(type)
+ && !(getStructProperty(type) & kPropIncomplete)
+ && cmpStructName(type, name, cstr);
+}
+
+int numeric_leaf(int* value, const void* leaf)
+{
+ unsigned short int type = *(const unsigned short int*) leaf;
+ leaf = (const unsigned short int*) leaf + 2;
+ int length = 2;
+
+ *value = 0;
+ switch (type)
+ {
+ case LF_CHAR:
+ length += 1;
+ *value = *(const char*)leaf;
+ break;
+
+ case LF_SHORT:
+ length += 2;
+ *value = *(const short*)leaf;
+ break;
+
+ case LF_USHORT:
+ length += 2;
+ *value = *(const unsigned short*)leaf;
+ break;
+
+ case LF_LONG:
+ case LF_ULONG:
+ length += 4;
+ *value = *(const int*)leaf;
+ break;
+
+ case LF_COMPLEX64:
+ case LF_QUADWORD:
+ case LF_UQUADWORD:
+ case LF_REAL64:
+ length += 8;
+ break;
+
+ case LF_COMPLEX32:
+ case LF_REAL32:
+ length += 4;
+ break;
+
+ case LF_REAL48:
+ length += 6;
+ break;
+
+ case LF_COMPLEX80:
+ case LF_REAL80:
+ length += 10;
+ break;
+
+ case LF_COMPLEX128:
+ case LF_REAL128:
+ length += 16;
+ break;
+
+ case LF_VARSTRING:
+ length += 2 + *(const unsigned short*)leaf;
+ break;
+
+ default:
+ if (type < LF_NUMERIC)
+ *value = type;
+ else
+ {
+ length = 0; // error!
+ }
+ break;
+ }
+ return length;
+}
+
diff --git a/src/cvutil.h b/src/cvutil.h new file mode 100644 index 0000000..83b0939 --- /dev/null +++ b/src/cvutil.h @@ -0,0 +1,51 @@ +// Convert DMD CodeView debug information to PDB files
+// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
+//
+// License for redistribution is given by the Artistic License 2.0
+// see file LICENSE for further details
+
+#ifndef __CVUTIL_H__
+#define __CVUTIL_H__
+
+#include "cv2pdb.h"
+#include "symutil.h"
+
+#define OBJECT_SYMBOL "object@Object"
+#define IFACE_SYMBOL "DInterface"
+#define CPPIFACE_SYMBOL "CppInterface"
+
+#define P_OBJECT_SYMBOL ((const BYTE*)("\x0d" OBJECT_SYMBOL))
+
+#define CLASSTYPEENUM_TYPE "__ClassType"
+#define CLASSTYPEENUM_NAME "__classtype"
+
+enum
+{
+ kClassTypeObject = 1,
+ kClassTypeIface = 2,
+ kClassTypeCppIface = 3,
+ kClassTypeStruct = 4
+};
+
+// class properties (also apply to struct,union and enum)
+static const int kPropPacked = 0x01;
+static const int kPropHasCtorDtor = 0x02;
+static const int kPropHasOverOps = 0x04;
+static const int kPropIsNested = 0x08;
+static const int kPropHasNested = 0x10;
+static const int kPropHasOverAsgn = 0x20;
+static const int kPropHasCasting = 0x40;
+static const int kPropIncomplete = 0x80;
+static const int kPropScoped = 0x100;
+
+bool isStruct(const codeview_type* cvtype);
+int getStructProperty(const codeview_type* cvtype);
+int getStructFieldlist(const codeview_type* cvtype);
+bool isCompleteStruct(const codeview_type* type, const BYTE* name, bool cstr);
+
+const BYTE* getStructName(const codeview_type* cvtype, bool &cstr);
+bool cmpStructName(const codeview_type* cvtype, const BYTE* name, bool cstr);
+
+int numeric_leaf(int* value, const void* leaf);
+
+#endif // __CVUTIL_H__
diff --git a/src/demangle.cpp b/src/demangle.cpp index ef5dec6..6c1ff30 100644 --- a/src/demangle.cpp +++ b/src/demangle.cpp @@ -202,8 +202,26 @@ public: case 'W': // Windows function
case 'V': // Pascal function
case 'R': // C++ function
- { char mc = name[ni - 1];
+ {
+ char mc = name[ni - 1];
string args;
+ string prop;
+ while(name[ni] == 'N')
+ {
+ switch(name[ni+1])
+ {
+ case 'a': prop += "pure "; break;
+ case 'b': prop += "nothrow "; break;
+ case 'c': prop += "ref "; break;
+ case 'd': prop += "@property "; break;
+ case 'e': prop += "@trusted "; break;
+ case 'f': prop += "@safe "; break;
+ default:
+ goto no_prop;
+ }
+ ni += 2;
+ }
+ no_prop:
while (1)
{
@@ -260,9 +278,9 @@ public: default: assert(0);
}
p += parseType() + " " + identifier + "(" + args + ")";
- return p;
+ return prop + p;
}
- p = parseType() +
+ p = prop + parseType() +
(isdelegate ? " delegate(" : " function(") + args + ")";
isdelegate = 0;
goto L1;
@@ -504,7 +522,7 @@ void unittest() bool d_demangle(const char* name, char* demangled, int maxlen, bool plain)
{
-#ifdef _DEBUG
+#if 0 // && def _DEBUG
static bool once; if(!once) { once = true; unittest(); }
#endif
diff --git a/src/main.cpp b/src/main.cpp index 644e27d..2c6da50 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -142,6 +142,9 @@ int main(int argc, char** argv) if (!cv2pdb.initSegMap())
fatal("%s: %s", argv[1], cv2pdb.getLastError());
+ if (!cv2pdb.initGlobalSymbols())
+ fatal("%s: %s", argv[1], cv2pdb.getLastError());
+
if (!cv2pdb.initGlobalTypes())
fatal("%s: %s", argv[1], cv2pdb.getLastError());
diff --git a/src/symutil.cpp b/src/symutil.cpp index 0b761f2..0c2c3ee 100644 --- a/src/symutil.cpp +++ b/src/symutil.cpp @@ -15,20 +15,23 @@ extern "C" { char dotReplacementChar = '@';
-int dsym2c(const BYTE* p, BYTE len, char* cname, int maxclen)
+int dsym2c(const BYTE* p, int len, char* cname, int maxclen)
{
+ const BYTE* end = p + len;
int zlen, zpos, cpos = 0;
// decompress symbol
- while (len-- > 0)
+ while (p < end)
{
int ch = *p++;
+ if(ch == 0)
+ break;
if (ch == 0x80)
{
- if (len-- <= 0)
+ if (p >= end)
break;
zlen = *p++ & 0x7f;
- if (len-- <= 0)
+ if (p >= end)
break;
zpos = *p++ & 0x7f;
if (zpos > cpos)
@@ -62,10 +65,28 @@ int dsym2c(const BYTE* p, BYTE len, char* cname, int maxclen) return cpos;
}
+int pstrlen(const BYTE* &p)
+{
+ int len = *p++;
+ if(len == 0xff && *p == 0)
+ {
+ len = p[1] | (p[2] << 8);
+ p += 3;
+ }
+ return len;
+}
+
+int dstrlen(const BYTE* &p, bool cstr)
+{
+ if(cstr)
+ return strlen((const char*)p);
+ return pstrlen(p);
+}
+
char* p2c(const BYTE* p, int idx)
{
static char cname[4][2560];
- int len = *p++;
+ int len = pstrlen(p);
#if 1
memcpy(cname[idx], p, len);
@@ -83,15 +104,20 @@ char* p2c(const p_string& p, int idx) int p2ccpy(char* p, const BYTE* s)
{
- memcpy(p, s + 1, *s);
- p[*s] = 0;
- return *s + 1;
+ int len = pstrlen(s);
+ memcpy(p, s, len);
+ p[len] = 0;
+ return len + 1;
}
int pstrcpy(BYTE* p, const BYTE* s)
{
- int len = *p = *s;
- for(int i = 1; i <= len; i++)
+ const BYTE* src = s;
+ int len = pstrlen(s);
+ for(int i = 0; i <= s - src; i++)
+ *p++ = src[i];
+
+ for(int i = 0; i < len; i++)
if (s[i] == '.')
{
//p[i++] = ':';
@@ -99,7 +125,25 @@ int pstrcpy(BYTE* p, const BYTE* s) }
else
p[i] = s[i];
- return len + 1; // *(BYTE*) memcpy (p, s, *s + 1) + 1;
+ return len + src - s; // *(BYTE*) memcpy (p, s, *s + 1) + 1;
+}
+
+int dmemcmp(const void* v1, const void* v2, int len)
+{
+ const BYTE* p1 = (const BYTE*) v1;
+ const BYTE* p2 = (const BYTE*) v2;
+ for(int i = 0; i < len; i++)
+ {
+ int b1 = p1[i];
+ int b2 = p2[i];
+ if(b1 == '.')
+ b1 = dotReplacementChar;
+ if(b2 == '.')
+ b2 = dotReplacementChar;
+ if(b1 != b2)
+ return b2 - b1;
+ }
+ return 0;
}
int pstrcpy(p_string& p, const p_string& s)
@@ -109,29 +153,42 @@ int pstrcpy(p_string& p, const p_string& s) int pstrcmp(const BYTE* p1, const BYTE* p2)
{
- if (*p1 != *p2)
- return *p2 - *p1;
- return memcmp(p1 + 1, p2 + 1, *p1);
+ int len1 = pstrlen(p1);
+ int len2 = pstrlen(p2);
+ if (len1 != len2)
+ return len2 - len1;
+ return dmemcmp(p1, p2, len1);
}
bool p2ccmp(const BYTE* pp, const char* cp)
{
int len = strlen(cp);
- if (len != *pp)
+ int plen = pstrlen(pp);
+ if (len != plen)
return false;
- return memcmp(pp + 1, cp, len) == 0;
+ return dmemcmp(pp, cp, len) == 0;
}
+
bool p2ccmp(const p_string& pp, const char* cp)
{
return p2ccmp(&pp.namelen, cp);
}
+bool dstrcmp(const BYTE* s1, bool cstr1, const BYTE* s2, bool cstr2)
+{
+ int len1 = dstrlen(s1, cstr1);
+ int len2 = dstrlen(s2, cstr2);
+ if(len1 != len2)
+ return false;
+ return dmemcmp(s1, s2, len1) == 0;
+}
+
int pstrcpy_v(bool v3, BYTE* d, const BYTE* s)
{
if (!v3)
return pstrcpy(d, s);
- int len = *s++;
+ int len = pstrlen(s);
int clen = dsym2c(s, len, (char*) d, 1000) + 1;
return clen;
diff --git a/src/symutil.h b/src/symutil.h index aa69987..2fd483d 100644 --- a/src/symutil.h +++ b/src/symutil.h @@ -11,7 +11,7 @@ struct p_string;
-int dsym2c(const BYTE* p, BYTE len, char* cname, int maxclen);
+int dsym2c(const BYTE* p, int len, char* cname, int maxclen);
char* p2c(const BYTE* p, int idx = 0);
char* p2c(const p_string& p, int idx = 0);
@@ -23,7 +23,8 @@ bool p2ccmp(const BYTE* pp, const char* cp); bool p2ccmp(const p_string& pp, const char* cp);
int pstrcpy_v(bool v3, BYTE* d, const BYTE* s);
int cstrcpy_v(bool v3, BYTE* d, const char* s);
+bool dstrcmp(const BYTE* s1, bool cstr1, const BYTE* s2, bool cstr2);
extern char dotReplacementChar;
-#endif //__SYMUTIL_H__
\ No newline at end of file +#endif //__SYMUTIL_H__
|