Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -21,7 +21,7 @@ extern class LinkerDriver *Driver; // Entry point of the ELF linker. -void link(ArrayRef Args); +bool link(ArrayRef Args); class LinkerDriver { public: Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -29,12 +29,14 @@ Configuration *elf2::Config; LinkerDriver *elf2::Driver; -void elf2::link(ArrayRef Args) { +bool elf2::link(ArrayRef Args) { + HasError = false; Configuration C; LinkerDriver D; Config = &C; Driver = &D; Driver->main(Args.slice(1)); + return !HasError; } static std::pair parseEmulation(StringRef S) { @@ -53,22 +55,22 @@ if (S == "aarch64linux") return {ELF64LEKind, EM_AARCH64}; if (S == "i386pe" || S == "i386pep" || S == "thumb2pe") - error("Windows targets are not supported on the ELF frontend: " + S); - error("Unknown emulation: " + S); + fatal("Windows targets are not supported on the ELF frontend: " + S); + fatal("Unknown emulation: " + S); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. static std::vector getArchiveMembers(MemoryBufferRef MB) { ErrorOr> FileOrErr = Archive::create(MB); - error(FileOrErr, "Failed to parse archive"); + fatal(FileOrErr, "Failed to parse archive"); std::unique_ptr File = std::move(*FileOrErr); std::vector V; for (const ErrorOr &C : File->children()) { - error(C, "Could not get the child of the archive " + File->getFileName()); + fatal(C, "Could not get the child of the archive " + File->getFileName()); ErrorOr MbOrErr = C->getMemoryBufferRef(); - error(MbOrErr, "Could not get the buffer for a child of the archive " + + fatal(MbOrErr, "Could not get the buffer for a child of the archive " + File->getFileName()); V.push_back(*MbOrErr); } @@ -82,7 +84,7 @@ if (Config->Verbose) llvm::outs() << Path << "\n"; auto MBOrErr = MemoryBuffer::getFile(Path); - error(MBOrErr, "cannot open " + Path); + fatal(MBOrErr, "cannot open " + Path); std::unique_ptr &MB = *MBOrErr; MemoryBufferRef MBRef = MB->getMemBufferRef(); OwningMBs.push_back(std::move(MB)); // take MB ownership @@ -114,15 +116,15 @@ // of executables or DSOs. We don't support that since the feature // does not seem to provide more value than the static archiver. if (Args.hasArg(OPT_relocatable)) - error("-r option is not supported. Use 'ar' command instead."); + fatal("-r option is not supported. Use 'ar' command instead."); // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. if (Config->EMachine == EM_MIPS && Config->GnuHash) - error("The .gnu.hash section is not compatible with the MIPS target."); + fatal("The .gnu.hash section is not compatible with the MIPS target."); if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty()) - error("-e option is not valid for AMDGPU."); + fatal("-e option is not valid for AMDGPU."); } static StringRef @@ -161,7 +163,7 @@ link(Args); return; default: - error("-m or at least a .o file required"); + fatal("-m or at least a .o file required"); } } @@ -217,7 +219,7 @@ if (auto *Arg = Args.getLastArg(OPT_O)) { StringRef Val = Arg->getValue(); if (Val.getAsInteger(10, Config->Optimize)) - error("Invalid optimization level"); + fatal("Invalid optimization level"); } if (auto *Arg = Args.getLastArg(OPT_hash_style)) { @@ -228,7 +230,7 @@ } else if (S == "both") { Config->GnuHash = true; } else if (S != "sysv") - error("Unknown hash style: " + S); + fatal("Unknown hash style: " + S); } for (auto *Arg : Args.filtered(OPT_undefined)) @@ -267,7 +269,7 @@ } if (Files.empty()) - error("no input files."); + fatal("no input files."); } template void LinkerDriver::link(opt::InputArgList &Args) { Index: ELF/DriverUtils.cpp =================================================================== --- ELF/DriverUtils.cpp +++ ELF/DriverUtils.cpp @@ -66,7 +66,7 @@ // Parse options and then do error checking. opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount); if (MissingCount) - error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + + fatal(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + "\", expected " + Twine(MissingCount) + (MissingCount == 1 ? " argument.\n" : " arguments")); @@ -74,7 +74,7 @@ for (auto *Arg : Unknowns) warning("warning: unknown argument: " + Arg->getSpelling()); if (Unknowns.begin() != Unknowns.end()) - error("unknown argument(s) found"); + fatal("unknown argument(s) found"); return Args; } @@ -104,7 +104,7 @@ if (!S.empty()) return S; } - error("Unable to find library -l" + Path); + fatal("Unable to find library -l" + Path); } // Makes a path by concatenating Dir and File. Index: ELF/Error.h =================================================================== --- ELF/Error.h +++ ELF/Error.h @@ -15,9 +15,11 @@ namespace lld { namespace elf2 { +extern thread_local bool HasError; + void warning(const Twine &Msg); -LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg); +void error(const Twine &Msg); void error(std::error_code EC, const Twine &Prefix); void error(std::error_code EC); @@ -26,6 +28,15 @@ } template void error(const ErrorOr &V) { error(V.getError()); } +LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); +void fatal(std::error_code EC, const Twine &Prefix); +void fatal(std::error_code EC); + +template void fatal(const ErrorOr &V, const Twine &Prefix) { + fatal(V.getError(), Prefix); +} +template void fatal(const ErrorOr &V) { fatal(V.getError()); } + } // namespace elf2 } // namespace lld Index: ELF/Error.cpp =================================================================== --- ELF/Error.cpp +++ ELF/Error.cpp @@ -15,23 +15,38 @@ namespace lld { namespace elf2 { +thread_local bool HasError; + void warning(const Twine &Msg) { llvm::errs() << Msg << "\n"; } void error(const Twine &Msg) { llvm::errs() << Msg << "\n"; - exit(1); + HasError = true; } void error(std::error_code EC, const Twine &Prefix) { - if (!EC) - return; - error(Prefix + ": " + EC.message()); + if (EC) + error(Prefix + ": " + EC.message()); } void error(std::error_code EC) { - if (!EC) - return; - error(EC.message()); + if (EC) + error(EC.message()); +} + +void fatal(const Twine &Msg) { + llvm::errs() << Msg << "\n"; + exit(1); +} + +void fatal(std::error_code EC, const Twine &Prefix) { + if (EC) + fatal(Prefix + ": " + EC.message()); +} + +void fatal(std::error_code EC) { + if (EC) + fatal(EC.message()); } } // namespace elf2 Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -27,7 +27,7 @@ public: std::error_code &getEC() { return EC; } - ~ECRAII() { error(EC); } + ~ECRAII() { fatal(EC); } }; } @@ -51,7 +51,7 @@ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); uint32_t FirstNonLocal = Symtab->sh_info; if (FirstNonLocal > NumSymbols) - error("Invalid sh_info in symbol table"); + fatal("Invalid sh_info in symbol table"); if (!Local) return make_range(Syms.begin() + FirstNonLocal, Syms.end()); // +1 to skip over dummy symbol. @@ -72,7 +72,7 @@ if (!Symtab) return; ErrorOr StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab); - error(StringTableOrErr); + fatal(StringTableOrErr); StringTable = *StringTableOrErr; } @@ -122,14 +122,14 @@ const ELFFile &Obj = this->ELFObj; uint32_t SymtabdSectionIndex = Sec.sh_link; ErrorOr SecOrErr = Obj.getSection(SymtabdSectionIndex); - error(SecOrErr); + fatal(SecOrErr); const Elf_Shdr *SymtabSec = *SecOrErr; uint32_t SymIndex = Sec.sh_info; const Elf_Sym *Sym = Obj.getSymbol(SymtabSec, SymIndex); ErrorOr StringTableOrErr = Obj.getStringTableForSymtab(*SymtabSec); - error(StringTableOrErr); + fatal(StringTableOrErr); ErrorOr SignatureOrErr = Sym->getName(*StringTableOrErr); - error(SignatureOrErr); + fatal(SignatureOrErr); return *SignatureOrErr; } @@ -139,10 +139,10 @@ const ELFFile &Obj = this->ELFObj; ErrorOr> EntriesOrErr = Obj.template getSectionContentsAsArray(&Sec); - error(EntriesOrErr); + fatal(EntriesOrErr); ArrayRef Entries = *EntriesOrErr; if (Entries.empty() || Entries[0] != GRP_COMDAT) - error("Unsupported SHT_GROUP format"); + fatal("Unsupported SHT_GROUP format"); return Entries.slice(1); } @@ -153,10 +153,10 @@ if (!(Flags & SHF_MERGE)) return false; if (Flags & SHF_WRITE) - error("Writable SHF_MERGE sections are not supported"); + fatal("Writable SHF_MERGE sections are not supported"); uintX_t EntSize = Sec.sh_entsize; if (!EntSize || Sec.sh_size % EntSize) - error("SHF_MERGE section size must be a multiple of sh_entsize"); + fatal("SHF_MERGE section size must be a multiple of sh_entsize"); // Don't try to merge if the aligment is larger than the sh_entsize. // @@ -191,7 +191,7 @@ continue; for (uint32_t SecIndex : getShtGroupEntries(Sec)) { if (SecIndex >= Size) - error("Invalid section index in group"); + fatal("Invalid section index in group"); Sections[SecIndex] = &InputSection::Discarded; } break; @@ -200,7 +200,7 @@ break; case SHT_SYMTAB_SHNDX: { ErrorOr> ErrorOrTable = Obj.getSHNDXTable(Sec); - error(ErrorOrTable); + fatal(ErrorOrTable); this->SymtabSHNDX = *ErrorOrTable; break; } @@ -211,19 +211,19 @@ case SHT_REL: { uint32_t RelocatedSectionIndex = Sec.sh_info; if (RelocatedSectionIndex >= Size) - error("Invalid relocated section index"); + fatal("Invalid relocated section index"); InputSectionBase *RelocatedSection = Sections[RelocatedSectionIndex]; if (!RelocatedSection) - error("Unsupported relocation reference"); + fatal("Unsupported relocation reference"); if (auto *S = dyn_cast>(RelocatedSection)) { S->RelocSections.push_back(&Sec); } else if (auto *S = dyn_cast>(RelocatedSection)) { if (S->RelocSection) - error("Multiple relocation sections to .eh_frame are not supported"); + fatal("Multiple relocation sections to .eh_frame are not supported"); S->RelocSection = &Sec; } else { - error("Relocations pointing to SHF_MERGE are not supported"); + fatal("Relocations pointing to SHF_MERGE are not supported"); } break; } @@ -236,7 +236,7 @@ template InputSectionBase * ObjectFile::createInputSection(const Elf_Shdr &Sec) { ErrorOr NameOrErr = this->ELFObj.getSectionName(&Sec); - error(NameOrErr); + fatal(NameOrErr); StringRef Name = *NameOrErr; // .note.GNU-stack is a marker section to control the presence of @@ -276,14 +276,14 @@ if (Index == 0) return nullptr; if (Index >= Sections.size() || !Sections[Index]) - error("Invalid section index"); + fatal("Invalid section index"); return Sections[Index]; } template SymbolBody *ObjectFile::createSymbolBody(const Elf_Sym *Sym) { ErrorOr NameOrErr = Sym->getName(this->StringTable); - error(NameOrErr); + fatal(NameOrErr); StringRef Name = *NameOrErr; switch (Sym->st_shndx) { @@ -297,7 +297,7 @@ switch (Sym->getBinding()) { default: - error("unexpected binding"); + fatal("unexpected binding"); case STB_GLOBAL: case STB_WEAK: case STB_GNU_UNIQUE: { @@ -311,7 +311,7 @@ void ArchiveFile::parse() { ErrorOr> FileOrErr = Archive::create(MB); - error(FileOrErr, "Failed to parse archive"); + fatal(FileOrErr, "Failed to parse archive"); File = std::move(*FileOrErr); // Allocate a buffer for Lazy objects. @@ -326,7 +326,7 @@ // Returns a buffer pointing to a member file containing a given symbol. MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) { ErrorOr COrErr = Sym->getMember(); - error(COrErr, "Could not get the member for symbol " + Sym->getName()); + fatal(COrErr, "Could not get the member for symbol " + Sym->getName()); const Archive::Child &C = *COrErr; if (!Seen.insert(C.getChildOffset()).second) @@ -334,7 +334,7 @@ ErrorOr RefOrErr = C.getMemoryBufferRef(); if (!RefOrErr) - error(RefOrErr, "Could not get the buffer for the member defining symbol " + + fatal(RefOrErr, "Could not get the buffer for the member defining symbol " + Sym->getName()); return *RefOrErr; } @@ -350,7 +350,7 @@ if (Index == 0) return nullptr; ErrorOr Ret = this->ELFObj.getSection(Index); - error(Ret); + fatal(Ret); return *Ret; } @@ -374,7 +374,7 @@ break; case SHT_SYMTAB_SHNDX: { ErrorOr> ErrorOrTable = Obj.getSHNDXTable(Sec); - error(ErrorOrTable); + fatal(ErrorOrTable); this->SymtabSHNDX = *ErrorOrTable; break; } @@ -394,7 +394,7 @@ if (Dyn.d_tag == DT_SONAME) { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) - error("Invalid DT_SONAME entry"); + fatal("Invalid DT_SONAME entry"); SoName = StringRef(this->StringTable.data() + Val); return; } @@ -408,7 +408,7 @@ SymbolBodies.reserve(NumSymbols); for (const Elf_Sym &Sym : Syms) { ErrorOr NameOrErr = Sym.getName(this->StringTable); - error(NameOrErr.getError()); + fatal(NameOrErr.getError()); StringRef Name = *NameOrErr; if (Sym.isUndefined()) @@ -437,7 +437,7 @@ static std::unique_ptr createELFFile(MemoryBufferRef MB) { std::pair Type = getElfArchType(MB.getBuffer()); if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB) - error("Invalid data encoding: " + MB.getBufferIdentifier()); + fatal("Invalid data encoding: " + MB.getBufferIdentifier()); if (Type.first == ELF::ELFCLASS32) { if (Type.second == ELF::ELFDATA2LSB) @@ -449,7 +449,7 @@ return createELFFileAux>(MB); return createELFFileAux>(MB); } - error("Invalid file class: " + MB.getBufferIdentifier()); + fatal("Invalid file class: " + MB.getBufferIdentifier()); } std::unique_ptr elf2::createObjectFile(MemoryBufferRef MB) { Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -29,7 +29,7 @@ template StringRef InputSectionBase::getSectionName() const { ErrorOr Name = File->getObj().getSectionName(this->Header); - error(Name); + fatal(Name); return *Name; } @@ -37,7 +37,7 @@ ArrayRef InputSectionBase::getSectionData() const { ErrorOr> Ret = this->File->getObj().getSectionContents(this->Header); - error(Ret); + fatal(Ret); return *Ret; } @@ -325,7 +325,7 @@ StringRef Data((const char *)D.data(), D.size()); uintX_t Size = Data.size(); if (Offset >= Size) - error("Entry is past the end of the section"); + fatal("Entry is past the end of the section"); // Find the element this offset points to. auto I = std::upper_bound( @@ -369,7 +369,7 @@ // Initialize this->Reginfo. ArrayRef D = this->getSectionData(); if (D.size() != sizeof(Elf_Mips_RegInfo)) - error("Invalid size of .reginfo section"); + fatal("Invalid size of .reginfo section"); Reginfo = reinterpret_cast *>(D.data()); } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -86,7 +86,7 @@ } else if (Tok == "SECTIONS") { readSections(); } else { - error("unknown directive: " + Tok); + fatal("unknown directive: " + Tok); } } } @@ -103,7 +103,7 @@ if (S.startswith("\"")) { size_t E = S.find("\"", 1); if (E == StringRef::npos) - error("unclosed quote"); + fatal("unclosed quote"); Ret.push_back(S.substr(1, E - 1)); S = S.substr(E + 1); continue; @@ -128,7 +128,7 @@ if (S.startswith("/*")) { size_t E = S.find("*/", 2); if (E == StringRef::npos) - error("unclosed comment in a linker script"); + fatal("unclosed comment in a linker script"); S = S.substr(E + 2); continue; } @@ -141,13 +141,13 @@ StringRef LinkerScript::next() { if (atEOF()) - error("unexpected EOF"); + fatal("unexpected EOF"); return Tokens[Pos++]; } bool LinkerScript::skip(StringRef Tok) { if (atEOF()) - error("unexpected EOF"); + fatal("unexpected EOF"); if (Tok != Tokens[Pos]) return false; ++Pos; @@ -157,7 +157,7 @@ void LinkerScript::expect(StringRef Expect) { StringRef Tok = next(); if (Tok != Expect) - error(Expect + " expected, but got " + Tok); + fatal(Expect + " expected, but got " + Tok); } void LinkerScript::addFile(StringRef S) { @@ -184,7 +184,7 @@ } else { std::string Path = findFromSearchPaths(S); if (Path.empty()) - error("Unable to find " + S); + fatal("Unable to find " + S); Driver->addFile(Saver.save(Path)); } } @@ -238,7 +238,7 @@ void LinkerScript::readInclude() { StringRef Tok = next(); auto MBOrErr = MemoryBuffer::getFile(Tok); - error(MBOrErr, "cannot open " + Tok); + fatal(MBOrErr, "cannot open " + Tok); std::unique_ptr &MB = *MBOrErr; StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); std::vector V = tokenize(S); @@ -269,7 +269,7 @@ if (Tok == ")") return; if (Tok != ",") - error("unexpected token: " + Tok); + fatal("unexpected token: " + Tok); next(); expect(","); next(); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -770,7 +770,7 @@ return FdeOff + read64(F.PCRel); return FdeOff + read32(F.PCRel); } - error("unknown FDE size encoding"); + fatal("unknown FDE size encoding"); } template void EhFrameHeader::writeTo(uint8_t *Buf) { @@ -813,7 +813,7 @@ template void EhFrameHeader::addFde(uint8_t Enc, size_t Off, uint8_t *PCRel) { if (Live && (Enc & 0xF0) == dwarf::DW_EH_PE_datarel) - error("DW_EH_PE_datarel encoding unsupported for FDEs by .eh_frame_hdr"); + fatal("DW_EH_PE_datarel encoding unsupported for FDEs by .eh_frame_hdr"); FdeList.push_back(FdeData{Enc, Off, PCRel}); } @@ -904,7 +904,7 @@ File.getObj().getRelocationSymbol(&RI, File.getSymbolTable()); if (!Sym) - error("Unsupported relocation without symbol"); + fatal("Unsupported relocation without symbol"); InputSectionBase *Section = File.getSection(*Sym); @@ -1001,7 +1001,7 @@ // Read a byte and advance D by one byte. static uint8_t readByte(ArrayRef &D) { if (D.empty()) - error("corrupted or unsupported CIE information"); + fatal("corrupted or unsupported CIE information"); uint8_t B = D.front(); D = D.slice(1); return B; @@ -1014,14 +1014,14 @@ if ((Val & 0x80) == 0) return; } - error("corrupted or unsupported CIE information"); + fatal("corrupted or unsupported CIE information"); } template static unsigned getSizeForEncoding(unsigned Enc) { typedef typename ELFFile::uintX_t uintX_t; switch (Enc & 0x0f) { default: - error("unknown FDE encoding"); + fatal("unknown FDE encoding"); case dwarf::DW_EH_PE_absptr: case dwarf::DW_EH_PE_signed: return sizeof(uintX_t); @@ -1041,7 +1041,7 @@ uint8_t EHOutputSection::getFdeEncoding(ArrayRef D) { auto Check = [](bool C) { if (!C) - error("corrupted or unsupported CIE information"); + fatal("corrupted or unsupported CIE information"); }; Check(D.size() >= 8); @@ -1049,7 +1049,7 @@ uint8_t Version = readByte(D); if (Version != 1 && Version != 3) - error("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version)); + fatal("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version)); auto AugEnd = std::find(D.begin() + 1, D.end(), '\0'); Check(AugEnd != D.end()); @@ -1058,7 +1058,7 @@ // Code alignment factor should always be 1 for .eh_frame. if (readByte(D) != 1) - error("CIE code alignment must be 1"); + fatal("CIE code alignment must be 1"); // Skip data alignment factor skipLeb128(D); @@ -1079,7 +1079,7 @@ case 'P': { uint8_t Enc = readByte(D); if ((Enc & 0xf0) == dwarf::DW_EH_PE_aligned) - error("DW_EH_PE_aligned encoding for address of a personality routine " + fatal("DW_EH_PE_aligned encoding for address of a personality routine " "handler not supported"); unsigned EncSize = getSizeForEncoding(Enc); Check(D.size() >= EncSize); @@ -1093,7 +1093,7 @@ // handler break; default: - error("unknown .eh_frame augmentation string value"); + fatal("unknown .eh_frame augmentation string value"); } } return dwarf::DW_EH_PE_absptr; @@ -1159,13 +1159,13 @@ OffsetToIndex[Offset] = P.first->second; } else { if (!HasReloc) - error("FDE doesn't reference another section"); + fatal("FDE doesn't reference another section"); InputSectionBase *Target = S->getRelocTarget(*RelI); if (Target != &InputSection::Discarded && Target->isLive()) { uint32_t CieOffset = Offset + 4 - ID; auto I = OffsetToIndex.find(CieOffset); if (I == OffsetToIndex.end()) - error("Invalid CIE reference"); + fatal("Invalid CIE reference"); Cies[I->second].Fdes.push_back(EHRegion(S, Index)); Out::EhFrameHdr->reserveFde(); this->Header.sh_size += alignTo(Length, sizeof(uintX_t)); @@ -1183,23 +1183,23 @@ const endianness E = ELFT::TargetEndianness; if (D.size() < 4) - error("Truncated CIE/FDE length"); + fatal("Truncated CIE/FDE length"); uint64_t Len = read32(D.data()); if (Len < UINT32_MAX) { if (Len > (UINT32_MAX - 4)) - error("CIE/FIE size is too large"); + fatal("CIE/FIE size is too large"); if (Len + 4 > D.size()) - error("CIE/FIE ends past the end of the section"); + fatal("CIE/FIE ends past the end of the section"); return Len + 4; } if (D.size() < 12) - error("Truncated CIE/FDE length"); + fatal("Truncated CIE/FDE length"); Len = read64(D.data() + 4); if (Len > (UINT64_MAX - 12)) - error("CIE/FIE size is too large"); + fatal("CIE/FIE size is too large"); if (Len + 12 > D.size()) - error("CIE/FIE ends past the end of the section"); + fatal("CIE/FIE ends past the end of the section"); return Len + 12; } @@ -1305,7 +1305,7 @@ while (!Data.empty()) { size_t End = findNull(Data, EntSize); if (End == StringRef::npos) - error("String is not null terminated"); + fatal("String is not null terminated"); StringRef Entry = Data.substr(0, End + EntSize); uintX_t OutputOffset = Builder.add(Entry); if (shouldTailMerge()) @@ -1460,7 +1460,7 @@ for (const std::unique_ptr> &File : Table.getObjectFiles()) { for (const Elf_Sym *Sym : File->KeptLocalSyms) { ErrorOr SymNameOrErr = Sym->getName(File->getStringTable()); - error(SymNameOrErr); + fatal(SymNameOrErr); StringRef SymName = *SymNameOrErr; auto *ESym = reinterpret_cast(Buf); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -41,7 +41,7 @@ StringRef B = Config->Emulation; if (B.empty()) B = Config->FirstElf->getName(); - error(A + " is incompatible with " + B); + fatal(A + " is incompatible with " + B); } // Add symbols in File to the symbol table. @@ -182,7 +182,7 @@ } if (New->isTls() != Existing->isTls()) - error("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New)); + fatal("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New)); // compare() returns -1, 0, or 1 if the lhs symbol is less preferable, // equivalent (conflicting), or more preferable, respectively. @@ -190,7 +190,7 @@ if (Comp == 0) { std::string S = "duplicate symbol: " + conflictMsg(Existing, New); if (!Config->AllowMultipleDefinition) - error(S); + fatal(S); warning(S); return; } Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -46,28 +46,28 @@ if (isInt(V)) return; StringRef S = getELFRelocationTypeName(Config->EMachine, Type); - error("Relocation " + S + " out of range"); + fatal("Relocation " + S + " out of range"); } template static void checkUInt(uint64_t V, uint32_t Type) { if (isUInt(V)) return; StringRef S = getELFRelocationTypeName(Config->EMachine, Type); - error("Relocation " + S + " out of range"); + fatal("Relocation " + S + " out of range"); } template static void checkIntUInt(uint64_t V, uint32_t Type) { if (isInt(V) || isUInt(V)) return; StringRef S = getELFRelocationTypeName(Config->EMachine, Type); - error("Relocation " + S + " out of range"); + fatal("Relocation " + S + " out of range"); } template static void checkAlignment(uint64_t V, uint32_t Type) { if ((V & (N - 1)) == 0) return; StringRef S = getELFRelocationTypeName(Config->EMachine, Type); - error("Improper alignment for relocation " + S); + fatal("Improper alignment for relocation " + S); } template bool isGnuIFunc(const SymbolBody &S) { @@ -260,7 +260,7 @@ case ELF32BEKind: return new MipsTargetInfo(); default: - error("Unsupported MIPS target"); + fatal("Unsupported MIPS target"); } case EM_PPC: return new PPCTargetInfo(); @@ -269,7 +269,7 @@ case EM_X86_64: return new X86_64TargetInfo(); } - error("Unknown target machine"); + fatal("Unknown target machine"); } TargetInfo::~TargetInfo() {} @@ -463,7 +463,7 @@ write32le(Loc, Out::TlsPhdr->p_memsz - SA); break; default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } @@ -926,7 +926,7 @@ write32le(Loc, SA - P); break; default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } @@ -969,7 +969,7 @@ write16be(Loc, applyPPCLo(SA)); break; default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } @@ -1182,7 +1182,7 @@ write64be(Loc, SA); break; default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } @@ -1201,7 +1201,7 @@ if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64) return Type; StringRef S = getELFRelocationTypeName(EM_AARCH64, Type); - error("Relocation " + S + " cannot be used when making a shared object; " + fatal("Relocation " + S + " cannot be used when making a shared object; " "recompile with -fPIC."); } @@ -1421,7 +1421,7 @@ break; } default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } @@ -1472,7 +1472,7 @@ if (Type == R_MIPS_32 || Type == R_MIPS_64) return R_MIPS_REL32; StringRef S = getELFRelocationTypeName(EM_MIPS, Type); - error("Relocation " + S + " cannot be used when making a shared object; " + fatal("Relocation " + S + " cannot be used when making a shared object; " "recompile with -fPIC."); } @@ -1600,7 +1600,7 @@ break; } default: - error("unrecognized reloc " + Twine(Type)); + fatal("unrecognized reloc " + Twine(Type)); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -162,7 +162,7 @@ openFile(Config->OutputFile); writeHeader(); writeSections(); - error(Buffer->commit()); + fatal(Buffer->commit()); } namespace { @@ -382,7 +382,7 @@ if (Config->NoInhibitExec) warning(Msg); else - error(Msg); + fatal(Msg); } template @@ -421,7 +421,7 @@ for (const std::unique_ptr> &F : Symtab.getObjectFiles()) { for (const Elf_Sym &Sym : F->getLocalSymbols()) { ErrorOr SymNameOrErr = Sym.getName(F->getStringTable()); - error(SymNameOrErr); + fatal(SymNameOrErr); StringRef SymName = *SymNameOrErr; if (!shouldKeepInSymtab(*F, SymName, Sym)) continue; @@ -1318,7 +1318,7 @@ template void Writer::openFile(StringRef Path) { ErrorOr> BufferOrErr = FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable); - error(BufferOrErr, "failed to open " + Path); + fatal(BufferOrErr, "failed to open " + Path); Buffer = std::move(*BufferOrErr); } Index: include/lld/Driver/Driver.h =================================================================== --- include/lld/Driver/Driver.h +++ include/lld/Driver/Driver.h @@ -125,7 +125,7 @@ } namespace elf2 { -void link(llvm::ArrayRef args); +bool link(llvm::ArrayRef args); } /// Driver for lld unit tests Index: lib/Driver/UniversalDriver.cpp =================================================================== --- lib/Driver/UniversalDriver.cpp +++ lib/Driver/UniversalDriver.cpp @@ -205,8 +205,7 @@ case Flavor::old_gnu_ld: return GnuLdDriver::linkELF(args, diagnostics); case Flavor::gnu_ld: - elf2::link(args); - return true; + return elf2::link(args); case Flavor::darwin_ld: return DarwinLdDriver::linkMachO(args, diagnostics); case Flavor::win_link: