This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL346669: [ClangASTContext] Extract VTable pointers from C++ 
objects (authored by aleksandr.urakov, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D53506?vs=170430&id=173684#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D53506

Files:
  lldb/trunk/include/lldb/Core/ValueObject.h
  lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.cpp
  lldb/trunk/lit/SymbolFile/PDB/Inputs/VBases.script
  lldb/trunk/lit/SymbolFile/PDB/vbases.test
  lldb/trunk/source/Core/ValueObject.cpp
  lldb/trunk/source/Symbol/ClangASTContext.cpp

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<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 @@
             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)
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/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/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,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to