summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorAleksandr Urakov <aleksandr.urakov@jetbrains.com>2018-11-12 16:23:50 +0000
committerAleksandr Urakov <aleksandr.urakov@jetbrains.com>2018-11-12 16:23:50 +0000
commit1dc51db75764d427189a16332131f76d4f21c9e8 (patch)
tree399eca66ca518aabdf923790375f52dc14cce9f1 /lldb/source
parentde62b76c5105215d4e14cc869e07ad423c6a3a98 (diff)
downloadbcm5719-llvm-1dc51db75764d427189a16332131f76d4f21c9e8.tar.gz
bcm5719-llvm-1dc51db75764d427189a16332131f76d4f21c9e8.zip
[ClangASTContext] Extract VTable pointers from C++ objects
This patch processes the case of retrieving a virtual base when the object is already read from the debuggee memory. To achieve that ValueObject::GetCPPVTableAddress was removed and was reimplemented in ClangASTContext (because access to the process is needed to retrieve the VTable pointer in general, and because this is the only place that used old version of ValueObject::GetCPPVTableAddress). This patch allows to use real object's VTable instead of searching virtual bases by offsets restored by MicrosoftRecordLayoutBuilder. PDB has no enough info to restore VBase offsets properly, so we have to read real VTable instead. Differential revision: https://reviews.llvm.org/D53506 llvm-svn: 346669
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Core/ValueObject.cpp25
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp196
2 files changed, 122 insertions, 99 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 3fcd68e15fd..96a171688c9 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -2804,31 +2804,6 @@ ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
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();
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 47c5e144b13..4a33143cfcc 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -201,6 +201,122 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) {
}
}
+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<clang::MicrosoftVTableContext &>(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<clang::ItaniumVTableContext &>(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<clang::ASTContext *, ClangASTContext *>
ClangASTMap;
@@ -6545,80 +6661,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
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<clang::MicrosoftVTableContext *>(
- 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<clang::ItaniumVTableContext *>(
- 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)
OpenPOWER on IntegriCloud