Skip to content

Commit 9d61eaa

Browse files
authored
[lldb] Make GetRowForFunctionOffset compatible with discontinuous functions (#133250)
The function had special handling for -1, but that is incompatible with functions whose entry point is not the first address. Use std::nullopt instead.
1 parent 5c65a32 commit 9d61eaa

File tree

4 files changed

+33
-31
lines changed

4 files changed

+33
-31
lines changed

lldb/include/lldb/Symbol/UnwindPlan.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,12 @@ class UnwindPlan {
467467
void InsertRow(Row row, bool replace_existing = false);
468468

469469
// Returns a pointer to the best row for the given offset into the function's
470-
// instructions. If offset is -1 it indicates that the function start is
471-
// unknown - the final row in the UnwindPlan is returned. In practice, the
472-
// UnwindPlan for a function with no known start address will be the
473-
// architectural default UnwindPlan which will only have one row.
474-
const UnwindPlan::Row *GetRowForFunctionOffset(int offset) const;
470+
// instructions. If offset is std::nullopt it indicates that the function
471+
// start is unknown - the final row in the UnwindPlan is returned. In
472+
// practice, the UnwindPlan for a function with no known start address will be
473+
// the architectural default UnwindPlan which will only have one row.
474+
const UnwindPlan::Row *
475+
GetRowForFunctionOffset(std::optional<int> offset) const;
475476

476477
lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
477478

lldb/include/lldb/Target/RegisterContextUnwind.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -228,18 +228,17 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
228228
lldb_private::Address m_start_pc;
229229
lldb_private::Address m_current_pc;
230230

231-
int m_current_offset; // how far into the function we've executed; -1 if
232-
// unknown
233-
// 0 if no instructions have been executed yet.
234-
235-
// 0 if no instructions have been executed yet.
236-
// On architectures where the return address on the stack points
237-
// to the instruction after the CALL, this value will have 1
238-
// subtracted from it. Else a function that ends in a CALL will
239-
// have an offset pointing into the next function's address range.
231+
/// How far into the function we've executed. 0 if no instructions have been
232+
/// executed yet, std::nullopt if unknown.
233+
std::optional<int> m_current_offset;
234+
235+
// How far into the function we've executed. 0 if no instructions have been
236+
// executed yet, std::nullopt if unknown. On architectures where the return
237+
// address on the stack points to the instruction after the CALL, this value
238+
// will have 1 subtracted from it. Otherwise, a function that ends in a CALL
239+
// will have an offset pointing into the next function's address range.
240240
// m_current_pc has the actual address of the "current" pc.
241-
int m_current_offset_backed_up_one; // how far into the function we've
242-
// executed; -1 if unknown
241+
std::optional<int> m_current_offset_backed_up_one;
243242

244243
bool m_behaves_like_zeroth_frame; // this frame behaves like frame zero
245244

lldb/source/Symbol/UnwindPlan.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,10 @@ void UnwindPlan::InsertRow(Row row, bool replace_existing) {
417417
}
418418
}
419419

420-
const UnwindPlan::Row *UnwindPlan::GetRowForFunctionOffset(int offset) const {
421-
auto it = offset == -1 ? m_row_list.end()
422-
: llvm::upper_bound(m_row_list, offset, RowLess());
420+
const UnwindPlan::Row *
421+
UnwindPlan::GetRowForFunctionOffset(std::optional<int> offset) const {
422+
auto it = offset ? llvm::upper_bound(m_row_list, *offset, RowLess())
423+
: m_row_list.end();
423424
if (it == m_row_list.begin())
424425
return nullptr;
425426
// upper_bound returns the row strictly greater than our desired offset, which

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC(
9494
return true;
9595
}
9696

97-
// if m_current_offset <= 0, we've got nothing else to try
98-
if (m_current_offset <= 0)
97+
// If don't have an offset or we're at the start of the function, we've got
98+
// nothing else to try.
99+
if (!m_current_offset || m_current_offset == 0)
99100
return false;
100101

101102
// check pc - 1 to see if it's valid
@@ -198,8 +199,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
198199
m_current_offset_backed_up_one = m_current_offset;
199200
} else {
200201
m_start_pc = m_current_pc;
201-
m_current_offset = -1;
202-
m_current_offset_backed_up_one = -1;
202+
m_current_offset = std::nullopt;
203+
m_current_offset_backed_up_one = std::nullopt;
203204
}
204205

205206
// We've set m_frame_type and m_sym_ctx before these calls.
@@ -437,8 +438,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
437438
m_frame_type = eNormalFrame;
438439
}
439440
m_all_registers_available = false;
440-
m_current_offset = -1;
441-
m_current_offset_backed_up_one = -1;
441+
m_current_offset = std::nullopt;
442+
m_current_offset_backed_up_one = std::nullopt;
442443
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
443444
if (const UnwindPlan::Row *row =
444445
m_full_unwind_plan_sp->GetRowForFunctionOffset(0)) {
@@ -569,16 +570,16 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
569570
m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
570571
m_current_offset_backed_up_one = m_current_offset;
571572
if (decr_pc_and_recompute_addr_range &&
572-
m_current_offset_backed_up_one > 0) {
573-
m_current_offset_backed_up_one--;
573+
m_current_offset_backed_up_one != 0) {
574+
--*m_current_offset_backed_up_one;
574575
if (m_sym_ctx_valid) {
575576
m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget());
576577
}
577578
}
578579
} else {
579580
m_start_pc = m_current_pc;
580-
m_current_offset = -1;
581-
m_current_offset_backed_up_one = -1;
581+
m_current_offset = std::nullopt;
582+
m_current_offset_backed_up_one = std::nullopt;
582583
}
583584

584585
if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
@@ -746,7 +747,7 @@ bool RegisterContextUnwind::BehavesLikeZerothFrame() const {
746747
// 2. m_sym_ctx should already be filled in, and
747748
// 3. m_current_pc should have the current pc value for this frame
748749
// 4. m_current_offset_backed_up_one should have the current byte offset into
749-
// the function, maybe backed up by 1, -1 if unknown
750+
// the function, maybe backed up by 1, std::nullopt if unknown
750751

751752
UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() {
752753
UnwindPlanSP unwind_plan_sp;
@@ -790,7 +791,7 @@ UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() {
790791
// 2. m_sym_ctx should already be filled in, and
791792
// 3. m_current_pc should have the current pc value for this frame
792793
// 4. m_current_offset_backed_up_one should have the current byte offset into
793-
// the function, maybe backed up by 1, -1 if unknown
794+
// the function, maybe backed up by 1, std::nullopt if unknown
794795

795796
UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
796797
UnwindPlanSP unwind_plan_sp;

0 commit comments

Comments
 (0)