From 60cbfcd62a1d8c81b01342f302df4d06a1ae0cb2 Mon Sep 17 00:00:00 2001 From: sagitario Date: Sun, 8 May 2011 07:45:27 +0000 Subject: * fixed decoding of compressed symbols * added command line switch * fixed crash with more than 32767 types --- CHANGES | 16 +++- INSTALL | 2 +- TODO | 2 +- VERSION | 2 +- src/cv2pdb.cpp | 49 +++++++++-- src/cv2pdb.h | 1 + src/cv2pdb.vcproj | 2 + src/cvutil.h | 2 + src/demangle.cpp | 148 ++++++++++++++++++++++++++++++-- src/main.cpp | 7 +- src/mscvpdb.h | 252 +++++++++++++++++++++++++++--------------------------- src/symutil.cpp | 34 +++++++- src/symutil.h | 1 + test/cvtest.d | 10 +++ 14 files changed, 376 insertions(+), 152 deletions(-) diff --git a/CHANGES b/CHANGES index 5f21471..3a198b5 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,7 @@ This is the CHANGES file for cv2pdb, a converter of DMD CodeView debug information to PDB files -Copyright (c) 2009 by Rainer Schuetze, All Rights Reserved +Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved Version history --------------- @@ -133,8 +133,20 @@ Version history * fixed error with nested types longer than 255 characters * more fixes for names longer than 300 characters -2010-12-03 Version 0.19 +2010-12-10 Version 0.19 * now converting only class pointers to references, not pointers to structs or void * changed default D-version to 2.043 to create correct associative array type information for recent compilers by default + +2010-12-30 Version 0.20 + + * fixed another issue with user defined type names longer than 300 characters + * now corrects the debug info when dmc/optlink emits multiple struct definitions, + but only one UDT record. + +2010-05-08 Version 0.21 + + * fixed decoding of compressed symbols + * added command line switch + * fixed crash with more than 32767 types diff --git a/INSTALL b/INSTALL index 8237cd0..6cd551c 100644 --- a/INSTALL +++ b/INSTALL @@ -2,7 +2,7 @@ This is the INSTALL file for cv2pdb, a converter of DMD CodeView debug information to PDB files -Copyright (c) 2009 by Rainer Schuetze, All Rights Reserved +Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved Prerequisites ------------- diff --git a/TODO b/TODO index 979f607..776451d 100644 --- a/TODO +++ b/TODO @@ -2,7 +2,7 @@ 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 +Copyright (c) 2009-2010 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 diff --git a/VERSION b/VERSION index 53d6fa9..76d9889 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.19 +VERSION = 0.21 diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index f4f674e..72cb610 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -1875,12 +1875,15 @@ void CV2PDB::ensureUDT(int type, const codeview_type* cvtype) if (getStructProperty(cvtype) & kPropIncomplete) cvtype = findCompleteClassType(cvtype, &type); - if(!findUdtSymbol(type + 0x1000)) - { - char name[kMaxNameLen]; - int value, leaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen); - pstrcpy_v(true, (BYTE*) name, (const BYTE*) &cvtype->struct_v1.structlen + leaf_len); + if(findUdtSymbol(type + 0x1000)) + return; + char name[kMaxNameLen]; + int value, leaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen); + pstrcpy_v(true, (BYTE*) name, (const BYTE*) &cvtype->struct_v1.structlen + leaf_len); + + if (getStructProperty(cvtype) & kPropIncomplete) + { checkUserTypeAlloc(); codeview_reftype* rdtype = (codeview_reftype*) (userTypes + cbUserTypes); @@ -1895,6 +1898,8 @@ void CV2PDB::ensureUDT(int type, const codeview_type* cvtype) // addUdtSymbol(viewHelperType, "object_viewhelper"); addUdtSymbol(viewHelperType, name); } + else + addUdtSymbol(type + 0x1000, name); } int CV2PDB::appendTypedef(int type, const char* name) @@ -1916,7 +1921,7 @@ int CV2PDB::appendTypedef(int type, const char* name) dtype->enumeration_v2.type = basetype; dtype->enumeration_v2.fieldlist = fieldlistType; dtype->enumeration_v2.count = 0; - dtype->enumeration_v2.property = 0x200; + dtype->enumeration_v2.property = kPropReserved2; int len = cstrcpy_v (v3, (BYTE*) &dtype->enumeration_v2.p_name, name); len += sizeof(dtype->enumeration_v2) - sizeof(dtype->enumeration_v2.p_name); writeUserTypeLen(dtype, len); @@ -2091,7 +2096,7 @@ bool CV2PDB::initGlobalTypes() if(td->common.id == LF_FIELDLIST_V1 || td->common.id == LF_FIELDLIST_V2) dtype->struct_v2.n_element = countFields((const codeview_reftype*)td); dtype->struct_v2.property = fixProperty(t + 0x1000, type->struct_v1.property, - type->struct_v1.fieldlist) | 0x200; + type->struct_v1.fieldlist) | kPropReserved2; #if REMOVE_LF_DERIVED dtype->struct_v2.derived = 0; #else @@ -2903,11 +2908,37 @@ codeview_symbol* CV2PDB::findUdtSymbol(int type) return 0; } +codeview_symbol* CV2PDB::findUdtSymbol(const char* name) +{ + for(int p = 0; p < cbGlobalSymbols; ) + { + codeview_symbol* sym = (codeview_symbol*) (globalSymbols + p); + if(sym->common.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name)) + 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 && p2ccmp(sym->udt_v1.p_name, name)) + return sym; + p += sym->common.len + 2; + } + for(int p = 0; p < cbUdtSymbols; ) + { + codeview_symbol* sym = (codeview_symbol*) (udtSymbols + p); + if(sym->common.id == S_UDT_V1 && p2ccmp(sym->udt_v1.p_name, name)) + return sym; + p += sym->common.len + 2; + } + return 0; +} + bool CV2PDB::addUdtSymbol(int type, const char* name) { - if (cbUdtSymbols + 300 > allocUdtSymbols) + if (cbUdtSymbols + 100 + kMaxNameLen > allocUdtSymbols) { - allocUdtSymbols += 5000; + allocUdtSymbols += kMaxNameLen + 5000; udtSymbols = (BYTE*) realloc(udtSymbols, allocUdtSymbols); } diff --git a/src/cv2pdb.h b/src/cv2pdb.h index cdfed36..e352dcc 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -123,6 +123,7 @@ public: bool addPublics(); codeview_symbol* findUdtSymbol(int type); + codeview_symbol* findUdtSymbol(const char* name); bool addUdtSymbol(int type, const char* name); void ensureUDT(int type, const codeview_type* cvtype); diff --git a/src/cv2pdb.vcproj b/src/cv2pdb.vcproj index cc0a479..fd3c973 100644 --- a/src/cv2pdb.vcproj +++ b/src/cv2pdb.vcproj @@ -69,6 +69,7 @@ GenerateDebugInformation="true" SubSystem="1" TargetMachine="1" + Profile="true" /> string(const char (&p)[N]) : _cp(p), _len(N-1), _const(true) {} + ~string() { if(!_const) pool.put(_p); } + + size_t length() const { return _len; } + + char operator[] (size_t idx) const + { + return _p[idx]; + } + string substr(size_t pos, size_t len) const + { + return string(_p + pos, len); + } + + template string operator+(const char (&p)[N]) + { + assert(!_const); + assert(_len + N-1 < maxLen); + + memcpy(_p + _len, p, N-1); + return string(_p, _len + N-1); + } + string operator+(string s) + { + assert(!_const); + assert(_len + s._len < maxLen); + + memcpy(_p + _len, s._p, s._len); + return string(_p, _len + s._len); + } + template string operator+=(const char (&p)[N]) + { + assert(!_const); + assert(_len + N-1 < maxLen); + memcpy(_p + _len, p, N-1); + _len += N - 1; + return *this; + } + string operator+=(const string& s) + { + assert(!_const); + assert(_len + s._len < maxLen); + memcpy(_p + _len, s._p, s._len); + _len += s._len; + return *this; + } + string operator+=(char c) + { + assert(!_const); + assert(_len < maxLen); + _p[_len++] = c; + return *this; + } + templatestring operator=(const char (&p)[N]) + { + _len = N-1; + memcpy(_p, p, _len); + _const = true; + return *this; + } + string operator=(const string& s) + { + assert(!_const); + _len = s._len; + memcpy(_p, s._p, _len); + return *this; + } + bool operator==(const string& s) const + { + return _len == s._len && memcmp(_p, s._p, _len) == 0; + } + + const char* c_str() + { + assert(!_const); + assert(_len < maxLen); + _p[_len] = 0; + return _p; + } + + union + { + const char* _cp; + char* _p; + }; + size_t _len; + bool _const; +}; + +template string operator+(const char (&p)[N], string s) +{ + assert(!s._const); + assert(s._len + N-1 < maxLen); + memmove(s._p + N - 1, s._p, s._len); + memcpy(s._p, p, N-1); + return string(s._p, s._len + N-1); +} +#endif typedef unsigned char ubyte; typedef long double real; @@ -38,7 +172,6 @@ class Demangle public: size_t ni; string name; - string (Demangle::*fparseTemplateInstanceName)(); static void error() { @@ -88,7 +221,7 @@ public: ni += 3; try { - result = parseTemplateInstanceName(); // (this->*fparseTemplateInstanceName)(); + result = parseTemplateInstanceName(); if (ni != nisave + i) err = true; } @@ -281,7 +414,7 @@ public: return prop + p; } p = prop + parseType() + - (isdelegate ? " delegate(" : " function(") + args + ")"; + (isdelegate ? string(" delegate(") : string(" function(")) + args + ")"; isdelegate = 0; goto L1; } @@ -454,8 +587,6 @@ public: goto Lnot; } - // fparseTemplateInstanceName = &parseTemplateInstanceName; - try { string result = parseQualifiedName(); @@ -522,12 +653,13 @@ void unittest() bool d_demangle(const char* name, char* demangled, int maxlen, bool plain) { -#if 0 // && def _DEBUG +#ifdef _DEBUG static bool once; if(!once) { once = true; unittest(); } #endif Demangle d; - string r = d.demangle(name, plain); + string nm(name, strlen(name)); + string r = d.demangle(nm, plain); if (r.length == 0) return false; strncpy(demangled, r.c_str(), maxlen); diff --git a/src/main.cpp b/src/main.cpp index 96864cc..9b6c247 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "PEImage.h" #include "cv2pdb.h" +#include "symutil.h" #include @@ -81,12 +82,12 @@ int main(int argc, char** argv) if (argc < 2) { printf("Convert DMD CodeView debug information to PDB files, Version %g\n", VERSION); - printf("Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved\n"); + printf("Copyright (c) 2009-2011 by Rainer Schuetze, All Rights Reserved\n"); printf("\n"); printf("License for redistribution is given by the Artistic License 2.0\n"); printf("see file LICENSE for further details\n"); printf("\n"); - printf("usage: %s [-Dversion|-C] [new-exe-file] [pdb-file]\n", argv[0]); + printf("usage: %s [-Dversion|-C|-n] [new-exe-file] [pdb-file]\n", argv[0]); return -1; } @@ -103,6 +104,8 @@ int main(int argc, char** argv) Dversion = strtod (argv[0] + 2, 0); else if (argv[0][1] == 'C') Dversion = 0; + else if (argv[0][1] == 'n') + demangleSymbols = false; else fatal("unknwon option: %s", argv[0]); } diff --git a/src/mscvpdb.h b/src/mscvpdb.h index f8cf6a6..9a55e1f 100644 --- a/src/mscvpdb.h +++ b/src/mscvpdb.h @@ -126,7 +126,7 @@ union codeview_type unsigned short int len; short int id; short int attribute; - short int type; + unsigned short int type; } modifier_v1; struct @@ -142,7 +142,7 @@ union codeview_type unsigned short int len; short int id; short int attribute; - short int datatype; + unsigned short int datatype; struct p_string p_name; } pointer_v1; @@ -159,8 +159,8 @@ union codeview_type { unsigned short int len; short int id; - short int elemtype; - short int idxtype; + unsigned short int elemtype; + unsigned short int idxtype; unsigned short int arrlen; /* numeric leaf */ #if 0 struct p_string p_name; @@ -196,10 +196,10 @@ union codeview_type unsigned short int len; short int id; short int n_element; - short int fieldlist; + unsigned short int fieldlist; short int property; - short int derived; - short int vshape; + unsigned short int derived; + unsigned short int vshape; unsigned short int structlen; /* numeric leaf */ #if 0 struct p_string p_name; @@ -240,8 +240,8 @@ union codeview_type { unsigned short int len; short int id; - short int count; - short int fieldlist; + unsigned short int count; + unsigned short int fieldlist; short int property; unsigned short int un_len; /* numeric leaf */ #if 0 @@ -253,7 +253,7 @@ union codeview_type { unsigned short int len; short int id; - short int count; + unsigned short int count; short int property; unsigned int fieldlist; unsigned short int un_len; /* numeric leaf */ @@ -266,7 +266,7 @@ union codeview_type { unsigned short int len; short int id; - short int count; + unsigned short int count; short int property; unsigned int fieldlist; unsigned short int un_len; /* numeric leaf */ @@ -279,9 +279,9 @@ union codeview_type { unsigned short int len; short int id; - short int count; - short int type; - short int fieldlist; + unsigned short int count; + unsigned short int type; + unsigned short int fieldlist; short int property; struct p_string p_name; } enumeration_v1; @@ -290,7 +290,7 @@ union codeview_type { unsigned short int len; short int id; - short int count; + unsigned short int count; short int property; unsigned int type; unsigned int fieldlist; @@ -301,7 +301,7 @@ union codeview_type { unsigned short int len; short int id; - short int count; + unsigned short int count; short int property; unsigned int type; unsigned int fieldlist; @@ -434,27 +434,27 @@ union codeview_fieldtype struct { - short int id; - short int type; - short int attribute; - unsigned short int offset; /* numeric leaf */ + short int id; + unsigned short int type; + short int attribute; + unsigned short int offset; /* numeric leaf */ } bclass_v1; struct { - short int id; - short int attribute; - unsigned int type; - unsigned short int offset; /* numeric leaf */ + short int id; + short int attribute; + unsigned int type; + unsigned short int offset; /* numeric leaf */ } bclass_v2; struct { - short int id; - short int btype; - short int vbtype; - short int attribute; - unsigned short int vbpoff; /* numeric leaf */ + short int id; + unsigned short int btype; + unsigned short int vbtype; + short int attribute; + unsigned short int vbpoff; /* numeric leaf */ #if 0 unsigned short int vboff; /* numeric leaf */ #endif @@ -462,11 +462,11 @@ union codeview_fieldtype struct { - short int id; - short int attribute; - unsigned int btype; - unsigned int vbtype; - unsigned short int vbpoff; /* numeric leaf */ + short int id; + short int attribute; + unsigned int btype; + unsigned int vbtype; + unsigned short int vbpoff; /* numeric leaf */ #if 0 unsigned short int vboff; /* numeric leaf */ #endif @@ -494,38 +494,38 @@ union codeview_fieldtype struct { - short int id; - short int type; - struct p_string p_name; + short int id; + unsigned short int type; + struct p_string p_name; } friendfcn_v1; struct { - short int id; - short int _pad0; - unsigned int type; - struct p_string p_name; + short int id; + short int _pad0; + unsigned int type; + struct p_string p_name; } friendfcn_v2; struct { - short int id; - short int type; - short int attribute; - unsigned short int offset; /* numeric leaf */ + short int id; + unsigned short int type; + short int attribute; + unsigned short int offset; /* numeric leaf */ #if 0 - struct p_string p_name; + struct p_string p_name; #endif } member_v1; struct { - short int id; - short int attribute; - unsigned int type; - unsigned short int offset; /* numeric leaf */ + short int id; + short int attribute; + unsigned int type; + unsigned short int offset; /* numeric leaf */ #if 0 - struct p_string p_name; + struct p_string p_name; #endif } member_v2; @@ -543,132 +543,132 @@ union codeview_fieldtype struct { - short int id; - short int type; - short int attribute; - struct p_string p_name; + short int id; + unsigned short int type; + short int attribute; + struct p_string p_name; } stmember_v1; struct { - short int id; - short int attribute; - unsigned int type; - struct p_string p_name; + short int id; + short int attribute; + unsigned int type; + struct p_string p_name; } stmember_v2; struct { - short int id; - short int attribute; - unsigned int type; - char name[1]; + short int id; + short int attribute; + unsigned int type; + char name[1]; } stmember_v3; struct { - short int id; - short int count; - short int mlist; - struct p_string p_name; + short int id; + short int count; + unsigned short int mlist; + struct p_string p_name; } method_v1; struct { - short int id; - short int count; - unsigned int mlist; - struct p_string p_name; + short int id; + short int count; + unsigned int mlist; + struct p_string p_name; } method_v2; struct { - short int id; - short int count; - unsigned int mlist; - char name[1]; + short int id; + short int count; + unsigned int mlist; + char name[1]; } method_v3; struct { - short int id; - short int type; - struct p_string p_name; + short int id; + unsigned short int type; + struct p_string p_name; } nesttype_v1; struct { - short int id; - short int _pad0; - unsigned int type; - struct p_string p_name; + short int id; + short int _pad0; + unsigned int type; + struct p_string p_name; } nesttype_v2; struct { - short int id; - short int _pad0; - unsigned int type; - char name[1]; + short int id; + short int _pad0; + unsigned int type; + char name[1]; } nesttype_v3; struct { - short int id; - short int type; + short int id; + unsigned short int type; } vfunctab_v1; struct { - short int id; - short int _pad0; - unsigned int type; + short int id; + short int _pad0; + unsigned int type; } vfunctab_v2; struct { - short int id; - short int type; + short int id; + unsigned short int type; } friendcls_v1; struct { - short int id; - short int _pad0; - unsigned int type; + short int id; + short int _pad0; + unsigned int type; } friendcls_v2; struct { - short int id; - short int attribute; - short int type; - struct p_string p_name; + short int id; + short int attribute; + unsigned short int type; + struct p_string p_name; } onemethod_v1; struct { - short int id; - short int attribute; - unsigned int type; - struct p_string p_name; + short int id; + short int attribute; + unsigned int type; + struct p_string p_name; } onemethod_v2; struct { - short int id; - short int attribute; - unsigned int type; - char name[1]; + short int id; + short int attribute; + unsigned int type; + char name[1]; } onemethod_v3; struct { - short int id; - short int attribute; - short int type; - unsigned int vtab_offset; - struct p_string p_name; + short int id; + short int attribute; + unsigned short int type; + unsigned int vtab_offset; + struct p_string p_name; } onemethod_virt_v1; struct @@ -691,9 +691,9 @@ union codeview_fieldtype struct { - short int id; - short int type; - unsigned int offset; + short int id; + unsigned short int type; + unsigned int offset; } vfuncoff_v1; struct @@ -706,10 +706,10 @@ union codeview_fieldtype struct { - short int id; - short int attribute; - short int type; - struct p_string p_name; + short int id; + short int attribute; + unsigned short int type; + struct p_string p_name; } nesttypeex_v1; struct @@ -744,8 +744,8 @@ union codeview_oem_type short int oemid; // 0x42 for D short int id; // 1 short int count; // 2 - short int index_type; - short int elem_type; + short unsigned int index_type; + short unsigned int elem_type; } d_dyn_array; struct @@ -753,8 +753,8 @@ union codeview_oem_type short int oemid; // 0x42 for D short int id; // 2 short int count; // 2 - short int key_type; - short int elem_type; + short unsigned int key_type; + short unsigned int elem_type; } d_assoc_array; struct @@ -762,8 +762,8 @@ union codeview_oem_type short int oemid; // 0x42 for D short int id; // 3 short int count; // 2 - short int this_type; - short int func_type; + short unsigned int this_type; + short unsigned int func_type; } d_delegate; }; diff --git a/src/symutil.cpp b/src/symutil.cpp index 2660ea4..faed579 100644 --- a/src/symutil.cpp +++ b/src/symutil.cpp @@ -14,6 +14,7 @@ extern "C" { #include char dotReplacementChar = '@'; +bool demangleSymbols = true; int dsym2c(const BYTE* p, int len, char* cname, int maxclen) { @@ -26,6 +27,33 @@ int dsym2c(const BYTE* p, int len, char* cname, int maxclen) int ch = *p++; if(ch == 0) break; + if ((ch & 0xc0) == 0xc0) + { + zlen = (ch & 0x7) + 1; + zpos = ((ch >> 3) & 7) + 1; // + zlen; + if (zpos > cpos) + break; + for (int z = 0; z < zlen; z++) + cname[cpos + z] = cname[cpos - zpos + z]; + cpos += zlen; + } + else if (ch >= 0x80) + { + if (p >= end) + break; + int ch2 = *p++; + zlen = (ch2 & 0x7f) | ((ch & 0x38) << 4); + if (p >= end) + break; + int ch3 = *p++; + zpos = (ch3 & 0x7f) | ((ch & 7) << 7); + if (zpos > cpos) + break; + for(int z = 0; z < zlen; z++) + cname[cpos + z] = cname[cpos - zpos + z]; + cpos += zlen; + } +#if 0 if (ch == 0x80) { if (p >= end) @@ -48,13 +76,15 @@ int dsym2c(const BYTE* p, int len, char* cname, int maxclen) cname[cpos + z] = cname[cpos - zpos + z]; cpos += zlen; } +#endif else cname[cpos++] = ch; } cname[cpos] = 0; - if (cname[0] == '_' && cname[1] == 'D' && isdigit(cname[2])) - d_demangle(cname, cname, maxclen, true); + if(demangleSymbols) + if (cname[0] == '_' && cname[1] == 'D' && isdigit(cname[2])) + d_demangle(cname, cname, maxclen, true); #if 1 for(int i = 0; i < cpos; i++) diff --git a/src/symutil.h b/src/symutil.h index b3f020f..dfc8b76 100644 --- a/src/symutil.h +++ b/src/symutil.h @@ -30,5 +30,6 @@ 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; +extern bool demangleSymbols; #endif //__SYMUTIL_H__ diff --git a/test/cvtest.d b/test/cvtest.d index 283e972..4d64873 100644 --- a/test/cvtest.d +++ b/test/cvtest.d @@ -231,8 +231,18 @@ int arrays() return iarr.length; } +enum { Forward, Accept, Reject } +alias int Action; + +Action convertEnum() +{ + return Accept; +} + int main2(char[][]argv) { + convertEnum(); + enum_name inst_enum = enum_name.kEnum2; class_member inst_member = new class_member; base_class inst_base = new base_class; -- cgit v0.12