Skip to content

Commit 218d7ec

Browse files
committed
[lldb] Make GetRowForFunctionOffset compatible with discontinuous functions
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 f4f4d06 commit 218d7ec

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
@@ -450,11 +450,12 @@ class UnwindPlan {
450450
void InsertRow(Row row, bool replace_existing = false);
451451

452452
// Returns a pointer to the best row for the given offset into the function's
453-
// instructions. If offset is -1 it indicates that the function start is
454-
// unknown - the final row in the UnwindPlan is returned. In practice, the
455-
// UnwindPlan for a function with no known start address will be the
456-
// architectural default UnwindPlan which will only have one row.
457-
const UnwindPlan::Row *GetRowForFunctionOffset(int offset) const;
453+
// instructions. If offset is std::nullopt it indicates that the function
454+
// start is unknown - the final row in the UnwindPlan is returned. In
455+
// practice, the UnwindPlan for a function with no known start address will be
456+
// the architectural default UnwindPlan which will only have one row.
457+
const UnwindPlan::Row *
458+
GetRowForFunctionOffset(std::optional<int> offset) const;
458459

459460
lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
460461

lldb/include/lldb/Target/RegisterContextUnwind.h

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

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

246245
bool m_behaves_like_zeroth_frame; // this frame behaves like frame zero
247246

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
@@ -199,8 +200,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
199200
m_current_offset_backed_up_one = m_current_offset;
200201
} else {
201202
m_start_pc = m_current_pc;
202-
m_current_offset = -1;
203-
m_current_offset_backed_up_one = -1;
203+
m_current_offset = std::nullopt;
204+
m_current_offset_backed_up_one = std::nullopt;
204205
}
205206

206207
// We've set m_frame_type and m_sym_ctx before these calls.
@@ -439,8 +440,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
439440
m_frame_type = eNormalFrame;
440441
}
441442
m_all_registers_available = false;
442-
m_current_offset = -1;
443-
m_current_offset_backed_up_one = -1;
443+
m_current_offset = std::nullopt;
444+
m_current_offset_backed_up_one = std::nullopt;
444445
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
445446
if (const UnwindPlan::Row *row =
446447
m_full_unwind_plan_sp->GetRowForFunctionOffset(0)) {
@@ -571,16 +572,16 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
571572
m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
572573
m_current_offset_backed_up_one = m_current_offset;
573574
if (decr_pc_and_recompute_addr_range &&
574-
m_current_offset_backed_up_one > 0) {
575-
m_current_offset_backed_up_one--;
575+
m_current_offset_backed_up_one != 0) {
576+
--*m_current_offset_backed_up_one;
576577
if (m_sym_ctx_valid) {
577578
m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget());
578579
}
579580
}
580581
} else {
581582
m_start_pc = m_current_pc;
582-
m_current_offset = -1;
583-
m_current_offset_backed_up_one = -1;
583+
m_current_offset = std::nullopt;
584+
m_current_offset_backed_up_one = std::nullopt;
584585
}
585586

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

753754
std::shared_ptr<const UnwindPlan>
754755
RegisterContextUnwind::GetFastUnwindPlanForFrame() {
@@ -790,7 +791,7 @@ 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
std::shared_ptr<const UnwindPlan>
796797
RegisterContextUnwind::GetFullUnwindPlanForFrame() {

0 commit comments

Comments
 (0)