Final report on Clang / LLD state

February 01, 2019 posted by Michał Górny

Starting this month, I will be focusing my effort on LLDB, the debugger of the LLVM toolchain, as work contracted by the NetBSD Foundation. In this entry, I would like to shortly summarize what I've been working on before and what I have been able to accomplish, and what I am going to do next.

Final status of LLD support

LLD is the link editor (linker) component of Clang toolchain. Its main advantage over GNU ld is much lower memory footprint, and linking speed. I started working on LLD this month, and encountered a few difficulties. I have explained them in detail in the first report on NetBSD LLD porting.

The aforementioned impasse between LLD and NetBSD toolchain maintainers still stands. A few comments have been exchanged but it doesn't seem that either of the sides have managed to convince the other. Right now, it seems that the most probable course of action for the future would be for NetBSD to maintain necessary changes as a local patchset.

To finish my work on LLD, I have committed devel/lld to pkgsrc. It is based on 7.0.1 release with NetBSD patches. I will update it to 8.0.0 once it is released.

Other work on LLVM

Besides the specific effort on LLD, I have been focusing on preparing and testing for the upcoming 8.0.0 release of LLVM. Upstream has set branching point to Jan 16th, and we wanted to get all the pending changes merged if possible.

Of the compiler-rt patches previously submitted for review, the following changes have been merged (and will be included in 8.0.0):

  • added interceptor tests for clearerr, feof, ferrno, fileno, fgetc, getc, ungetc (r350225)

  • fixed more interceptor tests to use assert in order to report potential errors verbosely (r350227)

  • fixed return type of devname_r() interceptor (r350228)

  • added interceptor tests for fputc, putc, putchar, getc_unlocked, putc_unlocked, putchar_unlocked (r350229)

  • added interceptor tests for popen, pclose (r350230)

  • added interceptor tests for funopen (r350231)

  • added interception support for popen, popenve, pclose (r350232)

  • added interception support for funopen* (r350233)

  • implemented FILE structure sanitization (r350882)

Additionally, the following changes have been made to other LLVM components and merged into 8.0.0:

  • enabled system-linker-elf LLD feature on NetBSD (NFC) (r350253)

  • made clang driver permit building instrumented code for all kinds of sanitizers (r351002)

  • added appropriate RPATH when building instrumented code with shared sanitizer runtime (e.g. via -shared-libasan option) (r352610)

Post-release commits were focused on fixing new or newly noticed bugs:

  • fixed Mac-specific compilation-db test to not fail on systems where getMainExecutable function results depends on argv[0] being correct (r351752) (see below)

  • fixed formatting error in polly that caused tests to fail (r351808)

  • fixed missing -lutil linkage in LLDB that caused build using LLD as linker to fail (r352116)

Finding executable path in LLVM

The LLVM support library defines getMainExecutable() function whose purpose is to find the path to the currently executed program. It is used e.g. by clang to determine the driver mode depending on whether you executed clang or clang++, etc. It is also used to determine resource directory when it is specified relatively to the program installation directory.

The function implements a few different execution paths depending on the platform used:

  • on Apple platforms, it uses _NSGetExecutablePath()

  • on BSD variants and AIX, it does path lookup on argv[0]

  • on Linux and Cygwin, it uses /proc/self/exe, or argv[0] lookup if it is not present

  • on other platforms supporting dladdr(), it attempts to find the program path via Dl_info structure corresponding to the main function

  • on Windows, it uses GetModuleFileNameW()

For consistency, all symlinks are eliminated via realpath().

The different function versions require different arguments. argv[0]-based methods require passing argv[0]; dladdr method requires passing pointer to the main function. Other variants ignore those parameters.

When clang-check-mac-libcxx-fixed-compilation-db test was added to clang, it failed on NetBSD because the variant of getMainExecutable() used on NetBSD requires passing argv[0], and the specific part of Clang did not pass it correctly. However, the test authors did not notice the problem since non-BSD platforms normally do not use argv[0] for executable path.

I have determined three possible solutions here (ideally, all of them would be implemented simultaneously):

  1. Modifying getMainExecutable() to use KERN_PROC_PATHNAME sysctl on NetBSD (D56975).

  2. Fixing the compilation database code to pass argv[0] through.

  3. Adding -ccc-install-dir argument to the invocation in the test to force assuming specific install directory (D56976).

The sysctl change was already historically implemented (r303015). It was afterwards reverted (r303285) since it did not provide expected paths on FreeBSD when the executable was referenced via multiple links. However, NetBSD does not suffer from the same issue, so we may switch back to sysctl.

Fixing compilation database would be non-trivial as it would probably involve passing argv[0] to constructor, and effectively some API changes. Given that the code is apparently only used on Apple where argv[0] is not used, I have decided not to explore it for the time being.

Finally, passing -ccc-install-dir seems like the simplest workaround for the problem. Other tests based on paths in clang already pass this option to reliably override path detection. I've committed it as r351752.

Future plans: LLDB

The plan for the next 6 months is as follows:

  1. Restore tracing in LLDB for NetBSD (i386/amd64/aarch64) for single-threaded applications.

  2. Restore execution of LLDB regression tests, unless there is need for a significant LLDB or kernel work, mark detected bugs as failing or unsupported ones.

  3. Enable execution of LLDB regression tests on the build bot in order to catch regressions.

  4. Upstream NetBSD (i386/amd64) core(5) support. Develop LLDB regression tests (and the testing framework enhancement) as requested by upstream.

  5. Upstream NetBSD aarch64 core(5) support. This might involve generic LLDB work on the interfaces and/or kernel fixes. Add regression tests as will be requested by upstream.

  6. Rework threading plan in LLDB in Remote Process Plugin to be more agnostic to non-Linux world and support the NetBSD threading model.

  7. Add support for FPU registers support for NetBSD/i386 and NetBSD/amd64.

  8. Support XSAVE, XSAVEOPT, ... registers in core(5) files on NetBSD/amd64.

  9. Add support for Debug Registers support for NetBSD/i386 and NetBSD/amd64.

  10. Add support to backtrace through signal trampoline and extend the support to libexecinfo, unwind implementations (LLVM, nongnu). Examine adding CFI support to interfaces that need it to provide more stable backtraces (both kernel and userland).

  11. Stabilize LLDB and address breaking tests from the test-suite.

  12. Merge LLDB with the basesystem (under LLVM-style distribution).

I will be working closely with Kamil Rytarowski who will support me on the NetBSD kernel side. I'm officially starting today in order to resolve the presented problems one by one.

This work will be sponsored by The NetBSD Foundation

The NetBSD Foundation is a non-profit organization and welcomes any donations to help us continue funding projects and services to the open-source community. Please consider visiting the following URL to chip in what you can:



Post a Comment:
Comments are closed for this entry.