[Lldb-commits] [lldb] Add the ability to get a C++ vtable ValueObject from another ValueObj… (PR #67599)

via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 27 14:39:05 PDT 2023


================
@@ -0,0 +1,325 @@
+//===-- ValueObjectVTable.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/ValueObjectVTable.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectChild.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
+
+using namespace lldb;
+using namespace lldb_private;
+
+class ValueObjectVTableChild : public ValueObject {
+public:
+  ValueObjectVTableChild(ValueObject &parent, uint32_t func_idx,
+                         uint64_t addr_size)
+      : ValueObject(parent), m_func_idx(func_idx), m_addr_size(addr_size) {
+    SetFormat(eFormatPointer);
+    SetName(ConstString(llvm::formatv("[{0}]", func_idx).str()));
+  }
+
+  ~ValueObjectVTableChild() override = default;
+
+  std::optional<uint64_t> GetByteSize() override { return m_addr_size; };
+
+  size_t CalculateNumChildren(uint32_t max) override { return 0; };
+
+  ValueType GetValueType() const override { return eValueTypeVTableEntry; };
+
+  bool IsInScope() override {
+    ValueObject *parent = GetParent();
+    if (parent)
+      return parent->IsInScope();
+    return false;
+  };
+
+protected:
+  bool UpdateValue() override {
+    SetValueIsValid(false);
+    m_value.Clear();
+    ValueObject *parent = GetParent();
+    if (!parent) {
+      m_error.SetErrorString("no parent object");
+      return false;
+    }
+
+    addr_t parent_addr = parent->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+    if (parent_addr == LLDB_INVALID_ADDRESS) {
+      m_error.SetErrorString("parent has invalid address");
+      return false;
+    }
+
+    ProcessSP process_sp = GetProcessSP();
+    if (!process_sp) {
+      m_error.SetErrorString("no process");
+      return false;
+    }
+
+    TargetSP target_sp = GetTargetSP();
+    if (!target_sp) {
+      m_error.SetErrorString("no target");
+      return false;
+    }
+
+    // Each `vtable_entry_addr` points to the function pointer.
+    addr_t vtable_entry_addr = parent_addr + m_func_idx * m_addr_size;
+    addr_t vfunc_ptr =
+        process_sp->ReadPointerFromMemory(vtable_entry_addr, m_error);
+    if (m_error.Fail()) {
+      m_error.SetErrorStringWithFormat(
+          "failed to read virtual function entry 0x%16.16" PRIx64,
+          vtable_entry_addr);
+      return false;
+    }
+
+    Address resolved_vfunc_ptr_address;
+    target_sp->ResolveLoadAddress(vfunc_ptr, resolved_vfunc_ptr_address);
+    if (!resolved_vfunc_ptr_address.IsValid()) {
+      m_error.SetErrorStringWithFormat(
+          "unable to resolve func ptr address: 0x%16.16" PRIx64, vfunc_ptr);
+      return false;
+    }
----------------
jimingham wrote:

One of the reasons that people have requested the ability to see vtables in the past has been to detect corruption in the vtable.  If the table is corrupt, it might very well point to bogus memory.  So it might be better to have this still be valid, but have the summary value report that this looks like a bogus entry?  Then when I dump the value object I'll be able to see some valid entries and some that say "Danger Will Robinson" which might be easier to work with than errors?

https://github.com/llvm/llvm-project/pull/67599


More information about the lldb-commits mailing list