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

ORC is currently failing to deregister the EH-frame section when the JIT is torn down #32248

Closed
llvmbot opened this issue May 3, 2017 · 3 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla orcjit

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented May 3, 2017

Bugzilla Link 32901
Resolution FIXED
Resolved on Jun 29, 2017 16:26
Version trunk
OS Linux
Attachments The reproduction case.
Reporter LLVM Bugzilla Contributor

Extended Description

I have a reproduction case (below) where if I throw an exception before I call JITSymbol::getAddress() everything works properly but throwing the same exception afterward will result in a SIGSEGV during stack unwinding. Lang Hames said on the llvm-dev mailing list:

"I've continued to dig in to this in my spare time and I've found the issue. It's a use-after-free, rather than any sort of memory smashing. ORC is currently failing to deregister the EH-frame section when the JIT is torn down (but is deallocating the memory for it). Normally that's not disastrous (though it does leave bogus EH frames in memory), but in your case the thrown exception tears down the JIT itself, so the unwinder ends up reading eh-frames that have been deallocated. I'm working on a fix to have the JIT properly deregister EH frames, but one workaround for now would be to make sure you catch the exception before it causes the JIT stack to be destructed."

This problem was initially discovered while working on my own project. While troubleshooting this I've discvoered that when LLVM is-DLLVM_USE_SANITIZER:STRING=Address the problem happens at different points during execution, perhaps having something to do with the padding around the stack variables added by the sanitizer? See the note after the call to runTest() in main().

I'm running this under an up-to-date Antergos Linux, clang version: 3.9.1 (tried compiling LLVM and the example program below with gcc 6.3.1 and the result is the same) clang set to default compiler by setting the following environment variables:

CC=/usr/bin/clang
CXX=/usr/bin/clang++

Commands used to build LLVM:

git clone https://github.com/llvm-mirror/llvm.git
git checkout release_40
cd llvm
mkdir build
cd build
cmake .. -DLLVM_BUILD_LLVM_DYLIB:BOOL=ON -DLLVM_ENABLE_RTTI:BOOL=ON -DLLVM_ENABLE_EH:BOOL=ON -DLLVM_USE_SANITIZER:STRING=Address -DLLVM_PARALLEL_COMPILE_JOBS:STRING=8 -DLLVM_ENABLE_ASSERTIONS:BOOL=ON
cmake --build . -- -j 8
sudo cmake --build . --target install

Command used to build test case executable:

clang test.cpp -std=c++14 -lstdc++ -lLLVM-4.0 -Wall -pedantic -Wextra  -fstack-protector-all -fsanitize=address -fexceptions

Then of course:

./a.out

Output from a.out:

ASAN:DEADLYSIGNAL

==6582==ERROR: AddressSanitizer: SEGV on unknown address 0x7f59eeb06020 (pc 0x7f59f1b20930 bp 0x000000000001 sp 0x7ffc5e546218 T0)
==6582==The signal is caused by a READ memory access.

The result if running backtrace in GDB while execution is paused after the SIGSEGV occurs:

#​0 read_encoded_value_with_base (encoding=encoding@entry=28 '\034', base=base@entry=0, p=p@entry=0x7fffe8a06020 <error: Cannot access memory at address 0x7fffe8a06020>, val=val@entry=0x7fffffffd6d8) at /build/gcc/src/gcc/libgcc/unwind-pe.h:252
#​1 0x00007fffeba05a61 in binary_search_single_encoding_fdes (pc=0x7fffeba04426 <_Unwind_Resume+54>, ob=0x0) at /build/gcc/src/gcc/libgcc/unwind-dw2-fde.c:908
#​2 search_object (ob=ob@entry=0x60400001d9d0, pc=pc@entry=0x7fffeba04426 <_Unwind_Resume+54>) at /build/gcc/src/gcc/libgcc/unwind-dw2-fde.c:977
#​3 0x00007fffeba05fdd in _Unwind_Find_registered_FDE (bases=0x7fffffffda78, pc=0x7fffeba04426 <_Unwind_Resume+54>) at /build/gcc/src/gcc/libgcc/unwind-dw2-fde.c:1013
#​4 _Unwind_Find_FDE (pc=0x7fffeba04426 <_Unwind_Resume+54>, bases=bases@entry=0x7fffffffda78) at /build/gcc/src/gcc/libgcc/unwind-dw2-fde-dip.c:454
#​5 0x00007fffeba02b23 in uw_frame_state_for (context=context@entry=0x7fffffffd9d0, fs=fs@entry=0x7fffffffd820) at /build/gcc/src/gcc/libgcc/unwind-dw2.c:1241
#​6 0x00007fffeba03d40 in uw_init_context_1 (context=context@entry=0x7fffffffd9d0, outer_cfa=outer_cfa@entry=0x7fffffffdc00, outer_ra=0x5110fc) at /build/gcc/src/gcc/libgcc/unwind-dw2.c:1562
#​7 0x00007fffeba04427 in _Unwind_Resume (exc=0x60d00000c7b0) at /build/gcc/src/gcc/libgcc/unwind.inc:224
#​8 0x00000000005110fc in runTest () at /home/dave/projects/untitled/test.cpp:124
#​9 0x0000000000511138 in main (argc=1, argv=0x7fffffffe698) at /home/dave/projects/untitled/test.cpp:132

My test-case is attached. In runTest(), note the commented out throw statement before symbol.getAddress() and the uncommented one after it. Also note the comments after the call to runTest() in main().

@llvmbot
Copy link
Collaborator Author

llvmbot commented May 3, 2017

assigned to @lhames

@lhames
Copy link
Contributor

lhames commented May 3, 2017

I've tracked this down to a use-after-free of JIT'd eh-frames.

The fix is to move responsibility for EH frame tracking from RuntimeDyld to RuntimeDyld::MemoryManager, and have the RTDyldObjectLinkingLayer deregister the frames when modules are unloaded.

The patch for this is currently out for review at https://reviews.llvm.org/D32829.

@lhames
Copy link
Contributor

lhames commented Jun 29, 2017

Belatedly closing: This should have been fixed by r302589.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla orcjit
Projects
None yet
Development

No branches or pull requests

2 participants