Skip to content

Commit 5cf9942

Browse files
committed
[lldb] Mark scripted frames as synthetic instead of artificial (llvm#153117)
This patch changes the way frames created from scripted affordances like Scripted Threads are displayed. Currently, they're marked artificial which is used usually for compiler generated frames. This patch changes that behaviour by introducing a new synthetic StackFrame kind and moves 'artificial' to be a distinct StackFrame attribut. On top of making these frames less confusing, this allows us to know when a frame was created from a scripted affordance. rdar://155949703 Signed-off-by: Med Ismail Bennani <[email protected]> (cherry picked from commit 6c10ab8)
1 parent 879d548 commit 5cf9942

File tree

17 files changed

+156
-109
lines changed

17 files changed

+156
-109
lines changed

lldb/include/lldb/API/SBFrame.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class LLDB_API SBFrame {
107107

108108
bool IsArtificial() const;
109109

110+
bool IsSynthetic() const;
111+
110112
/// Return whether a frame recognizer decided this frame should not
111113
/// be displayes in backtraces etc.
112114
bool IsHidden() const;

lldb/include/lldb/Core/FormatEntity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct Entry {
8080
FrameRegisterFlags,
8181
FrameRegisterByName,
8282
FrameIsArtificial,
83+
FrameKind,
8384
ScriptFrame,
8485
FunctionID,
8586
FunctionDidChange,

lldb/include/lldb/Target/StackFrame.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,9 @@ class StackFrame : public ExecutionContextScope,
6060
/// local variables.
6161
History,
6262

63-
/// An artificial stack frame (e.g. a synthesized result of inferring
64-
/// missing tail call frames from a backtrace) with limited support for
65-
/// local variables.
66-
Artificial
63+
/// An synthetic stack frame (e.g. a synthesized result from script
64+
/// resource) possibly without support for local variables or register.
65+
Synthetic
6766
};
6867

6968
/// Construct a StackFrame object without supplying a RegisterContextSP.
@@ -109,7 +108,8 @@ class StackFrame : public ExecutionContextScope,
109108
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
110109
lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa,
111110
bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind,
112-
bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr);
111+
bool artificial, bool behaves_like_zeroth_frame,
112+
const SymbolContext *sc_ptr);
113113

114114
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
115115
lldb::user_id_t concrete_frame_idx,
@@ -400,6 +400,9 @@ class StackFrame : public ExecutionContextScope,
400400
/// true if this is an inlined frame.
401401
bool IsInlined();
402402

403+
/// Query whether this frame is synthetic.
404+
bool IsSynthetic() const;
405+
403406
/// Query whether this frame is part of a historical backtrace.
404407
bool IsHistorical() const;
405408

@@ -565,6 +568,10 @@ class StackFrame : public ExecutionContextScope,
565568
/// Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS.
566569
bool m_cfa_is_valid;
567570
Kind m_stack_frame_kind;
571+
/// Is this an artificial stack frame (e.g. a synthesized result of inferring
572+
/// missing tail call frames from a backtrace) with limited support for
573+
/// local variables. Orthogonal to `StackFrame::Kind`.
574+
bool m_artificial;
568575

569576
/// Whether this frame behaves like the zeroth frame, in the sense
570577
/// that its pc value might not immediately follow a call (and thus might

lldb/source/API/SBFrame.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,22 @@ bool SBFrame::IsArtificial() const {
12081208
return false;
12091209
}
12101210

