Skip to content

Commit 583a83e

Browse files
committed
[lldb] Mark scripted frames as synthetic instead of artificial
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]>
1 parent 2fc0e2c commit 583a83e

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
@@ -104,6 +104,8 @@ class LLDB_API SBFrame {
104104

105105
bool IsArtificial() const;
106106

107+
bool IsSynthetic() const;
108+
107109
/// Return whether a frame recognizer decided this frame should not
108110
/// be displayes in backtraces etc.
109111
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

@@ -571,6 +574,10 @@ class StackFrame : public ExecutionContextScope,
571574
/// Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS.
572575
bool m_cfa_is_valid;
573576
Kind m_stack_frame_kind;
577+
/// Is this an artificial stack frame (e.g. a synthesized result of inferring
578+
/// missing tail call frames from a backtrace) with limited support for
579+
/// local variables. Orthogonal to `StackFrame::Kind`.
580+
bool m_artificial;
574581

575582
/// Whether this frame behaves like the zeroth frame, in the sense
576583
/// 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
@@ -1118,6 +1118,22 @@ bool SBFrame::IsArtificial() const {
11181118
return false;
11191119
}
11201120

1121+
bool SBFrame::IsSynthetic() const {
1122+
LLDB_INSTRUMENT_VA(this);
1123+
1124+
llvm::Expected<StoppedExecutionContext> exe_ctx =
1125+
GetStoppedExecutionContext(m_opaque_sp);
1126+
if (!exe_ctx) {
1127+
LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
1128+
return false;
1129+
}
1130+
1131+
if (StackFrame *frame = exe_ctx->GetFramePtr())
1132+
return frame->IsSynthetic();
1133+
1134+
return false;
1135+
}
1136+
11211137
bool SBFrame::IsHidden() const {
11221138
LLDB_INSTRUMENT_VA(this);
11231139

lldb/source/Core/CoreProperties.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let Definition = "debugger" in {
5959
Desc<"The default disassembly format string to use when disassembling instruction sequences.">;
6060
def FrameFormat: Property<"frame-format", "FormatEntity">,
6161
Global,
62-
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">,
62+
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">,
6363
Desc<"The default frame format string to use when displaying stack frame information for threads.">;
6464
def NotiftVoid: Property<"notify-void", "Boolean">,
6565
Global,
@@ -233,7 +233,7 @@ let Definition = "debugger" in {
233233
Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">;
234234
def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">,
235235
Global,
236-
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">,
236+
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">,
237237
Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">;
238238
def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
239239
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);
@@ -1747,6 +1749,18 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17471749
return false;
17481750
}
17491751

1752+
case Entry::Type::FrameKind: {
1753+
if (exe_ctx)
1754+
if (StackFrame *frame = exe_ctx->GetFramePtr()) {
1755+
if (frame->IsSynthetic())
1756+
s.PutCString(" [synthetic]");
1757+
else if (frame->IsHistorical())
1758+
s.PutCString(" [history]");
1759+
return true;
1760+
}
1761+
return false;
1762+
}
1763+
17501764
case Entry::Type::ScriptFrame:
17511765
if (exe_ctx) {
17521766
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
@@ -57,14 +57,14 @@ using namespace lldb_private;
5757
StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
5858
user_id_t unwind_frame_index, addr_t cfa,
5959
bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
60-
bool behaves_like_zeroth_frame,
60+
bool artificial, bool behaves_like_zeroth_frame,
6161
const SymbolContext *sc_ptr)
6262
: m_thread_wp(thread_sp), m_frame_index(frame_idx),
6363
m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
6464
m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),
6565
m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
6666
m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
67-
m_stack_frame_kind(kind),
67+
m_stack_frame_kind(kind), m_artificial(artificial),
6868
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
6969
m_variable_list_sp(), m_variable_list_value_objects(),
7070
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -92,7 +92,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
9292
m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),
9393
m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
9494
m_frame_base_error(), m_cfa_is_valid(true),
95-
m_stack_frame_kind(StackFrame::Kind::Regular),
95+
m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),
9696
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
9797
m_variable_list_sp(), m_variable_list_value_objects(),
9898
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -120,7 +120,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
120120
nullptr, thread_sp->GetProcess().get()),
121121
m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
122122
m_frame_base_error(), m_cfa_is_valid(true),
123-
m_stack_frame_kind(StackFrame::Kind::Regular),
123+
m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),
124124
m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
125125
m_variable_list_sp(), m_variable_list_value_objects(),
126126
m_recognized_frame_sp(), m_disassembly(), m_mutex() {
@@ -1264,10 +1264,12 @@ bool StackFrame::IsHistorical() const {
12641264
return m_stack_frame_kind == StackFrame::Kind::History;
12651265
}
12661266

1267-
bool StackFrame::IsArtificial() const {
1268-
return m_stack_frame_kind == StackFrame::Kind::Artificial;
1267+
bool StackFrame::IsSynthetic() const {
1268+
return m_stack_frame_kind == StackFrame::Kind::Synthetic;
12691269
}
12701270

1271+
bool StackFrame::IsArtificial() const { return m_artificial; }
1272+
12711273
bool StackFrame::IsHidden() {
12721274
if (auto recognized_frame_sp = GetRecognizedFrame())
12731275
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)