[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code

Everett Maus via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 9 15:51:17 PST 2020


>
> It depends on the amount of functionality here and how language specific
> this is. As it stands I don’t think this is C++ specific and could extend
> to other llvm language targets which makes it a better candidate with
> compiler-rt. It would be good to flesh out what behavior you want out of
> the personality function then go from there.
>

That makes sense.

I think there's one "must have" behavior and a few "very nice-to-have but
not required" behaviors.

The "must have" for the handler would be "it terminates the program when an
exception passes through code compiled with -fno-exceptions, hopefully in a
way that can be easily identified as different from a normal/healthy
program exit".

The nice-to-have list is probably longer:
1. Printing the exception type that was thrown
2. Recovering the place the exception was thrown /from/ and printing the
function name & offset.
3. Printing the function name that the unwinder reached that led to it
exiting.
4. (Extra fancy/pie in the sky "what I'd want if I were debugging this
situation"): printing the full demangled stack to the location the
exception was thrown from or the method that led to the exit.

I expect that (1) requires some language-specific handling (RTTI in
C++/etc.), so that'd imply that it might be good to have a libcxxabi
implementation even if there's also a compiler-rt version (it looks like
this is the case with __gxx_personality_v0 which is defined both in
compiler-rt here:
https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/gcc_personality_v0.c#L172
and in libcxxabi here:
https://github.com/llvm/llvm-project/blob/main/libcxxabi/src/cxa_personality.cpp#L953

I also think that possibly (2)/(3)/(4) might require some non-compiler-rt
components, but I'm not certain if they would (I haven't dug into what's in
compiler-rt in depth quite yet).  That may also be reasonable to defer or
to have a sanitizer handle.

--EJM


On Wed, Dec 9, 2020 at 12:15 PM Reid Kleckner via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> Bleh, early send. We'd also have to overcome the issue of functions being
> nounwind with -fno-exceptions, which means LLVM would optimize those
> invokes to calls immediately.
>
> On Wed, Dec 9, 2020 at 12:14 PM Reid Kleckner <rnk at google.com> wrote:
>
>> Using existing personality functions requires emitting an LLVM IR cleanup
>> around every function when building in this -fterminate-exceptions mode.
>> Then all functions would have IR like this:
>>
>> invoke void @foo(...) unwind to %terminate
>> invoke void @bar(...) unwind to %terminate
>> ...
>> landingpad cleanup ...
>>   call void @myterminate()
>>
>> On Tue, Dec 8, 2020 at 12:56 PM James Y Knight <jyknight at google.com>
>> wrote:
>>
>>> Why is adding a new personality function useful? Can't you share a
>>> single LSDA table for every noexcept function in a TU (both those
>>> implicitly noexcept due to -fno-exceptions and for those marked "noexcept")?
>>>
>>> On Tue, Dec 8, 2020 at 1:05 PM Reid Kleckner via llvm-dev <
>>> llvm-dev at lists.llvm.org> wrote:
>>>
>>>> I would suggest using a custom personality function for this. It will
>>>> optimize better and be much smaller than using a standard personality
>>>> function. It saves the LSDA tables.
>>>>
>>>> LLVM supports custom personality functions, so only clang changes are
>>>> required. You could either do something like add a flag to override the EH
>>>> personality with a custom one, or come up with a new dedicated
>>>> fno-exceptions termination personality and add it to compiler-rt.
>>>>
>>>> On Mon, Dec 7, 2020 at 3:31 PM Modi Mo via llvm-dev <
>>>> llvm-dev at lists.llvm.org> wrote:
>>>>
>>>>> If you don’t need to capture more information and can just terminate,
>>>>> you can directly register std::terminate as the personality routine as
>>>>> opposed to __gxx_personality_v0 or __CxxFrameHandler3/4 (Windows) which
>>>>> lets you omit other metadata and work cross-platform.
>>>>>
>>>>>
>>>>>
>>>>> Modi
>>>>>
>>>>>
>>>>>
>>>>> *From: *llvm-dev <llvm-dev-bounces at lists.llvm.org> on behalf of
>>>>> Everett Maus via llvm-dev <llvm-dev at lists.llvm.org>
>>>>> *Reply-To: *Everett Maus <evmaus at google.com>
>>>>> *Date: *Monday, December 7, 2020 at 12:47 PM
>>>>> *To: *"llvm-dev at lists.llvm.org" <llvm-dev at lists.llvm.org>
>>>>> *Subject: *[llvm-dev] Catching exceptions while unwinding through
>>>>> -fno-exceptions code
>>>>>
>>>>>
>>>>>
>>>>> Hey all:
>>>>>
>>>>>
>>>>>
>>>>> I wanted to bring up something that was discussed a few years ago
>>>>> around the behavior of exceptions when interacting with code compiled with
>>>>> -fno-exceptions. (In
>>>>> https://lists.llvm.org/pipermail/llvm-dev/2017-February/109992.html
>>>>> and
>>>>> https://lists.llvm.org/pipermail/llvm-dev/2017-February/109995.html)
>>>>>
>>>>>
>>>>>
>>>>> It's possible to compile (and link/etc.) code with -fexceptions for
>>>>> some compilation units and -fno-exceptions for others.  Unlike the behavior
>>>>> of noexcept (which requires termination), this doesn't have a specified
>>>>> behavior in the C++ standard as far as I can tell.  However, it can lead to
>>>>> memory leaks & other issues (e.x. with TSAN, it messes up the tracking of
>>>>> the current stack frame).
>>>>>
>>>>>
>>>>>
>>>>> I'd be interested in looking into potentially doing the work to add an
>>>>> option to clang/etc. to terminate when an exception traverses code compiled
>>>>> with -fno-exceptions, instead of simply allowing the unwinder to walk
>>>>> through the stack frame & leak memory/etc. (possibly behind a flag?).  This
>>>>> particular issue bit a team I work closely with, and I'd imagine it could
>>>>> be causing subtle issues for other clang users.
>>>>>
>>>>>
>>>>>
>>>>> I'm mostly concerned with solving this on Linux/x86_64, although if
>>>>> there's a way to solve it more generally I'm open to looking into doing
>>>>> that instead.
>>>>>
>>>>>
>>>>>
>>>>> I /think/ the right place to change this (from the discussions I
>>>>> linked) would be in the LLVM -> assembly layer, adding an appropriate
>>>>> .gcc_except_table for functions that are determined to be unable to throw
>>>>> exceptions (either due to noexcept or due to -fno-exceptions). Then the
>>>>> unwinder would find .eh_frame but no entry in the .gcc_except_table and
>>>>> should terminate (via  __gxx_personality_v0).
>>>>>
>>>>>
>>>>>
>>>>> Am I understanding that correctly?  What's the best way to propose
>>>>> this sort of change to clang? (document/just try to look at putting
>>>>> together a PR/other?)
>>>>>
>>>>>
>>>>>
>>>>> Alternatively--one other thing that occurred to me is that it could be
>>>>> reasonably cheap to simply add try/catch blocks that report an UBSAN error
>>>>> in all methods that shouldn't be able to throw an exception.  This
>>>>> obviously doesn't fix the code-generation problem and would lead to larger
>>>>> binary sizes, but that seems less bad for an UBSAN build in particular.
>>>>> That would likely meet my needs around wanting a way to automatically
>>>>> detect this behavior/problem, but might not address the more generic issue.
>>>>>
>>>>>
>>>>>
>>>>> Thanks,
>>>>>
>>>>> --
>>>>>
>>>>> --EJM
>>>>> _______________________________________________
>>>>> LLVM Developers mailing list
>>>>> llvm-dev at lists.llvm.org
>>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>>
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> llvm-dev at lists.llvm.org
>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>
>>> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>


-- 
--EJM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201209/0fd07d9d/attachment.html>


More information about the llvm-dev mailing list