From b1d416923e1698d2847f16ed065ae1c41149632d Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 17 Feb 2016 21:13:15 +0000 Subject: [PATCH] [DebugInfoPDB] Teach Variant to support string types. The IDiaSymbol::getValue() method returns a variant. Until now, I had never encountered a string value, so the Variant wrapper did not support VT_BSTR. Now we have need to support string values, so this patch just adds support for one extra type to Variant. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261152 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/PDBTypes.h | 30 +++++++++++++++++++++-- lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 33 +++++++++++++++++--------- lib/DebugInfo/PDB/PDBExtras.cpp | 25 ++++++++++--------- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h index 787107fdeea..77b98fb8574 100644 --- a/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -350,6 +350,7 @@ enum PDB_VariantType { UInt32, UInt64, Bool, + String }; struct Variant { @@ -357,6 +358,15 @@ struct Variant { : Type(PDB_VariantType::Empty) { } + Variant(const Variant &Other) : Type(PDB_VariantType::Empty) { + *this = Other; + } + + ~Variant() { + if (Type == PDB_VariantType::String && Value.String != nullptr) + delete[] Value.String; + } + PDB_VariantType Type; union { bool Bool; @@ -370,10 +380,11 @@ struct Variant { uint16_t UInt16; uint32_t UInt32; uint64_t UInt64; - }; + char *String; + } Value; #define VARIANT_EQUAL_CASE(Enum) \ case PDB_VariantType::Enum: \ - return Enum == Other.Enum; + return Value.Enum == Other.Value.Enum; bool operator==(const Variant &Other) const { if (Type != Other.Type) return false; @@ -389,12 +400,27 @@ struct Variant { VARIANT_EQUAL_CASE(UInt16) VARIANT_EQUAL_CASE(UInt32) VARIANT_EQUAL_CASE(UInt64) + VARIANT_EQUAL_CASE(String) default: return true; } } #undef VARIANT_EQUAL_CASE bool operator!=(const Variant &Other) const { return !(*this == Other); } + Variant &operator=(const Variant &Other) { + if (this == &Other) + return *this; + if (Type == PDB_VariantType::String && Value.String != nullptr) + delete[] Value.String; + Type = Other.Type; + Value = Other.Value; + if (Other.Type == PDB_VariantType::String && + Other.Value.String != nullptr) { + Value.String = new char[strlen(Other.Value.String) + 1]; + ::strcpy(Value.String, Other.Value.String); + } + return *this; + } }; namespace PDB { diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index abe0ab55e56..21b9a7aef82 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -22,49 +22,60 @@ Variant VariantFromVARIANT(const VARIANT &V) { Variant Result; switch (V.vt) { case VT_I1: - Result.Int8 = V.cVal; + Result.Value.Int8 = V.cVal; Result.Type = PDB_VariantType::Int8; break; case VT_I2: - Result.Int16 = V.iVal; + Result.Value.Int16 = V.iVal; Result.Type = PDB_VariantType::Int16; break; case VT_I4: - Result.Int32 = V.intVal; + Result.Value.Int32 = V.intVal; Result.Type = PDB_VariantType::Int32; break; case VT_I8: - Result.Int64 = V.llVal; + Result.Value.Int64 = V.llVal; Result.Type = PDB_VariantType::Int64; break; case VT_UI1: - Result.UInt8 = V.bVal; + Result.Value.UInt8 = V.bVal; Result.Type = PDB_VariantType::UInt8; break; case VT_UI2: - Result.UInt16 = V.uiVal; + Result.Value.UInt16 = V.uiVal; Result.Type = PDB_VariantType::UInt16; break; case VT_UI4: - Result.UInt32 = V.uintVal; + Result.Value.UInt32 = V.uintVal; Result.Type = PDB_VariantType::UInt32; break; case VT_UI8: - Result.UInt64 = V.ullVal; + Result.Value.UInt64 = V.ullVal; Result.Type = PDB_VariantType::UInt64; break; case VT_BOOL: - Result.Bool = (V.boolVal == VARIANT_TRUE) ? true : false; + Result.Value.Bool = (V.boolVal == VARIANT_TRUE) ? true : false; Result.Type = PDB_VariantType::Bool; break; case VT_R4: - Result.Single = V.fltVal; + Result.Value.Single = V.fltVal; Result.Type = PDB_VariantType::Single; break; case VT_R8: - Result.Double = V.dblVal; + Result.Value.Double = V.dblVal; Result.Type = PDB_VariantType::Double; break; + case VT_BSTR: { + const char *SrcBytes = reinterpret_cast(V.bstrVal); + llvm::ArrayRef SrcByteArray(SrcBytes, SysStringByteLen(V.bstrVal)); + std::string Result8; + if (!llvm::convertUTF16ToUTF8String(SrcByteArray, Result8)) + Result.Value.String = nullptr; + Result.Value.String = new char[Result8.length() + 1]; + ::strcpy(Result.Value.String, Result8.c_str()); + Result.Type = PDB_VariantType::String; + break; + } default: Result.Type = PDB_VariantType::Unknown; break; diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp index 29c0c32601d..52328db42c1 100644 --- a/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/lib/DebugInfo/PDB/PDBExtras.cpp @@ -284,37 +284,40 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) { raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) { switch (Value.Type) { case PDB_VariantType::Bool: - OS << (Value.Bool ? "true" : "false"); + OS << (Value.Value.Bool ? "true" : "false"); break; case PDB_VariantType::Double: - OS << Value.Double; + OS << Value.Value.Double; break; case PDB_VariantType::Int16: - OS << Value.Int16; + OS << Value.Value.Int16; break; case PDB_VariantType::Int32: - OS << Value.Int32; + OS << Value.Value.Int32; break; case PDB_VariantType::Int64: - OS << Value.Int64; + OS << Value.Value.Int64; break; case PDB_VariantType::Int8: - OS << static_cast(Value.Int8); + OS << static_cast(Value.Value.Int8); break; case PDB_VariantType::Single: - OS << Value.Single; + OS << Value.Value.Single; break; case PDB_VariantType::UInt16: - OS << Value.Double; + OS << Value.Value.Double; break; case PDB_VariantType::UInt32: - OS << Value.UInt32; + OS << Value.Value.UInt32; break; case PDB_VariantType::UInt64: - OS << Value.UInt64; + OS << Value.Value.UInt64; break; case PDB_VariantType::UInt8: - OS << static_cast(Value.UInt8); + OS << static_cast(Value.Value.UInt8); + break; + case PDB_VariantType::String: + OS << Value.Value.String; break; default: OS << Value.Type;