forked from OSchip/llvm-project
[ELF] Fail the link early if an output path is invalid
Patch from James Henderson. If a user has a long link, e.g. due to a large LTO link, they do not wish to run it and find that it failed because there was a mistake in their command-line, after they waited for some significant amount of time. This change adds some basic checking of the linker output file path, which is run shortly after parsing the command-line and linker script. An error is emitted if LLD cannot write to the specified path. Differential Revision: https://reviews.llvm.org/D30449 llvm-svn: 297645
This commit is contained in:
parent
140a8569ce
commit
eaeca5ed79
|
@ -42,6 +42,7 @@
|
|||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Object/Decompressor.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
@ -796,6 +797,17 @@ static uint64_t getImageBase(opt::InputArgList &Args) {
|
|||
return V;
|
||||
}
|
||||
|
||||
static void ensureWritable(StringRef Path) {
|
||||
if (Path.empty())
|
||||
return;
|
||||
|
||||
ErrorOr<std::unique_ptr<FileOutputBuffer>> Err =
|
||||
FileOutputBuffer::create(Path, 1);
|
||||
if (!Err)
|
||||
error("cannot open output file " + Path + ": " +
|
||||
Err.getError().message());
|
||||
}
|
||||
|
||||
// Do actual linking. Note that when this function is called,
|
||||
// all linker scripts have already been parsed.
|
||||
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
|
@ -819,6 +831,13 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
if (Config->Entry.empty() && !Config->Relocatable)
|
||||
Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
|
||||
|
||||
// Fail early if the output file is not writable. If a user has a long link,
|
||||
// e.g. due to a large LTO link, they do not wish to run it and find that it
|
||||
// failed because there was a mistake in their command-line.
|
||||
ensureWritable(Config->OutputFile);
|
||||
if (ErrorCount)
|
||||
return;
|
||||
|
||||
// Handle --trace-symbol.
|
||||
for (auto *Arg : Args.filtered(OPT_trace_symbol))
|
||||
Symtab.trace(Arg->getValue());
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
# RUN: not ld.lld %t -o /no/such/file 2>&1 | FileCheck -check-prefix=MISSING %s
|
||||
# MISSING: failed to open /no/such/file
|
||||
# MISSING: cannot open output file /no/such/file
|
||||
|
||||
# RUN: ld.lld --help 2>&1 | FileCheck -check-prefix=HELP %s
|
||||
# HELP: USAGE:
|
||||
|
@ -48,11 +48,11 @@
|
|||
|
||||
## "--output=foo" is equivalent to "-o foo".
|
||||
# RUN: not ld.lld %t --output=/no/such/file 2>&1 | FileCheck -check-prefix=ERR7 %s
|
||||
# ERR7: failed to open /no/such/file
|
||||
# ERR7: cannot open output file /no/such/file
|
||||
|
||||
## "-output=foo" is equivalent to "-o utput=foo".
|
||||
# RUN: not ld.lld %t -output=/no/such/file 2>&1 | FileCheck -check-prefix=ERR8 %s
|
||||
# ERR8: failed to open utput=/no/such/file
|
||||
# ERR8: cannot open output file utput=/no/such/file
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
|
||||
# RUN: not ld.lld %t.o -o does_not_exist/output 2>&1 | \
|
||||
# RUN: FileCheck %s -check-prefixes=NO-DIR,CHECK
|
||||
# RUN: not ld.lld %t.o -o %s/dir_is_a_file 2>&1 | \
|
||||
# RUN: FileCheck %s -check-prefixes=DIR-IS-FILE,CHECK
|
||||
|
||||
# RUN: echo "OUTPUT(\"does_not_exist/output\")" > %t.script
|
||||
# RUN: not ld.lld %t.o %t.script 2>&1 | \
|
||||
# RUN: FileCheck %s -check-prefixes=NO-DIR,CHECK
|
||||
# RUN: echo "OUTPUT(\"%s/dir_is_a_file\")" > %t.script
|
||||
# RUN: not ld.lld %t.o %t.script 2>&1 | \
|
||||
# RUN: FileCheck %s -check-prefixes=DIR-IS-FILE,CHECK
|
||||
|
||||
# NO-DIR: error: cannot open output file does_not_exist/output:
|
||||
# DIR-IS-FILE: error: cannot open output file {{.*}}/dir_is_a_file:
|
||||
|
||||
# We should exit before doing the actual link. If an undefined symbol error is
|
||||
# discovered we haven't bailed out early as expected.
|
||||
# CHECK-NOT: undefined_symbol
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call undefined_symbol
|
Loading…
Reference in New Issue