[ELF] Fail the link early if the map file path is invalid

As with the changes made in r297645, we do not want a potentially long link to
be run, if it will ultimately fail because the map file is not writable. This
change reuses the same functionality as the output file path check. See
https://reviews.llvm.org/D30449 for further justification and explanations.

Reviewers: ruiu

Differential Revision: https://reviews.llvm.org/D31603

llvm-svn: 299420
This commit is contained in:
James Henderson 2017-04-04 09:42:24 +00:00
parent 74f823a045
commit b7a90ef48e
5 changed files with 24 additions and 15 deletions

View File

@ -860,10 +860,12 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (Config->OutputFile.empty())
Config->OutputFile = "a.out";
// 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.
if (!isFileWritable(Config->OutputFile))
// Fail early if the output file or map 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.
if (!isFileWritable(Config->OutputFile, "output file"))
return;
if (!isFileWritable(Config->MapFile, "map file"))
return;
// Use default entry point name if no name was given via the command

View File

@ -70,9 +70,9 @@ void elf::unlinkAsync(StringRef Path) {
// FileOutputBuffer doesn't touch a desitnation file until commit()
// is called. We use that class without calling commit() to predict
// if the given file is writable.
bool elf::isFileWritable(StringRef Path) {
bool elf::isFileWritable(StringRef Path, StringRef Desc) {
if (auto EC = FileOutputBuffer::create(Path, 1).getError()) {
error("cannot open output file " + Path + ": " + EC.message());
error("cannot open " + Desc + " " + Path + ": " + EC.message());
return false;
}
return true;

View File

@ -15,7 +15,7 @@
namespace lld {
namespace elf {
void unlinkAsync(StringRef Path);
bool isFileWritable(StringRef Path);
bool isFileWritable(StringRef Path, StringRef FileDescription);
}
}

View File

@ -2,25 +2,32 @@
# 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: FileCheck %s -check-prefixes=NO-DIR-OUTPUT,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: FileCheck %s -check-prefixes=DIR-IS-OUTPUT,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: FileCheck %s -check-prefixes=NO-DIR-OUTPUT,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
# RUN: FileCheck %s -check-prefixes=DIR-IS-OUTPUT,CHECK
# NO-DIR: error: cannot open output file does_not_exist/output:
# DIR-IS-FILE: error: cannot open output file {{.*}}/dir_is_a_file:
# RUN: not ld.lld %t.o -o %t -Map=does_not_exist/output 2>&1 | \
# RUN: FileCheck %s -check-prefixes=NO-DIR-MAP,CHECK
# RUN: not ld.lld %t.o -o %t -Map=%s/dir_is_a_file 2>&1 | \
# RUN: FileCheck %s -check-prefixes=DIR-IS-MAP,CHECK
# NO-DIR-OUTPUT: error: cannot open output file does_not_exist/output:
# DIR-IS-OUTPUT: error: cannot open output file {{.*}}/dir_is_a_file:
# NO-DIR-MAP: error: cannot open map file does_not_exist/output:
# DIR-IS-MAP: error: cannot open map 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
# RUN: not ld.lld %t.o -o / 2>&1 | FileCheck %s -check-prefixes=ROOT
# RUN: not ld.lld %t.o -o / 2>&1 | FileCheck %s -check-prefixes=ROOT,CHECK
# ROOT: error: cannot open output file /
.globl _start

View File

@ -59,4 +59,4 @@ local:
// RUN: not ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=/ 2>&1 \
// RUN: | FileCheck -check-prefix=FAIL %s
// FAIL: cannot open /
// FAIL: cannot open map file /