1211+
bool SBFrame::IsSynthetic() const {
1212+
LLDB_INSTRUMENT_VA(this);
1213+
1214+
llvm::Expected<StoppedExecutionContext> exe_ctx =
1215+
GetStoppedExecutionContext(m_opaque_sp);
1216+
if (!exe_ctx) {
1217+
LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
1218+
return false;
1219+
}
1220+
1221+
if (StackFrame *frame = exe_ctx->GetFramePtr())
1222+
return frame->IsSynthetic();
1223+
1224+
return false;
1225+
}
1226+
12111227
bool SBFrame::IsHidden() const {
12121228
LLDB_INSTRUMENT_VA(this);
12131229

lldb/source/Core/CoreProperties.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ let Definition = "debugger" in {
115115
Desc<"The default disassembly format string to use when disassembling instruction sequences.">;
116116
def FrameFormat: Property<"frame-format", "FormatEntity">,
117117
Global,
118-
DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
118+
DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
119119
Desc<"The default frame format string to use when displaying stack frame information for threads.">;
120120
def NotiftVoid: Property<"notify-void", "Boolean">,
121121
Global,
@@ -271,7 +271,7 @@ let Definition = "debugger" in {
271271
Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">;
272272
def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">,
273273
Global,
274-
DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
274+
DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
275275
Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">;
276276
def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
277277
Global,

lldb/source/Core/FormatEntity.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ constexpr Definition g_frame_child_entries[] = {
108108
Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
109109
g_string_entry),
110110
Definition("is-artificial", EntryType::FrameIsArtificial),
111+
Definition("kind", EntryType::FrameKind),
111112
};
112113

113114
constexpr Definition g_function_child_entries[] = {
@@ -380,6 +381,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
380381
ENUM_TO_CSTR(FrameRegisterFlags);
381382
ENUM_TO_CSTR(FrameRegisterByName);
382383
ENUM_TO_CSTR(FrameIsArtificial);
384+
ENUM_TO_CSTR(FrameKind);
383385
ENUM_TO_CSTR(ScriptFrame);
384386
ENUM_TO_CSTR(FunctionID);
385387
ENUM_TO_CSTR(FunctionDidChange);
@@ -1757,6 +1759,18 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17571759
return false;
17581760
}
17591761

1762+
case Entry::Type::FrameKind: {
1763+
if (exe_ctx)
1764+
if (StackFrame *frame = exe_ctx->GetFramePtr()) {
1765+
if (frame->IsSynthetic())
1766+
s.PutCString(" [synthetic]");
1767+
else if (frame->IsHistorical())
1768+
s.PutCString(" [history]");
1769+
return true;
1770+
}
1771+
return false;
1772+
}
1773+
17601774
case Entry::Type::ScriptFrame:
17611775
if (exe_ctx) {
17621776
StackFrame *frame = exe_ctx->GetFramePtr();

lldb/source/Plugins/Process/scripted/ScriptedThread.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,15 @@ bool ScriptedThread::LoadArtificialStackFrames() {
200200

201201
lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
202202
bool cfa_is_valid = false;
203+
const bool artificial = false;
203204
const bool behaves_like_zeroth_frame = false;
204205
SymbolContext sc;
205206
symbol_addr.CalculateSymbolContext(&sc);
206207

207208
StackFrameSP synth_frame_sp = std::make_shared<StackFrame>(
208209
this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
209-
StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc);
210+
StackFrame::Kind::Synthetic, artificial, behaves_like_zeroth_frame,
211+
&sc);
210212

211213
if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
212214
return ScriptedInterface::ErrorWithMessage<bool>(

lldb/source/Target/StackFrame.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ using namespace lldb_private;
6060
StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
6161
user_id_t unwind_frame_index, addr_t cfa,
6262
bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
63-
bool behaves_like_zeroth_frame,
63+
bool artificial, bool behaves_like_zeroth_frame,
6464
const SymbolContext *sc_ptr)
6565
: m_thread_wp(thread_sp), m_frame_index(frame_idx),
6666
m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
6767
m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),
6868
m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
6969
m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
70-
m_stack_frame_kind(kind),
70+
m_stack_frame_kind(kind), m_artificial(artificial),
7171
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
7272
m_variable_list_sp(), m_variable_list_value_objects(),
7373
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -95,7 +95,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
9595
m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),
9696
m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
9797
m_frame_base_error(), m_cfa_is_valid(true),
98-
m_stack_frame_kind(StackFrame::Kind::Regular),
98+
m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),
9999
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
100100
m_variable_list_sp(), m_variable_list_value_objects(),
101101
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -123,7 +123,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
123123
nullptr, thread_sp->GetProcess().get()),
124124
m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
125125
m_frame_base_error(), m_cfa_is_valid(true),
126-
m_stack_frame_kind(StackFrame::Kind::Regular),
126+
m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),
127127
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
128128
m_variable_list_sp(), m_variable_list_value_objects(),
129129
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -1250,10 +1250,12 @@ bool StackFrame::IsHistorical() const {
12501250
return m_stack_frame_kind == StackFrame::Kind::History;
12511251
}
12521252

1253-
bool StackFrame::IsArtificial() const {
1254-
return m_stack_frame_kind == StackFrame::Kind::Artificial;
1253+
bool StackFrame::IsSynthetic() const {
1254+
return m_stack_frame_kind == StackFrame::Kind::Synthetic;
12551255
}
12561256

1257+
bool StackFrame::IsArtificial() const { return m_artificial; }
1258+
12571259
bool StackFrame::IsHidden() {
12581260
if (auto recognized_frame_sp = GetRecognizedFrame())
12591261
return recognized_frame_sp->ShouldHide();

lldb/source/Target/StackFrameList.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,14 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
321321
addr_t pc = calleeInfo.address;
322322
// If the callee address refers to the call instruction, we do not want to
323323
// subtract 1 from this value.
324+
const bool artificial = true;
324325
const bool behaves_like_zeroth_frame =
325326
calleeInfo.address_type == CallEdge::AddrType::Call;
326327
SymbolContext sc;
327328
callee->CalculateSymbolContext(&sc);
328329
auto synth_frame = std::make_shared<StackFrame>(
329330
m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
330-
cfa_is_valid, pc, StackFrame::Kind::Artificial,
331+
cfa_is_valid, pc, StackFrame::Kind::Regular, artificial,
331332
behaves_like_zeroth_frame, &sc);
332333
m_frames.push_back(synth_frame);
333334
LLDB_LOG(log, "Pushed frame {0} at {1:x}", callee->GetDisplayName(), pc);
@@ -470,7 +471,8 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
470471
const bool cfa_is_valid = true;
471472
unwind_frame_sp = std::make_shared<StackFrame>(
472473
m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid,
473-
pc, StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr);
474+
pc, StackFrame::Kind::Regular, false, behaves_like_zeroth_frame,
475+
nullptr);
474476

475477
// Create synthetic tail call frames between the previous frame and the
476478
// newly-found frame. The new frame's index may change after this call,

lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,6 @@ def cleanup():
284284
break
285285
self.assertEqual(idx, int(reg.value, 16))
286286

287-
self.assertTrue(frame.IsArtificial(), "Frame is not artificial")
287+
self.assertTrue(frame.IsSynthetic(), "Frame is not synthetic")
288288
pc = frame.GetPCAddress().GetLoadAddress(target_0)
289289
self.assertEqual(pc, 0x0100001B00)

0 commit comments

Comments
 (0)