Skip to content
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

[libunwind] fix unwinding from signal handler #92291

Merged
merged 1 commit into from
Jul 9, 2024

Conversation

azat
Copy link
Contributor

@azat azat commented May 15, 2024

In case of this is frame of signal handler, the IP should be incremented, because the IP saved in the signal handler points to first non-executed instruction, while FDE/CIE expects IP to be after the first non-executed instruction.

Refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208

@azat azat requested a review from a team as a code owner May 15, 2024 16:18
@llvmbot
Copy link
Collaborator

llvmbot commented May 15, 2024

@llvm/pr-subscribers-libunwind

Author: Azat Khuzhin (azat)

Changes

In case of this is frame of signal handler, the IP should be incremented, because the IP saved in the signal handler points to first non-executed instruction, while FDE/CIE expects IP to be after the first non-executed instruction.

Refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208


Full diff: https://github.com/llvm/llvm-project/pull/92291.diff

1 Files Affected:

  • (modified) libunwind/src/DwarfInstructions.hpp (+6-1)
diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp
index bd9ece60ee588..5ea535be4b974 100644
--- a/libunwind/src/DwarfInstructions.hpp
+++ b/libunwind/src/DwarfInstructions.hpp
@@ -365,7 +365,12 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
 
       // Return address is address after call site instruction, so setting IP to
       // that does simulates a return.
-      newRegisters.setIP(returnAddress);
+      //
+      // In case of this is frame of signal handler, the IP should be
+      // incremented, because the IP saved in the signal handler points to
+      // first non-executed instruction, while FDE/CIE expects IP to be after
+      // the first non-executed instruction.
+      newRegisters.setIP(returnAddress + cieInfo.isSignalFrame);
 
       // Simulate the step by replacing the register set with the new ones.
       registers = newRegisters;

@azat
Copy link
Contributor Author

azat commented May 16, 2024

Build and Test libc++ / stage3 (generic-ubsan, libcxx-runners-8-set) (pull_request) Failing after 10m

Looks like unrelated?

2024-05-15T17:48:22.3468783Z ##[error]The runner has received a shutdown signal. This can happen when the runner service is stopped, or a manually started runner is canceled.

@azat
Copy link
Contributor Author

azat commented Jul 5, 2024

Can someone take a look? Maybe @MaskRay @compnerd (according to the most frequent reviewers from Reviewed By tag)

@azat azat force-pushed the libunwind/signal-handler branch from 5e3635c to 7066c0d Compare July 9, 2024 14:34
In case of this is frame of signal handler, the IP should be
incremented, because the IP saved in the signal handler points to first
non-executed instruction, while FDE/CIE expects IP to be after the
first non-executed instruction.

v2: move the increment from DwarfInstructions<A, R>::stepWithDwarf()
into the UnwindCursor<A, R>::setInfoBasedOnIPRegister() to avoid
exposing posslibly unaligned IP (also note, that this matches with gcc
implementation as well)
v3: only for non _LIBUNWIND_SUPPORT_SEH_UNWIND/_WIN32 OS

Refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208
Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this seems like the right place to handle this.

@compnerd
Copy link
Member

compnerd commented Jul 9, 2024

@azat do you need this to be committed on your behalf?

@azat azat force-pushed the libunwind/signal-handler branch from 7066c0d to 1f1e3d2 Compare July 9, 2024 16:33
@azat
Copy link
Contributor Author

azat commented Jul 9, 2024

@azat do you need this to be committed on your behalf?

I would be very much appreciate that, since I don't have write access.

@compnerd compnerd merged commit 7b604cd into llvm:main Jul 9, 2024
51 of 53 checks passed
@azat azat deleted the libunwind/signal-handler branch July 9, 2024 20:03
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
In case of this is frame of signal handler, the IP should be
incremented, because the IP saved in the signal handler points to first
non-executed instruction, while FDE/CIE expects IP to be after the first
non-executed instruction.

Refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208
@ldionne
Copy link
Member

ldionne commented Jul 16, 2024

Is it possible to add a test case for this?

@daltenty
Copy link
Member

This is breaking a number of tests for the UBSAN on AIX, the traceback produced by the runtime are no longer correct.

