Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] internal lld linker #36120

Closed
wants to merge 9 commits into from
Closed

[WIP] internal lld linker #36120

wants to merge 9 commits into from

Commits on Sep 15, 2016

  1. internal lld linker

    this commit embeds lld, the LLVM linker, into rustc. If the `-Z use-lld`
    flag is passed to rustc, then rustc will use lld (via a library call),
    instead of an external linker like cc, to link a Rust executable.
    
    This has been tested by building the following minimal program:
    
    ``` rust
    #![feature(lang_items)]
    #![feature(no_core)]
    #![feature(start)]
    #![no_core]
    
    #[link(name = "c")]
    extern {}
    
    #[start]
    fn start(_: isize, _: *const *const u8) -> isize {
        0
    }
    
    #[lang = "copy"]
    trait Copy {}
    
    #[lang = "sized"]
    trait Sized {}
    ```
    
    Note that lld doesn't implicitly pass libraries (-lc) or startup
    object (crt1.o) like cc does, so one has to manually pass these to lld
    via `-C link-args`:
    
    ```
    $ rustc -Z print-link-args \
            -Z use-lld \
            -C link-args='-L /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/Scrt1.o /usr/lib/x86_64-linux-gnu/crti.o'
            zero.rs
    ["lld",
     "--as-needed",
     "-z", "noexecstack",
     "-L", "/root/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib",
     "zero.0.o",
     "-o", "zero",
     "--gc-sections",
     "--pie",
     "-L", "/root/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib",
     "--Bstatic", "--Bdynamic", "-l", "c",
     "-L", "/usr/lib/x86_64-linux-gnu",
     "/usr/lib/x86_64-linux-gnu/Scrt1.o",
     "/usr/lib/x86_64-linux-gnu/crti.o",
     "-l", "compiler-rt"]
    ```
    
    Which links correctly! But executing the produced binary yields a
    segfault :-(. There appears to be a problem when lld mixes Rust code and
    C code but I haven't investigated further.
    
    So was this an exercise in futility? No, not so fast. I did one more
    test: a Rust program with zero C dependencies, i.e. a Rust "kernel".
    Basically, I grabbed the "Hello, world" program from Intermezzos chapter
    3 [1] and turned it into a Cargo project [2] then proceeded to link it
    using lld:
    
    ```
    $ cargo rustc --target x86_64 --release -- -Z print-link-args -Z use-lld
    ["lld",
     "-Tlayout.ld",
     "-L", "/root/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64/lib",
     "/root/eighty-six/target/x86_64/release/kernel.0.o",
     "-o", "/root/eighty-six/target/x86_64/release/kernel",
     "--gc-sections",
     "-L", "/root/eighty-six/target/x86_64/release/deps",
     "-L", "/root/eighty-six/target/release/build/kernel-24c773dcbde95e48/out",
     "-L", "/root/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64/lib",
     "--Bstatic", "--whole-archive", "-l", "boot", "--no-whole-archive",
     "--Bdynamic", "/root/eighty-six/target/x86_64/release/deps/libcore.rlib"]
    ```
    
    This linked correctly and after turning the executable into a ISO image,
    it also worked perfectly under QEMU!
    
    ### Extra notes
    
    I've only tested ELF executables, not dylibs, MachO or COFF.
    
    lld supports ELFs, MachO and COFF formats. So in theory, with an
    internal lld we could drop the dependency on a external linker pretty
    much on all the platforms we support.
    
    lld is a multi-arch linker so it should be possible to link
    foreign (e.g. arm or mips) binaries as well but I haven't tested this
    yet. I actually intended to test this by linking Rust programs for the
    Cortex-M, as I have experience making C free programs for that target,
    but lld doesn't support Thumb (yet).
    
    Relevant news: "lld now implements almost all of the functionality
    necessary to function as a system linker for FreeBSD/amd64" -- FreeBSD
    folk @ LLVM mailing list [3]. The e-mail also mentions that other
    support for other archs is not quite ready for prime time.
    
    [1]: http://intermezzos.github.io/book/booting-up.html
    [2]: https://github.com/japaric/eighty-six/tree/lld2
    [3]: http://lists.llvm.org/pipermail/llvm-dev/2016-August/103998.html
    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    51963f0 View commit details
    Browse the repository at this point in the history
  2. build lld as an external project

    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    699454f View commit details
    Browse the repository at this point in the history
  3. [DoNotMerge] turn on lld by default

    just to test this on the try bots
    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    bd326ec View commit details
    Browse the repository at this point in the history
  4. skip cargo testing rustc_lld

    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    904efeb View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    cb39a7b View commit details
    Browse the repository at this point in the history
  6. lld-up

    should fix build on windows-gnu
    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    fa76b18 View commit details
    Browse the repository at this point in the history
  7. link rustc_lld against rustc_llvm

    should hopefully fix linking the rustc_lld dylib on osx
    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    fa0a31d View commit details
    Browse the repository at this point in the history
  8. some tidy fixes

    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    86c8377 View commit details
    Browse the repository at this point in the history
  9. [RFC] temporarily disable -pie support

    Jorge Aparicio committed Sep 15, 2016
    Configuration menu
    Copy the full SHA
    a4620cc View commit details
    Browse the repository at this point in the history