This is not true. Even for nounwind, you want to get basic tables sothat backtrace(3) works.
walk?(1) Should enough unwind data be provided for a basic, read-only stack
That said, the option already exists for changing the default:
-funwind-tables. There shouldn't be another ARM specific flag.
You can make GCC emit unwind tables for C if you use the command line option -funwind-tables.
This could be useful if you are compiling C code which is called by C++ code and which itself calls C++ code and you wish the C++ exception to propagate through the C code.
There is some interaction in that if you are generating a .eh_frame section for exception handling then there is little sense is generating a DWARF .debug_frame section as well; I would hope most debuggers could use the .eh_frame section if present as its format is so similar to a .debug_frame section.
What does -arm-disable-ehabi actually mean?
Currently it is effectively "don't generate exception tables".
Maybe is should it rather be "don't generate EHABI exception tables but generate .eh_frame tables instead"? Obviously this requires the necessary DWARF like support to generate the information for the .eh_frame tables.
IF(arm_disable_ehabi)USE ARMException
ELSE
USE DwarfCFIException
ENDIF
Hmmm! I'm very nervous about the backend making decisions based on the language.
IF (-funwind-tables || -fexceptions)
uwtable
IF (leaf / nothrow)
nounwind
ENDIF
ELSE
no uwtable
no nounwind
ENDIF
-fexceptions allows compiling exception handling constructs in the source language and enables the generation of unwind tables.
-funwind-tables only enables the generation of unwind tables.
Folks,We're having some discussions about the behaviour of exception handling and Dwarf sharing unwind logic, tables, etc. and it seems that the code around it wasn't designed with any particular goal in mind, but evolved (like the EHABI) and now we're seeing the results from it.The problems below are assuming C vs. C++, but it actually apply to any possibly-exceptional vs. never-exceptional cases.1. C vs. C++We have two unwind flags: nounwind, which flags functions that can't unwind (leaf, nothrow, etc) and uwtable, which forces generation of the table regardless of nounwind. It seems sensible that C++ code with exceptions enabled should generate the tables for all functions, in case they're called by (or call) external functions. In C we don't want any of that.GCC seems to never emit tables, and G++ always do, even on C code (.c files, no exception or anything), which is very sensible and in line with my reasoning above. Clang, on the other hand, always generates them. I guess it'll have to figure out what to do based on its impressions on what language is being used to produce similar results.I believe that emitting the tables on anything that could potentially interact with exceptional code makes sense, but that's clearly a front-end decision. To LLVM, nounwind and uwtables should be absolute:IF (uwtables)IF (nownwind)CantUnwindELSEUnwind TableELSEdo nothingENDIF
2. .fnstart/.fnend+friendsAnother problem is that the emission of unwinding tables (based on .fnstart/.fnend symbols and others) is conditional *only* to the existence (or not) of an exception handling class being loaded (EHABI, Dwarf). Which means that, we can't disable the EH on a per-function basis.We'll have to change the way these symbols are emitted, at least when using ARMException, so that we can emit the tables and honour the uwtable on a per-function basis.Again, this is a requirement for problem 1, but it'd need to be fixed after 3.3. Unwinding codeCurrently, even when no exception handling are needed, the exception code is used to generate Dwarf unwinding directives (CFI) for the debugger.Both DwarfCFIException and ARMException inherit from DwarfException, and they are called to do the debug info about the stack unwinding, which is (at least) misplaced. The consensus is that this code should be factored out.The part that is relevant to this thread is that, today, if -arm-disable-ehabi is requested, ARMException will not be used and we won't have a way of generating debug stack directives, which is wrong.Factoring out this code is a requirement for the unwinding problem (1), since if we disable EH today, we'll disable Dwarf stack unwinding altogether. But we also need a final solution for problem 4 below before we start.4. Clang EH controlThere are a number of Clang/LLVM options to control exception handling:* -fno-excetpion (enable/disable EH on C++ mode, off in C mode)* -fcxx-exception (no idea, is it objC++ specific? does it control tables in any way?)* -funwind-tables (forces uwtable attribute?)* -arm-disable-ehabi (ARM specific bogus flag)Those options are not always completely exclusive, and they damage different parts of the compilation process (as seen recently on the list), so we need a clear consensus on what each option mean (or should mean), and translate it to the back-end (via function attributes). This would considerably simplify the back-end and help us tackle this refactoring.
My main target for this problem is to have the one true option on the front-ends, and rely only on function attributes on the back-end (including tools like llc). For that, I'd love to be left with -fexception only and infer all the rest from the language / conditions of the code.Ex:IF (C++ mode)IF (-fno-exception)no uwtableno nounwindELSEuwtableIF (leaf / nothrow)nounwindENDIFENDIFELSEno uwtableno nounwind
ENDIFMy main goal is to get rid of (at least) -arm-disable-ehabi.
Finally,If you got this far, you're *really* interested in making the exception handling more user/dev friendly in LLVM, so I welcome any critics about the "proposal" above, as well as any explanations of the doubts expressed. I may be wrong about many things, feel free to enlighten me! We may have a lot less work to do, and I'll be happy. ;)I believe the dependency graph of the solutions are:4 -> 3 -> 2 -> 1So, we first should solve the flags problem, than refactor the unwinding code out of EH, make the debug generation use them as well, and then we can start with the EH specific changes. The problem is that 4 will change things considerably, so we might need some scaffolding during the whole process.Makes sense?cheers,--renato
if (uwtable || (!nounwind && need uwtable to unwind))unwind table
I believe the intent is:-fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.
-fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).-fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).
-fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions-fcxx-exceptions and -fobjc-exceptions require -fexceptions
-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode.
This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).
The 'nounwind' attribute is set if -fexceptions is specified, or if we have some other way of knowing the function does not throw.
The 'uwtable' attribute is set based on the value we determined for -funwind-tables (either through an explicit flag or from the target).
This seems wrong -- in C with -fexceptions we do not want nounwind, and sometimes want uwtable (depending on ABI).
can't unwind == unwind table + no EH directives + no EH tableif (uwtable || (!nounwind && need uwtable to unwind))unwind table"need unwind table to unwind" is probably true in almost all cases. At least in all where ARMException and DwarfCFIException are concerned, which is the ones we're discussing about.I'm beginning to think that there is no reason at all to have an uwtable attribute, given that the -funwind-tables is propagated to the back-end AND if we emit the table for one function we should do it for all.I believe the intent is:-fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.
Right. Landing pads, cleanups, etc. We'll need those for emitting the EH tables, but not the unwind tables, so for this particular discussion, we don't need to worry.
-fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).-fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).Language-specific stuff, not even important to the EH tables (since in the back end we don't care what constructs you use in the language, only the IR basic block structure).-fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions-fcxx-exceptions and -fobjc-exceptions require -fexceptionsWill -fcxx-exceptions also include -fexceptions? I mean, if the user specify -fcxx-exceptions in C, will that also turn on all the internal flags that -fexception would?If so, we really don't need to worry at all about them.
-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode.Right. They do clash in the back-end, since one generates EH unwinding and the other might only generate Dwarf unwinding. We need to clear that confusion in the back-end, but I don't think that the front-end should even care on how it gets implemented in the end, as long as it works.
This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).
I think that both -fexceptions and -g should turn -funwind-tables by default. The third user is the backtrace which doesn't need debug or EH info (just the unwind table), and you need the -funwind-tables IFF your target doesn't have it on by default.I can only think about GPU targets that won't need any of that, but they're not using Dwarf or EHABI handlers, so we shouldn't concern about that. Embedded CPUs might want them disabled to save space, and for that we should actively disable (-fno-unwind-tables or -Os/z).
This (-fexceptions and -g imply -funwind-tables) seems like it's probably the right thing for most targets. With SjLj exceptions, -fexceptions probably doesn't need -funwind-tables.
Do we have such logic in Clang at the moment?
Just to double check, none of this will change the current behavior on Darwin, right?
Just that: unwind tables are output for the function, even if nothing
else seems to say they are necessary.
> I don't see that attribute too often, but I still see tables being
> emitted in x86_64.
Strange. I see it even with simple C testcases:
void bar(void);
void zed(void) { bar();}
produces
define void @zed() #0 ....
attributes #0 = { nounwind uwtable...
>The rules on what to emit in beginFunction() are a
> bit convoluted, and I guess that's because uwtables' semantics is not
> definite. I was hoping for something a bit stronger, because we do
> lose a lot of information in the back-end, such as what exception
> style is has (depending on the target, language, flags).
>
> Is there any definitive explanation on the complete semantics of
> uwtables and nounwind? I could be wrong, but from what I can see,
> beginFunction() is based on circumstantial behaviour, not explicit
> semantics.
I agree that the logic in there seems a bit odd. What is called
shouldEmitMoves should probably include all possible
reasons for printing the unwind tables. We should probably also use
uwtable to guard the emission of other table formats
as you propose.
The semantics uwtable is just "make sure it is possible to unwind past
this function". It doesn't include anything more,
like the ability to run destructors. It is used for ABIs that require
it for use in debuggers and profilers.
I am not too sure about nounwind. I think it is more about using
unwind for control flow in the language. Having it allows us
to prune information used for exception handling.
> cheers,
> --renato
Cheers,
Rafael
Unwind table index '.ARM.exidx' at offset 0x818 contains 4 entries:
0x5d4 <main>: 0x1 [cantunwind]
because the latter prevent any unwinding, breaking
debuggers/profilers/sanitizers.
As I understand, the right way to enable basic unwind through any
function (without emitting landing pands etc, unless they are needed
for something else) is -funwind-tables. I'm going to add that in the
driver for all sanitizers then.