aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Target
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target')
-rw-r--r--lldb/source/Target/BorrowedStackFrame.cpp187
-rw-r--r--lldb/source/Target/CMakeLists.txt1
-rw-r--r--lldb/source/Target/ExecutionContext.cpp17
-rw-r--r--lldb/source/Target/Language.cpp42
-rw-r--r--lldb/source/Target/Process.cpp22
-rw-r--r--lldb/source/Target/StackFrame.cpp14
-rw-r--r--lldb/source/Target/StackFrameList.cpp49
-rw-r--r--lldb/source/Target/SyntheticFrameProvider.cpp25
-rw-r--r--lldb/source/Target/Target.cpp98
-rw-r--r--lldb/source/Target/TargetList.cpp5
-rw-r--r--lldb/source/Target/Thread.cpp72
-rw-r--r--lldb/source/Target/ThreadPlanStepOut.cpp11
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp4
-rw-r--r--lldb/source/Target/ThreadSpec.cpp4
-rw-r--r--lldb/source/Target/UnixSignals.cpp7
15 files changed, 520 insertions, 38 deletions
diff --git a/lldb/source/Target/BorrowedStackFrame.cpp b/lldb/source/Target/BorrowedStackFrame.cpp
new file mode 100644
index 0000000..5afadf2
--- /dev/null
+++ b/lldb/source/Target/BorrowedStackFrame.cpp
@@ -0,0 +1,187 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/Target/BorrowedStackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+char BorrowedStackFrame::ID;
+
+BorrowedStackFrame::BorrowedStackFrame(
+ StackFrameSP borrowed_frame_sp, uint32_t new_frame_index,
+ std::optional<uint32_t> new_concrete_frame_index)
+ : StackFrame(
+ borrowed_frame_sp->GetThread(), new_frame_index,
+ borrowed_frame_sp->GetConcreteFrameIndex(),
+ borrowed_frame_sp->GetRegisterContextSP(),
+ borrowed_frame_sp->GetStackID().GetPC(),
+ borrowed_frame_sp->GetStackID().GetCallFrameAddressWithoutMetadata(),
+ borrowed_frame_sp->m_behaves_like_zeroth_frame,
+ &borrowed_frame_sp->GetSymbolContext(eSymbolContextEverything)),
+ m_borrowed_frame_sp(borrowed_frame_sp),
+ m_new_frame_index(new_frame_index) {
+ if (new_concrete_frame_index)
+ m_new_concrete_frame_index = *new_concrete_frame_index;
+ else
+ m_new_concrete_frame_index =
+ IsInlined() ? LLDB_INVALID_FRAME_ID : new_frame_index;
+}
+
+uint32_t BorrowedStackFrame::GetFrameIndex() const { return m_new_frame_index; }
+
+void BorrowedStackFrame::SetFrameIndex(uint32_t index) {
+ m_new_frame_index = index;
+}
+
+uint32_t BorrowedStackFrame::GetConcreteFrameIndex() {
+ // FIXME: We need to find where the concrete frame into which this frame was
+ // inlined landed in the new stack frame list as that is the correct concrete
+ // frame index in this
+ // stack frame.
+ return m_new_concrete_frame_index;
+}
+
+StackID &BorrowedStackFrame::GetStackID() {
+ return m_borrowed_frame_sp->GetStackID();
+}
+
+const Address &BorrowedStackFrame::GetFrameCodeAddress() {
+ return m_borrowed_frame_sp->GetFrameCodeAddress();
+}
+
+Address BorrowedStackFrame::GetFrameCodeAddressForSymbolication() {
+ return m_borrowed_frame_sp->GetFrameCodeAddressForSymbolication();
+}
+
+bool BorrowedStackFrame::ChangePC(addr_t pc) {
+ return m_borrowed_frame_sp->ChangePC(pc);
+}
+
+const SymbolContext &
+BorrowedStackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
+ return m_borrowed_frame_sp->GetSymbolContext(resolve_scope);
+}
+
+llvm::Error BorrowedStackFrame::GetFrameBaseValue(Scalar &value) {
+ return m_borrowed_frame_sp->GetFrameBaseValue(value);
+}
+
+DWARFExpressionList *
+BorrowedStackFrame::GetFrameBaseExpression(Status *error_ptr) {
+ return m_borrowed_frame_sp->GetFrameBaseExpression(error_ptr);
+}
+
+Block *BorrowedStackFrame::GetFrameBlock() {
+ return m_borrowed_frame_sp->GetFrameBlock();
+}
+
+RegisterContextSP BorrowedStackFrame::GetRegisterContext() {
+ return m_borrowed_frame_sp->GetRegisterContext();
+}
+
+VariableList *BorrowedStackFrame::GetVariableList(bool get_file_globals,
+ Status *error_ptr) {
+ return m_borrowed_frame_sp->GetVariableList(get_file_globals, error_ptr);
+}
+
+VariableListSP
+BorrowedStackFrame::GetInScopeVariableList(bool get_file_globals,
+ bool must_have_valid_location) {
+ return m_borrowed_frame_sp->GetInScopeVariableList(get_file_globals,
+ must_have_valid_location);
+}
+
+ValueObjectSP BorrowedStackFrame::GetValueForVariableExpressionPath(
+ llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
+ VariableSP &var_sp, Status &error) {
+ return m_borrowed_frame_sp->GetValueForVariableExpressionPath(
+ var_expr, use_dynamic, options, var_sp, error);
+}
+
+bool BorrowedStackFrame::HasDebugInformation() {
+ return m_borrowed_frame_sp->HasDebugInformation();
+}
+
+const char *BorrowedStackFrame::Disassemble() {
+ return m_borrowed_frame_sp->Disassemble();
+}
+
+ValueObjectSP BorrowedStackFrame::GetValueObjectForFrameVariable(
+ const VariableSP &variable_sp, DynamicValueType use_dynamic) {
+ return m_borrowed_frame_sp->GetValueObjectForFrameVariable(variable_sp,
+ use_dynamic);
+}
+
+bool BorrowedStackFrame::IsInlined() {
+ return m_borrowed_frame_sp->IsInlined();
+}
+
+bool BorrowedStackFrame::IsSynthetic() const {
+ return m_borrowed_frame_sp->IsSynthetic();
+}
+
+bool BorrowedStackFrame::IsHistorical() const {
+ return m_borrowed_frame_sp->IsHistorical();
+}
+
+bool BorrowedStackFrame::IsArtificial() const {
+ return m_borrowed_frame_sp->IsArtificial();
+}
+
+bool BorrowedStackFrame::IsHidden() { return m_borrowed_frame_sp->IsHidden(); }
+
+const char *BorrowedStackFrame::GetFunctionName() {
+ return m_borrowed_frame_sp->GetFunctionName();
+}
+
+const char *BorrowedStackFrame::GetDisplayFunctionName() {
+ return m_borrowed_frame_sp->GetDisplayFunctionName();
+}
+
+ValueObjectSP BorrowedStackFrame::FindVariable(ConstString name) {
+ return m_borrowed_frame_sp->FindVariable(name);
+}
+
+SourceLanguage BorrowedStackFrame::GetLanguage() {
+ return m_borrowed_frame_sp->GetLanguage();
+}
+
+SourceLanguage BorrowedStackFrame::GuessLanguage() {
+ return m_borrowed_frame_sp->GuessLanguage();
+}
+
+ValueObjectSP BorrowedStackFrame::GuessValueForAddress(addr_t addr) {
+ return m_borrowed_frame_sp->GuessValueForAddress(addr);
+}
+
+ValueObjectSP
+BorrowedStackFrame::GuessValueForRegisterAndOffset(ConstString reg,
+ int64_t offset) {
+ return m_borrowed_frame_sp->GuessValueForRegisterAndOffset(reg, offset);
+}
+
+StructuredData::ObjectSP BorrowedStackFrame::GetLanguageSpecificData() {
+ return m_borrowed_frame_sp->GetLanguageSpecificData();
+}
+
+RecognizedStackFrameSP BorrowedStackFrame::GetRecognizedFrame() {
+ return m_borrowed_frame_sp->GetRecognizedFrame();
+}
+
+StackFrameSP BorrowedStackFrame::GetBorrowedFrame() const {
+ return m_borrowed_frame_sp;
+}
+
+bool BorrowedStackFrame::isA(const void *ClassID) const {
+ return ClassID == &ID || StackFrame::isA(ClassID);
+}
+
+bool BorrowedStackFrame::classof(const StackFrame *obj) {
+ return obj->isA(&ID);
+}
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index cff5904..df2ee03 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -41,6 +41,7 @@ add_lldb_library(lldbTarget
SyntheticFrameProvider.cpp
SectionLoadHistory.cpp
SectionLoadList.cpp
+ BorrowedStackFrame.cpp
StackFrame.cpp
StackFrameList.cpp
StackFrameRecognizer.cpp
diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp
index a795913..b16ff26 100644
--- a/lldb/source/Target/ExecutionContext.cpp
+++ b/lldb/source/Target/ExecutionContext.cpp
@@ -466,10 +466,13 @@ operator=(const ExecutionContext &exe_ctx) {
else
m_tid = LLDB_INVALID_THREAD_ID;
lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
- if (frame_sp)
+ if (frame_sp) {
m_stack_id = frame_sp->GetStackID();
- else
+ m_frame_list_wp = frame_sp->GetContainingStackFrameList();
+ } else {
m_stack_id.Clear();
+ m_frame_list_wp.reset();
+ }
return *this;
}
@@ -511,6 +514,7 @@ void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {
void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
if (frame_sp) {
m_stack_id = frame_sp->GetStackID();
+ m_frame_list_wp = frame_sp->GetContainingStackFrameList();
SetThreadSP(frame_sp->GetThread());
} else {
ClearFrame();
@@ -638,6 +642,15 @@ lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {
lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {
if (m_stack_id.IsValid()) {
+ // Try the remembered frame list first to avoid circular dependencies
+ // during frame provider initialization.
+ if (auto frame_list_sp = m_frame_list_wp.lock()) {
+ if (auto frame_sp = frame_list_sp->GetFrameWithStackID(m_stack_id))
+ return frame_sp;
+ }
+
+ // Fallback: ask the thread, which might re-trigger the frame provider
+ // initialization.
lldb::ThreadSP thread_sp(GetThreadSP());
if (thread_sp)
return thread_sp->GetFrameWithStackID(m_stack_id);
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 8268d4a..c8b09c3 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -159,6 +159,48 @@ void Language::ForEach(
}
}
+llvm::Expected<LanguageType>
+Language::GetExceptionLanguageForLanguage(llvm::StringRef lang_name) {
+ LanguageType language = Language::GetLanguageTypeFromString(lang_name);
+ LanguageType exception_language = eLanguageTypeUnknown;
+
+ llvm::StringRef error_context;
+ switch (language) {
+ case eLanguageTypeC89:
+ case eLanguageTypeC:
+ case eLanguageTypeC99:
+ case eLanguageTypeC11:
+ exception_language = eLanguageTypeC;
+ break;
+ case eLanguageTypeC_plus_plus:
+ case eLanguageTypeC_plus_plus_03:
+ case eLanguageTypeC_plus_plus_11:
+ case eLanguageTypeC_plus_plus_14:
+ exception_language = eLanguageTypeC_plus_plus;
+ break;
+ case eLanguageTypeObjC_plus_plus:
+ error_context =
+ "Set exception breakpoints separately for c++ and objective-c";
+ break;
+ case eLanguageTypeUnknown:
+ error_context = "Unknown language type for exception breakpoint";
+ break;
+ default:
+ if (Language *languagePlugin = Language::FindPlugin(language)) {
+ if (languagePlugin->SupportsExceptionBreakpointsOnThrow() ||
+ languagePlugin->SupportsExceptionBreakpointsOnCatch()) {
+ exception_language = language;
+ break;
+ }
+ }
+ error_context = "Unsupported language type for exception breakpoint";
+ }
+ if (!error_context.empty())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ error_context);
+ return exception_language;
+}
+
bool Language::IsTopLevelFunction(Function &function) { return false; }
lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 42ce198..9c8e8fa7 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2452,8 +2452,10 @@ size_t Process::ReadScalarIntegerFromMemory(addr_t addr, uint32_t byte_size,
scalar = data.GetMaxU32(&offset, byte_size);
else
scalar = data.GetMaxU64(&offset, byte_size);
- if (is_signed)
+ if (is_signed) {
+ scalar.MakeSigned();
scalar.SignExtend(byte_size * 8);
+ }
return bytes_read;
}
} else {
@@ -3256,6 +3258,7 @@ Status Process::ConnectRemote(llvm::StringRef remote_url) {
if (state == eStateStopped || state == eStateCrashed) {
// If we attached and actually have a process on the other end, then
// this ended up being the equivalent of an attach.
+ SetShouldDetach(true);
CompleteAttach();
// This delays passing the stopped event to listeners till
@@ -6544,7 +6547,7 @@ Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len,
// Create a CoreFileMemoryRange from a MemoryRegionInfo
static CoreFileMemoryRange
-CreateCoreFileMemoryRange(const MemoryRegionInfo &region) {
+CreateCoreFileMemoryRange(const lldb_private::MemoryRegionInfo &region) {
const addr_t addr = region.GetRange().GetRangeBase();
llvm::AddressRange range(addr, addr + region.GetRange().GetByteSize());
return {range, region.GetLLDBPermissions()};
@@ -6553,7 +6556,7 @@ CreateCoreFileMemoryRange(const MemoryRegionInfo &region) {
// Add dirty pages to the core file ranges and return true if dirty pages
// were added. Return false if the dirty page information is not valid or in
// the region.
-static bool AddDirtyPages(const MemoryRegionInfo &region,
+static bool AddDirtyPages(const lldb_private::MemoryRegionInfo &region,
CoreFileMemoryRanges &ranges) {
const auto &dirty_page_list = region.GetDirtyPageList();
if (!dirty_page_list)
@@ -6592,8 +6595,8 @@ static bool AddDirtyPages(const MemoryRegionInfo &region,
// given region. If the region has dirty page information, only dirty pages
// will be added to \a ranges, else the entire range will be added to \a
// ranges.
-static void AddRegion(const MemoryRegionInfo &region, bool try_dirty_pages,
- CoreFileMemoryRanges &ranges) {
+static void AddRegion(const lldb_private::MemoryRegionInfo &region,
+ bool try_dirty_pages, CoreFileMemoryRanges &ranges) {
// Don't add empty ranges.
if (region.GetRange().GetByteSize() == 0)
return;
@@ -6616,7 +6619,7 @@ static void SaveDynamicLoaderSections(Process &process,
if (!dyld)
return;
- std::vector<MemoryRegionInfo> dynamic_loader_mem_regions;
+ std::vector<lldb_private::MemoryRegionInfo> dynamic_loader_mem_regions;
std::function<bool(const lldb_private::Thread &)> save_thread_predicate =
[&](const lldb_private::Thread &t) -> bool {
return options.ShouldThreadBeSaved(t.GetID());
@@ -6741,10 +6744,11 @@ static void GetCoreFileSaveRangesStackOnly(Process &process,
// TODO: We should refactor CoreFileMemoryRanges to use the lldb range type, and
// then add an intersect method on it, or MemoryRegionInfo.
-static MemoryRegionInfo Intersect(const MemoryRegionInfo &lhs,
- const MemoryRegionInfo::RangeType &rhs) {
+static lldb_private::MemoryRegionInfo
+Intersect(const lldb_private::MemoryRegionInfo &lhs,
+ const lldb_private::MemoryRegionInfo::RangeType &rhs) {
- MemoryRegionInfo region_info;
+ lldb_private::MemoryRegionInfo region_info;
region_info.SetLLDBPermissions(lhs.GetLLDBPermissions());
region_info.GetRange() = lhs.GetRange().Intersect(rhs);
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 95b5154..3bbb851 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -45,6 +45,9 @@
using namespace lldb;
using namespace lldb_private;
+// LLVM RTTI support.
+char StackFrame::ID;
+
// The first bits in the flags are reserved for the SymbolContext::Scope bits
// so we know if we have tried to look up information in our internal symbol
// context (m_sc) already.
@@ -328,6 +331,13 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
// following the function call instruction...
Address lookup_addr(GetFrameCodeAddressForSymbolication());
+ // For PC-less frames (e.g., scripted frames), skip PC-based symbol
+ // resolution and preserve any already-populated SymbolContext fields.
+ if (!lookup_addr.IsValid()) {
+ m_flags.Set(resolve_scope | resolved);
+ return m_sc;
+ }
+
if (m_sc.module_sp) {
// We have something in our stack frame symbol context, lets check if we
// haven't already tried to lookup one of those things. If we haven't
@@ -2054,10 +2064,10 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
disasm_display = debugger.GetStopDisassemblyDisplay();
GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
- if (m_sc.comp_unit && m_sc.line_entry.IsValid()) {
+ if (m_sc.comp_unit || m_sc.line_entry.IsValid()) {
have_debuginfo = true;
if (source_lines_before > 0 || source_lines_after > 0) {
- SupportFileSP source_file_sp = m_sc.line_entry.file_sp;
+ SupportFileNSP source_file_sp = m_sc.line_entry.file_sp;
uint32_t start_line = m_sc.line_entry.line;
if (!start_line && m_sc.function) {
m_sc.function->GetStartLineSourceInfo(source_file_sp, start_line);
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index ccf874f..896a760 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -20,6 +20,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Unwind.h"
@@ -55,6 +56,49 @@ StackFrameList::~StackFrameList() {
Clear();
}
+SyntheticStackFrameList::SyntheticStackFrameList(
+ Thread &thread, lldb::StackFrameListSP input_frames,
+ const lldb::StackFrameListSP &prev_frames_sp, bool show_inline_frames)
+ : StackFrameList(thread, prev_frames_sp, show_inline_frames),
+ m_input_frames(std::move(input_frames)) {}
+
+bool SyntheticStackFrameList::FetchFramesUpTo(
+ uint32_t end_idx, InterruptionControl allow_interrupt) {
+
+ size_t num_synthetic_frames = 0;
+ // Check if the thread has a synthetic frame provider.
+ if (auto provider_sp = m_thread.GetFrameProvider()) {
+ // Use the synthetic frame provider to generate frames lazily.
+ // Keep fetching until we reach end_idx or the provider returns an error.
+ for (uint32_t idx = m_frames.size(); idx <= end_idx; idx++) {
+ if (allow_interrupt &&
+ m_thread.GetProcess()->GetTarget().GetDebugger().InterruptRequested())
+ return true;
+ auto frame_or_err = provider_sp->GetFrameAtIndex(idx);
+ if (!frame_or_err) {
+ // Provider returned error - we've reached the end.
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), frame_or_err.takeError(),
+ "Frame provider reached end at index {0}: {1}", idx);
+ SetAllFramesFetched();
+ break;
+ }
+ StackFrameSP frame_sp = *frame_or_err;
+ if (frame_sp->IsSynthetic())
+ frame_sp->GetStackID().SetCFA(num_synthetic_frames++,
+ GetThread().GetProcess().get());
+ // Set the frame list weak pointer so ExecutionContextRef can resolve
+ // the frame without calling Thread::GetStackFrameList().
+ frame_sp->m_frame_list_wp = shared_from_this();
+ m_frames.push_back(frame_sp);
+ }
+
+ return false; // Not interrupted.
+ }
+
+ // If no provider, fall back to the base implementation.
+ return StackFrameList::FetchFramesUpTo(end_idx, allow_interrupt);
+}
+
void StackFrameList::CalculateCurrentInlinedDepth() {
uint32_t cur_inlined_depth = GetCurrentInlinedDepth();
if (cur_inlined_depth == UINT32_MAX) {
@@ -330,6 +374,7 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
cfa_is_valid, pc, StackFrame::Kind::Regular, artificial,
behaves_like_zeroth_frame, &sc);
+ synth_frame->m_frame_list_wp = shared_from_this();
m_frames.push_back(synth_frame);
LLDB_LOG(log, "Pushed frame {0} at {1:x}", callee->GetDisplayName(), pc);
}
@@ -445,6 +490,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
unwind_frame_sp = std::make_shared<StackFrame>(
m_thread.shared_from_this(), m_frames.size(), idx, reg_ctx_sp,
cfa, pc, behaves_like_zeroth_frame, nullptr);
+ unwind_frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(unwind_frame_sp);
}
} else {
@@ -479,6 +525,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
// although its concrete index will stay the same.
SynthesizeTailCallFrames(*unwind_frame_sp.get());
+ unwind_frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(unwind_frame_sp);
}
@@ -503,6 +550,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
unwind_frame_sp->GetRegisterContextSP(), cfa, next_frame_address,
behaves_like_zeroth_frame, &next_frame_sc));
+ frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(frame_sp);
unwind_sc = next_frame_sc;
curr_frame_address = next_frame_address;
@@ -559,6 +607,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
// Now copy the fixed up previous frame into the current frames so the
// pointer doesn't change.
+ prev_frame_sp->m_frame_list_wp = shared_from_this();
m_frames[curr_frame_idx] = prev_frame_sp;
#if defined(DEBUG_STACK_FRAMES)
diff --git a/lldb/source/Target/SyntheticFrameProvider.cpp b/lldb/source/Target/SyntheticFrameProvider.cpp
index 241ce82..97ff42d 100644
--- a/lldb/source/Target/SyntheticFrameProvider.cpp
+++ b/lldb/source/Target/SyntheticFrameProvider.cpp
@@ -8,10 +8,12 @@
#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
@@ -21,12 +23,17 @@ SyntheticFrameProvider::SyntheticFrameProvider(StackFrameListSP input_frames)
SyntheticFrameProvider::~SyntheticFrameProvider() = default;
-void SyntheticFrameProviderDescriptor::Dump(Stream *s) const {
+void ScriptedFrameProviderDescriptor::Dump(Stream *s) const {
if (!s)
return;
+ s->Format(" ID: {0:x}\n", GetID());
s->Printf(" Name: %s\n", GetName().str().c_str());
+ std::string description = GetDescription();
+ if (!description.empty())
+ s->Printf(" Description: %s\n", description.c_str());
+
// Show thread filter information.
if (thread_specs.empty()) {
s->PutCString(" Thread Filter: (applies to all threads)\n");
@@ -41,9 +48,23 @@ void SyntheticFrameProviderDescriptor::Dump(Stream *s) const {
}
}
+uint32_t ScriptedFrameProviderDescriptor::GetID() const {
+ if (!scripted_metadata_sp)
+ return 0;
+
+ return scripted_metadata_sp->GetID();
+}
+
+std::string ScriptedFrameProviderDescriptor::GetDescription() const {
+ // If we have an interface, call get_description() to fetch it.
+ if (interface_sp && scripted_metadata_sp)
+ return interface_sp->GetDescription(scripted_metadata_sp->GetClassName());
+ return {};
+}
+
llvm::Expected<SyntheticFrameProviderSP> SyntheticFrameProvider::CreateInstance(
StackFrameListSP input_frames,
- const SyntheticFrameProviderDescriptor &descriptor) {
+ const ScriptedFrameProviderDescriptor &descriptor) {
if (!input_frames)
return llvm::createStringError(
"cannot create synthetic frame provider: invalid input frames");
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index ae6c4f7..2305f10 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -156,8 +156,6 @@ static Status installExecutable(const Installer &installer) {
return Status();
}
-constexpr std::chrono::milliseconds EvaluateExpressionOptions::default_timeout;
-
Target::Arch::Arch(const ArchSpec &spec)
: m_spec(spec),
m_plugin_up(PluginManager::CreateArchitectureInstance(spec)) {}
@@ -187,6 +185,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_internal_stop_hooks(), m_latest_stop_hook_id(0), m_valid(true),
m_suppress_stop_hooks(false), m_is_dummy_target(is_dummy_target),
m_target_unique_id(g_target_unique_id++),
+ m_target_session_name(
+ llvm::formatv("Session {0}", m_target_unique_id).str()),
m_frame_recognizer_manager_up(
std::make_unique<StackFrameRecognizerManager>()) {
SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
@@ -194,6 +194,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded");
SetEventName(eBroadcastBitWatchpointChanged, "watchpoint-changed");
SetEventName(eBroadcastBitSymbolsLoaded, "symbols-loaded");
+ SetEventName(eBroadcastBitNewTargetCreated, "new-target-created");
CheckInWithManager();
@@ -1855,6 +1856,9 @@ void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
}
void Target::ModulesDidLoad(ModuleList &module_list) {
+ if (GetPreloadSymbols())
+ module_list.PreloadSymbols(GetParallelModuleLoad());
+
const size_t num_images = module_list.GetSize();
if (m_valid && num_images) {
for (size_t idx = 0; idx < num_images; ++idx) {
@@ -2279,8 +2283,10 @@ size_t Target::ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_si
else
scalar = data.GetMaxU64(&offset, byte_size);
- if (is_signed)
+ if (is_signed) {
+ scalar.MakeSigned();
scalar.SignExtend(byte_size * 8);
+ }
return bytes_read;
}
} else {
@@ -2295,7 +2301,7 @@ int64_t Target::ReadSignedIntegerFromMemory(const Address &addr,
int64_t fail_value, Status &error,
bool force_live_memory) {
Scalar scalar;
- if (ReadScalarIntegerFromMemory(addr, integer_byte_size, false, scalar, error,
+ if (ReadScalarIntegerFromMemory(addr, integer_byte_size, true, scalar, error,
force_live_memory))
return scalar.SLongLong(fail_value);
return fail_value;
@@ -2509,10 +2515,6 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
if (symbol_file_spec)
module_sp->SetSymbolFileFileSpec(symbol_file_spec);
- // Preload symbols outside of any lock, so hopefully we can do this for
- // each library in parallel.
- if (GetPreloadSymbols())
- module_sp->PreloadSymbols();
llvm::SmallVector<ModuleSP, 1> replaced_modules;
for (ModuleSP &old_module_sp : old_modules) {
if (m_images.GetIndexForModule(old_module_sp.get()) !=
@@ -3207,6 +3209,11 @@ bool Target::RunStopHooks(bool at_initial_stop) {
bool should_stop = false;
bool requested_continue = false;
+ // A stop hook might get deleted while running stop hooks.
+ // We have to decide what that means. We will follow the rule that deleting
+ // a stop hook while processing these stop hooks will delete it for FUTURE
+ // stops but not this stop. Fortunately, copying the m_stop_hooks to the
+ // active_hooks list before iterating over the hooks has this effect.
for (auto cur_hook_sp : active_hooks) {
bool any_thread_matched = false;
for (auto exc_ctx : exc_ctx_with_reasons) {
@@ -3713,6 +3720,61 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
return error;
}
+llvm::Expected<uint32_t> Target::AddScriptedFrameProviderDescriptor(
+ const ScriptedFrameProviderDescriptor &descriptor) {
+ if (!descriptor.IsValid())
+ return llvm::createStringError("invalid frame provider descriptor");
+
+ llvm::StringRef name = descriptor.GetName();
+ if (name.empty())
+ return llvm::createStringError(
+ "frame provider descriptor has no class name");
+
+ std::lock_guard<std::recursive_mutex> guard(
+ m_frame_provider_descriptors_mutex);
+
+ uint32_t descriptor_id = descriptor.GetID();
+ m_frame_provider_descriptors[descriptor_id] = descriptor;
+
+ // Clear frame providers on existing threads so they reload with new config.
+ if (ProcessSP process_sp = GetProcessSP())
+ for (ThreadSP thread_sp : process_sp->Threads())
+ thread_sp->ClearScriptedFrameProvider();
+
+ return descriptor_id;
+}
+
+bool Target::RemoveScriptedFrameProviderDescriptor(uint32_t id) {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_frame_provider_descriptors_mutex);
+ bool removed = m_frame_provider_descriptors.erase(id);
+
+ if (removed)
+ if (ProcessSP process_sp = GetProcessSP())
+ for (ThreadSP thread_sp : process_sp->Threads())
+ thread_sp->ClearScriptedFrameProvider();
+
+ return removed;
+}
+
+void Target::ClearScriptedFrameProviderDescriptors() {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_frame_provider_descriptors_mutex);
+
+ m_frame_provider_descriptors.clear();
+
+ if (ProcessSP process_sp = GetProcessSP())
+ for (ThreadSP thread_sp : process_sp->Threads())
+ thread_sp->ClearScriptedFrameProvider();
+}
+
+const llvm::DenseMap<uint32_t, ScriptedFrameProviderDescriptor> &
+Target::GetScriptedFrameProviderDescriptors() const {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_frame_provider_descriptors_mutex);
+ return m_frame_provider_descriptors;
+}
+
void Target::FinalizeFileActions(ProcessLaunchInfo &info) {
Log *log = GetLog(LLDBLog::Process);
@@ -5083,17 +5145,17 @@ void TargetProperties::SetProcessLaunchInfo(
const FileAction *input_file_action =
launch_info.GetFileActionForFD(STDIN_FILENO);
if (input_file_action) {
- SetStandardInputPath(input_file_action->GetPath());
+ SetStandardInputPath(input_file_action->GetFileSpec().GetPath());
}
const FileAction *output_file_action =
launch_info.GetFileActionForFD(STDOUT_FILENO);
if (output_file_action) {
- SetStandardOutputPath(output_file_action->GetPath());
+ SetStandardOutputPath(output_file_action->GetFileSpec().GetPath());
}
const FileAction *error_file_action =
launch_info.GetFileActionForFD(STDERR_FILENO);
if (error_file_action) {
- SetStandardErrorPath(error_file_action->GetPath());
+ SetStandardErrorPath(error_file_action->GetFileSpec().GetPath());
}
SetDetachOnError(launch_info.GetFlags().Test(lldb::eLaunchFlagDetachOnError));
SetDisableASLR(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableASLR));
@@ -5196,6 +5258,11 @@ Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
const ModuleList &module_list)
: EventData(), m_target_sp(target_sp), m_module_list(module_list) {}
+Target::TargetEventData::TargetEventData(
+ const lldb::TargetSP &target_sp, const lldb::TargetSP &created_target_sp)
+ : EventData(), m_target_sp(target_sp),
+ m_created_target_sp(created_target_sp), m_module_list() {}
+
Target::TargetEventData::~TargetEventData() = default;
llvm::StringRef Target::TargetEventData::GetFlavorString() {
@@ -5230,6 +5297,15 @@ TargetSP Target::TargetEventData::GetTargetFromEvent(const Event *event_ptr) {
return target_sp;
}
+TargetSP
+Target::TargetEventData::GetCreatedTargetFromEvent(const Event *event_ptr) {
+ TargetSP created_target_sp;
+ const TargetEventData *event_data = GetEventDataFromEvent(event_ptr);
+ if (event_data)
+ created_target_sp = event_data->m_created_target_sp;
+ return created_target_sp;
+}
+
ModuleList
Target::TargetEventData::GetModuleListFromEvent(const Event *event_ptr) {
ModuleList module_list;
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 2e03bc1..ce04e9c 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -48,7 +48,7 @@ Status TargetList::CreateTarget(Debugger &debugger,
LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
TargetSP &target_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+
auto result = TargetList::CreateTargetInternal(
debugger, user_exe_path, triple_str, load_dependent_files,
platform_options, target_sp);
@@ -63,7 +63,7 @@ Status TargetList::CreateTarget(Debugger &debugger,
const ArchSpec &specified_arch,
LoadDependentFiles load_dependent_files,
PlatformSP &platform_sp, TargetSP &target_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+
auto result = TargetList::CreateTargetInternal(
debugger, user_exe_path, specified_arch, load_dependent_files,
platform_sp, target_sp);
@@ -521,6 +521,7 @@ uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
}
void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
lldbassert(!llvm::is_contained(m_target_list, target_sp) &&
"target already exists it the list");
UnregisterInProcessTarget(target_sp);
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 8c3e197..b40e753 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -13,9 +13,12 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
@@ -26,6 +29,7 @@
#include "lldb/Target/ScriptedThreadPlan.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
@@ -45,6 +49,7 @@
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
@@ -257,6 +262,7 @@ void Thread::DestroyThread() {
std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
m_curr_frames_sp.reset();
m_prev_frames_sp.reset();
+ m_frame_provider_sp.reset();
m_prev_framezero_pc.reset();
}
@@ -1439,13 +1445,76 @@ void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) {
StackFrameListSP Thread::GetStackFrameList() {
std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
- if (!m_curr_frames_sp)
+ if (m_curr_frames_sp)
+ return m_curr_frames_sp;
+
+ // First, try to load a frame provider if we don't have one yet.
+ if (!m_frame_provider_sp) {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp) {
+ Target &target = process_sp->GetTarget();
+ const auto &descriptors = target.GetScriptedFrameProviderDescriptors();
+
+ // Find first descriptor that applies to this thread.
+ for (const auto &entry : descriptors) {
+ const ScriptedFrameProviderDescriptor &descriptor = entry.second;
+ if (descriptor.IsValid() && descriptor.AppliesToThread(*this)) {
+ if (llvm::Error error = LoadScriptedFrameProvider(descriptor)) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(error),
+ "Failed to load scripted frame provider: {0}");
+ }
+ break; // Use first matching descriptor (success or failure).
+ }
+ }
+ }
+ }
+
+ // Create the frame list based on whether we have a provider.
+ if (m_frame_provider_sp) {
+ // We have a provider - create synthetic frame list.
+ StackFrameListSP input_frames = m_frame_provider_sp->GetInputFrames();
+ m_curr_frames_sp = std::make_shared<SyntheticStackFrameList>(
+ *this, input_frames, m_prev_frames_sp, true);
+ } else {
+ // No provider - use normal unwinder frames.
m_curr_frames_sp =
std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true);
+ }
return m_curr_frames_sp;
}
+llvm::Error Thread::LoadScriptedFrameProvider(
+ const ScriptedFrameProviderDescriptor &descriptor) {
+ std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
+
+ // Note: We don't create input_frames here - it will be created lazily
+ // by SyntheticStackFrameList when frames are first fetched.
+ // Creating them too early can cause crashes during thread initialization.
+
+ // Create a temporary StackFrameList just to get the thread reference for the
+ // provider. The provider won't actually use this - it will get real input
+ // frames from SyntheticStackFrameList later.
+ StackFrameListSP temp_frames =
+ std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true);
+
+ auto provider_or_err =
+ SyntheticFrameProvider::CreateInstance(temp_frames, descriptor);
+ if (!provider_or_err)
+ return provider_or_err.takeError();
+
+ ClearScriptedFrameProvider();
+ m_frame_provider_sp = *provider_or_err;
+ return llvm::Error::success();
+}
+
+void Thread::ClearScriptedFrameProvider() {
+ std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
+ m_frame_provider_sp.reset();
+ m_curr_frames_sp.reset();
+ m_prev_frames_sp.reset();
+}
+
std::optional<addr_t> Thread::GetPreviousFrameZeroPC() {
return m_prev_framezero_pc;
}
@@ -1466,6 +1535,7 @@ void Thread::ClearStackFrames() {
m_prev_frames_sp.swap(m_curr_frames_sp);
m_curr_frames_sp.reset();
+ m_frame_provider_sp.reset();
m_extended_info.reset();
m_extended_info_fetched = false;
}
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index d49a01b..0307b38 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -356,13 +356,10 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
}
}
- // If there was only one owner, then we're done. But if we also hit
- // some user breakpoint on our way out, we should mark ourselves as
- // done, but also not claim to explain the stop, since it is more
- // important to report the user breakpoint than the step out
- // completion.
-
- if (site_sp->GetNumberOfConstituents() == 1)
+ // If the thread also hit a user breakpoint on its way out, the plan is
+ // done but should not claim to explain the stop. It is more important
+ // to report the user breakpoint than the step out completion.
+ if (!site_sp->ContainsUserBreakpointForThread(GetThread()))
return true;
}
return false;
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index dca96cc..3a9deb6 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -431,10 +431,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
top_most_line_entry.original_file_sp =
std::make_shared<SupportFile>(call_site_file_spec);
top_most_line_entry.range = range;
- top_most_line_entry.file_sp.reset();
+ top_most_line_entry.file_sp = std::make_shared<SupportFile>();
top_most_line_entry.ApplyFileMappings(
GetThread().CalculateTarget());
- if (!top_most_line_entry.file_sp)
+ if (!top_most_line_entry.file_sp->GetSpecOnly())
top_most_line_entry.file_sp =
top_most_line_entry.original_file_sp;
}
diff --git a/lldb/source/Target/ThreadSpec.cpp b/lldb/source/Target/ThreadSpec.cpp
index ba4c3aa..624f64e 100644
--- a/lldb/source/Target/ThreadSpec.cpp
+++ b/lldb/source/Target/ThreadSpec.cpp
@@ -19,6 +19,10 @@ const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
ThreadSpec::ThreadSpec() : m_name(), m_queue_name() {}
+ThreadSpec::ThreadSpec(Thread &thread)
+ : m_index(thread.GetIndexID()), m_tid(thread.GetID()),
+ m_name(thread.GetName()), m_queue_name(thread.GetQueueName()) {}
+
std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
const StructuredData::Dictionary &spec_dict, Status &error) {
uint32_t index = UINT32_MAX;
diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp
index 6113c66..881431f 100644
--- a/lldb/source/Target/UnixSignals.cpp
+++ b/lldb/source/Target/UnixSignals.cpp
@@ -137,6 +137,13 @@ llvm::StringRef UnixSignals::GetSignalAsStringRef(int32_t signo) const {
return pos->second.m_name;
}
+llvm::StringRef UnixSignals::GetSignalNumberDescription(int32_t signo) const {
+ const auto pos = m_signals.find(signo);
+ if (pos == m_signals.end())
+ return {};
+ return pos->second.m_description;
+}
+
std::string UnixSignals::GetSignalDescription(
int32_t signo, std::optional<int32_t> code,
std::optional<lldb::addr_t> addr, std::optional<lldb::addr_t> lower,