On Thu, Jun 25, 2020 at 2:05 PM Fangrui Song maskray@google.com wrote:
On 2020-04-21, Fāng-ruì Sòng wrote:
On 2020-04-21, Gerd Hoffmann wrote:
Hi,
Hi Gerd, thank you for your comments.
You mean "Makefile: Change ET_EXEC to ET_REL so that lld can link bios.bin.elf"
Let me add more descriptions. I am a maintainer of lld ELF (I contributed most features and wrote most items of lld 9/10's release notes).
A linker accepts ET_REL as regular object files. The input sections are taken to make up output sections. The input symbols are taken to track dependencies and resolve relocations.
A linker accepts ET_DYN as shared objects. Input sections are ignored. Only symbols are used. Many sections are synthesized by a linker and do not make sense to be reused as input.
ET_EXEC, position dependent executables. The type is more similar to ET_DYN. Many synthesized sections (.hash .gnu.hash .plt .dynstr .dynsym) do not make sense to be reused as input. Sometimes there are needs to read its symbols so that another component can know which symbols should be exported. For this use case, --just-symbols is used.
seabios' use of ET_EXEC is very different. I have built thousands third-party pieces of software. seabios and (for a short period because I have fixed it) the Linux kernel are the only two cases an ET_EXEC input's sections are used. The symbol table appears to be ignored. This is really an unusual use case. Another lld maintainer and I think this is just a very error-prone case. I hence decide that this is not worth supporting. GNU ld accepts it, but note that GNU gold disallows it as well https://sourceware.org/git/?p=binutils-gdb.git;a=blob;hb=49d1d1f53df552f059%...
Since seabios just uses ET_EXEC as something similar to an ET_REL. Binary patching the file seems the most portable approach. (This Linux kernel patch has been merged into the mainline.)
Wouldn't it be better to add a switch to ld to request ET_REL output instead?
cheers, Gerd
I added some context in my previous comment. Before I said "binary patching", I analyzed possible linker input types (ET_REL/ET_DYN/ET_EXEC) and discussed why ET_EXEC as ET_REL is really a special case. Let me add a concrete example:
% cat a.c void _start() {} % clang -fuse-ld=bfd a.c -nostdlib -o a % clang -fuse-ld=bfd a -nostdlib -o aa /usr/bin/ld.bfd: warning: cannot create .eh_frame_hdr section, --eh-frame-hdr ignored /usr/bin/ld.bfd: error in a(.eh_frame); no .eh_frame_hdr table will be created
An ET_EXEC can have many linker synthetized sections (.eh_frame_hdr, .dynamic, .gnu.hash, .hash, .plt, etc) which will really make no sense for a subsequent link. seabios is special in that it has a linker script to explicitly concatenate some sections from the ET_EXEC input and (as I understand it) just ignores all symbols. This usage makes it really special and there is probably no other project doing the same. A lld specific linker option will be neither useful nor good for compatibility because GNU ld does not have the option.
For a new linker, we can take time to think what features are error-prone and reject such features in advance to help detect such problems. We are not in GNU ld's situation "our previous versions support this arguably brittle use cases and our future versions may have to be compatible".
Hope the explanation makes sense.
Hi Kevin,
Internally we have been using seabios built with LLD and llvm-readelf for two months now, without any issue. I hope the stability can give you more confidence accepting the patches.
About PATCH 3/5 "Makefile: Change ET_EXEC to ET_REL so that lld can link bios.bin.elf" The maintainer of binutils agreed with my resolution (ET_EXEC should not be accepted as linker input) and pushed https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=a87e1817a435dab6c6...
GNU ld from binutils 2.35 onwards will not allow this use case.
Hope you can take another look when you get time.
Friendly ping.
ET_EXEC issue was fixed. Hope you can take a look at other patches. Thanks