SHT_UNWIND instead of SHT_X86_64_UNWIND? (was: RFC: Usefulness of SHT_X86_64_UNWIND)

Fāng-ruì Sòng maskray@google.com
Fri Mar 13 22:33:47 GMT 2020


Original thread: https://groups.google.com/forum/#!topic/x86-64-abi/7sr4E6THl3g

+gnu-gabi and binutils

On 2020-03-13, Ali Bahrami wrote:
>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.

OK, so it is unfortunate that x86-64 psABI says 
"The call frame information needed for unwinding the stack is output into one or more ELF sections of type SHT_X86_64_UNWIND."
while there is no corresponding change made to the most widely assembler (GNU as).
This sentence triggered https://reviews.llvm.org/rL252300 which made clang integrated assembler diverge.

At this point, I agree that the world is not going to be simplified.
Toolchain has to continue to support SHT_X86_64_UNWIND.
However, I think clarifying the canonical section type can guide future assembly files and toolchain support.

Now we have two choices for the canonical and recommended section type (SHT_PROGBITS should still be supported)

a) SHT_UNWIND

   We need a definition `#define SHT_UNWIND 0x70000001` in binutils and glibc/elf/elf.h

   The canonical way to write .eh_frame in assembly (very rare, I've only
   seen instances in glibc/sysdeps/unix/sysv/linux/x86_64/sigaction.c ,
   LuaJIT, libffi) will be:

   .section .eh_frame,"a",@unwind
   # Older non-x86 GNU as will emit "Warning: unrecognized section type",
   # but an assembler warning will not break the build.

   Newer readelf/llvm-readelf -S should print "UNWIND" instead of "X86_64_UNWIND".

   Alpha may not be happy due to SHT_ALPHA_DEBUG, but that is for ECOFF.
   MIPS may not be happy due to SHT_MIPS_MSYM. I don't know whether it is
   legacy cruft from today's view of point, but I don't see a problem
   because MIPS already does a lot of non-standard stuff (its .debug_* use SHT_MIPS_DWARF)

b) SHT_PROGBITS

   https://reviews.llvm.org/D76151
   Unfortunately this does not follow the ELF spirit. I won't object to
   it if a) is excluded.


I maintain lld/ELF and LLVM binary utilities nowadays, and probably also
LLVM MC (integrated assembler). I can made relevant changes.

>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.

"gcc produces UNWIND" - I think you meant SHT_PROGBITS. In the GCC
repository, libphobos/libdruntime/core/sys/solaris/sys/elf_amd64.d is
the only place where SHT_X86_64_UNWIND is mentioned.

Thanks for sharing the history.
>> 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.

https://reviews.llvm.org/rL291107
As to section flags, at the very least SHF_GROUP and SHF_COMPRESSED should be ignored.
SHF_MERGE may be ignored as well.

As to section types, GNU as used the wrong section type for .init_array.nn until https://sourceware.org/bugzilla/show_bug.cgi?id=21287 (2017)...

A linker script essentially matches sections by name.
INPUT_SECTION_FLAGS exists but it is very rare and does not help with
section types.

So, in practice we have to diverge from the ELF spec.

>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.

I don't:) So it looks like https://github.com/libffi/libffi/pull/546 can be further simplified by deleting SHF_WRITE support completely.



More information about the Binutils mailing list