DavidSpickett created this revision. Herald added subscribers: kristof.beyls, mgorny. DavidSpickett requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
This adds a specific unwind plan for AArch64 Linux sigreturn frames. Previously we assumed that the fp would be valid here but it is not. https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S On Ubuntu Bionic it happened to point to an old frame info which meant you got what looked like a correct backtrace. On Focal, the info is completely invalid. (probably due to some code shuffling in libc) This adds an UnwindPlan that knows that the sp in a sigreturn frame points to an rt_sigframe from which we can offset to get saved sp and pc values to backtrace correctly. Based on LibUnwind's change: https://reviews.llvm.org/D90898 This also updates TestHandleAbort to check that common frames between signal and signal handler backtrace are in fact the same. Fixes https://bugs.llvm.org/show_bug.cgi?id=52165 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D112069 Files: lldb/include/lldb/Symbol/AArch64UnwindInfo.h lldb/source/Symbol/AArch64UnwindInfo.cpp lldb/source/Symbol/CMakeLists.txt lldb/source/Target/RegisterContextUnwind.cpp lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py
Index: lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py =================================================================== --- lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py +++ lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py @@ -16,8 +16,6 @@ NO_DEBUG_INFO_TESTCASE = True @skipIfWindows # signals do not exist on Windows - # Fails on Ubuntu Focal - @skipIf(archs=["aarch64"], oslist=["linux"]) @expectedFailureNetBSD def test_inferior_handle_sigabrt(self): """Inferior calls abort() and handles the resultant SIGABRT. @@ -47,6 +45,9 @@ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo, "The stop signal should be SIGABRT") + # Save the backtrace frames to compare to the handler backtrace later. + signal_frames = thread.get_thread_frames() + # Continue to breakpoint in abort handler bkpt = target.FindBreakpointByID( lldbutil.run_break_set_by_source_regexp(self, "Set a breakpoint here")) @@ -58,13 +59,21 @@ frame = thread.GetFrameAtIndex(0) self.assertEqual(frame.GetDisplayFunctionName(), "handler", "Unexpected break?") + handler_frames = thread.get_thread_frames() + # Expect that unwinding should find 'abort_caller' - foundFoo = False - for frame in thread: + found_caller = False + for frame in handler_frames: if frame.GetDisplayFunctionName() == "abort_caller": - foundFoo = True + found_caller = True + break + + self.assertTrue(found_caller, "Unwinding did not find func that called abort") - self.assertTrue(foundFoo, "Unwinding did not find func that called abort") + # Check that frames present in both backtraces have the same addresses. + # The signal handler backtrace has extra frames at the start. + self.assertEqual(signal_frames, handler_frames[-len(signal_frames):], + "Common frames for signal and signal handler backtrace do not match") # Continue until we exit. process.Continue() Index: lldb/source/Target/RegisterContextUnwind.cpp =================================================================== --- lldb/source/Target/RegisterContextUnwind.cpp +++ lldb/source/Target/RegisterContextUnwind.cpp @@ -12,6 +12,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/AArch64UnwindInfo.h" #include "lldb/Symbol/ArmUnwindInfo.h" #include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" @@ -900,6 +901,11 @@ // unwind out of sigtramp. if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); + + unwind_plan_sp = GetAArch64LinuxTrapHandlerUnwindPlan(process->GetTarget()); + if (unwind_plan_sp) + return unwind_plan_sp; + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); if (!unwind_plan_sp) Index: lldb/source/Symbol/CMakeLists.txt =================================================================== --- lldb/source/Symbol/CMakeLists.txt +++ lldb/source/Symbol/CMakeLists.txt @@ -7,6 +7,7 @@ endif() add_lldb_library(lldbSymbol + AArch64UnwindInfo.cpp ArmUnwindInfo.cpp Block.cpp CompactUnwindInfo.cpp Index: lldb/source/Symbol/AArch64UnwindInfo.cpp =================================================================== --- /dev/null +++ lldb/source/Symbol/AArch64UnwindInfo.cpp @@ -0,0 +1,63 @@ +//===-- AArch64UnwindInfo.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/AArch64UnwindInfo.h" +#include "Utility/ARM64_DWARF_Registers.h" + +using namespace lldb; +using namespace lldb_private; + +lldb::UnwindPlanSP +lldb_private::GetAArch64LinuxTrapHandlerUnwindPlan(const Target &target) { + lldb::UnwindPlanSP unwind_plan_sp; + ArchSpec arch = target.GetArchitecture(); + llvm::Triple::ArchType machine = arch.GetMachine(); + + if ((machine != llvm::Triple::ArchType::aarch64 && + machine != llvm::Triple::ArchType::aarch64_be && + machine != llvm::Triple::ArchType::aarch64_32) || + arch.GetTriple().getOS() != llvm::Triple::OSType::Linux) + return unwind_plan_sp; + + UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); + row->SetOffset(0); + + // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: + // - 128-byte siginfo struct + // - ucontext struct: + // - 8-byte long (uc_flags) + // - 8-byte pointer (uc_link) + // - 24-byte stack_t + // - 128-byte signal set + // - 8 bytes of padding because sigcontext has 16-byte alignment + // - sigcontext/mcontext_t + // [1] + // https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c + int32_t offset = 128 + 8 + 8 + 24 + 128 + 8; + // Then sigcontext[2] is: + // - 8 byte fault address + // - 31 8 byte registers + // - 8 byte sp + // - 8 byte pc + // [2] + // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/sigcontext.h + offset += 8 + (31 * 8); + row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, offset); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::fp, 0, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::pc, 8, false); + + unwind_plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric); + unwind_plan_sp->AppendRow(row); + unwind_plan_sp->SetSourceName("AArch64 Linux sigcontext"); + unwind_plan_sp->SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolYes); + unwind_plan_sp->SetRegisterKind(eRegisterKindDWARF); + + return unwind_plan_sp; +} Index: lldb/include/lldb/Symbol/AArch64UnwindInfo.h =================================================================== --- /dev/null +++ lldb/include/lldb/Symbol/AArch64UnwindInfo.h @@ -0,0 +1,26 @@ +//===-- AArch64UnwindInfo.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SYMBOL_AARCH64UNWINDINFO_H +#define LLDB_SYMBOL_AARCH64UNWINDINFO_H + +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Target.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// If target is AArch64 Linux return a shared pointer to +// an UnwindPlan. Otherwise return an invalid shared pointer. +// We assume the caller has checked that they are in a trap handler frame. +lldb::UnwindPlanSP GetAArch64LinuxTrapHandlerUnwindPlan(const Target &target); + +} // namespace lldb_private + +#endif // LLDB_SYMBOL_AARCH64UNWINDINFO_H
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits