From f327999a4551bc83d2d474d258228007f7427597 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Mon, 13 Mar 2017 23:23:40 +0000 Subject: [PATCH] Simplify and add comments. NFC. llvm-svn: 297686 --- lld/ELF/Driver.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index ac64b22250db..53a450eaf23e 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -799,15 +799,26 @@ static uint64_t getImageBase(opt::InputArgList &Args) { return V; } -static void ensureWritable(StringRef Path) { - if (Path.empty()) - return; - +// Returns true if a given file seems to be writable. +// +// Determining whether a file is writable or not is amazingly hard, +// and after all the only reliable way of doing that is to actually +// create a file. But we don't want to do that in this function +// because LLD shouldn't update any file if it will end in a failure. +// We also don't want to reimplement heuristics. So we'll let +// FileOutputBuffer do the work. +// +// 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. +static bool isWritable(StringRef Path) { ErrorOr> Err = FileOutputBuffer::create(Path, 1); - if (!Err) - error("cannot open output file " + Path + ": " + - Err.getError().message()); + if (auto EC = Err.getError()) { + error("cannot open output file " + Path + ": " + EC.message()); + return false; + } + return true; } // Do actual linking. Note that when this function is called, @@ -825,6 +836,12 @@ template 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 (!isWritable(Config->OutputFile)) + return; + // Use default entry point name if no name was given via the command // line nor linker scripts. For some reason, MIPS entry point name is // different from others. @@ -833,13 +850,6 @@ template 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());