On 3/13/20 1:20 PM, Fāng-ruì Sòng wrote:
> GNU as uses SHT_PROGBITS for .eh_frame all the time, at least on
> non-Solaris. (I don't know how to test Solaris)
> clang integrated assembler uses SHT_X86_64_UNWIND for non-Solaris
> since 2015-11 (
https://urldefense.com/v3/__https://reviews.llvm.org/rL252300__;!!GqivPVa7Brio!NfJGcj1nvZZaqv3GQplmmEnsoFvdbva-fe0qyEUJfeGtRHXUS8SLMPc6MyCJ-zrt$ ).
> So there are indeed some object files with SHT_X86_64_UNWIND.
> Fortunately, neither of GNU ld, gold, lld complains about mismatching
> section type (SHT_PROGBITS vs SHT_X86_64_UNWIND).
>
> So I don't think it is too late for removing SHT_X86_64_UNWIND and
> requiring .eh_frame to be SHT_PROGBITS.
>
> On the contrary, inventing SHT_UNWIND or SHT_GNU_UNWIND (generalizing
> SHT_PARISC_UNWIND/SHT_IA_64_UNWIND) and requiring every other
> architecture to adopt may be too late,
> but I think it may still be doable.
Let me clarify: It's not that I think it's too late to make
either of these changes. It's that I think it's too late
to simplify the world by doing so. You can create and use
SHT_UNWIND, or you can eliminate SHT_X86_64_UNWIND, but
in either direction, we must continue to drag around the
obsolete forms, because existing objects contain them. As
such, there's no real simplification --- the linkers need to
continue handling both cases. Given that, I'd prefer for the
ABI to continue documenting it.
The SHT_X86_64_UNWIND type (originally SHT_AMD64_UNWIND) arrived
with the 64-bit platform ABI, but the actual sections predate
x86_64, and are the same unwind sections that GNU had already
developed for other platforms, including 32-bit x86.
As I understand it, the order of events was roughly:
- GNU create unwind sections, based on the Itanium ABI,
to support C++. These were tagged SHT_PROGBITS, which
to me, was a missed opportunity to assign them a
proper section type, like SHT_UNWIND.
- GNU essentially wrote the x86_64 platform ABI, which
codified a lot of things that were already done
on other platforms. I'm not sure how SHT_X86_64_UNWIND
got added, but it did, and this was also a missed
opportunity, again, to generalize it to all the other
platforms as SHT_UNWIND.
Comparing section types is better than string matching, so
given a time machine, it would have been better to have
a generic section type from the start. However, without a
time machine, I'd leave well enough alone. Platform ABIs
aren't supposed to change very much, particularly when it
comes to removing things. It's a bit ugly, but it's done, and
it works.
As to Solaris behavior, we see the same behavior as Linux
regarding the above. gcc produces UNWIND. as (really, the
people who write assembly code) usually produce PROGBITS.
And on non-x86_64, it's all PROGBITS. As a result, our
linker also knows to combine the two types. It took several
bugs to work all of that out, but it's been done for years.
Whether or not the platform ABI now removes SHT_X86_64_UNWIND
or not, we have to keep that code, to support old compilers,
and old objects. Hence, changing this seems a bit academic
now. When I said that we wouldn't change anything, whatever
the decision about the psABI, this is what I meant.
> Will be appreciated if you can tell me why SHF_WRITE is there:)
> (SHF_WRITE really made me sad while fixing
>
https://urldefense.com/v3/__https://github.com/libffi/libffi/pull/546/files__;!!GqivPVa7Brio!NfJGcj1nvZZaqv3GQplmmEnsoFvdbva-fe0qyEUJfeGtRHXUS8SLMPc6M7K63TfA$ )
The Solaris ld follows the usual rules for combining
sections. Hence, readonly, and writable, sections with the
same name don't get combined, and you end up with 2 output
sections. At some point, 5-10 years ago, we started seeing
unwind sections with a mixture of SHF_WRITE and readonly, and
so, we were getting 2 different output sections, which for
unwind, is bad. On investigation, we determined that various gcc
supplied objects were inconsistent in this, but that that the
GNU linkers special cased them, merging them together without
regard for the WRITE bit.
As with the merging of PROGBITS and UNWIND, we followed suite with
a special case for combining readonly and writable UNWIND into a
single readonly output unwind section, and the issue went away.
This comment from our sources explains:
I /*
* A final object (executable, shared, or kmod) is only supposed to have a
* single .eh_frame section, so that a .eh_frame_hdr section can be generated
* to describe it. If a mixture of read-only and read-write sections are
* encountered, the default behavior would be to produce two output sections.
* Although it is best to fix the compilers to not create .eh_frame sections
* with different flags, we are willing to merge such .eh_frame sections into
* a single read-write output section in order to work with existing tools.
* This is largely driven by the fact that the GNU link-editors appear to do
* such merging for all sections based on name.
*/
static Ld_ret
uniquify_ehframe(Ent_desc *enp, Ofl_desc *ofl, Os_family *nofp, Is_desc *nisp)
We were a bit late to the party on this. I'll guess that your
code above dates from the window of time during which we weren't
merging these, and that some objects in the link were setting the
WRITE flag. Your adding that flag likely caused all the unwind
to land in one place.
I think you might change that now. Solaris 11 is clean on this, while
Solaris 10 (ancient) isn't. Do you know Rainer Orth (cc;d)?
I'll suggest that you contact him offline and discuss it. Feel free
to cc me, and thanks.
- Ali