Renato Golin
2014-Mar-20 09:52 UTC
[LLVMdev] Unwind, exception handling, debuggers and profilers
On 20 March 2014 02:09, Rafael EspĂndola <rafael.espindola at gmail.com> wrote:> I think this is just 2. It uses .eh_frame for unwinding proper. The > only difference in .eh_frame is that there is a personality function > defined.If there is no debug information, it should still be possible to unwind the stack via the saved LR on the stack, no? If there is only line info, you could even print the function names with just the LR. But yes, Debug and EH unwinding should be identical (modulo the PR).> No. The -g option should never change the set of optimizations that > are run.Bad wording. I meant fix the edge cases Logan reported on the LR removal, which might have some effect (bigger frames by one word), but that's discussion for another thread.>> * uwtable >> - Generated only when -g or -pg are specified > > No. Se above note about -g.I don't see how not having unwinding information would change the binary execution.> What we do today then is that on x86-64 "clang -S" adds uwtable to all > functions and "clang -S -fno-asynchronous-unwind-tables" doesn't.This is remarkably similar to the behaviour I want to create. But that can't be encoded in IR right now wrt. nothrow. These are the options: 1. no attr: don't emit tables 2. nounwind: emit CantUnwind 3. uwtable: emit table 4. uwtable + nounwind: emit table This is because uwtable means *also* debug/profiler use, and emitting CantUnwind could stop them from unwinding, since there is no information on how to continue unwinding the stack. The semantics I want is to be able to separate between EH unwinding and Debug/Profiler unwinding (even though they map to the same physical tables), so that we DO emit CantUnwind in those cases.> * arm-unwind-table. The other unwind table format.No. This is not an ARM specific issue. The table format is back-end specific, and the IR has no business in interfering with it. cheers, --renato
Logan Chien
2014-Mar-21 18:47 UTC
[LLVMdev] Unwind, exception handling, debuggers and profilers
Hi, I wrote that article because I encountered an issue[1] when I was throwing-and-catching in a C++ program (which is not related to the -g, -pg, or -Og.) I am not familiar with the debug_info issue, thus I have no comments on for the impact to the unwind table and debugging information. I think we can focus on this: We would like to add a flag (or reusing -fno-unwind-tables) to Clang so that the user can disable the generation of unwind table for each function. To address this issue, we have to consider several aspects: 1. What does the meaning of -funwind-tables? 2. What LLVM assembly will be generated by Clang? We have to compare the difference between C and C++ program. 3. What are the meanings of nounwind and uwtable attribute? What do they guarantee? How do they work? 4. Possible solution. Let's discuss these aspects one-by-one. 1. Meaning of -funwind-tables ----------------------------- According to the `clang --help`, the -funwind-tables will generate the unwind table even if the function does not need the exception handling mechanism. I have checked GCC manual as well. It says something similar. However, there is no precise definition to the unwind table. There is no guarantee on what the unwind table should contain. But from the empirical experience, the unwind table should contain sufficient information for unwinder to pass through this frame. Otherwise, several unwinder implementation such as _Unwind_Backtrace() might not work properly (either stop unwinding much earlier, terminate the program with abort(), or loops forever.) Currently, this flag will be turned on by default when the clang::ToolChain::IsUnwindTablesDefault() returns true, and the -fno-asynchronous-unwind-tables are not specified. For now, IsUnwindTablesDefault() only return true for x86_64 target. 2. What LLVM assembly will be generated? ---------------------------------------- When compiling following program with `clang -S -emit-llvm test.c` (in C mode): extern void may_throw_exception(); void test1() { } void test2() { may_throw_exception(); } * Generated function attributes for x86_64: test1(): nounwind, uwtable test2(): nounwind, uwtable * Genearted function attributes for arm: test1(): nounwind test2(): nounwind When compiling the same program with `clang -S -emit-llvm test.cpp` (in C++ mode): * Generated function attributes for x86_64: test1(): nounwind, uwtable test2(): uwtable * Generated function attributes for arm: test1(): nounwind test2(): (neither nounwind nor uwtable) 3. Meaning of `nounwind` and `uwtable` attribute? ------------------------------------------------- Given the generated LLVM function attributes, what will happen? * There's the table for x86_64 target: - no attribute => emit CFI directives - with nounwind => no CFI directives - with uwtable => emit CFI directives - with uwtable+nounwind => emit CFI directives * There's the table for ARM target: - no attribute => emit unwind table - with nounwind => emit unwind table with cantunwind - with uwtable => emit unwind table - with uwtable+nounwind => emit unwind table WITHOUT the cantunwind The cantunwind record will stop the unwinder, and cantunwind will conflict with the stack unwind information according to EHABI. Thus, we should not emit cantunwind for the function with uwtable. Please recall that in the C programming language mode, Clang will add nounwind attribute to function definitions, thus we have to specify -funwind-tables in order to support the interleaving of C and C++ programs. 4. Possible Solution -------------------- Back to the original issue, we would like to provide an option to the user so that the user can reduce the excutable size by omitting the unwind table (at their own risk.) In the first attempt, we might use the uwtable attribute to determine whether we can emit the unwind table or not. But according to the comparison in section 3, we can't do so because a) The function with no attribute will no have unwind table anymore. This won't be acceptable unless every targets are enabling -funwind-tables by default. b) The function with nounwind attribute can't be properly encoded for ARM. The implementation for nounwind is slightly different with uwtable+nounwind. In the nounwind case, the function will be marked with cantunwind, and _Unwind_RaiseException() will stop unwinding and __cxa_throw() will call std::terminate(). In the uwtable+nounwind case, if the exception occurs, then the exception might be caught by the caller. Although this difference might not be a problem because (i) throwing from a function with nounwind is actually an undefined behavior and (ii) clang will emit a landing pad as a safety net. IMO, maybe we can add a new "no-unwind-table" attribute to LLVM IR. If "no-unwind-table" attribute exists, then we should not emit any unwind table (including the CFI directives.) If the clang users explicitly specified -fno-unwind-tables, then Clang will add "no-unwind-table" to every function definitions in the translation unit. Best regards, Logan # Footnotes [1] This issue has been worked around in r202165. On Thu, Mar 20, 2014 at 5:52 PM, Renato Golin <renato.golin at linaro.org>wrote:> On 20 March 2014 02:09, Rafael EspĂndola <rafael.espindola at gmail.com> > wrote: > > I think this is just 2. It uses .eh_frame for unwinding proper. The > > only difference in .eh_frame is that there is a personality function > > defined. > > If there is no debug information, it should still be possible to > unwind the stack via the saved LR on the stack, no? > > If there is only line info, you could even print the function names > with just the LR. > > But yes, Debug and EH unwinding should be identical (modulo the PR). > > > > No. The -g option should never change the set of optimizations that > > are run. > > Bad wording. I meant fix the edge cases Logan reported on the LR > removal, which might have some effect (bigger frames by one word), but > that's discussion for another thread. > > > >> * uwtable > >> - Generated only when -g or -pg are specified > > > > No. Se above note about -g. > > I don't see how not having unwinding information would change the > binary execution. > > > > > What we do today then is that on x86-64 "clang -S" adds uwtable to all > > functions and "clang -S -fno-asynchronous-unwind-tables" doesn't. > > This is remarkably similar to the behaviour I want to create. But that > can't be encoded in IR right now wrt. nothrow. > > These are the options: > > 1. no attr: don't emit tables > 2. nounwind: emit CantUnwind > 3. uwtable: emit table > 4. uwtable + nounwind: emit table > > This is because uwtable means *also* debug/profiler use, and emitting > CantUnwind could stop them from unwinding, since there is no > information on how to continue unwinding the stack. > > The semantics I want is to be able to separate between EH unwinding > and Debug/Profiler unwinding (even though they map to the same > physical tables), so that we DO emit CantUnwind in those cases. > > > > * arm-unwind-table. The other unwind table format. > > No. This is not an ARM specific issue. The table format is back-end > specific, and the IR has no business in interfering with it. > > cheers, > --renato >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140322/471c62ba/attachment.html>
Renato Golin
2014-Mar-21 19:07 UTC
[LLVMdev] Unwind, exception handling, debuggers and profilers
On 21 March 2014 18:47, Logan Chien <tzuhsiang.chien at gmail.com> wrote:> * There's the table for ARM target: > > - no attribute => emit unwind table > - with nounwind => emit unwind table with cantunwind > - with uwtable => emit unwind table > - with uwtable+nounwind => emit unwind table WITHOUT the cantunwind > > The cantunwind record will stop the unwinder, and cantunwind will conflict > with the stack unwind information according to EHABI. Thus, we should not > emit cantunwind for the function with uwtable.Logan, Based on the current behaviour, you only need one flag: nounwind, which should only be emitted if -fno-unwind-tables is chosen AND the function can't unwind. Also, do not assume that EHABI behaviour in LLVM is currently correct, especially related to uwtable and nounwind. Those were made with the x86_64's ABI in mind, and have only interoperated seriously with DwarfCFIException until very recently. There has to be a way to disable unwind tables, so either the "no attribute" behaviour above is wrong or we need a new attribute "noehtable". There has to be a way to emit CantUnwind, so if the behaviour above is right, the "uwtables" attribute is only related to forced unwind (debug, profiler), not exception handling. There has to be a way to map "throw()" into IR, and "nounwind" seems to be the one to use. The fact that CantUnwind is only emitted without "uwtable" reinforces the idea that "uwtable" is forced unwind. cheers, --renato