Skip to content

Commit cdb9c61

Browse files
authored
[lldb] Support negative function offsets in UnwindPlans (#134662)
These are needed for functions whose entry point is not their lowest address.
1 parent d34437e commit cdb9c61

File tree

8 files changed

+161
-155
lines changed

8 files changed

+161
-155
lines changed

lldb/include/lldb/Symbol/UnwindPlan.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,11 @@ class UnwindPlan {
356356

357357
void RemoveRegisterInfo(uint32_t reg_num);
358358

359-
lldb::addr_t GetOffset() const { return m_offset; }
359+
int64_t GetOffset() const { return m_offset; }
360360

361-
void SetOffset(lldb::addr_t offset) { m_offset = offset; }
361+
void SetOffset(int64_t offset) { m_offset = offset; }
362362

363-
void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
363+
void SlideOffset(int64_t offset) { m_offset += offset; }
364364

365365
const FAValue &GetCFAValue() const { return m_cfa_value; }
366366
FAValue &GetCFAValue() { return m_cfa_value; }
@@ -420,7 +420,7 @@ class UnwindPlan {
420420

421421
protected:
422422
typedef std::map<uint32_t, AbstractRegisterLocation> collection;
423-
lldb::addr_t m_offset = 0; // Offset into the function for this row
423+
int64_t m_offset = 0; // Offset into the function for this row
424424

425425
FAValue m_cfa_value;
426426
FAValue m_afa_value;
@@ -455,7 +455,7 @@ class UnwindPlan {
455455
// practice, the UnwindPlan for a function with no known start address will be
456456
// the architectural default UnwindPlan which will only have one row.
457457
const UnwindPlan::Row *
458-
GetRowForFunctionOffset(std::optional<int> offset) const;
458+
GetRowForFunctionOffset(std::optional<int64_t> offset) const;
459459

460460
lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
461461

lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1390,11 +1390,12 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
13901390

13911391
// If we already have one row for this instruction, we can continue.
13921392
while (row_id < unwind_plan.GetRowCount() &&
1393-
unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) {
1393+
unwind_plan.GetRowAtIndex(row_id)->GetOffset() <=
1394+
static_cast<int64_t>(offset)) {
13941395
row_id++;
13951396
}
13961397
const UnwindPlan::Row *original_row = unwind_plan.GetRowAtIndex(row_id - 1);
1397-
if (original_row->GetOffset() == offset) {
1398+
if (original_row->GetOffset() == static_cast<int64_t>(offset)) {
13981399
row = *original_row;
13991400
continue;
14001401
}

lldb/source/Symbol/DWARFCallFrameInfo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
735735
__FUNCTION__, dwarf_offset, startaddr.GetFileAddress());
736736
break;
737737
}
738-
lldb::addr_t offset = row.GetOffset();
738+
int64_t offset = row.GetOffset();
739739
row = std::move(stack.back());
740740
stack.pop_back();
741741
row.SetOffset(offset);

lldb/source/Symbol/UnwindPlan.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,10 @@ void UnwindPlan::AppendRow(Row row) {
398398
}
399399

400400
struct RowLess {
401-
bool operator()(addr_t a, const UnwindPlan::Row &b) const {
401+
bool operator()(int64_t a, const UnwindPlan::Row &b) const {
402402
return a < b.GetOffset();
403403
}
404-
bool operator()(const UnwindPlan::Row &a, addr_t b) const {
404+
bool operator()(const UnwindPlan::Row &a, int64_t b) const {
405405
return a.GetOffset() < b;
406406
}
407407
};
@@ -418,7 +418,7 @@ void UnwindPlan::InsertRow(Row row, bool replace_existing) {
418418
}
419419

420420
const UnwindPlan::Row *
421-
UnwindPlan::GetRowForFunctionOffset(std::optional<int> offset) const {
421+
UnwindPlan::GetRowForFunctionOffset(std::optional<int64_t> offset) const {
422422
auto it = offset ? llvm::upper_bound(m_row_list, *offset, RowLess())
423423
: m_row_list.end();
424424
if (it == m_row_list.begin())

lldb/unittests/Symbol/UnwindPlanTest.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static UnwindPlan::Row make_simple_row(addr_t offset, uint64_t cfa_value) {
2424
TEST(UnwindPlan, InsertRow) {
2525
UnwindPlan::Row row1 = make_simple_row(0, 42);
2626
UnwindPlan::Row row2 = make_simple_row(0, 47);
27+
UnwindPlan::Row row3 = make_simple_row(-1, 4242);
2728

2829
UnwindPlan plan(eRegisterKindGeneric);
2930
plan.InsertRow(row1);
@@ -34,6 +35,10 @@ TEST(UnwindPlan, InsertRow) {
3435

3536
plan.InsertRow(row2, /*replace_existing=*/true);
3637
EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(row2));
38+
39+
EXPECT_THAT(plan.GetRowForFunctionOffset(-1), nullptr);
40+
plan.InsertRow(row3);
41+
EXPECT_THAT(plan.GetRowForFunctionOffset(-1), testing::Pointee(row3));
3742
}
3843

3944
TEST(UnwindPlan, GetRowForFunctionOffset) {

lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp

+25-25
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
9090

9191
// CFA=sp +0 => fp= <same> lr= <same>
9292
row = unwind_plan.GetRowForFunctionOffset(0);
93-
EXPECT_EQ(0ull, row->GetOffset());
93+
EXPECT_EQ(0, row->GetOffset());
9494
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
9595
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
9696
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
@@ -103,7 +103,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
103103

104104
// CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
105105
row = unwind_plan.GetRowForFunctionOffset(4);
106-
EXPECT_EQ(4ull, row->GetOffset());
106+
EXPECT_EQ(4, row->GetOffset());
107107
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
108108
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
109109
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -118,7 +118,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
118118

119119
// CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
120120
row = unwind_plan.GetRowForFunctionOffset(8);
121-
EXPECT_EQ(8ull, row->GetOffset());
121+
EXPECT_EQ(8, row->GetOffset());
122122
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
123123
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
124124
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -133,7 +133,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
133133

134134
// CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
135135
row = unwind_plan.GetRowForFunctionOffset(16);
136-
EXPECT_EQ(16ull, row->GetOffset());
136+
EXPECT_EQ(16, row->GetOffset());
137137
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
138138
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
139139
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -148,7 +148,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
148148

149149
// CFA=sp +0 => fp= <same> lr= <same>
150150
row = unwind_plan.GetRowForFunctionOffset(20);
151-
EXPECT_EQ(20ull, row->GetOffset());
151+
EXPECT_EQ(20, row->GetOffset());
152152
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
153153
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
154154
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
@@ -219,14 +219,14 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
219219

220220
// 0: CFA=sp +0 =>
221221
row = unwind_plan.GetRowForFunctionOffset(0);
222-
EXPECT_EQ(0ull, row->GetOffset());
222+
EXPECT_EQ(0, row->GetOffset());
223223
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
224224
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
225225
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
226226

227227
// 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48]
228228
row = unwind_plan.GetRowForFunctionOffset(4);
229-
EXPECT_EQ(4ull, row->GetOffset());
229+
EXPECT_EQ(4, row->GetOffset());
230230
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
231231
EXPECT_EQ(48, row->GetCFAValue().GetOffset());
232232

@@ -240,7 +240,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
240240

241241
// 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
242242
row = unwind_plan.GetRowForFunctionOffset(8);
243-
EXPECT_EQ(8ull, row->GetOffset());
243+
EXPECT_EQ(8, row->GetOffset());
244244
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
245245
EXPECT_EQ(48, row->GetCFAValue().GetOffset());
246246

@@ -255,7 +255,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
255255
// 12: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
256256
// fp=[CFA-16] lr=[CFA-8]
257257
row = unwind_plan.GetRowForFunctionOffset(12);
258-
EXPECT_EQ(12ull, row->GetOffset());
258+
EXPECT_EQ(12, row->GetOffset());
259259
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
260260
EXPECT_EQ(48, row->GetCFAValue().GetOffset());
261261

@@ -270,23 +270,23 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
270270
// 16: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
271271
// fp=[CFA-16] lr=[CFA-8]
272272
row = unwind_plan.GetRowForFunctionOffset(16);
273-
EXPECT_EQ(16ull, row->GetOffset());
273+
EXPECT_EQ(16, row->GetOffset());
274274
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
275275
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
276276
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
277277

278278
// 28: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
279279
// fp=[CFA-16] lr=[CFA-8]
280280
row = unwind_plan.GetRowForFunctionOffset(28);
281-
EXPECT_EQ(28ull, row->GetOffset());
281+
EXPECT_EQ(28, row->GetOffset());
282282
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
283283
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
284284
EXPECT_EQ(48, row->GetCFAValue().GetOffset());
285285

286286
// 32: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] fp=
287287
// <same> lr= <same>
288288
row = unwind_plan.GetRowForFunctionOffset(32);
289-
EXPECT_EQ(32ull, row->GetOffset());
289+
EXPECT_EQ(32, row->GetOffset());
290290

291291
// I'd prefer if these restored registers were cleared entirely instead of set
292292
// to IsSame...
@@ -299,7 +299,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
299299
// 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp=
300300
// <same> lr= <same>
301301
row = unwind_plan.GetRowForFunctionOffset(36);
302-
EXPECT_EQ(36ull, row->GetOffset());
302+
EXPECT_EQ(36, row->GetOffset());
303303

304304
EXPECT_TRUE(row->GetRegisterInfo(gpr_x19_arm64, regloc));
305305
EXPECT_TRUE(regloc.IsSame());
@@ -310,7 +310,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
310310
// 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same>
311311
// lr= <same>
312312
row = unwind_plan.GetRowForFunctionOffset(40);
313-
EXPECT_EQ(40ull, row->GetOffset());
313+
EXPECT_EQ(40, row->GetOffset());
314314
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
315315
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
316316
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
@@ -373,7 +373,7 @@ TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) {
373373

374374
// 0: CFA=sp +0 =>
375375
row = unwind_plan.GetRowForFunctionOffset(0);
376-
EXPECT_EQ(0ull, row->GetOffset());
376+
EXPECT_EQ(0, row->GetOffset());
377377
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
378378
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
379379
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
@@ -503,7 +503,7 @@ TEST_F(TestArm64InstEmulation, TestRegisterSavedTwice) {
503503
sample_range, data, sizeof(data), unwind_plan));
504504

505505
row = unwind_plan.GetRowForFunctionOffset(36);
506-
EXPECT_EQ(28ull, row->GetOffset());
506+
EXPECT_EQ(28, row->GetOffset());
507507
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
508508
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
509509
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -513,7 +513,7 @@ TEST_F(TestArm64InstEmulation, TestRegisterSavedTwice) {
513513
EXPECT_EQ(-32, regloc.GetOffset());
514514

515515
row = unwind_plan.GetRowForFunctionOffset(40);
516-
EXPECT_EQ(28ull, row->GetOffset());
516+
EXPECT_EQ(28, row->GetOffset());
517517
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
518518
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
519519
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -619,7 +619,7 @@ TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) {
619619
// d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
620620
// d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
621621
row = unwind_plan.GetRowForFunctionOffset(28);
622-
EXPECT_EQ(28ull, row->GetOffset());
622+
EXPECT_EQ(28, row->GetOffset());
623623
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
624624
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
625625
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
@@ -658,7 +658,7 @@ TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) {
658658

659659
// 60: CFA=sp +0 =>
660660
row = unwind_plan.GetRowForFunctionOffset(60);
661-
EXPECT_EQ(60ull, row->GetOffset());
661+
EXPECT_EQ(60, row->GetOffset());
662662
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
663663
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
664664
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
@@ -765,30 +765,30 @@ TEST_F(TestArm64InstEmulation, TestCFARegisterTrackedAcrossJumps) {
765765

766766
// Confirm CFA at mid-func epilogue 'ret' is $sp+0
767767
row = unwind_plan.GetRowForFunctionOffset(40);
768-
EXPECT_EQ(40ull, row->GetOffset());
768+
EXPECT_EQ(40, row->GetOffset());
769769
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
770770
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
771771
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
772772

773773
// After the 'ret', confirm we're back to the correct CFA of $fp+16
774774
row = unwind_plan.GetRowForFunctionOffset(44);
775-
EXPECT_EQ(44ull, row->GetOffset());
775+
EXPECT_EQ(44, row->GetOffset());
776776
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
777777
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
778778
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
779779

780780
// Confirm that we have no additional UnwindPlan rows before the
781781
// real epilogue -- we still get the Row at offset 44.
782782
row = unwind_plan.GetRowForFunctionOffset(60);
783-
EXPECT_EQ(44ull, row->GetOffset());
783+
EXPECT_EQ(44, row->GetOffset());
784784
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
785785
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
786786
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
787787

788788
// And in the epilogue, confirm that we start by switching back to
789789
// defining the CFA in terms of $sp.
790790
row = unwind_plan.GetRowForFunctionOffset(64);
791-
EXPECT_EQ(64ull, row->GetOffset());
791+
EXPECT_EQ(64, row->GetOffset());
792792
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
793793
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
794794
EXPECT_EQ(32, row->GetCFAValue().GetOffset());
@@ -845,14 +845,14 @@ TEST_F(TestArm64InstEmulation, TestCFAResetToSP) {
845845

846846
// Confirm CFA before epilogue instructions is in terms of $fp
847847
row = unwind_plan.GetRowForFunctionOffset(12);
848-
EXPECT_EQ(12ull, row->GetOffset());
848+
EXPECT_EQ(12, row->GetOffset());
849849
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
850850
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
851851

852852
// Confirm that after restoring $fp to caller's value, CFA is now in
853853
// terms of $sp
854854
row = unwind_plan.GetRowForFunctionOffset(16);
855-
EXPECT_EQ(16ull, row->GetOffset());
855+
EXPECT_EQ(16, row->GetOffset());
856856
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
857857
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
858858
}

0 commit comments

Comments
 (0)