Before this change:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==52887862==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x00000000 (pc 0x10000784 bp 0x2ff22020 sp 0x2ff22020 T59639729)
==52887862==The signal is caused by a UNKNOWN memory access.
==52887862==Hint: address points to the zero page.
    #0 0x10000784 in .void Xyz::Abc<int, int>() /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:20
    #1 0x1000073c in .bar /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:25
    #2 0x100007cc in .FOO() /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:29
    #3 0x10000834 in .main /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:33
    #4 0x100002d0 in .__start (/home/daltenty/llvm/dev/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/ubsan-powerpc-AIX/Posix/Output/dedup_token_length_test.cpp.tmp+0x100002d0)

DEDUP_TOKEN: .void Xyz::Abc<int, int>()--.bar
UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:20 in .void Xyz::Abc<int, int>()
==52887862==ABORTING

After:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1704572==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x00000000 (pc 0x10000784 bp 0x2ff221b0 sp 0x2ff221b0 T56035233)
==1704572==The signal is caused by a UNKNOWN memory access.
==1704572==Hint: address points to the zero page.
    #0 0x10000784 in .void Xyz::Abc<int, int>() /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:20
    #1 0x1001d764 in .ubsan_GetStackTrace(__sanitizer::BufferedStackTrace*, unsigned int, unsigned int, unsigned int, void*, bool) /home/daltenty/llvm/dev/llvm-project/compiler-rt/lib/ubsan/ubsan_diag.cpp:41
    #2 0x10025ca4 in .__ubsan::OnStackUnwind(__sanitizer::SignalContext const&, void const*, __sanitizer::BufferedStackTrace*) /home/daltenty/llvm/dev/llvm-project/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp:53
    #3 0x1001cd10 in ReportDeadlySignalImpl /home/daltenty/llvm/dev/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp:272
    #4 0x1001cd10 in .__sanitizer::ReportDeadlySignal(__sanitizer::SignalContext const&, unsigned int, void (*)(__sanitizer::SignalContext const&, void const*, __sanitizer::BufferedStackTrace*), void const*) /home/daltenty/llvm/dev/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp:286
    #5 0x1001d2d4 in .__sanitizer::HandleDeadlySignal(void*, void*, unsigned int, void (*)(__sanitizer::SignalContext const&, void const*, __sanitizer::BufferedStackTrace*), void const*) /home/daltenty/llvm/dev/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp:295

DEDUP_TOKEN: .void Xyz::Abc<int, int>()--.ubsan_GetStackTrace(__sanitizer::BufferedStackTrace*, unsigned int, unsigned int, unsigned int, void*, bool)
UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV /home/daltenty/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cpp:20 in .void Xyz::Abc<int, int>()
==1704572==ABORTING

xingxue-ibm added a commit to xingxue-ibm/llvm-project that referenced this pull request Jul 29, 2024
…e added to exclude traceback based unwinding used for AIX.
tru pushed a commit to xingxue-ibm/llvm-project that referenced this pull request Jul 30, 2024
…e added to exclude traceback based unwinding used for AIX.
xingxue-ibm added a commit that referenced this pull request Jul 30, 2024
Patch [#92291](#92291)
causes wrong traceback from a signal handler for AIX because the AIX
unwinder uses the traceback table at the end of each function instead of
FDE/CIE for unwinding. This patch adds a condition to exclude traceback
table based unwinding from the code added by the patch.
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 30, 2024
…1069)

Patch [llvm#92291](llvm#92291)
causes wrong traceback from a signal handler for AIX because the AIX
unwinder uses the traceback table at the end of each function instead of
FDE/CIE for unwinding. This patch adds a condition to exclude traceback
table based unwinding from the code added by the patch.

(cherry picked from commit d90fa61)
tru pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 31, 2024
…1069)

Patch [llvm#92291](llvm#92291)
causes wrong traceback from a signal handler for AIX because the AIX
unwinder uses the traceback table at the end of each function instead of
FDE/CIE for unwinding. This patch adds a condition to exclude traceback
table based unwinding from the code added by the patch.

(cherry picked from commit d90fa61)
banach-space pushed a commit to banach-space/llvm-project that referenced this pull request Aug 7, 2024
…1069)

Patch [llvm#92291](llvm#92291)
causes wrong traceback from a signal handler for AIX because the AIX
unwinder uses the traceback table at the end of each function instead of
FDE/CIE for unwinding. This patch adds a condition to exclude traceback
table based unwinding from the code added by the patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants