Modi Mo via llvm-dev
2020-Dec-07 23:31 UTC
[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code
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<https://lists.llvm.org/pipermail/llvm-dev/2017-February/109992.html> and https://lists.llvm.org/pipermail/llvm-dev/2017-February/109995.html<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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201207/d7a27041/attachment.html>
Everett Maus via llvm-dev
2020-Dec-08 11:51 UTC
[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code
So yes--that would work. I think for that route, though, it would be probably useful to try to output some more information than just std::terminate does. (i.e. that would work as a proof of concept, but getting more debug information the way you do with noexcept functions or functions without a handler would be more user friendly). The other reason I was hesitant to go that route is that I was worried about the impact of that on binary size (as that's... I think 4+ bytes per function added for the .gcc_except_table sections, as opposed to just 4 bytes for the empty section). That seems fine for a small binary, but seems likely to be expensive-to-prohibitive for large binaries/libraries. --EJM On Mon, Dec 7, 2020 at 3:31 PM Modi Mo <modimo at fb.com> 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 >-- --EJM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201208/fd7b4555/attachment.html>
Reid Kleckner via llvm-dev
2020-Dec-08 18:04 UTC
[llvm-dev] Catching exceptions while unwinding through -fno-exceptions code
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 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201208/c15d2f18/attachment.html>