summaryrefslogtreecommitdiffstats
path: root/lldb/source/Symbol/ClangASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/ClangASTContext.cpp')
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp196
1 files changed, 122 insertions, 74 deletions
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