[LLVMdev] Unwind, exception handling, debuggers and profilers

Robinson, Paul Paul_Robinson at playstation.sony.com
Wed Mar 19 14:53:33 PDT 2014


Just a couple things, I haven't really been following all of the
discussion.

> Folks,
> 
> I'm sorry for getting at this again, but this will not be the last
> discussion on the topic, so let's just get to business. We're about to
> merge the last critical patch to make EHABI compatible with other EH
> mechanisms in LLVM (D3079), and that has unearthed a few issues with
> the function attributes.
> 
> Logan's blog post [1] contains a proposal to split unwinding from
> exceptional logic which I think we should give it a try. I'm trying to
> make it as backward compatible as possible, but the point is to make
> the IR authoritative on how and when to emit what kind of unwind
> information.
> 
> ** Unwinding **
> 
> AFAIK, there are three ways to unwind the stack:
> 
> 1. Checking the return information on the stack (LR). This might be
> optimized away, so debuggers and profilers can't rely on it. Binaries
> with no debug or EH information at all have to resort to this when
> back-tracing during a segfault or similar.
> 
> 2. Dwarf unwinding. This is a carefully constructed stack unwinding
> Dwarf information for each frame that debuggers and profilers can use
> to gather precise information on the stack, typically stored on
> .eh_frame sections.
> 
> 3. Itanium-compatible exception handling. This is another format of
> unwind tables using personality routines and similar unwinding logic
> to Dwarf CFI directives, also on .eh_frame. This is why you can use
> CFI to build the EH tables, and why debuggers can also use this table
> to unwind the stack.
> 
> ** Exception Handling **
> 
> LLVM has four types of EH: Dwarf, ARM, SjLj and Win64. Of them, only
> SjLj doesn't need unwind tables, and each of the others, even being
> Itanium-compatible, need slightly different logic.
> 
> In LLVM, all targets that use DwarfCFIException are using the same
> tables as the debugger and profilers would, but ARM and Win64 have
> separate unwind logic. This is where the problem begins.
> 
> We're left with three EH types:
> 
> 1. No tables (SjLj)
> 2. Dwarf tables (DwarfCFI)
> 3. Specific EH tables (ARM, Win64?)
> 
> ** Debug & Profiling **
> 
> In debug/profile mode (-g, -pg), none of the optimizations that prune
> unwind information should be allowed to run. I believe currently this
> is informed via the uwtable/nothrow function attributes, but since
> their use is controversial, we can reach situations where information
> is indeed removed when it shouldn't happen. (see Logan's post).

It is an article of faith among debugger and debug-info people that
adding -g must not affect the generated code in any way.  Although I
have never had to investigate it closely, DWARF unwind info should be
able to describe whatever the compiler is willing to produce.  And if
the program itself will not do unwinding, it's okay for the debug
unwind info to be imperfect (see my next comment).

Please don't require/assume/imply that -g should disturb optimizations,
in particular function attributes that affect optimization should not
be present or absent based on -g.

> 
> ** Function Attributes Proposal **
> 
> I still don't have a clear idea on what do we need, but being overly
> conservative, we should plan for every behaviour to be expressed by a
> flag, and during the discussion, merge similar behaviour and possibly
> remove unused flags along the way.
> 
> Today we have uwtable and nothrow, which are interchangeably being
> used to mean debug and EH unwinding, which is just wrong. Logan's
> proposal is to split uwtable and ehtable, nothrow and nounwind and to
> understand which trumps which if combined.
> 
> In my view, nounwind has no purpose. I may be wrong, but I can't think
> of a case where you want to generate debug unwind tables and NOT want
> to unwind a particular function on a purely non-EH context. Supposing
> nounwind has meaning, I'm happy with the semantics Logan proposes in
> his post.

Um, does your concept of "unwind" include "debugger displays a backtrace"?
A debugger likes to be able to display the chain of subprogram activations
that led to the current stopping point (backtrace), but this is different
from manipulating the process state to imitate the effect of a sequence of
subprogram de-activations (unwind).
A debugger also likes to be able to virtually present the process state
during some not-the-most-recent activation, which is like a virtual unwind,
but this is not a reason to require full EH tables in all cases; this
particular debugger feature is well understood by users to be lossy.

--paulr

> 
> A function without any of the attributes below should emit *no* tables
> at all.
> 
> The remaining possibilities are:
> 
> * uwtable
>   - Generated only when -g or -pg are specified
>   - Option -fno-unwind-tables loses meaning (unless nounwind has
> meaning)
>   - Generate full EH/Debug tables on all archs
> 
> * ehtable
>   - Generated for EH only (front-end/arch/lang specific)
>   - Could be forced enabled/disabled via -feh-tables/-fno-eh-tables
>   - Only emits EH directives on ARM, full debug on others, nothing on
> SjLj
> 
> * nothrow
>   - Leaf functions, throw(), languages without EH, etc.
>   - On its own, do nothing (no tables are emitted anyway)
>   - +uwtable, do nothing (we don't want to break debug)
>   - +ehtable, emit CantUnwind (the whole purpose)
> 
> * nounwind
>   - No idea why, but assuming there is a reason
>   - On its own, do nothing (no tables are emitted anyway)
>   - +uwtable, emit CantUnwind (given Logan's semantics)
>   - +ehtable, emit CantUnwind (given Logan's semantics)
> 
> The primary reason for adding the ehtable attribute is to be able to
> control the nothrow flag correctly. Other reasons are to limit
> emitting tables to archs that support it (ie. no SjLj) and to focus
> -fno-eh-table on EH info only, not Debug, so you don't get broken
> debug info when you just add "-g" to a build that already has
> -fno-eh-tables.
> 
> The option -fno-unwind-tables should either be removed (if nounwind
> has no meaning apart from EH context), or carefully merged with
> -fno-eh-tables. Logan can expand on that.
> 
> The reason why uwtable emits both EH and debug is backwards
> compatibility. ARM currently emits both directives for binutils' sake,
> and others have fused Debug/EH directives anyway. This attribute
> should also prevents any optimization related to stack unwinding, even
> on recursive or tail calls.
> 
> LangRef would have to change, but I don't think old IR would stop
> working.
> 
> Does that sound like a reasonable plan? Anything I haven't mentioned
> that needs mentioning? Any conflict that this will generate on any
> optimization pass?
> 
> cheers,
> --renato
> 
> [1] http://loganchien.github.io/llvm/nounwind.html
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev






More information about the llvm-dev mailing list