Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 30 additions & 22 deletions lldb/source/Commands/CommandObjectFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,29 @@ class CommandObjectFrameSelect : public CommandObjectParsed {

Options *GetOptions() override { return &m_options; }

private:
void SkipHiddenFrames(Thread &thread, uint32_t frame_idx) {
uint32_t candidate_idx = frame_idx;
const unsigned max_depth = 12;
for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
candidate_idx = UINT32_MAX;
break;
}
candidate_idx += *m_options.relative_frame_offset;
if (auto candidate_sp = thread.GetStackFrameAtIndex(candidate_idx)) {
if (candidate_sp->IsHidden())
continue;
// Now candidate_idx is the first non-hidden frame.
break;
}
candidate_idx = UINT32_MAX;
break;
};
if (candidate_idx != UINT32_MAX)
m_options.relative_frame_offset = candidate_idx - frame_idx;
}

protected:
void DoExecute(Args &command, CommandReturnObject &result) override {
// No need to check "thread" for validity as eCommandRequiresThread ensures
Expand All @@ -278,28 +301,13 @@ class CommandObjectFrameSelect : public CommandObjectParsed {
if (frame_idx == UINT32_MAX)
frame_idx = 0;

// If moving up/down by one, skip over hidden frames.
if (*m_options.relative_frame_offset == 1 ||
*m_options.relative_frame_offset == -1) {
uint32_t candidate_idx = frame_idx;
const unsigned max_depth = 12;
for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
candidate_idx = UINT32_MAX;
break;
}
candidate_idx += *m_options.relative_frame_offset;
if (auto candidate_sp = thread->GetStackFrameAtIndex(candidate_idx)) {
if (candidate_sp->IsHidden())
continue;
// Now candidate_idx is the first non-hidden frame.
break;
}
candidate_idx = UINT32_MAX;
break;
};
if (candidate_idx != UINT32_MAX)
m_options.relative_frame_offset = candidate_idx - frame_idx;
// If moving up/down by one, skip over hidden frames, unless we started
// in a hidden frame.
if ((*m_options.relative_frame_offset == 1 ||
*m_options.relative_frame_offset == -1)) {
if (auto current_frame_sp = thread->GetStackFrameAtIndex(frame_idx);
!current_frame_sp->IsHidden())
SkipHiddenFrames(*thread, frame_idx);
}

if (*m_options.relative_frame_offset < 0) {
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/commands/frame/select-hidden/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class NavigateHiddenFrameTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True

@add_test_categories(["libc++"])
def test(self):
"""Test going up/down a backtrace but we started in a hidden frame."""
self.build()
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Break here", lldb.SBFileSpec("main.cpp")
)
# up
self.assertIn("__impl2", thread.selected_frame.GetFunctionName())
self.expect("up")
self.assertIn("__impl1", thread.selected_frame.GetFunctionName())
self.expect("up")
self.assertIn("__impl", thread.selected_frame.GetFunctionName())
self.expect("up")
self.assertIn("non_impl", thread.selected_frame.GetFunctionName())

# Back down again.
self.expect("down")
self.assertIn("__impl", thread.selected_frame.GetFunctionName())
self.expect("down")
self.assertIn("__impl1", thread.selected_frame.GetFunctionName())
self.expect("down")
self.assertIn("__impl2", thread.selected_frame.GetFunctionName())
13 changes: 13 additions & 0 deletions lldb/test/API/commands/frame/select-hidden/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace std {
namespace __1 {
static const char *__impl2() { return "Break here"; }
static const char *__impl1() { return __impl2(); }
static const char *__impl() { return __impl1(); }
static const char *non_impl() { return __impl(); }
} // namespace __1
} // namespace std

int main() {
std::__1::non_impl();
__builtin_debugtrap();
}
Loading