This is an archive of the discontinued LLVM Phabricator instance.

[LLD] Add NetBSD support as a new flavor of LLD (nb.lld)
AbandonedPublic

Authored by krytarowski on Nov 2 2019, 2:39 PM.

Details

Summary

The NetBSD target wraps the default Linux/ELF target with OS specific
customization. It is implemented as a light nb.lld program that
mutates arguments in argv[] and spawns ld.lld.

This flavor detects the native/current and target Triple based on
argv[0] parsing. This is prerequisite for cross-compilation, in
particular the NetBSD distribution is cross-built always.

The default configuration of the ELF target is tuned for Linux and
there is no way to costomize in-place for the NetBSD target in the
same way as FreeBSD/OpenBSD. FreeBSD whenever needed can check
emulation name ("*_fbsd") and OpenBSD calls its extensions
"PT_OPENBSD_*".

This distinct flavor is needed for NetBSD as:

  • the linker MUST work in the standalone mode
  • it must be useful with gcc/pcc/others out of the box
  • clang NetBSD driver shall not hardcode LLD specific options
  • the linker must have support for cross-building
  • LLD shall be a drop-in replacement for (NetBSD-patched) GNU ld

nb.lld calls internally ld.lld and there is no code-duplication
between nb.lld and ld.lld. There is no functional or code
maintenance change for other Operating Systems, especially the ELF
ones.

Equivalent customization is already done for the Darwin mode. For
instance there are hardcoded default search paths such as "/usr/lib"
and "/Library/Frameworks" in DarwinLdDriver.cpp.

This change is a starting point for development of NetBSD support
in LLD. This is also another approach to achieve the same goal as
mutating the default LLD/ELF target based on Triple, but in a
less invasive way as everything is moved out of LLD to nb.lld now.

Diff Detail

Event Timeline

krytarowski created this revision.Nov 2 2019, 2:39 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptNov 2 2019, 2:39 PM
  • upload diff with wider context

I still have the feeling that such configurations should be added to clangDriver/gcc specs or a shell script wrapper of lld.

How do you decide to handle "Handling of indirect shared library dependencies"? It does not seem to be favored by lld contributors.

lld/tools/nb.lld/nb.lld.cpp
94

You can't use DT_RUNPATH probably because the change Add support for DT_RUNPATH - it is just the same as we always have treated DT_RPATH. Approved by core. (2018-12-30) is still considered new. If you do this in clangDriver, you need a comment with a TODO about the migration process.

krytarowski marked an inline comment as done.Nov 2 2019, 4:07 PM
krytarowski added inline comments.
lld/tools/nb.lld/nb.lld.cpp
94

I am pretty sure that the only reason to pick it was rust (prebuilt snapshot) and its hard-coding of RUNPATH. We still want to disable it everywhere always.

I still have the feeling that such configurations should be added to clangDriver/gcc specs or a shell script wrapper of lld.

OK, as you allow now a shell wrapper of lld, this is a progress. nb.lld is a C++ wrapper on steroids doing the right job and part of the upstream repo (this is required).

We do not allow downstream LLVM/Clang/... patches in our basesystem and keeping this code upstream is required. Also from maintenance burden as LLVM APIs evolve quickly.

How do you decide to handle "Handling of indirect shared library dependencies"? It does not seem to be favored by lld contributors.

The modern Linux/GNU behavior is rejected in NetBSD and we keep the traditional behavior that is considered by our community as desired.

This is another topic and indeed probably our next major target to get to work within LLD.

MaskRay added a comment.EditedNov 5 2019, 10:44 AM

I still have the feeling that such configurations should be added to clangDriver/gcc specs or a shell script wrapper of lld.

OK, as you allow now a shell wrapper of lld, this is a progress. nb.lld is a C++ wrapper on steroids doing the right job and part of the upstream repo (this is required).

We do not allow downstream LLVM/Clang/... patches in our basesystem and keeping this code upstream is required. Also from maintenance burden as LLVM APIs evolve quickly.

Yes, by upstreaming you will share maintenance burden with the upstream.. but do we really need it? LLVM and Clang APIs and unstable and evolve quickly, but that is unrelated to the linker. I have reviewed the options added in this patch. These GNU ld options (with the exception or --no-rosegment and --image-base) have been so ingrained that I don't think the lld upstream can suddenly stop supporting some options or make disruptive changes that break the behaviors.

How do you decide to handle "Handling of indirect shared library dependencies"? It does not seem to be favored by lld contributors.

The modern Linux/GNU behavior is rejected in NetBSD and we keep the traditional behavior that is considered by our community as desired.

Can you give links about the (1) rejection and (2) community needs? I am under the impression that some of the decisions are simply GNU hatred. I've mentioned in previous review comments that I don't like many GNU ELF things (STB_GNU_UNIQUE, STT_GNU_IFUNC, 4-byte Elf64_Nhdr fields, strip/objcopy --strip-all not stripping non-SHF_ALLOC, etc), some are bearable, because diverging the behavior may just cost more. However, for this particular DT_RUNPATH case, I don't really understand what it will cost if you follow the GNU behavior.

// force-disable RO segment on NetBSD due to ld.elf_so limitations

args.push_back("--no-rosegment");

I hope you can fix the limitation soon. I just implemented the --only-keep-debug feature for llvm-objcopy. My observation is that --no-rosegment can make the debug file produced by --only-keep-debug larger (larger readonly sections such as .dynsym, .dynstr, .rodata and .eh_frame will occupy much space that cannot be eliminated). Mixing sections of different permission in the same RX segment does not look nice, either.

This is another topic and indeed probably our next major target to get to work within LLD.

I'm very concerned about this...... This traditional behavior will bring much complexity to the linker, while its usefulness is still very unclear to me.

krytarowski added a comment.EditedNov 5 2019, 12:50 PM

I don't want to diverge this patch on offtopic or general discussion.

Does it look good for landing? We need this support to be functional out of the box and as a part of LLVM. E.g. clang -fuse-ld= currently tries to call ld.lld, with this patch it will go through nb.lld as expected.

--no-rosegment is fixed with our WIP patches, but we NEED any support in LLD as a starting point so we can later just detach it (or add a check for version of NetBSD as we need Triple). Later we will the set the options on our own. I actually forgot to e.g. disable GNU stack and keep delaying it until the patch will land the sources.

We e.g. miss certain -switches in LLD, but hard to do anything in LLD without starting point. They will be proposed in future.

krytarowski added a comment.EditedNov 5 2019, 12:52 PM

burden with the upstream

We are the part of upstream and have 4 developers in LLVM + few others contributing. We run the NetBSD buildbot that builds and runs test of LLD.

http://lab.llvm.org:8014/builders/netbsd-amd64