bool ZNow;
bool ZOrigin;
bool ZRelro;
+ bool ExitEarly;
bool ZWxneeded;
DiscardPolicy Discard;
SortSectionPolicy SortSection;
Configuration *elf::Config;
LinkerDriver *elf::Driver;
-bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
+bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
+ raw_ostream &Error) {
HasError = false;
ErrorOS = &Error;
Argv0 = Args[0];
Driver = &D;
ScriptConfig = &SC;
- Driver->main(Args);
+ Driver->main(Args, CanExitEarly);
InputFile::freePool();
return !HasError;
}
return Default;
}
-void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
+void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
ELFOptTable Parser;
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
if (Args.hasArg(OPT_help)) {
}
if (Args.hasArg(OPT_version))
outs() << getLLDVersion() << "\n";
+ Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
if (const char *Path = getReproduceOption(Args)) {
// Note that --reproduce is a debug option so you can ignore it
class LinkerDriver {
public:
- void main(ArrayRef<const char *> Args);
+ void main(ArrayRef<const char *> Args, bool CanExitEarly);
void addFile(StringRef Path);
void addLibrary(StringRef Name);
llvm::LLVMContext Context; // to parse bitcode files
def fini: S<"fini">, MetaVarName<"<symbol>">,
HelpText<"Specify a finalizer function">;
+def full_shutdown : F<"full-shutdown">,
+ HelpText<"Perform a full shutdown instead of calling _exit">;
+
def format: J<"format=">, MetaVarName<"<input-format>">,
HelpText<"Change the input format of the inputs following this option">;
#include "llvm/Support/raw_ostream.h"
#include <climits>
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#endif
+
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
return;
if (auto EC = Buffer->commit())
error(EC, "failed to write to the output file");
+ if (Config->ExitEarly) {
+ // Flush the output streams and exit immediately. A full shutdown is a good
+ // test that we are keeping track of all allocated memory, but actually
+ // freeing it is a wast of time in a regular linker run.
+ outs().flush();
+ errs().flush();
+ _exit(0);
+ }
}
template <class ELFT>
}
namespace elf {
-bool link(llvm::ArrayRef<const char *> Args,
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
llvm::raw_ostream &Diag = llvm::errs());
}
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
-# RUN: lld -flavor gnu %t.o -o %t
+# RUN: ld.lld %t.o -o %t
# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
# REQUIRES: amdgpu
NoPreJunk = r"(?<!(-|\.|/))"
NoPostJunk = r"(?!(-|\.))"
+config.substitutions.append( (r"\bld.lld\b", 'ld.lld --full-shutdown') )
+
tool_patterns = [r"\bFileCheck\b",
r"\bnot\b",
NoPreJunk + r"\blld\b" + NoPostJunk,
std::vector<const char *> Args(Argv, Argv + Argc);
switch (parseFlavor(Args)) {
case Gnu:
- return !elf::link(Args);
+ return !elf::link(Args, true);
case WinLink:
return !coff::link(Args);
case Darwin: