Index: lldb/trunk/include/lldb/Core/ValueObject.h =================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h +++ lldb/trunk/include/lldb/Core/ValueObject.h @@ -635,9 +635,6 @@ virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, AddressType address_type = eAddressTypeLoad) {} - // Find the address of the C++ vtable pointer - virtual lldb::addr_t GetCPPVTableAddress(AddressType &address_type); - virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type); virtual lldb::ValueObjectSP CastPointerType(const char *name, Index: lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.cpp +++ lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.cpp @@ -0,0 +1,16 @@ +struct A { + char a = 1; +}; + +struct B { + int b = 2; +}; + +struct C : virtual A, virtual B { + short c = 3; +}; + +int main() { + C c{}; + return 0; +} Index: lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.script =================================================================== --- lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.script +++ lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.script @@ -0,0 +1,7 @@ +breakpoint set --file VBases.cpp --line 15 + +run + +print c + +frame variable c \ No newline at end of file Index: lldb/trunk/lit/SymbolFile/PDB/vbases.test =================================================================== --- lldb/trunk/lit/SymbolFile/PDB/vbases.test +++ lldb/trunk/lit/SymbolFile/PDB/vbases.test @@ -0,0 +1,15 @@ +REQUIRES: windows +RUN: clang-cl /Zi %S/Inputs/VBases.cpp /o %t.exe +RUN: %lldb -b -s %S/Inputs/VBases.script -- %t.exe | FileCheck %s + +CHECK: { +CHECK: A = (a = '\x01') +CHECK: B = (b = 2) +CHECK: c = 3 +CHECK: } + +CHECK: { +CHECK: A = (a = '\x01') +CHECK: B = (b = 2) +CHECK: c = 3 +CHECK: } Index: lldb/trunk/source/Core/ValueObject.cpp =================================================================== --- lldb/trunk/source/Core/ValueObject.cpp +++ lldb/trunk/source/Core/ValueObject.cpp @@ -2804,31 +2804,6 @@ return result_sp; } -lldb::addr_t ValueObject::GetCPPVTableAddress(AddressType &address_type) { - CompilerType pointee_type; - CompilerType this_type(GetCompilerType()); - uint32_t type_info = this_type.GetTypeInfo(&pointee_type); - if (type_info) { - bool ptr_or_ref = false; - if (type_info & (eTypeIsPointer | eTypeIsReference)) { - ptr_or_ref = true; - type_info = pointee_type.GetTypeInfo(); - } - - const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; - if ((type_info & cpp_class) == cpp_class) { - if (ptr_or_ref) { - address_type = GetAddressTypeOfChildren(); - return GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - } else - return GetAddressOf(false, &address_type); - } - } - - address_type = eAddressTypeInvalid; - return LLDB_INVALID_ADDRESS; -} - ValueObjectSP ValueObject::Dereference(Status &error) { if (m_deref_valobj) return m_deref_valobj->GetSP(); Index: lldb/trunk/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp +++ lldb/trunk/source/Symbol/ClangASTContext.cpp @@ -201,6 +201,122 @@ } } +static lldb::addr_t GetVTableAddress(Process &process, + VTableContextBase &vtable_ctx, + ValueObject &valobj, + const ASTRecordLayout &record_layout) { + // Retrieve type info + CompilerType pointee_type; + CompilerType this_type(valobj.GetCompilerType()); + uint32_t type_info = this_type.GetTypeInfo(&pointee_type); + if (!type_info) + return LLDB_INVALID_ADDRESS; + + // Check if it's a pointer or reference + bool ptr_or_ref = false; + if (type_info & (eTypeIsPointer | eTypeIsReference)) { + ptr_or_ref = true; + type_info = pointee_type.GetTypeInfo(); + } + + // We process only C++ classes + const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; + if ((type_info & cpp_class) != cpp_class) + return LLDB_INVALID_ADDRESS; + + // Calculate offset to VTable pointer + lldb::offset_t vbtable_ptr_offset = + vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity() + : 0; + + if (ptr_or_ref) { + // We have a pointer / ref to object, so read + // VTable pointer from process memory + + if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad) + return LLDB_INVALID_ADDRESS; + + auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + vbtable_ptr_addr += vbtable_ptr_offset; + + Status err; + return process.ReadPointerFromMemory(vbtable_ptr_addr, err); + } + + // We have an object already read from process memory, + // so just extract VTable pointer from it + + DataExtractor data; + Status err; + auto size = valobj.GetData(data, err); + if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size) + return LLDB_INVALID_ADDRESS; + + return data.GetPointer(&vbtable_ptr_offset); +} + +static int64_t ReadVBaseOffsetFromVTable(Process &process, + VTableContextBase &vtable_ctx, + lldb::addr_t vtable_ptr, + const CXXRecordDecl *cxx_record_decl, + const CXXRecordDecl *base_class_decl) { + if (vtable_ctx.isMicrosoft()) { + clang::MicrosoftVTableContext &msoft_vtable_ctx = + static_cast(vtable_ctx); + + // Get the index into the virtual base table. The + // index is the index in uint32_t from vbtable_ptr + const unsigned vbtable_index = + msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4; + Status err; + return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX, + err); + } + + clang::ItaniumVTableContext &itanium_vtable_ctx = + static_cast(vtable_ctx); + + clang::CharUnits base_offset_offset = + itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl, + base_class_decl); + const lldb::addr_t base_offset_addr = + vtable_ptr + base_offset_offset.getQuantity(); + const uint32_t base_offset_size = process.GetAddressByteSize(); + Status err; + return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size, + INT64_MAX, err); +} + +static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx, + ValueObject &valobj, + const ASTRecordLayout &record_layout, + const CXXRecordDecl *cxx_record_decl, + const CXXRecordDecl *base_class_decl, + int32_t &bit_offset) { + ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (!process) + return false; + + lldb::addr_t vtable_ptr = + GetVTableAddress(*process, vtable_ctx, valobj, record_layout); + if (vtable_ptr == LLDB_INVALID_ADDRESS) + return false; + + auto base_offset = ReadVBaseOffsetFromVTable( + *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl); + if (base_offset == INT64_MAX) + return false; + + bit_offset = base_offset * 8; + + return true; +} + typedef lldb_private::ThreadSafeDenseMap ClangASTMap; @@ -6545,80 +6661,12 @@ if (base_class->isVirtual()) { bool handled = false; if (valobj) { - Status err; - AddressType addr_type = eAddressTypeInvalid; - lldb::addr_t vtable_ptr_addr = - valobj->GetCPPVTableAddress(addr_type); - - if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && - addr_type == eAddressTypeLoad) { - - ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) { - clang::VTableContextBase *vtable_ctx = - getASTContext()->getVTableContext(); - if (vtable_ctx) { - if (vtable_ctx->isMicrosoft()) { - clang::MicrosoftVTableContext *msoft_vtable_ctx = - static_cast( - vtable_ctx); - - if (vtable_ptr_addr) { - const lldb::addr_t vbtable_ptr_addr = - vtable_ptr_addr + - record_layout.getVBPtrOffset().getQuantity(); - - const lldb::addr_t vbtable_ptr = - process->ReadPointerFromMemory(vbtable_ptr_addr, - err); - if (vbtable_ptr != LLDB_INVALID_ADDRESS) { - // Get the index into the virtual base table. The - // index is the index in uint32_t from vbtable_ptr - const unsigned vbtable_index = - msoft_vtable_ctx->getVBTableIndex( - cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = - vbtable_ptr + vbtable_index * 4; - const int32_t base_offset = - process->ReadSignedIntegerFromMemory( - base_offset_addr, 4, INT32_MAX, err); - if (base_offset != INT32_MAX) { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } else { - clang::ItaniumVTableContext *itanium_vtable_ctx = - static_cast( - vtable_ctx); - if (vtable_ptr_addr) { - const lldb::addr_t vtable_ptr = - process->ReadPointerFromMemory(vtable_ptr_addr, - err); - if (vtable_ptr != LLDB_INVALID_ADDRESS) { - clang::CharUnits base_offset_offset = - itanium_vtable_ctx->getVirtualBaseOffsetOffset( - cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = - vtable_ptr + base_offset_offset.getQuantity(); - const uint32_t base_offset_size = - process->GetAddressByteSize(); - const int64_t base_offset = - process->ReadSignedIntegerFromMemory( - base_offset_addr, base_offset_size, - UINT32_MAX, err); - if (base_offset < UINT32_MAX) { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - } - } - } + clang::VTableContextBase *vtable_ctx = + getASTContext()->getVTableContext(); + if (vtable_ctx) + handled = GetVBaseBitOffset(*vtable_ctx, *valobj, + record_layout, cxx_record_decl, + base_class_decl, bit_offset); } if (!handled) bit_offset = record_layout.getVBaseClassOffset(base_class_decl)