Reid Kleckner via llvm-dev
2020-Dec-09 20:15 UTC
[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code
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 >>> >>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201209/6e6f4142/attachment.html>
Everett Maus via llvm-dev
2020-Dec-09 23:51 UTC
[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code
> > 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>