From 3fd917d8860e9bdcabc14c536da4377307906be0 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Fri, 19 Jul 2019 14:05:55 +0000 Subject: Support Linux signal return trampolines in frame initialization Summary: Add __kernel_rt_sigreturn to the list of trap handlers for Linux (it's used as such on aarch64 at least), and __restore_rt as well (used on x86_64). Skip decrement-and-recompute for trap handlers in InitializeNonZerothFrame, as signal dispatch may point the child frame's return address to the start of the return trampoline. Parse the 'S' flag for signal handlers from eh_frame augmentation, and propagate it to the unwind plan. Reviewers: labath, jankratochvil, compnerd, jfb, jasonmolenda Reviewed By: jasonmolenda Subscribers: clayborg, MaskRay, wuzish, nemanjai, kbarton, jrtc27, atanasyan, jsji, javed.absar, kristof.beyls, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D63667 llvm-svn: 366580 --- .../functionalities/signal/handle-abrt/Makefile | 5 ++ .../signal/handle-abrt/TestHandleAbort.py | 72 ++++++++++++++++++++++ .../test/functionalities/signal/handle-abrt/main.c | 25 ++++++++ 3 files changed, 102 insertions(+) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c (limited to 'lldb/packages/Python/lldbsuite') diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile new file mode 100644 index 00000000000..b09a579159d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py new file mode 100644 index 00000000000..022ad929162 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py @@ -0,0 +1,72 @@ +"""Test that we can unwind out of a SIGABRT handler""" + +from __future__ import print_function + + +import os +import re + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class HandleAbortTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @skipIfWindows # signals do not exist on Windows + def test_inferior_handle_sigabrt(self): + """Inferior calls abort() and handles the resultant SIGABRT. + Stopped at a breakpoint in the handler, verify that the backtrace + includes the function that called abort().""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # launch + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetState(), lldb.eStateStopped) + signo = process.GetUnixSignals().GetSignalNumberFromName("SIGABRT") + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + self.assertTrue( + thread and thread.IsValid(), + "Thread should be stopped due to a signal") + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There should be data in the event.") + self.assertEqual(thread.GetStopReasonDataAtIndex(0), + signo, "The stop signal should be SIGABRT") + + # Continue to breakpoint in abort handler + bkpt = target.FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp(self, "Set a breakpoint here")) + threads = lldbutil.continue_to_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "Expected single thread") + thread = threads[0] + + # Expect breakpoint in 'handler' + frame = thread.GetFrameAtIndex(0) + self.assertEqual(frame.GetDisplayFunctionName(), "handler", "Unexpected break?") + + # Expect that unwinding should find 'abort_caller' + foundFoo = False + for frame in thread: + if frame.GetDisplayFunctionName() == "abort_caller": + foundFoo = True + + self.assertTrue(foundFoo, "Unwinding did not find func that called abort") + + # Continue until we exit. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c new file mode 100644 index 00000000000..c2daea1e84e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void handler(int sig) +{ + printf("Set a breakpoint here.\n"); + exit(0); +} + +void abort_caller() { + abort(); +} + +int main() +{ + if (signal(SIGABRT, handler) == SIG_ERR) + { + perror("signal"); + return 1; + } + + abort_caller(); + return 2; +} -- cgit v1.2.3