diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -304,7 +304,14 @@ private: void buildInitialSymbolTable(const OwnedObject &Obj) { for (auto &Symbol : Obj.getBinary()->symbols()) { - if (Symbol.getFlags() & object::SymbolRef::SF_Undefined) + auto SymbolFlagsOrErr = Symbol.getFlags(); + // FIXME: Raise an error for bad symbols. + if (!SymbolFlagsOrErr) { + consumeError(SymbolFlagsOrErr.takeError()); + continue; + } + + if (*SymbolFlagsOrErr & object::SymbolRef::SF_Undefined) continue; Expected SymbolName = Symbol.getName(); // FIXME: Raise an error for bad symbols. diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -896,7 +896,7 @@ uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -43,7 +43,7 @@ return Error::success(); } - uint32_t getSymbolFlags(DataRefImpl Symb) const override { + Expected getSymbolFlags(DataRefImpl Symb) const override { return SymbolRef::SF_Global; } diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -261,7 +261,7 @@ uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; uint8_t getSymbolBinding(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; @@ -609,7 +609,7 @@ } template -uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { +Expected ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { const Elf_Sym *ESym = getSymbol(Sym); uint32_t Result = SymbolRef::SF_None; @@ -626,12 +626,25 @@ if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) Result |= SymbolRef::SF_FormatSpecific; - auto DotSymtabSecSyms = EF.symbols(DotSymtabSec); - if (DotSymtabSecSyms && ESym == (*DotSymtabSecSyms).begin()) - Result |= SymbolRef::SF_FormatSpecific; - auto DotDynSymSecSyms = EF.symbols(DotDynSymSec); - if (DotDynSymSecSyms && ESym == (*DotDynSymSecSyms).begin()) - Result |= SymbolRef::SF_FormatSpecific; + auto IsNullSymbol = [this](const Elf_Sym *Sym, + const Elf_Shdr *SymSec) -> Expected { + if (auto SymbolsOrErr = EF.symbols(SymSec)) + return Sym == SymbolsOrErr->begin(); + else + return SymbolsOrErr.takeError(); + }; + + if (auto IsNullSymOrErr = IsNullSymbol(ESym, DotSymtabSec)) { + if (*IsNullSymOrErr) + Result |= SymbolRef::SF_FormatSpecific; + } else + return IsNullSymOrErr.takeError(); + + if (auto IsNullSymOrErr = IsNullSymbol(ESym, DotDynSymSec)) { + if (*IsNullSymOrErr) + Result |= SymbolRef::SF_FormatSpecific; + } else + return IsNullSymOrErr.takeError(); if (EF.getHeader()->e_machine == ELF::EM_ARM) { if (Expected NameOrErr = getSymbolName(Sym)) { @@ -639,10 +652,9 @@ if (Name.startswith("$d") || Name.startswith("$t") || Name.startswith("$a")) Result |= SymbolRef::SF_FormatSpecific; - } else { - // TODO: Actually report errors helpfully. - consumeError(NameOrErr.takeError()); - } + } else + return NameOrErr.takeError(); + if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) Result |= SymbolRef::SF_Thumb; } diff --git a/llvm/include/llvm/Object/IRObjectFile.h b/llvm/include/llvm/Object/IRObjectFile.h --- a/llvm/include/llvm/Object/IRObjectFile.h +++ b/llvm/include/llvm/Object/IRObjectFile.h @@ -38,7 +38,7 @@ ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; basic_symbol_iterator symbol_end() const override; diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -287,7 +287,7 @@ uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; unsigned getSymbolSectionID(SymbolRef Symb) const; unsigned getSectionID(SectionRef Sec) const; diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -296,7 +296,10 @@ ObjectFile(const ObjectFile &other) = delete; uint64_t getCommonSymbolSize(DataRefImpl Symb) const { - assert(getSymbolFlags(Symb) & SymbolRef::SF_Common); + auto SymbolFlagsOrErr = getSymbolFlags(Symb); + if (!SymbolFlagsOrErr) + report_fatal_error(SymbolFlagsOrErr.takeError()); + assert(*SymbolFlagsOrErr & SymbolRef::SF_Common); return getCommonSymbolSizeImpl(Symb); } diff --git a/llvm/include/llvm/Object/SymbolicFile.h b/llvm/include/llvm/Object/SymbolicFile.h --- a/llvm/include/llvm/Object/SymbolicFile.h +++ b/llvm/include/llvm/Object/SymbolicFile.h @@ -129,7 +129,7 @@ Error printName(raw_ostream &OS) const; /// Get symbol flags (bitwise OR of SymbolRef::Flags) - uint32_t getFlags() const; + Expected getFlags() const; DataRefImpl getRawDataRefImpl() const; const SymbolicFile *getObject() const; @@ -147,7 +147,7 @@ virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; - virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + virtual Expected getSymbolFlags(DataRefImpl Symb) const = 0; virtual basic_symbol_iterator symbol_begin() const = 0; @@ -196,7 +196,7 @@ return OwningObject->printSymbolName(OS, SymbolPimpl); } -inline uint32_t BasicSymbolRef::getFlags() const { +inline Expected BasicSymbolRef::getFlags() const { return OwningObject->getSymbolFlags(SymbolPimpl); } diff --git a/llvm/include/llvm/Object/TapiFile.h b/llvm/include/llvm/Object/TapiFile.h --- a/llvm/include/llvm/Object/TapiFile.h +++ b/llvm/include/llvm/Object/TapiFile.h @@ -33,7 +33,7 @@ Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override; - uint32_t getSymbolFlags(DataRefImpl DRI) const override; + Expected getSymbolFlags(DataRefImpl DRI) const override; basic_symbol_iterator symbol_begin() const override; diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -155,7 +155,7 @@ uint32_t getNumSections() const { return Sections.size(); } void moveSymbolNext(DataRefImpl &Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -268,7 +268,7 @@ // Interface inherited from base classes. void moveSymbolNext(DataRefImpl &Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; basic_symbol_iterator symbol_end() const override; diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp --- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp @@ -93,12 +93,16 @@ SymbolFlagsMap SymbolFlags; for (auto &Sym : (*Obj)->symbols()) { + auto SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) + return SymFlagsOrErr.takeError(); + // Skip symbols not defined in this object file. - if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) continue; // Skip symbols that are not global. - if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; // Skip symbols that have type SF_File. diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -125,8 +125,15 @@ return; } + auto SymFlags = Sym.getFlags(); + if (!SymFlags) { + ES.reportError(SymFlags.takeError()); + R.failMaterialization(); + return; + } + // Don't include symbols that aren't global. - if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) { + if (!(*SymFlags & object::BasicSymbolRef::SF_Global)) { if (auto SymName = Sym.getName()) InternalSymbols->insert(*SymName); else { @@ -200,7 +207,10 @@ // check whether the symbol is in a comdat section and if so mark it as // weak. for (auto &Sym : COFFObj->symbols()) { - if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) + auto SymFlags = Sym.getFlags(); + if (!SymFlags) + return SymFlags.takeError(); + if (*SymFlags & object::BasicSymbolRef::SF_Undefined) continue; auto Name = Sym.getName(); if (!Name) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -55,12 +55,16 @@ Expected llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + auto SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + return SymbolFlagsOrErr.takeError(); + JITSymbolFlags Flags = JITSymbolFlags::None; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak) Flags |= JITSymbolFlags::Weak; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common) Flags |= JITSymbolFlags::Common; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported) Flags |= JITSymbolFlags::Exported; auto SymbolType = Symbol.getType(); @@ -75,8 +79,11 @@ ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + auto SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + report_fatal_error(SymbolFlagsOrErr.takeError()); ARMJITSymbolFlags Flags; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb) Flags |= ARMJITSymbolFlags::Thumb; return Flags; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -214,8 +214,11 @@ { JITSymbolResolver::LookupSet Symbols; for (auto &Sym : Obj.symbols()) { - uint32_t Flags = Sym.getFlags(); - if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) { + auto FlagsOrErr = Sym.getFlags(); + if (!FlagsOrErr) + return FlagsOrErr.takeError(); + if ((*FlagsOrErr & SymbolRef::SF_Common) || + (*FlagsOrErr & SymbolRef::SF_Weak)) { // Get symbol name. if (auto NameOrErr = Sym.getName()) Symbols.insert(*NameOrErr); @@ -234,10 +237,12 @@ LLVM_DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); + auto FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + return FlagsOrErr.takeError(); // Skip undefined symbols. - if (Flags & SymbolRef::SF_Undefined) + if (*FlagsOrErr & SymbolRef::SF_Undefined) continue; // Get the symbol type. @@ -287,7 +292,7 @@ } } - if (Flags & SymbolRef::SF_Absolute && + if (*FlagsOrErr & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { uint64_t Addr = 0; if (auto AddrOrErr = I->getAddress()) @@ -300,7 +305,7 @@ LLVM_DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)Addr) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, *JITSymFlags); } else if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || @@ -332,7 +337,7 @@ LLVM_DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, SectOffset, *JITSymFlags); } @@ -592,8 +597,10 @@ uint32_t CommonAlign = 1; for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); - if (Flags & SymbolRef::SF_Common) { + Expected FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + return FlagsOrErr.takeError(); + if (*FlagsOrErr & SymbolRef::SF_Common) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = I->getCommonSize(); uint32_t Align = I->getAlignment(); diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -264,12 +264,14 @@ } static bool isArchiveSymbol(const object::BasicSymbolRef &S) { - uint32_t Symflags = S.getFlags(); - if (Symflags & object::SymbolRef::SF_FormatSpecific) + Expected SymFlagsOrErr = S.getFlags(); + if (!SymFlagsOrErr) + report_fatal_error(SymFlagsOrErr.takeError()); + if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific) return false; - if (!(Symflags & object::SymbolRef::SF_Global)) + if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) return false; - if (Symflags & object::SymbolRef::SF_Undefined) + if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) return false; return true; } diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -209,7 +209,7 @@ return SymbolRef::ST_Other; } -uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { +Expected COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp --- a/llvm/lib/Object/IRObjectFile.cpp +++ b/llvm/lib/Object/IRObjectFile.cpp @@ -47,7 +47,7 @@ return Error::success(); } -uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { return SymTab.getSymbolFlags(getSym(Symb)); } diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1804,8 +1804,11 @@ } uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { - uint32_t flags = getSymbolFlags(DRI); - if (flags & SymbolRef::SF_Common) { + Expected FlagsOrErr = getSymbolFlags(DRI); + if (!FlagsOrErr) + // getSymbolFlags() on Mach-O symbol can not fail. + report_fatal_error(FlagsOrErr.takeError()); + if (*FlagsOrErr & SymbolRef::SF_Common) { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); } @@ -1840,7 +1843,7 @@ return SymbolRef::ST_Other; } -uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { +Expected MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); uint8_t MachOType = Entry.n_type; diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -55,11 +55,14 @@ } uint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const { - uint32_t Flags = getSymbolFlags(Ref); - if (Flags & SymbolRef::SF_Undefined) - return 0; - if (Flags & SymbolRef::SF_Common) - return getCommonSymbolSize(Ref); + if (auto FlagsOrErr = getSymbolFlags(Ref)) { + if (*FlagsOrErr & SymbolRef::SF_Undefined) + return 0; + if (*FlagsOrErr & SymbolRef::SF_Common) + return getCommonSymbolSize(Ref); + } else + // TODO: Actually report errors helpfully. + consumeError(FlagsOrErr.takeError()); return getSymbolValueImpl(Ref); } diff --git a/llvm/lib/Object/TapiFile.cpp b/llvm/lib/Object/TapiFile.cpp --- a/llvm/lib/Object/TapiFile.cpp +++ b/llvm/lib/Object/TapiFile.cpp @@ -86,7 +86,7 @@ return Error::success(); } -uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const { +Expected TapiFile::getSymbolFlags(DataRefImpl DRI) const { const auto *Sym = reinterpret_cast(DRI.p); return Sym->Flags; } diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -1260,7 +1260,7 @@ void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } -uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = SymbolRef::SF_None; const WasmSymbol &Sym = getWasmSymbol(Symb); diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -392,7 +392,7 @@ Result.append(Res.begin(), Res.end()); } -uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = 0; llvm_unreachable("Not yet implemented!"); return Result; diff --git a/llvm/test/tools/llvm-nm/invalid-symbol-table-size.test b/llvm/test/tools/llvm-nm/invalid-symbol-table-size.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-nm/invalid-symbol-table-size.test @@ -0,0 +1,30 @@ +## This test ensures llvm-nm will emit helpful error message when dumping a symbol table +## whose sh_size isn't a multiple of the symbol size (sh_size % sizeof(Elf_Sym) != 0). + +# RUN: yaml2obj -DBITS=32 -DSIZE=33 %s -o %t.32-bit.o +# RUN: not llvm-nm %t.32-bit.o 2>&1 | FileCheck -DSIZE=33 -DSYMSIZE=16 %s +# RUN: yaml2obj -DBITS=64 -DSIZE=49 %s -o %t.64-bit.o +# RUN: not llvm-nm %t.64-bit.o 2>&1 | FileCheck -DSIZE=49 -DSYMSIZE=24 %s + +# RUN: not llvm-nm --dynamic %t.32-bit.o 2>&1 | FileCheck -DSIZE=33 -DSYMSIZE=16 %s +# RUN: not llvm-nm --dynamic %t.64-bit.o 2>&1 | FileCheck -DSIZE=49 -DSYMSIZE=24 %s + +# CHECK: error: {{.*}} section [index 2] has an invalid sh_size ([[SIZE]]) which is not a multiple of its sh_entsize ([[SYMSIZE]]) +# CHECK-EMPTY: + +--- !ELF +FileHeader: + Class: ELFCLASS[[BITS]] + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .dynstr + Type: SHT_STRTAB + Content: "00" + - Name: .symtab + Type: SHT_SYMTAB + Size: [[SIZE]] + - Name: .dynsym + Type: SHT_DYNSYM + Size: [[SIZE]] diff --git a/llvm/test/tools/llvm-objdump/ELF/invalid-symbol-table-size.test b/llvm/test/tools/llvm-objdump/ELF/invalid-symbol-table-size.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/invalid-symbol-table-size.test @@ -0,0 +1,30 @@ +## This test ensures llvm-objdump will emit helpful error message when dumping a symbol table +## whose sh_size isn't a multiple of the symbol size (sh_size % sizeof(Elf_Sym) != 0). + +# RUN: yaml2obj -DBITS=32 -DSIZE=33 %s -o %t.32-bit.o +# RUN: not llvm-objdump --syms %t.32-bit.o 2>&1 | FileCheck -DSIZE=33 -DSYMSIZE=16 %s +# RUN: yaml2obj -DBITS=64 -DSIZE=49 %s -o %t.64-bit.o +# RUN: not llvm-objdump --syms %t.64-bit.o 2>&1 | FileCheck -DSIZE=49 -DSYMSIZE=24 %s + +# RUN: not llvm-objdump --dynamic-syms %t.32-bit.o 2>&1 | FileCheck -DSIZE=33 -DSYMSIZE=16 %s +# RUN: not llvm-objdump --dynamic-syms %t.64-bit.o 2>&1 | FileCheck -DSIZE=49 -DSYMSIZE=24 %s + +# CHECK: error: {{.*}} section [index 2] has an invalid sh_size ([[SIZE]]) which is not a multiple of its sh_entsize ([[SYMSIZE]]) +# CHECK-EMPTY: + +--- !ELF +FileHeader: + Class: ELFCLASS[[BITS]] + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .dynstr + Type: SHT_STRTAB + Content: "00" + - Name: .symtab + Type: SHT_SYMTAB + Size: [[SIZE]] + - Name: .dynsym + Type: SHT_DYNSYM + Size: [[SIZE]] diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp --- a/llvm/tools/dsymutil/DebugMap.cpp +++ b/llvm/tools/dsymutil/DebugMap.cpp @@ -256,9 +256,12 @@ for (const auto &Sym : Object->symbols()) { uint64_t Address = Sym.getValue(); Expected Name = Sym.getName(); - if (!Name || (Sym.getFlags() & - (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) { + Expected FlagsOrErr = Sym.getFlags(); + if (!Name || !FlagsOrErr || + (*FlagsOrErr & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) { // TODO: Actually report errors helpfully. + if (!FlagsOrErr) + consumeError(FlagsOrErr.takeError()); if (!Name) consumeError(Name.takeError()); continue; diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -493,10 +493,13 @@ // relocations will use the symbol itself, and won't need an // object file address. The object file address field is optional // in the DebugMap, leave it unassigned for these symbols. - uint32_t Flags = Sym.getFlags(); - if (Flags & SymbolRef::SF_Absolute) { + Expected FlagsOrErr = Sym.getFlags(); + if (!FlagsOrErr) + // getFlags() on Mach-O symbol can not fail. + report_fatal_error(FlagsOrErr.takeError()); + if (*FlagsOrErr & SymbolRef::SF_Absolute) { CurrentObjectAddresses[*Name] = None; - } else if (Flags & SymbolRef::SF_Common) { + } else if (*FlagsOrErr & SymbolRef::SF_Common) { CurrentObjectAddresses[*Name] = None; CommonSymbols.push_back(std::string(*Name)); } else { diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -306,13 +306,21 @@ static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { bool ADefined; + Expected AFlagsOrErr = A.Sym.getFlags(); + if (!AFlagsOrErr) + // Symbol flags have been checked in caller. + report_fatal_error(AFlagsOrErr.takeError()); if (A.Sym.getRawDataRefImpl().p) - ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); + ADefined = !(*AFlagsOrErr & SymbolRef::SF_Undefined); else ADefined = A.TypeChar != 'U'; bool BDefined; + Expected BFlagsOrErr = B.Sym.getFlags(); + if (!BFlagsOrErr) + // Symbol flags have been checked in caller. + report_fatal_error(BFlagsOrErr.takeError()); if (B.Sym.getRawDataRefImpl().p) - BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); + BDefined = !(*BFlagsOrErr & SymbolRef::SF_Undefined); else BDefined = B.TypeChar != 'U'; return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < @@ -366,26 +374,29 @@ uint64_t NValue = 0; MachOObjectFile *MachO = dyn_cast(&Obj); if (Obj.isIR()) { - uint32_t SymFlags = S.Sym.getFlags(); - if (SymFlags & SymbolRef::SF_Global) + Expected SymFlags = S.Sym.getFlags(); + if (!SymFlags) + // getFlags() on Mach-O symbol can not fail. + report_fatal_error(SymFlags.takeError()); + if (*SymFlags & SymbolRef::SF_Global) NType |= MachO::N_EXT; - if (SymFlags & SymbolRef::SF_Hidden) + if (*SymFlags & SymbolRef::SF_Hidden) NType |= MachO::N_PEXT; - if (SymFlags & SymbolRef::SF_Undefined) + if (*SymFlags & SymbolRef::SF_Undefined) NType |= MachO::N_EXT | MachO::N_UNDF; else { // Here we have a symbol definition. So to fake out a section name we // use 1, 2 and 3 for section numbers. See below where they are used to // print out fake section names. NType |= MachO::N_SECT; - if (SymFlags & SymbolRef::SF_Const) + if (*SymFlags & SymbolRef::SF_Const) NSect = 3; - else if (SymFlags & SymbolRef::SF_Executable) + else if (*SymFlags & SymbolRef::SF_Executable) NSect = 1; else NSect = 2; } - if (SymFlags & SymbolRef::SF_Weak) + if (*SymFlags & SymbolRef::SF_Weak) NDesc |= MachO::N_WEAK_DEF; } else { DataRefImpl SymDRI = S.Sym.getRawDataRefImpl(); @@ -794,9 +805,14 @@ if (Optional Opt = demangle(S.Name, MachO)) Name = *Opt; } - if (S.Sym.getRawDataRefImpl().p) - SymFlags = S.Sym.getFlags(); - else + if (S.Sym.getRawDataRefImpl().p) { + Expected SymFlagsOrErr = S.Sym.getFlags(); + if (!SymFlagsOrErr) { + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + SymFlags = *SymFlagsOrErr; + } else SymFlags = S.SymFlags; bool Undefined = SymFlags & SymbolRef::SF_Undefined; @@ -1037,20 +1053,26 @@ } static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); - if (Flags & SymbolRef::SF_Executable) + Expected FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // getFlags() on WASM symbol can not fail. + report_fatal_error(FlagsOrErr.takeError()); + if (*FlagsOrErr & SymbolRef::SF_Executable) return 't'; return 'd'; } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); + Expected FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // getFlags() on IR symbol can not fail. + report_fatal_error(FlagsOrErr.takeError()); // FIXME: should we print 'b'? At the IR level we cannot be sure if this // will be in bss or not, but we could approximate. - if (Flags & SymbolRef::SF_Executable) + if (*FlagsOrErr & SymbolRef::SF_Executable) return 't'; else if (Triple(Obj.getTargetTriple()).isOSDarwin() && - (Flags & SymbolRef::SF_Const)) + (*FlagsOrErr & SymbolRef::SF_Const)) return 's'; else return 'd'; @@ -1076,13 +1098,17 @@ // section and name, to be used in format=sysv output. static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, StringRef &SecName) { - uint32_t Symflags = I->getFlags(); + Expected SymFlagsOrErr = I->getFlags(); + if (!SymFlagsOrErr) { + consumeError(SymFlagsOrErr.takeError()); + return '?'; + } if (ELFObjectFileBase *ELFObj = dyn_cast(&Obj)) { - if (Symflags & object::SymbolRef::SF_Absolute) + if (*SymFlagsOrErr & object::SymbolRef::SF_Absolute) SecName = "*ABS*"; - else if (Symflags & object::SymbolRef::SF_Common) + else if (*SymFlagsOrErr & object::SymbolRef::SF_Common) SecName = "*COM*"; - else if (Symflags & object::SymbolRef::SF_Undefined) + else if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) SecName = "*UND*"; else { elf_symbol_iterator SymI(I); @@ -1104,19 +1130,21 @@ } } - if ((Symflags & object::SymbolRef::SF_Weak) && !isa(Obj)) { + if ((*SymFlagsOrErr & object::SymbolRef::SF_Weak) && + !isa(Obj)) { char Ret = isObject(Obj, I) ? 'v' : 'w'; - return (!(Symflags & object::SymbolRef::SF_Undefined)) ? toupper(Ret) : Ret; + return (!(*SymFlagsOrErr & object::SymbolRef::SF_Undefined)) ? toupper(Ret) + : Ret; } - if (Symflags & object::SymbolRef::SF_Undefined) + if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) return 'U'; - if (Symflags & object::SymbolRef::SF_Common) + if (*SymFlagsOrErr & object::SymbolRef::SF_Common) return 'C'; char Ret = '?'; - if (Symflags & object::SymbolRef::SF_Absolute) + if (*SymFlagsOrErr & object::SymbolRef::SF_Absolute) Ret = 'a'; else if (IRObjectFile *IR = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*IR, I); @@ -1137,7 +1165,7 @@ } else llvm_unreachable("unknown binary format"); - if (!(Symflags & object::SymbolRef::SF_Global)) + if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) return Ret; return toupper(Ret); @@ -1205,10 +1233,14 @@ } if (!(MachO && DyldInfoOnly)) { for (BasicSymbolRef Sym : Symbols) { - uint32_t SymFlags = Sym.getFlags(); - if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) { + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) continue; - if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect)) + if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) continue; // If a "-s segname sectname" option was specified and this is a Mach-O // file and this section appears in this file, Nsect will be non-zero then diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -7559,7 +7559,11 @@ symbolTableWorked = true; DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); - bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; + Expected SymbolFlagsOrErr = MachOOF->getSymbolFlags(Symb); + if (!SymbolFlagsOrErr) + // getSymbolFlags() on Mach-O symbol can not fail. + report_fatal_error(SymbolFlagsOrErr.takeError()); + bool IsThumb = *SymbolFlagsOrErr & SymbolRef::SF_Thumb; // We only need the dedicated Thumb target if there's a real choice // (i.e. we're not targeting M-class) and the function is Thumb. diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1930,7 +1930,8 @@ return; SymbolRef::Type Type = unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName); - uint32_t Flags = Symbol.getFlags(); + uint32_t Flags = + unwrapOrError(Symbol.getFlags(), FileName, ArchiveName, ArchitectureName); // Don't ask a Mach-O STAB symbol for its section unless you know that // STAB symbol's section field refers to a valid section index. Otherwise diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -198,9 +198,14 @@ /// Total size of all ELF common symbols static uint64_t getCommonSize(ObjectFile *Obj) { uint64_t TotalCommons = 0; - for (auto &Sym : Obj->symbols()) - if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common) + for (auto &Sym : Obj->symbols()) { + auto SymFlagsOrErr = Obj->getSymbolFlags(Sym.getRawDataRefImpl()); + if (!SymFlagsOrErr) + // FIXME: Actually report errors helpfully. + report_fatal_error(SymFlagsOrErr.takeError()); + if (*SymFlagsOrErr & SymbolRef::SF_Common) TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl()); + } return TotalCommons; } diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp --- a/llvm/tools/sancov/sancov.cpp +++ b/llvm/tools/sancov/sancov.cpp @@ -657,7 +657,11 @@ failIfError(NameOrErr); StringRef Name = NameOrErr.get(); - if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined) && + Expected FlagsOrErr = Symbol.getFlags(); + failIfError(FlagsOrErr); + uint32_t Flags = FlagsOrErr.get(); + + if (!(Flags & object::BasicSymbolRef::SF_Undefined) && isCoveragePointSymbol(Name)) { Result.insert(Address); }