Background
llvm-mc generates unwind info in both compact unwind and DWARF
formats. LLD already handles the compact unwind format; this diff gets
us close to handling the DWARF format properly.
Caveats
It's not quite done yet, but I figure it's worth getting this reviewed
and landed first as it's shaping up to be a fairly large code change.
Known limitations of the current code:
- Only works for x86_64, for which llvm-mc emits "abs-ified" relocations as described in https://github.com/llvm/llvm-project/commit/618def651b59bd42c05bbd91d825af2fb2145683. llvm-mc emits regular relocations for ARM EH frames, which we do not yet handle correctly.
Since the feature is not ready for real use yet, I've gated it behind a
flag that only gets toggled on during test suite runs. With most of the
new code disabled, we see just a hint of perf regression, so I don't
think it'd be remiss to land this as-is:
base diff difference (95% CI) sys_time 1.926 ± 0.168 1.979 ± 0.117 [ -1.2% .. +6.6%] user_time 3.590 ± 0.033 3.606 ± 0.028 [ +0.0% .. +0.9%] wall_time 7.104 ± 0.184 7.179 ± 0.151 [ -0.2% .. +2.3%] samples 30 31
Design
Like compact unwind entries, EH frames are also represented as regular
ConcatInputSections that get pointed to via Defined::unwindEntry. This
allows them to be handled generically by e.g. the MarkLive and ICF
code. (But note that unlike compact unwind subsections, EH frame
subsections do end up in the final binary.)
In order to make EH frames "look like" a regular ConcatInputSection,
some processing is required. First, we need to split the __eh_frame
section along EH frame boundaries rather than along symbol boundaries.
We do this by decoding the length field of each EH frame. Second, the
abs-ified relocations need to be turned into regular Relocs.
Next Steps
In order to support EH frames on ARM targets, we will either have to
teach LLD how to handle EH frames with explicit relocs, or we can try to
make llvm-mc emit abs-ified relocs for ARM as well. I'm hoping to do
the latter as I think it will make the LLD implementation both simpler
and faster to execute.
Misc
The obj-file-with-stabs.s test had to be updated as the previous
version would trip assertion errors in the code. It appears that in our
attempt to produce a minimal YAML test input, we created a file with
invalid EH frame data. I've fixed this by re-generating the YAML and not
doing any hand-pruning of it.
Why is there a copy of *off for errors? Could we not use *off in the case of errors?