Previously, omitting unnecessary DWARF unwinds was only done in two
- For Darwin + aarch64, if no DWARF unwind info is needed for all the functions in a TU, then the __eh_frame section would be omitted entirely. If any one function needed DWARF unwind, then MC would emit DWARF unwind entries for all the functions in the TU.
- For watchOS, MC would omit DWARF unwind on a per-function basis, as long as compact unwind was available for that function.
This diff makes it so that we omit DWARF unwind on a per-function basis
for Darwin + aarch64 as well. In addition, we introduce the flag
--emit-dwarf-unwind= which can toggle between always,
no-compact-unwind (only emit DWARF when CU cannot be emitted for a
given function), and the target platform default. no-compact-unwind
is particularly useful for newer x86_64 platforms: we don't want to omit
DWARF unwind for x86_64 in general due to possible backwards compat
issues, but we should make it possible for people to opt into this
behavior if they are only targeting newer platforms.
Motivation: I'm working on adding support for __eh_frame to LLD,
but I'm concerned that we would suffer a perf hit. Processing compact
unwind is already expensive, and that's a simpler format than EH frames.
Given that MC currently produces one EH frame entry for every compact
unwind entry, I don't think processing them will be cheap. I tried to do
something clever on LLD's end to drop the unnecessary EH frames at parse
time, but this made the code significantly more complex. So I'm looking
at fixing this at the MC level instead.
Addendum: It turns out that there was a latent bug in the X86
backend when OmitDwarfIfHaveCompactUnwind is naively enabled, which is
not too surprising given that this combination has not been heretofore
For functions that have unwind info that cannot be encoded with CU, MC
would end up dropping both the compact unwind entry (OK; existing
behavior) as well as the DWARF entries (not OK). This diff fixes things
so that we emit the DWARF entry, as well as a CU entry with encoding
UNWIND_X86_MODE_DWARF -- this basically tells the unwinder to look for
the DWARF entry. I'm not 100% sure the UNWIND_X86_MODE_DWARF CU entry
is necessary, this was the simplest fix. ld64 seems to be able to handle
both the absence and presence of this CU entry. Ultimately ld64 (and
LLD) will synthesize UNWIND_X86_MODE_DWARF if it is absent, so there
is no impact to the final binary size.