Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lldb] Make ValueObjectDynamicValue::UpdateValue() point to a host b… #125143

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

augusto2112
Copy link
Contributor

…uffer

ValueObjectDynamicValue::UpdateValue() assumes that the dynamic type found by GetDynamicTypeAndAddress() would return an address in the inferior. This commit makes it so it can deal with being passed a host address instead.

This is needed downstream by the Swift fork.

rdar://143357274

…ffer

ValueObjectDynamicValue::UpdateValue() assumes that the dynamic type
found by GetDynamicTypeAndAddress() would return an address in the
inferior.  This commit makes it so it can deal with being passed a
host address instead.

This is needed downstream by the Swift fork.

rdar://143357274
@llvmbot
Copy link
Member

llvmbot commented Jan 31, 2025

@llvm/pr-subscribers-lldb

Author: Augusto Noronha (augusto2112)

Changes

…uffer

ValueObjectDynamicValue::UpdateValue() assumes that the dynamic type found by GetDynamicTypeAndAddress() would return an address in the inferior. This commit makes it so it can deal with being passed a host address instead.

This is needed downstream by the Swift fork.

rdar://143357274


Full diff: https://github.com/llvm/llvm-project/pull/125143.diff

2 Files Affected:

  • (modified) lldb/include/lldb/Target/LanguageRuntime.h (+3-1)
  • (modified) lldb/source/ValueObject/ValueObjectDynamicValue.cpp (+18-6)
diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h
index 4a0214b04e235e..08db8a17a67e69 100644
--- a/lldb/include/lldb/Target/LanguageRuntime.h
+++ b/lldb/include/lldb/Target/LanguageRuntime.h
@@ -105,7 +105,9 @@ class LanguageRuntime : public Runtime, public PluginInterface {
         "language doesn't support getting vtable information");
   }
 
-  // this call should return true if it could set the name and/or the type
+  // This call should return true if it could set the name and/or the type.
+  // address can be either a legitimate address on the inferior, or an address
+  // in lldb, if value_type == HostAddress.
   virtual bool GetDynamicTypeAndAddress(ValueObject &in_value,
                                         lldb::DynamicValueType use_dynamic,
                                         TypeAndOrName &class_type_or_name,
diff --git a/lldb/source/ValueObject/ValueObjectDynamicValue.cpp b/lldb/source/ValueObject/ValueObjectDynamicValue.cpp
index 588c644bbfd07b..10a5a9d0b76919 100644
--- a/lldb/source/ValueObject/ValueObjectDynamicValue.cpp
+++ b/lldb/source/ValueObject/ValueObjectDynamicValue.cpp
@@ -239,11 +239,19 @@ bool ValueObjectDynamicValue::UpdateValue() {
     if (m_address.IsValid())
       SetValueDidChange(true);
 
-    // We've moved, so we should be fine...
-    m_address = dynamic_address;
-    lldb::TargetSP target_sp(GetTargetSP());
-    lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
-    m_value.GetScalar() = load_address;
+    // If we found a host address, point to the buffer in host memory.
+    // Later on this function will copy the buffer over.
+    if (value_type == Value::ValueType::HostAddress) {
+      m_value.GetScalar() = dynamic_address.GetOffset();
+      m_address = LLDB_INVALID_ADDRESS;
+    } else {
+      // Otherwise we have a legitimate address on the target. Point to the load
+      // address.
+      m_address = dynamic_address;
+      lldb::TargetSP target_sp(GetTargetSP());
+      lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
+      m_value.GetScalar() = load_address;
+    }
   }
 
   if (runtime)
@@ -258,7 +266,11 @@ bool ValueObjectDynamicValue::UpdateValue() {
     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
               static_cast<void *>(this), GetTypeName().GetCString());
 
-  if (m_address.IsValid() && m_dynamic_type_info) {
+  // m_address could be invalid but we could still have a local buffer
+  // containing the dynamic value.
+  if ((m_address.IsValid() ||
+       m_value.GetValueType() == Value::ValueType::HostAddress) &&
+      m_dynamic_type_info) {
     // The variable value is in the Scalar value inside the m_value. We can
     // point our m_data right to it.
     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());

@jimingham
Copy link
Collaborator

I worry a bit about the fact that in the host case, GetValueAsData is going to end up calling:

  memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size);

where address is the host data buffer and byte_size is the size of the new dynamic type. But in the case where the Value has data in the m_data_buffer, address points to a buffer. The code makes sure that the destination buffer (pointed to by dst) is big enough to fit byte_size, but I don't see the guarantee that the original contents are not smaller than the new dynamic type byte size.
If we get that wrong, then we'll crash here or worse sample lldb internal memory and present that to the user as a value.
How do you know that can't happen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants