From b18c4cfef0250eb7cc9b7e8273325878be72c242 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Jun 2014 12:54:56 -0700 Subject: [PATCH] rustc: Always include the morestack library It was previously assumed that the object file generated by LLVM would always require the __morestack function, but that assumption appears to be incorrect, as outlined in #15108. This commit forcibly tells the linker to include the entire archive, regardless of whether it's currently necessary or not. Closes #15108 --- src/librustc/back/link.rs | 41 +++++++++++++++++++++----------- src/test/run-pass/issue-15108.rs | 13 ++++++++++ 2 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 src/test/run-pass/issue-15108.rs diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index d644a0cc353..7a3e912b629 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1170,26 +1170,39 @@ fn link_args(cmd: &mut Command, // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. let lib_path = sess.target_filesearch().get_lib_path(); - cmd.arg("-L").arg(lib_path); + cmd.arg("-L").arg(&lib_path); cmd.arg("-o").arg(out_filename).arg(obj_filename); // Stack growth requires statically linking a __morestack function. Note - // that this is listed *before* all other libraries, even though it may be - // used to resolve symbols in other libraries. The only case that this - // wouldn't be pulled in by the object file is if the object file had no - // functions. + // that this is listed *before* all other libraries. Due to the usage of the + // --as-needed flag below, the standard library may only be useful for its + // rust_stack_exhausted function. In this case, we must ensure that the + // libmorestack.a file appears *before* the standard library (so we put it + // at the very front). // - // If we're building an executable, there must be at least one function (the - // main function), and if we're building a dylib then we don't need it for - // later libraries because they're all dylibs (not rlibs). + // Most of the time this is sufficient, except for when LLVM gets super + // clever. If, for example, we have a main function `fn main() {}`, LLVM + // will optimize out calls to `__morestack` entirely because the function + // doesn't need any stack at all! // - // I'm honestly not entirely sure why this needs to come first. Apparently - // the --as-needed flag above sometimes strips out libstd from the command - // line, but inserting this farther to the left makes the - // "rust_stack_exhausted" symbol an outstanding undefined symbol, which - // flags libstd as a required library (or whatever provides the symbol). - cmd.arg("-lmorestack"); + // To get around this snag, we specially tell the linker to always include + // all contents of this library. This way we're guaranteed that the linker + // will include the __morestack symbol 100% of the time, always resolving + // references to it even if the object above didn't use it. + match sess.targ_cfg.os { + abi::OsMacos | abi::OsiOS => { + let morestack = lib_path.join("libmorestack.a"); + + let mut v = "-Wl,-force_load,".as_bytes().to_owned(); + v.push_all(morestack.as_vec()); + cmd.arg(v.as_slice()); + } + _ => { + cmd.args(["-Wl,--whole-archive", "-lmorestack", + "-Wl,--no-whole-archive"]); + } + } // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main diff --git a/src/test/run-pass/issue-15108.rs b/src/test/run-pass/issue-15108.rs new file mode 100644 index 00000000000..736bd6cd3ab --- /dev/null +++ b/src/test/run-pass/issue-15108.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-O + +fn main() {} -- 2.44.0