Author: Adrian Prantl Date: 2024-11-20T08:49:07-08:00 New Revision: e660e6503ba14684bd460b7baaf3da7336d0f46e
URL: https://github.com/llvm/llvm-project/commit/e660e6503ba14684bd460b7baaf3da7336d0f46e DIFF: https://github.com/llvm/llvm-project/commit/e660e6503ba14684bd460b7baaf3da7336d0f46e.diff LOG: [lldb] Add an API to derive language-specific runtime information (#116904) This is motivated by exposing some Swift language-specific flags through the API, in the example here it is used to communicate the Objective-C runtime version. This could also be a meaningful extension point to get information about "embedded: languages, such as extracting the C++ version in an Objective-C++ frame or something along those lines. Added: lldb/test/API/lang/objc/languageinfo/Makefile lldb/test/API/lang/objc/languageinfo/TestObjCLanguageInfo.py lldb/test/API/lang/objc/languageinfo/main.m Modified: lldb/include/lldb/API/SBFrame.h lldb/include/lldb/API/SBStructuredData.h lldb/include/lldb/Target/LanguageRuntime.h lldb/include/lldb/Target/StackFrame.h lldb/source/API/SBFrame.cpp lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h lldb/source/Target/LanguageRuntime.cpp lldb/source/Target/StackFrame.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index e0d15c3ecc5b1c..e1ff217767cb98 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -122,6 +122,11 @@ class LLDB_API SBFrame { lldb::SBValue EvaluateExpression(const char *expr, const SBExpressionOptions &options); + /// Language plugins can use this API to report language-specific + /// runtime information about this compile unit, such as additional + /// language version details or feature flags. + SBStructuredData GetLanguageInfo(); + /// Gets the lexical block that defines the stack frame. Another way to think /// of this is it will return the block that contains all of the variables /// for a stack frame. Inlined functions are represented as SBBlock objects diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h index ccdd12cab94b2f..c0d214a7374c65 100644 --- a/lldb/include/lldb/API/SBStructuredData.h +++ b/lldb/include/lldb/API/SBStructuredData.h @@ -114,6 +114,7 @@ class SBStructuredData { friend class SBCommandReturnObject; friend class SBLaunchInfo; friend class SBDebugger; + friend class SBFrame; friend class SBTarget; friend class SBProcess; friend class SBThread; diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index 21bdc61b8cbcf0..4f4d426eaa1dab 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -241,6 +241,11 @@ class LanguageRuntime : public Runtime, public PluginInterface { lldb_private::RegisterContext *regctx, bool &behaves_like_zeroth_frame); + /// Language runtime plugins can use this API to report + /// language-specific runtime information about this compile unit, + /// such as additional language version details or feature flags. + virtual StructuredData::ObjectSP GetLanguageInfo(SymbolContext sc); + protected: // The static GetRuntimeUnwindPlan method above is only implemented in the // base class; subclasses may override this protected member if they can diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index e85430791b7d93..5e82657706339c 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -22,6 +22,7 @@ #include "lldb/Utility/Scalar.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/Utility/UserID.h" #include "lldb/ValueObject/ValueObjectList.h" @@ -408,6 +409,11 @@ class StackFrame : public ExecutionContextScope, /// system implementation details this way. bool IsHidden(); + /// Language plugins can use this API to report language-specific + /// runtime information about this compile unit, such as additional + /// language version details or feature flags. + StructuredData::ObjectSP GetLanguageInfo(); + /// Get the frame's demangled name. /// /// /// \return diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index e2c691fa9bfd45..d17bb5cc146086 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -47,6 +47,7 @@ #include "lldb/API/SBExpressionOptions.h" #include "lldb/API/SBFormat.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBSymbolContext.h" #include "lldb/API/SBThread.h" #include "lldb/API/SBValue.h" @@ -1154,6 +1155,21 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, return expr_result; } +SBStructuredData SBFrame::GetLanguageInfo() { + LLDB_INSTRUMENT_VA(this); + + SBStructuredData sb_data; + std::unique_lock<std::recursive_mutex> lock; + ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (!frame) + return sb_data; + + StructuredData::ObjectSP data(frame->GetLanguageInfo()); + sb_data.m_impl_up->SetObjectSP(data); + return sb_data; +} + bool SBFrame::IsInlined() { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 4c794b81809c6e..7298ab0e7336bf 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -3398,6 +3398,13 @@ std::optional<uint64_t> AppleObjCRuntimeV2::GetSharedCacheImageHeaderVersion() { return std::nullopt; } +StructuredData::ObjectSP AppleObjCRuntimeV2::GetLanguageInfo(SymbolContext sc) { + auto dict_up = std::make_unique<StructuredData::Dictionary>(); + dict_up->AddItem("Objective-C runtime version", + std::make_unique<StructuredData::UnsignedInteger>(2)); + return dict_up; +} + #pragma mark Frame recognizers class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index c9d0b3a907b54b..7117b778a1c0e9 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -106,6 +106,8 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime { std::optional<uint64_t> GetSharedCacheImageHeaderVersion(); + StructuredData::ObjectSP GetLanguageInfo(SymbolContext sc) override; + protected: lldb::BreakpointResolverSP CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp, diff --git a/lldb/source/Target/LanguageRuntime.cpp b/lldb/source/Target/LanguageRuntime.cpp index ce3646c8b05c88..89bad75995ff14 100644 --- a/lldb/source/Target/LanguageRuntime.cpp +++ b/lldb/source/Target/LanguageRuntime.cpp @@ -277,6 +277,10 @@ LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx, return UnwindPlanSP(); } +StructuredData::ObjectSP LanguageRuntime::GetLanguageInfo(SymbolContext sc) { + return {}; +} + void LanguageRuntime::InitializeCommands(CommandObject *parent) { if (!parent) return; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index ca02de15295cac..e7d3b883bdec56 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -22,6 +22,7 @@ #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrameRecognizer.h" @@ -1230,6 +1231,18 @@ bool StackFrame::IsHidden() { return false; } +StructuredData::ObjectSP StackFrame::GetLanguageInfo() { + auto process_sp = CalculateProcess(); + SourceLanguage language = GetLanguage(); + if (!language) + return {}; + if (auto runtime_sp = + process_sp->GetLanguageRuntime(language.AsLanguageType())) + return runtime_sp->GetLanguageInfo( + GetSymbolContext(eSymbolContextFunction)); + return {}; +} + const char *StackFrame::GetFunctionName() { const char *name = nullptr; SymbolContext sc = GetSymbolContext( diff --git a/lldb/test/API/lang/objc/languageinfo/Makefile b/lldb/test/API/lang/objc/languageinfo/Makefile new file mode 100644 index 00000000000000..11fce1e5c52196 --- /dev/null +++ b/lldb/test/API/lang/objc/languageinfo/Makefile @@ -0,0 +1,4 @@ +OBJC_SOURCES := main.m +LD_EXTRAS := -lobjc + +include Makefile.rules diff --git a/lldb/test/API/lang/objc/languageinfo/TestObjCLanguageInfo.py b/lldb/test/API/lang/objc/languageinfo/TestObjCLanguageInfo.py new file mode 100644 index 00000000000000..18e04c9e8bac50 --- /dev/null +++ b/lldb/test/API/lang/objc/languageinfo/TestObjCLanguageInfo.py @@ -0,0 +1,16 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ObjCiVarIMPTestCase(TestBase): + @skipUnlessDarwin + @no_debug_info_test + def test_imp_ivar_type(self): + self.build() + target, process, thread, bkpt = lldbutil.run_to_name_breakpoint(self, "main") + frame = thread.GetFrameAtIndex(0) + lang_info = frame.GetLanguageInfo() + version = lang_info.GetValueForKey("Objective-C runtime version") + self.assertEqual(version.GetIntegerValue(), 2) diff --git a/lldb/test/API/lang/objc/languageinfo/main.m b/lldb/test/API/lang/objc/languageinfo/main.m new file mode 100644 index 00000000000000..06e216a2fde641 --- /dev/null +++ b/lldb/test/API/lang/objc/languageinfo/main.m @@ -0,0 +1 @@ +int main(int argc, char const *argv[]) { return 0; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits