llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: David Mentler (mentlerd)
<details>
<summary>Changes</summary>
Allow manipulating the scripted synthetic children frontend selection process
for individual `SBValue` instances.
The motivating use-case is supporting custom data structures, type erasure
systems, and facilitating debugging handle based C APIs. Below is an example of
such a use-case of an anonymized 3rd party C library:
```C
using ErrorCode = int;
using Handle = int;
using FooHandle = Handle;
using BarHandle = Handle;
struct ArrayOfHandles {
int size;
Handle* data;
};
struct AllHandles {
ArrayOfHandles foos;
ArrayOfHandles bars;
};
ErrorCode GetAllHandles(AllHandles* into);
```
The current LLDB feature-set allows attaching a synthetic children provider to
`AllHandles`, but the scripted frontend has no chance to select an appropriate
alternative frontend implementation class for `foos` and `bars` based on type
information it is aware of.
> [!NOTE]
> I am aware the state of this PR doesn't reach contributing standards yet
due to lacking tests! I am raising it to ask for feedback on the API
implications and implementation direction which I largely borrowed from
`SBProcess`'s scripted implementation.
---
Full diff: https://github.com/llvm/llvm-project/pull/209056.diff
7 Files Affected:
- (modified) lldb/include/lldb/API/SBValue.h (+16)
- (modified) lldb/include/lldb/DataFormatters/TypeSynthetic.h (+4)
- (modified) lldb/include/lldb/ValueObject/ValueObject.h (+6)
- (modified) lldb/include/lldb/ValueObject/ValueObjectSynthetic.h (+2)
- (modified) lldb/source/API/SBValue.cpp (+25)
- (modified) lldb/source/DataFormatters/TypeSynthetic.cpp (+10)
- (modified) lldb/source/ValueObject/ValueObjectSynthetic.cpp (+5)
``````````diff
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index 16a9f0837454c..9d746f74c9b09 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -132,6 +132,22 @@ class LLDB_API SBValue {
lldb::SBTypeSynthetic GetTypeSynthetic();
+ /// Override the `SBTypeSynthetic` chosen by the DataFormatter system for
this
+ /// instance.
+ ///
+ /// This can be used to great effect in scripted synthetic children providers
+ /// where a child's underlying type can only be figured out by inspecting the
+ /// containing object's other members.
+ void SetTypeSynthetic(lldb::SBTypeSynthetic &synthetic);
+
+ /// This function's primary use is to ease inspecting the internal state of
+ /// scripted synthetic children providers for debugging purposes.
+ ///
+ /// An other alternative usecase is for parent synthetic children providers
to
+ /// imbue their children's synthetic children providers with additional
+ /// context after creation.
+ lldb::SBScriptObject GetTypeSyntheticImplementation();
+
lldb::SBValue GetChildAtIndex(uint32_t idx);
lldb::SBValue CreateChildAtOffset(const char *name, uint32_t offset,
diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h
b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
index ae44d7e8f96eb..9c17adbde7465 100644
--- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
@@ -83,6 +83,8 @@ class SyntheticChildrenFrontEnd {
// display purposes
virtual ConstString GetSyntheticTypeName() { return ConstString(); }
+ virtual void *GetImplementation() { return nullptr; }
+
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
typedef std::unique_ptr<SyntheticChildrenFrontEnd> UniquePointer;
@@ -469,6 +471,8 @@ class ScriptedSyntheticChildren : public SyntheticChildren {
ConstString GetSyntheticTypeName() override;
+ void *GetImplementation() override;
+
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
private:
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h
b/lldb/include/lldb/ValueObject/ValueObject.h
index 6e4d93b815761..583dd3faac482 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -917,6 +917,10 @@ class ValueObject {
return m_synthetic_children_sp;
}
+ virtual SyntheticChildrenFrontEnd *GetSyntheticChildrenFrontEnd() {
+ return nullptr;
+ }
+
// Use GetParent for display purposes, but if you want to tell the parent to
// update itself then use m_parent. The ValueObjectDynamicValue's parent is
// not the correct parent for displaying, they are really siblings, so for
@@ -982,6 +986,8 @@ class ValueObject {
lldb::ValueObjectSP CheckValueObjectOwnership(ValueObject *child);
+ virtual void *GetImplementation() { return nullptr; }
+
protected:
typedef ClusterManager<ValueObject> ValueObjectManager;
diff --git a/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
b/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
index 60803697ee020..32475aa02a5e8 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
@@ -128,6 +128,8 @@ class ValueObjectSynthetic : public ValueObject {
GetExpressionPathFormat epformat =
eGetExpressionPathFormatDereferencePointers) override;
+ SyntheticChildrenFrontEnd *GetSyntheticChildrenFrontEnd() override;
+
protected:
bool UpdateValue() override;
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index de660577b3a9b..c2509e89633df 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -393,6 +393,31 @@ lldb::SBTypeSynthetic SBValue::GetTypeSynthetic() {
return synthetic;
}
+void SBValue::SetTypeSynthetic(lldb::SBTypeSynthetic &synthetic) {
+ LLDB_INSTRUMENT_VA(this);
+
+ ValueLocker locker;
+ lldb::ValueObjectSP value_sp(GetSP(locker));
+ lldb::ScriptedSyntheticChildrenSP synthetic_sp(synthetic.GetSP());
+ if (value_sp && synthetic_sp) {
+ value_sp->SetSyntheticChildren(synthetic_sp);
+ }
+}
+
+lldb::SBScriptObject SBValue::GetTypeSyntheticImplementation() {
+ LLDB_INSTRUMENT_VA(this);
+
+ ValueLocker locker;
+ lldb::ValueObjectSP value_sp(GetSP(locker));
+
+ auto frontend = value_sp->GetSyntheticChildrenFrontEnd();
+ if (!frontend) {
+ return lldb::SBScriptObject(nullptr, eScriptLanguageDefault);
+ }
+ return lldb::SBScriptObject(frontend->GetImplementation(),
+ eScriptLanguageDefault);
+}
+
lldb::SBValue SBValue::CreateChildAtOffset(const char *name, uint32_t offset,
SBType type) {
LLDB_INSTRUMENT_VA(this, name, offset, type);
diff --git a/lldb/source/DataFormatters/TypeSynthetic.cpp
b/lldb/source/DataFormatters/TypeSynthetic.cpp
index 76eb61b92e446..53852fc291980 100644
--- a/lldb/source/DataFormatters/TypeSynthetic.cpp
+++ b/lldb/source/DataFormatters/TypeSynthetic.cpp
@@ -247,6 +247,16 @@ ConstString
ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() {
return m_interpreter->GetSyntheticTypeName(m_wrapper_sp);
}
+void *ScriptedSyntheticChildren::FrontEnd::GetImplementation() {
+ if (!m_wrapper_sp || m_interpreter == nullptr)
+ return nullptr;
+
+ if (m_wrapper_sp->GetType() != eStructuredDataTypeGeneric)
+ return nullptr;
+
+ return m_wrapper_sp->GetAsGeneric()->GetValue();
+}
+
std::string ScriptedSyntheticChildren::GetDescription() {
StreamString sstr;
sstr.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)",
diff --git a/lldb/source/ValueObject/ValueObjectSynthetic.cpp
b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
index 1485dc1827480..74a3cfa4cc0f5 100644
--- a/lldb/source/ValueObject/ValueObjectSynthetic.cpp
+++ b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
@@ -484,3 +484,8 @@ void ValueObjectSynthetic::GetExpressionPath(Stream &stream,
}
return ValueObject::GetExpressionPath(stream, epformat);
}
+
+SyntheticChildrenFrontEnd *
+ValueObjectSynthetic::GetSyntheticChildrenFrontEnd() {
+ return m_synth_filter_up.get();
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/209056
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits