Skip to content

Reapply "[lldb/aarch64] Fix unwinding when signal interrupts a leaf f… #92503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 21, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ bool EmulateInstructionARM64::CreateFunctionEntryUnwind(

// Our previous Call Frame Address is the stack pointer
row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0);
row->SetRegisterLocationToSame(gpr_lr_arm64, /*must_replace=*/false);
row->SetRegisterLocationToSame(gpr_fp_arm64, /*must_replace=*/false);

unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("EmulateInstructionARM64");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,6 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
log->PutString(strm.GetString());
}

const bool cant_replace = false;

switch (context.type) {
default:
case EmulateInstruction::eContextInvalid:
Expand Down Expand Up @@ -467,7 +465,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
m_pushed_regs[reg_num] = addr;
const int32_t offset = addr - m_initial_sp;
m_curr_row->SetRegisterLocationToAtCFAPlusOffset(reg_num, offset,
cant_replace);
/*can_replace=*/true);
m_curr_row_modified = true;
}
}
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Target/RegisterContextUnwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1555,12 +1555,12 @@ RegisterContextUnwind::SavedLocationForRegister(
}

if (unwindplan_regloc.IsSame()) {
if (!IsFrameZero() &&
if (!m_all_registers_available &&
(regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC ||
regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) {
UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or "
"return address reg on a non-zero frame -- treat as if we "
"have no information",
"return address reg on a frame which does not have all "
"registers available -- treat as if we have no information",
regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
} else {
Expand Down
1 change: 1 addition & 0 deletions lldb/test/API/functionalities/bt-interrupt/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct Foo {

int
forgot_termination(int input, struct Foo my_foo) {
char frame_increasing_buffer[0x1000]; // To blow the stack sooner.
return forgot_termination(++input, my_foo);
}

Expand Down
15 changes: 15 additions & 0 deletions lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <signal.h>
#include <unistd.h>

int __attribute__((naked)) signal_generating_add(int a, int b) {
asm("add w0, w1, w0\n\t"
"udf #0xdead\n\t"
"ret");
}

void sigill_handler(int signo) { _exit(0); }

int main() {
signal(SIGILL, sigill_handler);
return signal_generating_add(42, 47);
}
30 changes: 30 additions & 0 deletions lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# REQUIRES: target-aarch64 && native
# UNSUPPORTED: system-windows
# llvm.org/pr91610, rdar://128031075
# XFAIL: system-darwin


# RUN: %clang_host %S/Inputs/signal-in-leaf-function-aarch64.c -o %t
# RUN: %lldb -s %s -o exit %t | FileCheck %s

# Convert EXC_BAD_INSTRUCTION to SIGILL on darwin
settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_INSTRUCTION

breakpoint set -n sigill_handler
# CHECK: Breakpoint 1: where = {{.*}}`sigill_handler

run
# CHECK: thread #1, {{.*}} stop reason = signal SIGILL

thread backtrace
# CHECK: frame #0: [[ADD:0x[0-9a-fA-F]*]] {{.*}}`signal_generating_add
# CHECK: frame #1: [[MAIN:0x[0-9a-fA-F]*]] {{.*}}`main

continue
# CHECK: thread #1, {{.*}} stop reason = breakpoint 1

thread backtrace
# CHECK: frame #0: {{.*}}`sigill_handler
# Unknown number of signal trampoline frames
# CHECK: frame #{{[0-9]+}}: [[ADD]] {{.*}}`signal_generating_add
# CHECK: frame #{{[0-9]+}}: [[MAIN]] {{.*}}`main
24 changes: 20 additions & 4 deletions lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {

// UnwindPlan we expect:

// row[0]: 0: CFA=sp +0 =>
// row[0]: 0: CFA=sp +0 => fp= <same> lr= <same>
// row[1]: 4: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
// row[2]: 8: CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
// row[2]: 16: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
Expand All @@ -88,13 +88,19 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
sample_range, data, sizeof(data), unwind_plan));

// CFA=sp +0
// CFA=sp +0 => fp= <same> lr= <same>
row_sp = unwind_plan.GetRowForFunctionOffset(0);
EXPECT_EQ(0ull, row_sp->GetOffset());
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());

// CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
row_sp = unwind_plan.GetRowForFunctionOffset(4);
EXPECT_EQ(4ull, row_sp->GetOffset());
Expand Down Expand Up @@ -146,6 +152,12 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());
}

TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
Expand Down Expand Up @@ -381,8 +393,12 @@ TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) {
EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());

EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
EXPECT_TRUE(regloc.IsSame());

row_sp = unwind_plan.GetRowForFunctionOffset(36);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
Expand Down
Loading