[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.
This commit is contained in:
Adrian Prantl
2024-11-20 08:49:07 -08:00
committed by GitHub
parent fb4ecada81
commit e660e6503b
12 changed files with 80 additions and 0 deletions

View File

@@ -122,6 +122,11 @@ public:
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

View File

@@ -114,6 +114,7 @@ protected:
friend class SBCommandReturnObject;
friend class SBLaunchInfo;
friend class SBDebugger;
friend class SBFrame;
friend class SBTarget;
friend class SBProcess;
friend class SBThread;

View File

@@ -241,6 +241,11 @@ public:
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

View File

@@ -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 @@ public:
/// 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

View File

@@ -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);

View File

@@ -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 {

View File

@@ -106,6 +106,8 @@ public:
std::optional<uint64_t> GetSharedCacheImageHeaderVersion();
StructuredData::ObjectSP GetLanguageInfo(SymbolContext sc) override;
protected:
lldb::BreakpointResolverSP
CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,

View File

@@ -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;

View File

@@ -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(

View File

@@ -0,0 +1,4 @@
OBJC_SOURCES := main.m
LD_EXTRAS := -lobjc
include Makefile.rules

View File

@@ -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)

View File

@@ -0,0 +1 @@
int main(int argc, char const *argv[]) { return 0; }