diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Object | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r-- | llvm/lib/Object/Archive.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Object/ArchiveWriter.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Object/COFFImportFile.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Object/COFFModuleDefinition.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 573 | ||||
-rw-r--r-- | llvm/lib/Object/ELF.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/Object/ELFObjectFile.cpp | 101 | ||||
-rw-r--r-- | llvm/lib/Object/Error.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Object/IRObjectFile.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Object/IRSymtab.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 41 | ||||
-rw-r--r-- | llvm/lib/Object/ModuleSymbolTable.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Object/ObjectFile.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/Object/RecordStreamer.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Object/RecordStreamer.h | 15 | ||||
-rw-r--r-- | llvm/lib/Object/RelocationResolver.cpp | 50 | ||||
-rw-r--r-- | llvm/lib/Object/SymbolSize.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Object/TapiFile.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Object/TapiUniversal.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Object/WasmObjectFile.cpp | 229 | ||||
-rw-r--r-- | llvm/lib/Object/WindowsResource.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Object/XCOFFObjectFile.cpp | 110 |
22 files changed, 787 insertions, 539 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 148c011d9cd4c..c18dd11a72ccd 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -392,12 +392,8 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) } Expected<uint64_t> Archive::Child::getSize() const { - if (Parent->IsThin) { - Expected<uint32_t> Size = Header.getSize(); - if (!Size) - return Size.takeError(); - return Size.get(); - } + if (Parent->IsThin) + return Header.getSize(); return Data.size() - StartOfFile; } @@ -423,12 +419,12 @@ Expected<std::string> Archive::Child::getFullName() const { return NameOrErr.takeError(); StringRef Name = *NameOrErr; if (sys::path::is_absolute(Name)) - return Name; + return std::string(Name); SmallString<128> FullName = sys::path::parent_path( Parent->getMemoryBufferRef().getBufferIdentifier()); sys::path::append(FullName, Name); - return StringRef(FullName); + return std::string(FullName.str()); } Expected<StringRef> Archive::Child::getBuffer() const { @@ -437,7 +433,7 @@ Expected<StringRef> Archive::Child::getBuffer() const { return isThinOrErr.takeError(); bool isThin = isThinOrErr.get(); if (!isThin) { - Expected<uint32_t> Size = getSize(); + Expected<uint64_t> Size = getSize(); if (!Size) return Size.takeError(); return StringRef(Data.data() + StartOfFile, Size.get()); diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index 5234b0e18233b..6f92c547164ba 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -12,6 +12,7 @@ #include "llvm/Object/ArchiveWriter.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/IR/LLVMContext.h" @@ -263,12 +264,15 @@ static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) { } static bool isArchiveSymbol(const object::BasicSymbolRef &S) { - uint32_t Symflags = S.getFlags(); - if (Symflags & object::SymbolRef::SF_FormatSpecific) + Expected<uint32_t> SymFlagsOrErr = S.getFlags(); + if (!SymFlagsOrErr) + // TODO: Actually report errors helpfully. + 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; } @@ -545,7 +549,7 @@ Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) { for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI) sys::path::append(Relative, sys::path::Style::posix, *ToI); - return Relative.str(); + return std::string(Relative.str()); } Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index ff4a799be60c7..69bbf70b43a15 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -600,7 +600,7 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, : getNameType(SymbolName, E.Name, Machine, MinGW); Expected<std::string> Name = E.ExtName.empty() - ? SymbolName + ? std::string(SymbolName) : replace(SymbolName, E.Name, E.ExtName); if (!Name) diff --git a/llvm/lib/Object/COFFModuleDefinition.cpp b/llvm/lib/Object/COFFModuleDefinition.cpp index 64d4cf0efda2d..8f29f7a658fdd 100644 --- a/llvm/lib/Object/COFFModuleDefinition.cpp +++ b/llvm/lib/Object/COFFModuleDefinition.cpp @@ -229,14 +229,14 @@ private: Error parseExport() { COFFShortExport E; - E.Name = Tok.Value; + E.Name = std::string(Tok.Value); read(); if (Tok.K == Equal) { read(); if (Tok.K != Identifier) return createError("identifier expected, but got " + Tok.Value); E.ExtName = E.Name; - E.Name = Tok.Value; + E.Name = std::string(Tok.Value); } else { unget(); } @@ -285,7 +285,7 @@ private: } if (Tok.K == EqualEqual) { read(); - E.AliasTarget = Tok.Value; + E.AliasTarget = std::string(Tok.Value); if (Machine == IMAGE_FILE_MACHINE_I386 && !isDecorated(E.AliasTarget, MingwDef)) E.AliasTarget = std::string("_").append(E.AliasTarget); continue; @@ -315,7 +315,7 @@ private: Error parseName(std::string *Out, uint64_t *Baseaddr) { read(); if (Tok.K == Identifier) { - *Out = Tok.Value; + *Out = std::string(Tok.Value); } else { *Out = ""; unget(); diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 2c0f6dc2b1e9b..c26d7721b3fe9 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/COFF.h" @@ -54,14 +55,13 @@ static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. // Returns unexpected_eof if error. template <typename T> -static std::error_code getObject(const T *&Obj, MemoryBufferRef M, - const void *Ptr, - const uint64_t Size = sizeof(T)) { +static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, + const uint64_t Size = sizeof(T)) { uintptr_t Addr = uintptr_t(Ptr); - if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) - return EC; + if (Error E = Binary::checkOffset(M, Addr, Size)) + return E; Obj = reinterpret_cast<const T *>(Addr); - return std::error_code(); + return Error::success(); } // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without @@ -147,11 +147,7 @@ void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { } Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { - COFFSymbolRef Symb = getCOFFSymbol(Ref); - StringRef Result; - if (std::error_code EC = getSymbolName(Symb, Result)) - return errorCodeToError(EC); - return Result; + return getSymbolName(getCOFFSymbol(Ref)); } uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { @@ -166,7 +162,7 @@ uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { } Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { - uint64_t Result = getSymbolValue(Ref); + uint64_t Result = cantFail(getSymbolValue(Ref)); COFFSymbolRef Symb = getCOFFSymbol(Ref); int32_t SectionNumber = Symb.getSectionNumber(); @@ -174,10 +170,10 @@ Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { COFF::isReservedSectionNumber(SectionNumber)) return Result; - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(SectionNumber, Section)) - return errorCodeToError(EC); - Result += Section->VirtualAddress; + Expected<const coff_section *> Section = getSection(SectionNumber); + if (!Section) + return Section.takeError(); + Result += (*Section)->VirtualAddress; // The section VirtualAddress does not include ImageBase, and we want to // return virtual addresses. @@ -209,7 +205,7 @@ Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { return SymbolRef::ST_Other; } -uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { +Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; @@ -250,11 +246,11 @@ COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) return section_end(); - const coff_section *Sec = nullptr; - if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) - return errorCodeToError(EC); + Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber()); + if (!Sec) + return Sec.takeError(); DataRefImpl Ret; - Ret.p = reinterpret_cast<uintptr_t>(Sec); + Ret.p = reinterpret_cast<uintptr_t>(*Sec); return section_iterator(SectionRef(Ret, this)); } @@ -328,6 +324,12 @@ bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { return (Sec->Characteristics & BssFlags) == BssFlags; } +// The .debug sections are the only debug sections for COFF +// (\see MCObjectFileInfo.cpp). +bool COFFObjectFile::isDebugSection(StringRef SectionName) const { + return SectionName.startswith(".debug"); +} + unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { uintptr_t Offset = uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); @@ -350,9 +352,12 @@ static uint32_t getNumberOfRelocations(const coff_section *Sec, // VirtualAddress field in the first relocation entry. if (Sec->hasExtendedRelocations()) { const coff_relocation *FirstReloc; - if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( - base + Sec->PointerToRelocations))) + if (Error E = getObject(FirstReloc, M, + reinterpret_cast<const coff_relocation *>( + base + Sec->PointerToRelocations))) { + consumeError(std::move(E)); return 0; + } // -1 to exclude this first relocation entry. return FirstReloc->VirtualAddress - 1; } @@ -371,9 +376,11 @@ getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { // relocations. begin++; } - if (Binary::checkOffset(M, uintptr_t(begin), - sizeof(coff_relocation) * NumRelocs)) + if (auto E = Binary::checkOffset(M, uintptr_t(begin), + sizeof(coff_relocation) * NumRelocs)) { + consumeError(std::move(E)); return nullptr; + } return begin; } @@ -398,18 +405,18 @@ relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { } // Initialize the pointer to the symbol table. -std::error_code COFFObjectFile::initSymbolTablePtr() { +Error COFFObjectFile::initSymbolTablePtr() { if (COFFHeader) - if (std::error_code EC = getObject( + if (Error E = getObject( SymbolTable16, Data, base() + getPointerToSymbolTable(), (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) - return EC; + return E; if (COFFBigObjHeader) - if (std::error_code EC = getObject( + if (Error E = getObject( SymbolTable32, Data, base() + getPointerToSymbolTable(), (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) - return EC; + return E; // Find string table. The first four byte of the string table contains the // total size of the string table, including the size field itself. If the @@ -418,22 +425,21 @@ std::error_code COFFObjectFile::initSymbolTablePtr() { getNumberOfSymbols() * getSymbolTableEntrySize(); const uint8_t *StringTableAddr = base() + StringTableOffset; const ulittle32_t *StringTableSizePtr; - if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) - return EC; + if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr)) + return E; StringTableSize = *StringTableSizePtr; - if (std::error_code EC = - getObject(StringTable, Data, StringTableAddr, StringTableSize)) - return EC; + if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize)) + return E; // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some // tools like cvtres write a size of 0 for an empty table instead of 4. if (StringTableSize < 4) - StringTableSize = 4; + StringTableSize = 4; // Check that the string table is null terminated if has any in it. if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) - return object_error::parse_failed; - return std::error_code(); + return errorCodeToError(object_error::parse_failed); + return Error::success(); } uint64_t COFFObjectFile::getImageBase() const { @@ -446,7 +452,7 @@ uint64_t COFFObjectFile::getImageBase() const { } // Returns the file offset for the given VA. -std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { +Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { uint64_t ImageBase = getImageBase(); uint64_t Rva = Addr - ImageBase; assert(Rva <= UINT32_MAX); @@ -454,7 +460,7 @@ std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { } // Returns the file offset for the given RVA. -std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { +Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { for (const SectionRef &S : sections()) { const coff_section *Section = getCOFFSection(S); uint32_t SectionStart = Section->VirtualAddress; @@ -462,15 +468,14 @@ std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { if (SectionStart <= Addr && Addr < SectionEnd) { uint32_t Offset = Addr - SectionStart; Res = uintptr_t(base()) + Section->PointerToRawData + Offset; - return std::error_code(); + return Error::success(); } } - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); } -std::error_code -COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, - ArrayRef<uint8_t> &Contents) const { +Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const { for (const SectionRef &S : sections()) { const coff_section *Section = getCOFFSection(S); uint32_t SectionStart = Section->VirtualAddress; @@ -483,196 +488,207 @@ COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; Contents = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); - return std::error_code(); + return Error::success(); } } - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); } // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name // table entry. -std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, - StringRef &Name) const { +Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, + StringRef &Name) const { uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(Rva, IntPtr)) - return EC; + if (Error E = getRvaPtr(Rva, IntPtr)) + return E; const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); - return std::error_code(); + return Error::success(); } -std::error_code -COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, - const codeview::DebugInfo *&PDBInfo, - StringRef &PDBFileName) const { +Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, + const codeview::DebugInfo *&PDBInfo, + StringRef &PDBFileName) const { ArrayRef<uint8_t> InfoBytes; - if (std::error_code EC = getRvaAndSizeAsBytes( + if (Error E = getRvaAndSizeAsBytes( DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) - return EC; + return E; if (InfoBytes.size() < sizeof(*PDBInfo) + 1) - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), InfoBytes.size()); // Truncate the name at the first null byte. Ignore any padding. PDBFileName = PDBFileName.split('\0').first; - return std::error_code(); + return Error::success(); } -std::error_code -COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, - StringRef &PDBFileName) const { +Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, + StringRef &PDBFileName) const { for (const debug_directory &D : debug_directories()) if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) return getDebugPDBInfo(&D, PDBInfo, PDBFileName); // If we get here, there is no PDB info to return. PDBInfo = nullptr; PDBFileName = StringRef(); - return std::error_code(); + return Error::success(); } // Find the import table. -std::error_code COFFObjectFile::initImportTablePtr() { +Error COFFObjectFile::initImportTablePtr() { // First, we get the RVA of the import table. If the file lacks a pointer to // the import table, do nothing. - const data_directory *DataEntry; - if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) - return std::error_code(); + const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE); + if (!DataEntry) + return Error::success(); // Do nothing if the pointer to import table is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; // Find the section that contains the RVA. This is needed because the RVA is // the import table's memory address which is different from its file offset. uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) - return EC; - if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) - return EC; + if (Error E = getRvaPtr(ImportTableRva, IntPtr)) + return E; + if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) + return E; ImportDirectory = reinterpret_cast< const coff_import_directory_table_entry *>(IntPtr); - return std::error_code(); + return Error::success(); } // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. -std::error_code COFFObjectFile::initDelayImportTablePtr() { - const data_directory *DataEntry; - if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) - return std::error_code(); +Error COFFObjectFile::initDelayImportTablePtr() { + const data_directory *DataEntry = + getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR); + if (!DataEntry) + return Error::success(); if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); uint32_t RVA = DataEntry->RelativeVirtualAddress; NumberOfDelayImportDirectory = DataEntry->Size / sizeof(delay_import_directory_table_entry) - 1; uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(RVA, IntPtr)) - return EC; + if (Error E = getRvaPtr(RVA, IntPtr)) + return E; DelayImportDirectory = reinterpret_cast< const delay_import_directory_table_entry *>(IntPtr); - return std::error_code(); + return Error::success(); } // Find the export table. -std::error_code COFFObjectFile::initExportTablePtr() { +Error COFFObjectFile::initExportTablePtr() { // First, we get the RVA of the export table. If the file lacks a pointer to // the export table, do nothing. - const data_directory *DataEntry; - if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) - return std::error_code(); + const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE); + if (!DataEntry) + return Error::success(); // Do nothing if the pointer to export table is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) - return EC; + if (Error E = getRvaPtr(ExportTableRva, IntPtr)) + return E; ExportDirectory = reinterpret_cast<const export_directory_table_entry *>(IntPtr); - return std::error_code(); + return Error::success(); } -std::error_code COFFObjectFile::initBaseRelocPtr() { - const data_directory *DataEntry; - if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) - return std::error_code(); +Error COFFObjectFile::initBaseRelocPtr() { + const data_directory *DataEntry = + getDataDirectory(COFF::BASE_RELOCATION_TABLE); + if (!DataEntry) + return Error::success(); if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) - return EC; + if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return E; BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( IntPtr); BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( IntPtr + DataEntry->Size); // FIXME: Verify the section containing BaseRelocHeader has at least // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. - return std::error_code(); + return Error::success(); } -std::error_code COFFObjectFile::initDebugDirectoryPtr() { +Error COFFObjectFile::initDebugDirectoryPtr() { // Get the RVA of the debug directory. Do nothing if it does not exist. - const data_directory *DataEntry; - if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) - return std::error_code(); + const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY); + if (!DataEntry) + return Error::success(); // Do nothing if the RVA is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); // Check that the size is a multiple of the entry size. if (DataEntry->Size % sizeof(debug_directory) != 0) - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) - return EC; + if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return E; DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( IntPtr + DataEntry->Size); // FIXME: Verify the section containing DebugDirectoryBegin has at least // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. - return std::error_code(); + return Error::success(); } -std::error_code COFFObjectFile::initLoadConfigPtr() { +Error COFFObjectFile::initLoadConfigPtr() { // Get the RVA of the debug directory. Do nothing if it does not exist. - const data_directory *DataEntry; - if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) - return std::error_code(); + const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE); + if (!DataEntry) + return Error::success(); // Do nothing if the RVA is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return std::error_code(); + return Error::success(); uintptr_t IntPtr = 0; - if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) - return EC; + if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return E; LoadConfig = (const void *)IntPtr; - return std::error_code(); + return Error::success(); +} + +Expected<std::unique_ptr<COFFObjectFile>> +COFFObjectFile::create(MemoryBufferRef Object) { + std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object))); + if (Error E = Obj->initialize()) + return std::move(E); + return std::move(Obj); } -COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) +COFFObjectFile::COFFObjectFile(MemoryBufferRef Object) : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), - ImportDirectory(nullptr), - DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), - ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), - DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { + ImportDirectory(nullptr), DelayImportDirectory(nullptr), + NumberOfDelayImportDirectory(0), ExportDirectory(nullptr), + BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), + DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {} + +Error COFFObjectFile::initialize() { // Check that we at least have enough room for a header. + std::error_code EC; if (!checkSize(Data, EC, sizeof(coff_file_header))) - return; + return errorCodeToError(EC); // The current location in the file where we are looking at. uint64_t CurPtr = 0; @@ -690,24 +706,23 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) CurPtr = DH->AddressOfNewExeHeader; // Check the PE magic bytes. ("PE\0\0") if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { - EC = object_error::parse_failed; - return; + return errorCodeToError(object_error::parse_failed); } CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. HasPEHeader = true; } } - if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) - return; + if (Error E = getObject(COFFHeader, Data, base() + CurPtr)) + return E; // It might be a bigobj file, let's check. Note that COFF bigobj and COFF // import libraries share a common prefix but bigobj is more restrictive. if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && COFFHeader->NumberOfSections == uint16_t(0xffff) && checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { - if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) - return; + if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr)) + return E; // Verify that we are dealing with bigobj. if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && @@ -727,13 +742,13 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) CurPtr += sizeof(coff_file_header); if (COFFHeader->isImportLibrary()) - return; + return errorCodeToError(EC); } if (HasPEHeader) { const pe32_header *Header; - if ((EC = getObject(Header, Data, base() + CurPtr))) - return; + if (Error E = getObject(Header, Data, base() + CurPtr)) + return E; const uint8_t *DataDirAddr; uint64_t DataDirSize; @@ -747,23 +762,27 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; } else { // It's neither PE32 nor PE32+. - EC = object_error::parse_failed; - return; + return errorCodeToError(object_error::parse_failed); } - if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) - return; + if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)) + return E; } if (COFFHeader) CurPtr += COFFHeader->SizeOfOptionalHeader; - if ((EC = getObject(SectionTable, Data, base() + CurPtr, - (uint64_t)getNumberOfSections() * sizeof(coff_section)))) - return; + assert(COFFHeader || COFFBigObjHeader); + + if (Error E = + getObject(SectionTable, Data, base() + CurPtr, + (uint64_t)getNumberOfSections() * sizeof(coff_section))) + return E; // Initialize the pointer to the symbol table. if (getPointerToSymbolTable() != 0) { - if ((EC = initSymbolTablePtr())) { + if (Error E = initSymbolTablePtr()) { + // Recover from errors reading the symbol table. + consumeError(std::move(E)); SymbolTable16 = nullptr; SymbolTable32 = nullptr; StringTable = nullptr; @@ -772,33 +791,32 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) } else { // We had better not have any symbols if we don't have a symbol table. if (getNumberOfSymbols() != 0) { - EC = object_error::parse_failed; - return; + return errorCodeToError(object_error::parse_failed); } } // Initialize the pointer to the beginning of the import table. - if ((EC = initImportTablePtr())) - return; - if ((EC = initDelayImportTablePtr())) - return; + if (Error E = initImportTablePtr()) + return E; + if (Error E = initDelayImportTablePtr()) + return E; // Initialize the pointer to the export table. - if ((EC = initExportTablePtr())) - return; + if (Error E = initExportTablePtr()) + return E; // Initialize the pointer to the base relocation table. - if ((EC = initBaseRelocPtr())) - return; + if (Error E = initBaseRelocPtr()) + return E; // Initialize the pointer to the export table. - if ((EC = initDebugDirectoryPtr())) - return; + if (Error E = initDebugDirectoryPtr()) + return E; - if ((EC = initLoadConfigPtr())) - return; + if (Error E = initLoadConfigPtr()) + return E; - EC = std::error_code(); + return Error::success(); } basic_symbol_iterator COFFObjectFile::symbol_begin() const { @@ -936,86 +954,54 @@ iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { return make_range(base_reloc_begin(), base_reloc_end()); } -std::error_code -COFFObjectFile::getDataDirectory(uint32_t Index, - const data_directory *&Res) const { - // Error if there's no data directory or the index is out of range. - if (!DataDirectory) { - Res = nullptr; - return object_error::parse_failed; - } +const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const { + if (!DataDirectory) + return nullptr; assert(PE32Header || PE32PlusHeader); uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize : PE32PlusHeader->NumberOfRvaAndSize; - if (Index >= NumEnt) { - Res = nullptr; - return object_error::parse_failed; - } - Res = &DataDirectory[Index]; - return std::error_code(); + if (Index >= NumEnt) + return nullptr; + return &DataDirectory[Index]; } -std::error_code COFFObjectFile::getSection(int32_t Index, - const coff_section *&Result) const { - Result = nullptr; +Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const { + // Perhaps getting the section of a reserved section index should be an error, + // but callers rely on this to return null. if (COFF::isReservedSectionNumber(Index)) - return std::error_code(); + return (const coff_section *)nullptr; if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { // We already verified the section table data, so no need to check again. - Result = SectionTable + (Index - 1); - return std::error_code(); - } - return object_error::parse_failed; -} - -std::error_code COFFObjectFile::getSection(StringRef SectionName, - const coff_section *&Result) const { - Result = nullptr; - for (const SectionRef &Section : sections()) { - auto NameOrErr = Section.getName(); - if (!NameOrErr) - return errorToErrorCode(NameOrErr.takeError()); - - if (*NameOrErr == SectionName) { - Result = getCOFFSection(Section); - return std::error_code(); - } + return SectionTable + (Index - 1); } - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); } -std::error_code COFFObjectFile::getString(uint32_t Offset, - StringRef &Result) const { +Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const { if (StringTableSize <= 4) // Tried to get a string from an empty string table. - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); if (Offset >= StringTableSize) - return object_error::unexpected_eof; - Result = StringRef(StringTable + Offset); - return std::error_code(); + return errorCodeToError(object_error::unexpected_eof); + return StringRef(StringTable + Offset); } -std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, - StringRef &Res) const { - return getSymbolName(Symbol.getGeneric(), Res); +Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const { + return getSymbolName(Symbol.getGeneric()); } -std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, - StringRef &Res) const { +Expected<StringRef> +COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const { // Check for string table entry. First 4 bytes are 0. - if (Symbol->Name.Offset.Zeroes == 0) { - if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) - return EC; - return std::error_code(); - } + if (Symbol->Name.Offset.Zeroes == 0) + return getString(Symbol->Name.Offset.Offset); + // Null terminated, let ::strlen figure out the length. if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) - // Null terminated, let ::strlen figure out the length. - Res = StringRef(Symbol->Name.ShortName); - else - // Not null terminated, use all 8 bytes. - Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); - return std::error_code(); + return StringRef(Symbol->Name.ShortName); + + // Not null terminated, use all 8 bytes. + return StringRef(Symbol->Name.ShortName, COFF::NameSize); } ArrayRef<uint8_t> @@ -1067,14 +1053,13 @@ COFFObjectFile::getSectionName(const coff_section *Sec) const { if (Name.startswith("//")) { if (decodeBase64StringEntry(Name.substr(2), Offset)) return createStringError(object_error::parse_failed, - "inalid section name"); + "invalid section name"); } else { if (Name.substr(1).getAsInteger(10, Offset)) return createStringError(object_error::parse_failed, "invalid section name"); } - if (std::error_code EC = getString(Offset, Name)) - return errorCodeToError(EC); + return getString(Offset); } return Name; @@ -1107,8 +1092,8 @@ Error COFFObjectFile::getSectionContents(const coff_section *Sec, // data, as there's nothing that says that is not allowed. uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; uint32_t SectionSize = getSectionSize(Sec); - if (checkOffset(Data, ConStart, SectionSize)) - return make_error<BinaryError>(); + if (Error E = checkOffset(Data, ConStart, SectionSize)) + return E; Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); return Error::success(); } @@ -1304,7 +1289,7 @@ void ImportDirectoryEntryRef::moveNext() { } } -std::error_code ImportDirectoryEntryRef::getImportTableEntry( +Error ImportDirectoryEntryRef::getImportTableEntry( const coff_import_directory_table_entry *&Result) const { return getObject(Result, OwningObject->Data, ImportTable + Index); } @@ -1323,14 +1308,16 @@ makeImportedSymbolIterator(const COFFObjectFile *Object, static imported_symbol_iterator importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { uintptr_t IntPtr = 0; - Object->getRvaPtr(RVA, IntPtr); + // FIXME: Handle errors. + cantFail(Object->getRvaPtr(RVA, IntPtr)); return makeImportedSymbolIterator(Object, IntPtr, 0); } static imported_symbol_iterator importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { uintptr_t IntPtr = 0; - Object->getRvaPtr(RVA, IntPtr); + // FIXME: Handle errors. + cantFail(Object->getRvaPtr(RVA, IntPtr)); // Forward the pointer to the last entry which is null. int Index = 0; if (Object->getBytesInAddress() == 4) { @@ -1377,25 +1364,24 @@ ImportDirectoryEntryRef::lookup_table_symbols() const { return make_range(lookup_table_begin(), lookup_table_end()); } -std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { +Error ImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = - OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) - return EC; + if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) + return E; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return std::error_code(); + return Error::success(); } -std::error_code +Error ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { Result = ImportTable[Index].ImportLookupTableRVA; - return std::error_code(); + return Error::success(); } -std::error_code -ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { +Error ImportDirectoryEntryRef::getImportAddressTableRVA( + uint32_t &Result) const { Result = ImportTable[Index].ImportAddressTableRVA; - return std::error_code(); + return Error::success(); } bool DelayImportDirectoryEntryRef:: @@ -1424,32 +1410,32 @@ DelayImportDirectoryEntryRef::imported_symbols() const { return make_range(imported_symbol_begin(), imported_symbol_end()); } -std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { +Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) - return EC; + if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) + return E; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return std::error_code(); + return Error::success(); } -std::error_code DelayImportDirectoryEntryRef:: -getDelayImportTable(const delay_import_directory_table_entry *&Result) const { +Error DelayImportDirectoryEntryRef::getDelayImportTable( + const delay_import_directory_table_entry *&Result) const { Result = &Table[Index]; - return std::error_code(); + return Error::success(); } -std::error_code DelayImportDirectoryEntryRef:: -getImportAddress(int AddrIndex, uint64_t &Result) const { +Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex, + uint64_t &Result) const { uint32_t RVA = Table[Index].DelayImportAddressTable + AddrIndex * (OwningObject->is64() ? 8 : 4); uintptr_t IntPtr = 0; - if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) - return EC; + if (Error E = OwningObject->getRvaPtr(RVA, IntPtr)) + return E; if (OwningObject->is64()) Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); else Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); - return std::error_code(); + return Error::success(); } bool ExportDirectoryEntryRef:: @@ -1463,46 +1449,44 @@ void ExportDirectoryEntryRef::moveNext() { // Returns the name of the current export symbol. If the symbol is exported only // by ordinal, the empty string is set as a result. -std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { +Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = - OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) - return EC; + if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) + return E; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return std::error_code(); + return Error::success(); } // Returns the starting ordinal number. -std::error_code -ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { +Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { Result = ExportTable->OrdinalBase; - return std::error_code(); + return Error::success(); } // Returns the export ordinal of the current export symbol. -std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { +Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { Result = ExportTable->OrdinalBase + Index; - return std::error_code(); + return Error::success(); } // Returns the address of the current export symbol. -std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { +Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = + if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) return EC; const export_address_table_entry *entry = reinterpret_cast<const export_address_table_entry *>(IntPtr); Result = entry[Index].ExportRVA; - return std::error_code(); + return Error::success(); } // Returns the name of the current export symbol. If the symbol is exported only // by ordinal, the empty string is set as a result. -std::error_code +Error ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = + if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) return EC; const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); @@ -1513,33 +1497,34 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { I < E; ++I, ++Offset) { if (*I != Index) continue; - if (std::error_code EC = + if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) return EC; const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); - if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) + if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return std::error_code(); + return Error::success(); } Result = ""; - return std::error_code(); + return Error::success(); } -std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { - const data_directory *DataEntry; - if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) - return EC; +Error ExportDirectoryEntryRef::isForwarder(bool &Result) const { + const data_directory *DataEntry = + OwningObject->getDataDirectory(COFF::EXPORT_TABLE); + if (!DataEntry) + return errorCodeToError(object_error::parse_failed); uint32_t RVA; if (auto EC = getExportRVA(RVA)) return EC; uint32_t Begin = DataEntry->RelativeVirtualAddress; uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; Result = (Begin <= RVA && RVA < End); - return std::error_code(); + return Error::success(); } -std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { +Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { uint32_t RVA; if (auto EC = getExportRVA(RVA)) return EC; @@ -1547,7 +1532,7 @@ std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return std::error_code(); + return Error::success(); } bool ImportedSymbolRef:: @@ -1560,72 +1545,67 @@ void ImportedSymbolRef::moveNext() { ++Index; } -std::error_code -ImportedSymbolRef::getSymbolName(StringRef &Result) const { +Error ImportedSymbolRef::getSymbolName(StringRef &Result) const { uint32_t RVA; if (Entry32) { // If a symbol is imported only by ordinal, it has no name. if (Entry32[Index].isOrdinal()) - return std::error_code(); + return Error::success(); RVA = Entry32[Index].getHintNameRVA(); } else { if (Entry64[Index].isOrdinal()) - return std::error_code(); + return Error::success(); RVA = Entry64[Index].getHintNameRVA(); } uintptr_t IntPtr = 0; - if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; // +2 because the first two bytes is hint. Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); - return std::error_code(); + return Error::success(); } -std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { +Error ImportedSymbolRef::isOrdinal(bool &Result) const { if (Entry32) Result = Entry32[Index].isOrdinal(); else Result = Entry64[Index].isOrdinal(); - return std::error_code(); + return Error::success(); } -std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { +Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { if (Entry32) Result = Entry32[Index].getHintNameRVA(); else Result = Entry64[Index].getHintNameRVA(); - return std::error_code(); + return Error::success(); } -std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { +Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const { uint32_t RVA; if (Entry32) { if (Entry32[Index].isOrdinal()) { Result = Entry32[Index].getOrdinal(); - return std::error_code(); + return Error::success(); } RVA = Entry32[Index].getHintNameRVA(); } else { if (Entry64[Index].isOrdinal()) { Result = Entry64[Index].getOrdinal(); - return std::error_code(); + return Error::success(); } RVA = Entry64[Index].getHintNameRVA(); } uintptr_t IntPtr = 0; - if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); - return std::error_code(); + return Error::success(); } Expected<std::unique_ptr<COFFObjectFile>> ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { - std::error_code EC; - std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); - if (EC) - return errorCodeToError(EC); - return std::move(Ret); + return COFFObjectFile::create(Object); } bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { @@ -1650,16 +1630,16 @@ void BaseRelocRef::moveNext() { } } -std::error_code BaseRelocRef::getType(uint8_t &Type) const { +Error BaseRelocRef::getType(uint8_t &Type) const { auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); Type = Entry[Index].getType(); - return std::error_code(); + return Error::success(); } -std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { +Error BaseRelocRef::getRVA(uint32_t &Result) const { auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); Result = Header->PageRVA + Entry[Index].getOffset(); - return std::error_code(); + return Error::success(); } #define RETURN_IF_ERROR(Expr) \ @@ -1823,15 +1803,16 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); if (!Sym) return Sym.takeError(); - const coff_section *Section = nullptr; // And the symbol's section - if (std::error_code EC = Obj->getSection(Sym->getSectionNumber(), Section)) - return errorCodeToError(EC); + Expected<const coff_section *> Section = + Obj->getSection(Sym->getSectionNumber()); + if (!Section) + return Section.takeError(); // Add the initial value of DataRVA to the symbol's offset to find the // data it points at. uint64_t Offset = Entry.DataRVA + Sym->getValue(); ArrayRef<uint8_t> Contents; - if (Error E = Obj->getSectionContents(Section, Contents)) + if (Error E = Obj->getSectionContents(*Section, Contents)) return std::move(E); if (Offset + Entry.DataSize > Contents.size()) return createStringError(object_error::parse_failed, diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index f17a6da23d7d3..2515695095a1c 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -145,6 +145,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, break; } break; + case ELF::EM_VE: + switch (Type) { +#include "llvm/BinaryFormat/ELFRelocs/VE.def" + default: + break; + } + break; default: break; } @@ -223,6 +230,9 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS); } break; + case ELF::EM_RISCV: + switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_RISCV_ATTRIBUTES); } + break; default: break; } @@ -499,7 +509,6 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(uint64_t Type) const { template <class ELFT> Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { ArrayRef<Elf_Dyn> Dyn; - size_t DynSecSize = 0; auto ProgramHeadersOrError = program_headers(); if (!ProgramHeadersOrError) @@ -510,7 +519,6 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { Dyn = makeArrayRef( reinterpret_cast<const Elf_Dyn *>(base() + Phdr.p_offset), Phdr.p_filesz / sizeof(Elf_Dyn)); - DynSecSize = Phdr.p_filesz; break; } } @@ -529,7 +537,6 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { if (!DynOrError) return DynOrError.takeError(); Dyn = *DynOrError; - DynSecSize = Sec.sh_size; break; } } @@ -542,10 +549,6 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { // TODO: this error is untested. return createError("invalid empty dynamic section"); - if (DynSecSize % sizeof(Elf_Dyn) != 0) - // TODO: this error is untested. - return createError("malformed dynamic section"); - if (Dyn.back().d_tag != ELF::DT_NULL) // TODO: this error is untested. return createError("dynamic sections must be DT_NULL terminated"); @@ -580,7 +583,18 @@ Expected<const uint8_t *> ELFFile<ELFT>::toMappedAddr(uint64_t VAddr) const { if (Delta >= Phdr.p_filesz) return createError("virtual address is not in any segment: 0x" + Twine::utohexstr(VAddr)); - return base() + Phdr.p_offset + Delta; + + uint64_t Offset = Phdr.p_offset + Delta; + if (Offset >= getBufSize()) + return createError("can't map virtual address 0x" + + Twine::utohexstr(VAddr) + " to the segment with index " + + Twine(&Phdr - (*ProgramHeadersOrError).data() + 1) + + ": the segment ends at 0x" + + Twine::utohexstr(Phdr.p_offset + Phdr.p_filesz) + + ", which is greater than the file size (0x" + + Twine::utohexstr(getBufSize()) + ")"); + + return base() + Offset; } template class llvm::object::ELFFile<ELF32LE>; diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index bf6ffd6c37b95..c919d25855d24 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -23,6 +23,8 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/RISCVAttributeParser.h" +#include "llvm/Support/RISCVAttributes.h" #include "llvm/Support/TargetRegistry.h" #include <algorithm> #include <cstddef> @@ -157,17 +159,21 @@ SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { SubtargetFeatures Features; ARMAttributeParser Attributes; - if (Error E = getBuildAttributes(Attributes)) + if (Error E = getBuildAttributes(Attributes)) { + consumeError(std::move(E)); return SubtargetFeatures(); + } // both ARMv7-M and R have to support thumb hardware div bool isV7 = false; - if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) - isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) - == ARMBuildAttrs::v7; - - if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { + Optional<unsigned> Attr = + Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); + if (Attr.hasValue()) + isV7 = Attr.getValue() == ARMBuildAttrs::v7; + + Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); + if (Attr.hasValue()) { + switch (Attr.getValue()) { case ARMBuildAttrs::ApplicationProfile: Features.AddFeature("aclass"); break; @@ -184,8 +190,9 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { } } - if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { + Attr = Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use); + if (Attr.hasValue()) { + switch (Attr.getValue()) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -198,8 +205,9 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { } } - if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { + Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch); + if (Attr.hasValue()) { + switch (Attr.getValue()) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -221,8 +229,9 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { } } - if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { + Attr = Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch); + if (Attr.hasValue()) { + switch (Attr.getValue()) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -239,8 +248,9 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { } } - if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { + Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch); + if (Attr.hasValue()) { + switch (Attr.getValue()) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -257,8 +267,9 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { } } - if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { + Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use); + if (Attr.hasValue()) { + switch (Attr.getValue()) { default: break; case ARMBuildAttrs::DisallowDIV: @@ -283,6 +294,51 @@ SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { Features.AddFeature("c"); } + // Add features according to the ELF attribute section. + // If there are any unrecognized features, ignore them. + RISCVAttributeParser Attributes; + if (Error E = getBuildAttributes(Attributes)) { + // TODO Propagate Error. + consumeError(std::move(E)); + return Features; // Keep "c" feature if there is one in PlatformFlags. + } + + Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); + if (Attr.hasValue()) { + // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* + // Version string pattern is (major)p(minor). Major and minor are optional. + // For example, a version number could be 2p0, 2, or p92. + StringRef Arch = Attr.getValue(); + if (Arch.consume_front("rv32")) + Features.AddFeature("64bit", false); + else if (Arch.consume_front("rv64")) + Features.AddFeature("64bit"); + + while (!Arch.empty()) { + switch (Arch[0]) { + default: + break; // Ignore unexpected features. + case 'i': + Features.AddFeature("e", false); + break; + case 'd': + Features.AddFeature("f"); // D-ext will imply F-ext. + LLVM_FALLTHROUGH; + case 'e': + case 'm': + case 'a': + case 'f': + case 'c': + Features.AddFeature(Arch.take_front()); + break; + } + + // FIXME: Handle version numbers. + Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; }); + Arch = Arch.drop_while([](char c) { return c == '_'; }); + } + } + return Features; } @@ -305,8 +361,11 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { return; ARMAttributeParser Attributes; - if (Error E = getBuildAttributes(Attributes)) + if (Error E = getBuildAttributes(Attributes)) { + // TODO Propagate Error. + consumeError(std::move(E)); return; + } std::string Triple; // Default to ARM, but use the triple if it's been set. @@ -315,8 +374,10 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { else Triple = "arm"; - if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { - switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { + Optional<unsigned> Attr = + Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); + if (Attr.hasValue()) { + switch (Attr.getValue()) { case ARMBuildAttrs::v4: Triple += "v4"; break; diff --git a/llvm/lib/Object/Error.cpp b/llvm/lib/Object/Error.cpp index 010c5b42dac25..bc75bc6c0445c 100644 --- a/llvm/lib/Object/Error.cpp +++ b/llvm/lib/Object/Error.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/Error.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" @@ -60,9 +61,10 @@ void BinaryError::anchor() {} char BinaryError::ID = 0; char GenericBinaryError::ID = 0; -GenericBinaryError::GenericBinaryError(Twine Msg) : Msg(Msg.str()) {} +GenericBinaryError::GenericBinaryError(const Twine &Msg) : Msg(Msg.str()) {} -GenericBinaryError::GenericBinaryError(Twine Msg, object_error ECOverride) +GenericBinaryError::GenericBinaryError(const Twine &Msg, + object_error ECOverride) : Msg(Msg.str()) { setErrorCode(make_error_code(ECOverride)); } diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp index 636f1521262fd..befba5d57127b 100644 --- a/llvm/lib/Object/IRObjectFile.cpp +++ b/llvm/lib/Object/IRObjectFile.cpp @@ -47,7 +47,7 @@ Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { return Error::success(); } -uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { return SymTab.getSymbolFlags(getSym(Symb)); } @@ -94,6 +94,7 @@ IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { return Object; case file_magic::elf_relocatable: case file_magic::macho_object: + case file_magic::wasm_object: case file_magic::coff_object: { Expected<std::unique_ptr<ObjectFile>> ObjFile = ObjectFile::createObjectFile(Object, Type); diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp index e4282b9d6bd32..e39cb732add10 100644 --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -181,7 +181,7 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) { llvm::raw_string_ostream OS(Name); Mang.getNameWithPrefix(OS, GV, false); } else { - Name = C->getName(); + Name = std::string(C->getName()); } storage::Comdat Comdat; @@ -264,9 +264,13 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, Sym.Flags |= unsigned(GV->getVisibility()) << storage::Symbol::FB_visibility; if (Flags & object::BasicSymbolRef::SF_Common) { + auto *GVar = dyn_cast<GlobalVariable>(GV); + if (!GVar) + return make_error<StringError>("Only variables can have common linkage!", + inconvertibleErrorCode()); Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize( GV->getType()->getElementType()); - Uncommon().CommonAlign = GV->getAlignment(); + Uncommon().CommonAlign = GVar->getAlignment(); } const GlobalObject *Base = GV->getBaseObject(); diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 8540b7ab03cdf..4d85e6f40ec41 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1804,8 +1804,8 @@ Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { } uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { - uint32_t flags = getSymbolFlags(DRI); - if (flags & SymbolRef::SF_Common) { + uint32_t Flags = cantFail(getSymbolFlags(DRI)); + if (Flags & SymbolRef::SF_Common) { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); } @@ -1840,7 +1840,7 @@ MachOObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Other; } -uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { +Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); uint8_t MachOType = Entry.n_type; @@ -2030,6 +2030,11 @@ bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { SectionType == MachO::S_GB_ZEROFILL); } +bool MachOObjectFile::isDebugSection(StringRef SectionName) const { + return SectionName.startswith("__debug") || + SectionName.startswith("__zdebug") || SectionName == "__gdb_index"; +} + unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { return Sec.getRawDataRefImpl().d.a; } @@ -3214,6 +3219,7 @@ void MachORebaseEntry::moveNext() { SegmentOffset) << "\n"); break; case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: + SegmentOffset += ImmValue * PointerSize; error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset, PointerSize); if (error) { @@ -3223,18 +3229,6 @@ void MachORebaseEntry::moveNext() { moveToEnd(); return; } - SegmentOffset += ImmValue * PointerSize; - error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset, - PointerSize); - if (error) { - *E = - malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " - " (after adding immediate times the pointer size) " + - Twine(error) + " for opcode at: 0x" + - Twine::utohexstr(OpcodeStart - Opcodes.begin())); - moveToEnd(); - return; - } DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " << format("SegmentOffset=0x%06X", @@ -3803,15 +3797,6 @@ void MachOBindEntry::moveNext() { moveToEnd(); return; } - error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset, - PointerSize); - if (error) { - *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " + - Twine(error) + " for opcode at: 0x" + - Twine::utohexstr(OpcodeStart - Opcodes.begin())); - moveToEnd(); - return; - } if (SymbolName == StringRef()) { *E = malformedError( "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " @@ -3835,11 +3820,9 @@ void MachOBindEntry::moveNext() { error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset + AdvanceAmount, PointerSize); if (error) { - *E = - malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " - " (after adding immediate times the pointer size) " + - Twine(error) + " for opcode at: 0x" + - Twine::utohexstr(OpcodeStart - Opcodes.begin())); + *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " + + Twine(error) + " for opcode at: 0x" + + Twine::utohexstr(OpcodeStart - Opcodes.begin())); moveToEnd(); return; } diff --git a/llvm/lib/Object/ModuleSymbolTable.cpp b/llvm/lib/Object/ModuleSymbolTable.cpp index 17ac4afda2d64..7f3055b5dcfab 100644 --- a/llvm/lib/Object/ModuleSymbolTable.cpp +++ b/llvm/lib/Object/ModuleSymbolTable.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -63,7 +64,8 @@ void ModuleSymbolTable::addModule(Module *M) { SymTab.push_back(&GV); CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) { - SymTab.push_back(new (AsmSymbols.Allocate()) AsmSymbol(Name, Flags)); + SymTab.push_back(new (AsmSymbols.Allocate()) + AsmSymbol(std::string(Name), Flags)); }); } @@ -115,6 +117,10 @@ initializeRecordStreamer(const Module &M, if (!TAP) return; + // Module-level inline asm is assumed to use At&t syntax (see + // AsmPrinter::doInitialization()). + Parser->setAssemblerDialect(InlineAsm::AD_ATT); + Parser->setTargetParser(*TAP); if (Parser->Run(false)) return; diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp index 098b3d8f8dd05..61b36ea0f448a 100644 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -54,12 +54,15 @@ bool SectionRef::containsSymbol(SymbolRef S) const { return *this == **SymSec; } -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); +Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const { + if (Expected<uint32_t> FlagsOrErr = getSymbolFlags(Ref)) { + if (*FlagsOrErr & SymbolRef::SF_Undefined) + return 0; + if (*FlagsOrErr & SymbolRef::SF_Common) + return getCommonSymbolSize(Ref); + } else + // TODO: Test this error. + return FlagsOrErr.takeError(); return getSymbolValueImpl(Ref); } @@ -91,6 +94,10 @@ bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { return isSectionData(Sec); } +bool ObjectFile::isDebugSection(StringRef SectionName) const { + return false; +} + Expected<section_iterator> ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); @@ -108,14 +115,17 @@ Triple ObjectFile::makeTriple() const { setARMSubArch(TheTriple); // TheTriple defaults to ELF, and COFF doesn't have an environment: - // the best we can do here is indicate that it is mach-o. - if (isMachO()) + // something we can do here is indicate that it is mach-o. + if (isMachO()) { TheTriple.setObjectFormat(Triple::MachO); - - if (isCOFF()) { + } else if (isCOFF()) { const auto COFFObj = cast<COFFObjectFile>(this); if (COFFObj->getArch() == Triple::thumb) TheTriple.setTriple("thumbv7-windows"); + } else if (isXCOFF()) { + // XCOFF implies AIX. + TheTriple.setOS(Triple::AIX); + TheTriple.setObjectFormat(Triple::XCOFF); } return TheTriple; diff --git a/llvm/lib/Object/RecordStreamer.cpp b/llvm/lib/Object/RecordStreamer.cpp index f39a6c28ed50c..b2f973eff3614 100644 --- a/llvm/lib/Object/RecordStreamer.cpp +++ b/llvm/lib/Object/RecordStreamer.cpp @@ -81,22 +81,22 @@ RecordStreamer::const_iterator RecordStreamer::begin() { RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } -void RecordStreamer::EmitInstruction(const MCInst &Inst, +void RecordStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { - MCStreamer::EmitInstruction(Inst, STI); + MCStreamer::emitInstruction(Inst, STI); } -void RecordStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - MCStreamer::EmitLabel(Symbol); +void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { + MCStreamer::emitLabel(Symbol); markDefined(*Symbol); } -void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { +void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) { markDefined(*Symbol); - MCStreamer::EmitAssignment(Symbol, Value); + MCStreamer::emitAssignment(Symbol, Value); } -bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { if (Attribute == MCSA_Global || Attribute == MCSA_Weak) markGlobal(*Symbol, Attribute); @@ -105,13 +105,13 @@ bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, return true; } -void RecordStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, +void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, SMLoc Loc) { markDefined(*Symbol); } -void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, +void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { markDefined(*Symbol); } @@ -224,9 +224,9 @@ void RecordStreamer::flushSymverDirectives() { if (IsDefined) markDefined(*Alias); // Don't use EmitAssignment override as it always marks alias as defined. - MCStreamer::EmitAssignment(Alias, Value); + MCStreamer::emitAssignment(Alias, Value); if (Attr != MCSA_Invalid) - EmitSymbolAttribute(Alias, Attr); + emitSymbolAttribute(Alias, Attr); } } } diff --git a/llvm/lib/Object/RecordStreamer.h b/llvm/lib/Object/RecordStreamer.h index c8b75bcc6d1df..99d15f790a156 100644 --- a/llvm/lib/Object/RecordStreamer.h +++ b/llvm/lib/Object/RecordStreamer.h @@ -13,13 +13,12 @@ #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/Support/SMLoc.h" #include <vector> namespace llvm { -class GlobalValue; +class MCSymbol; class Module; class RecordStreamer : public MCStreamer { @@ -46,13 +45,13 @@ private: public: RecordStreamer(MCContext &Context, const Module &M); - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; - void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; - bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; - void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, SMLoc Loc = SMLoc()) override; - void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; // Ignore COFF-specific directives; we do not need any information from them, diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index 31478be7899ed..3f3f79b0f4ff7 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -127,6 +127,27 @@ static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) { } } +static bool supportsMSP430(uint64_t Type) { + switch (Type) { + case ELF::R_MSP430_32: + case ELF::R_MSP430_16_BYTE: + return true; + default: + return false; + } +} + +static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) { + switch (R.getType()) { + case ELF::R_MSP430_32: + return (S + getELFAddend(R)) & 0xFFFFFFFF; + case ELF::R_MSP430_16_BYTE: + return (S + getELFAddend(R)) & 0xFFFF; + default: + llvm_unreachable("Invalid relocation type"); + } +} + static bool supportsPPC64(uint64_t Type) { switch (Type) { case ELF::R_PPC64_ADDR32: @@ -498,12 +519,24 @@ static bool supportsWasm32(uint64_t Type) { case wasm::R_WASM_FUNCTION_OFFSET_I32: case wasm::R_WASM_SECTION_OFFSET_I32: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_GLOBAL_INDEX_I32: return true; default: return false; } } +static bool supportsWasm64(uint64_t Type) { + switch (Type) { + case wasm::R_WASM_MEMORY_ADDR_LEB64: + case wasm::R_WASM_MEMORY_ADDR_SLEB64: + case wasm::R_WASM_MEMORY_ADDR_I64: + return true; + default: + return supportsWasm32(Type); + } +} + static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { switch (R.getType()) { case wasm::R_WASM_FUNCTION_INDEX_LEB: @@ -517,6 +550,7 @@ static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { case wasm::R_WASM_FUNCTION_OFFSET_I32: case wasm::R_WASM_SECTION_OFFSET_I32: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_GLOBAL_INDEX_I32: // For wasm section, its offset at 0 -- ignoring Value return A; default: @@ -524,6 +558,18 @@ static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { } } +static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) { + switch (R.getType()) { + case wasm::R_WASM_MEMORY_ADDR_LEB64: + case wasm::R_WASM_MEMORY_ADDR_SLEB64: + case wasm::R_WASM_MEMORY_ADDR_I64: + // For wasm section, its offset at 0 -- ignoring Value + return A; + default: + return resolveWasm32(R, S, A); + } +} + std::pair<bool (*)(uint64_t), RelocationResolver> getRelocationResolver(const ObjectFile &Obj) { if (Obj.isCOFF()) { @@ -589,6 +635,8 @@ getRelocationResolver(const ObjectFile &Obj) { case Triple::mipsel: case Triple::mips: return {supportsMips32, resolveMips32}; + case Triple::msp430: + return {supportsMSP430, resolveMSP430}; case Triple::sparc: return {supportsSparc32, resolveSparc32}; case Triple::hexagon: @@ -605,6 +653,8 @@ getRelocationResolver(const ObjectFile &Obj) { } else if (Obj.isWasm()) { if (Obj.getArch() == Triple::wasm32) return {supportsWasm32, resolveWasm32}; + if (Obj.getArch() == Triple::wasm64) + return {supportsWasm64, resolveWasm64}; return {nullptr, nullptr}; } diff --git a/llvm/lib/Object/SymbolSize.cpp b/llvm/lib/Object/SymbolSize.cpp index bdf4dc55cf3cc..84eed4d169d3a 100644 --- a/llvm/lib/Object/SymbolSize.cpp +++ b/llvm/lib/Object/SymbolSize.cpp @@ -11,6 +11,7 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" +#include "llvm/Object/Wasm.h" using namespace llvm; using namespace object; @@ -27,12 +28,17 @@ int llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) { static unsigned getSectionID(const ObjectFile &O, SectionRef Sec) { if (auto *M = dyn_cast<MachOObjectFile>(&O)) return M->getSectionID(Sec); + if (isa<WasmObjectFile>(&O)) + return Sec.getIndex(); + return cast<COFFObjectFile>(O).getSectionID(Sec); } static unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) { if (auto *M = dyn_cast<MachOObjectFile>(&O)) return M->getSymbolSectionID(Sym); + if (const auto *M = dyn_cast<WasmObjectFile>(&O)) + return M->getSymbolSectionId(Sym); return cast<COFFObjectFile>(O).getSymbolSectionID(Sym); } @@ -55,8 +61,11 @@ llvm::object::computeSymbolSizes(const ObjectFile &O) { unsigned SymNum = 0; for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { SymbolRef Sym = *I; - uint64_t Value = Sym.getValue(); - Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)}); + Expected<uint64_t> ValueOrErr = Sym.getValue(); + if (!ValueOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(ValueOrErr.takeError()); + Addresses.push_back({I, *ValueOrErr, SymNum, getSymbolSectionID(O, Sym)}); ++SymNum; } for (SectionRef Sec : O.sections()) { diff --git a/llvm/lib/Object/TapiFile.cpp b/llvm/lib/Object/TapiFile.cpp index c409bd8e59951..7a361990ba5d2 100644 --- a/llvm/lib/Object/TapiFile.cpp +++ b/llvm/lib/Object/TapiFile.cpp @@ -40,7 +40,7 @@ static uint32_t getFlags(const Symbol *Sym) { TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface, Architecture Arch) - : SymbolicFile(ID_TapiFile, Source) { + : SymbolicFile(ID_TapiFile, Source), Arch(Arch) { for (const auto *Symbol : interface.symbols()) { if (!Symbol->getArchitectures().has(Arch)) continue; @@ -75,30 +75,28 @@ TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface, TapiFile::~TapiFile() = default; -void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { - const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p); - DRI.p = reinterpret_cast<uintptr_t>(++Sym); -} +void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; } Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const { - const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p); - OS << Sym->Prefix << Sym->Name; + assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds"); + const Symbol &Sym = Symbols[DRI.d.a]; + OS << Sym.Prefix << Sym.Name; return Error::success(); } -uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const { - const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p); - return Sym->Flags; +Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const { + assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds"); + return Symbols[DRI.d.a].Flags; } basic_symbol_iterator TapiFile::symbol_begin() const { DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.begin()); + DRI.d.a = 0; return BasicSymbolRef{DRI, this}; } basic_symbol_iterator TapiFile::symbol_end() const { DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.end()); + DRI.d.a = Symbols.size(); return BasicSymbolRef{DRI, this}; } diff --git a/llvm/lib/Object/TapiUniversal.cpp b/llvm/lib/Object/TapiUniversal.cpp index b3273e345a61d..48cb949cb6f4d 100644 --- a/llvm/lib/Object/TapiUniversal.cpp +++ b/llvm/lib/Object/TapiUniversal.cpp @@ -22,7 +22,7 @@ using namespace object; TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) : Binary(ID_TapiUniversal, Source) { - auto Result = TextAPIReader::get(Source); + Expected<std::unique_ptr<InterfaceFile>> Result = TextAPIReader::get(Source); ErrorAsOutParameter ErrAsOuParam(&Err); if (!Result) { Err = Result.takeError(); @@ -30,9 +30,16 @@ TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) } ParsedFile = std::move(Result.get()); - auto Archs = ParsedFile->getArchitectures(); - for (auto Arch : Archs) - Architectures.emplace_back(Arch); + auto FlattenObjectInfo = [this](const auto &File) { + StringRef Name = File->getInstallName(); + for (const Architecture Arch : File->getArchitectures()) + Libraries.emplace_back(Library({Name, Arch})); + }; + + FlattenObjectInfo(ParsedFile); + // Get inlined documents from tapi file. + for (const std::shared_ptr<InterfaceFile> &File : ParsedFile->documents()) + FlattenObjectInfo(File); } TapiUniversal::~TapiUniversal() = default; @@ -41,7 +48,7 @@ Expected<std::unique_ptr<TapiFile>> TapiUniversal::ObjectForArch::getAsObjectFile() const { return std::unique_ptr<TapiFile>(new TapiFile(Parent->getMemoryBufferRef(), *Parent->ParsedFile.get(), - Parent->Architectures[Index])); + Parent->Libraries[Index].Arch)); } Expected<std::unique_ptr<TapiUniversal>> diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index ab8918ce1919c..bb2e81d64047f 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/SubtargetFeature.h" @@ -155,6 +156,10 @@ static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) { return readLEB128(Ctx); } +static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) { + return readULEB128(Ctx); +} + static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { return readUint8(Ctx); } @@ -179,6 +184,14 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, case wasm::WASM_OPCODE_GLOBAL_GET: Expr.Value.Global = readULEB128(Ctx); break; + case wasm::WASM_OPCODE_REF_NULL: { + wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx)); + if (Ty != wasm::ValType::EXTERNREF) { + return make_error<GenericBinaryError>("Invalid type for ref.null", + object_error::parse_failed); + } + break; + } default: return make_error<GenericBinaryError>("Invalid opcode in init_expr", object_error::parse_failed); @@ -195,9 +208,9 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { wasm::WasmLimits Result; Result.Flags = readVaruint32(Ctx); - Result.Initial = readVaruint32(Ctx); + Result.Initial = readVaruint64(Ctx); if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) - Result.Maximum = readVaruint32(Ctx); + Result.Maximum = readVaruint64(Ctx); return Result; } @@ -302,10 +315,10 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) { return parseTableSection(Ctx); case wasm::WASM_SEC_MEMORY: return parseMemorySection(Ctx); - case wasm::WASM_SEC_GLOBAL: - return parseGlobalSection(Ctx); case wasm::WASM_SEC_EVENT: return parseEventSection(Ctx); + case wasm::WASM_SEC_GLOBAL: + return parseGlobalSection(Ctx); case wasm::WASM_SEC_EXPORT: return parseExportSection(Ctx); case wasm::WASM_SEC_START: @@ -508,13 +521,16 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Function.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; - if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); - else + Info.ImportName = Import.Field; + } else { Info.Name = Import.Field; + } Signature = &Signatures[Import.SigIndex]; - Info.ImportName = Import.Field; - Info.ImportModule = Import.Module; + if (!Import.Module.empty()) { + Info.ImportModule = Import.Module; + } } break; @@ -537,25 +553,29 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Global.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; - if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); - else + Info.ImportName = Import.Field; + } else { Info.Name = Import.Field; + } GlobalType = &Import.Global; Info.ImportName = Import.Field; - Info.ImportModule = Import.Module; + if (!Import.Module.empty()) { + Info.ImportModule = Import.Module; + } } break; case wasm::WASM_SYMBOL_TYPE_DATA: Info.Name = readString(Ctx); if (IsDefined) { - uint32_t Index = readVaruint32(Ctx); + auto Index = readVaruint32(Ctx); if (Index >= DataSegments.size()) return make_error<GenericBinaryError>("invalid data symbol index", object_error::parse_failed); - uint32_t Offset = readVaruint32(Ctx); - uint32_t Size = readVaruint32(Ctx); + auto Offset = readVaruint64(Ctx); + auto Size = readVaruint64(Ctx); if (Offset + Size > DataSegments[Index].Data.Content.size()) return make_error<GenericBinaryError>("invalid data symbol offset", object_error::parse_failed); @@ -597,14 +617,17 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { } else { wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; - if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); - else + Info.ImportName = Import.Field; + } else { Info.Name = Import.Field; + } EventType = &Import.Event; Signature = &Signatures[EventType->SigIndex]; - Info.ImportName = Import.Field; - Info.ImportModule = Import.Module; + if (!Import.Module.empty()) { + Info.ImportModule = Import.Module; + } } break; } @@ -708,7 +731,7 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) { "Producers section contains repeated producer", object_error::parse_failed); } - ProducerVec->emplace_back(Name, Version); + ProducerVec->emplace_back(std::string(Name), std::string(Version)); } } if (Ctx.Ptr != Ctx.End) @@ -732,7 +755,7 @@ Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) { return make_error<GenericBinaryError>("Unknown feature policy prefix", object_error::parse_failed); } - Feature.Name = readString(Ctx); + Feature.Name = std::string(readString(Ctx)); if (!FeaturesSeen.insert(Feature.Name).second) return make_error<GenericBinaryError>( "Target features section contains repeated feature \"" + @@ -788,6 +811,11 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { return make_error<GenericBinaryError>("Bad relocation global index", object_error::parse_failed); break; + case wasm::R_WASM_GLOBAL_INDEX_I32: + if (!isValidGlobalSymbol(Reloc.Index)) + return make_error<GenericBinaryError>("Bad relocation global index", + object_error::parse_failed); + break; case wasm::R_WASM_EVENT_INDEX_LEB: if (!isValidEventSymbol(Reloc.Index)) return make_error<GenericBinaryError>("Bad relocation event index", @@ -802,6 +830,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { object_error::parse_failed); Reloc.Addend = readVarint32(Ctx); break; + case wasm::R_WASM_MEMORY_ADDR_LEB64: + case wasm::R_WASM_MEMORY_ADDR_SLEB64: + case wasm::R_WASM_MEMORY_ADDR_I64: + case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: + if (!isValidDataSymbol(Reloc.Index)) + return make_error<GenericBinaryError>("Bad relocation data index", + object_error::parse_failed); + Reloc.Addend = readVarint64(Ctx); + break; case wasm::R_WASM_FUNCTION_OFFSET_I32: if (!isValidFunctionSymbol(Reloc.Index)) return make_error<GenericBinaryError>("Bad relocation function index", @@ -824,11 +861,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { // also shouldn't overlap a function/element boundary, but we don't bother // to check that. uint64_t Size = 5; + if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 || + Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 || + Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64) + Size = 10; if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || - Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32) + Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || + Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) Size = 4; + if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64) + Size = 8; if (Reloc.Offset + Size > EndOffset) return make_error<GenericBinaryError>("Bad relocation offset", object_error::parse_failed); @@ -983,6 +1027,24 @@ Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { return Error::success(); } +Error WasmObjectFile::parseEventSection(ReadContext &Ctx) { + EventSection = Sections.size(); + uint32_t Count = readVarint32(Ctx); + Events.reserve(Count); + while (Count--) { + wasm::WasmEvent Event; + Event.Index = NumImportedEvents + Events.size(); + Event.Type.Attribute = readVaruint32(Ctx); + Event.Type.SigIndex = readVarint32(Ctx); + Events.push_back(Event); + } + + if (Ctx.Ptr != Ctx.End) + return make_error<GenericBinaryError>("Event section ended prematurely", + object_error::parse_failed); + return Error::success(); +} + Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { GlobalSection = Sections.size(); uint32_t Count = readVaruint32(Ctx); @@ -1002,24 +1064,6 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { return Error::success(); } -Error WasmObjectFile::parseEventSection(ReadContext &Ctx) { - EventSection = Sections.size(); - uint32_t Count = readVarint32(Ctx); - Events.reserve(Count); - while (Count--) { - wasm::WasmEvent Event; - Event.Index = NumImportedEvents + Events.size(); - Event.Type.Attribute = readVaruint32(Ctx); - Event.Type.SigIndex = readVarint32(Ctx); - Events.push_back(Event); - } - - if (Ctx.Ptr != Ctx.End) - return make_error<GenericBinaryError>("Event section ended prematurely", - object_error::parse_failed); - return Error::success(); -} - Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { uint32_t Count = readVaruint32(Ctx); Exports.reserve(Count); @@ -1250,7 +1294,7 @@ const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } -uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = SymbolRef::SF_None; const WasmSymbol &Sym = getWasmSymbol(Symb); @@ -1314,8 +1358,13 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { // offset within the segment. uint32_t SegmentIndex = Sym.Info.DataRef.Segment; const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; - assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST); - return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; + if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) { + return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; + } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) { + return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset; + } else { + llvm_unreachable("unknown init expr opcode"); + } } case wasm::WASM_SYMBOL_TYPE_SECTION: return 0; @@ -1365,26 +1414,30 @@ WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { return section_end(); DataRefImpl Ref; + Ref.d.a = getSymbolSectionIdImpl(Sym); + return section_iterator(SectionRef(Ref, this)); +} + +uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const { + const WasmSymbol &Sym = getWasmSymbol(Symb); + return getSymbolSectionIdImpl(Sym); +} + +uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { switch (Sym.Info.Kind) { case wasm::WASM_SYMBOL_TYPE_FUNCTION: - Ref.d.a = CodeSection; - break; + return CodeSection; case wasm::WASM_SYMBOL_TYPE_GLOBAL: - Ref.d.a = GlobalSection; - break; + return GlobalSection; case wasm::WASM_SYMBOL_TYPE_DATA: - Ref.d.a = DataSection; - break; + return DataSection; case wasm::WASM_SYMBOL_TYPE_SECTION: - Ref.d.a = Sym.Info.ElementIndex; - break; + return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_EVENT: - Ref.d.a = EventSection; - break; + return EventSection; default: llvm_unreachable("Unknown WasmSymbol::SymbolType"); } - return section_iterator(SectionRef(Ref, this)); } void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } @@ -1455,8 +1508,6 @@ bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } -bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } - relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { DataRefImpl RelocRef; RelocRef.d.a = Ref.d.a; @@ -1608,30 +1659,50 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID, // Represents the edges in a directed graph where any node B reachable from node // A is not allowed to appear before A in the section ordering, but may appear // afterward. -int WasmSectionOrderChecker::DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { - {}, // WASM_SEC_ORDER_NONE - {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, // WASM_SEC_ORDER_TYPE, - {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, // WASM_SEC_ORDER_IMPORT, - {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, // WASM_SEC_ORDER_FUNCTION, - {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, // WASM_SEC_ORDER_TABLE, - {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_GLOBAL}, // WASM_SEC_ORDER_MEMORY, - {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EVENT}, // WASM_SEC_ORDER_GLOBAL, - {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_EXPORT}, // WASM_SEC_ORDER_EVENT, - {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, // WASM_SEC_ORDER_EXPORT, - {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, // WASM_SEC_ORDER_START, - {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, // WASM_SEC_ORDER_ELEM, - {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, // WASM_SEC_ORDER_DATACOUNT, - {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, // WASM_SEC_ORDER_CODE, - {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, // WASM_SEC_ORDER_DATA, - - // Custom Sections - {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, // WASM_SEC_ORDER_DYLINK, - {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, // WASM_SEC_ORDER_LINKING, - {}, // WASM_SEC_ORDER_RELOC (can be repeated), - {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_NAME, - {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, // WASM_SEC_ORDER_PRODUCERS, - {WASM_SEC_ORDER_TARGET_FEATURES} // WASM_SEC_ORDER_TARGET_FEATURES -}; +int WasmSectionOrderChecker::DisallowedPredecessors + [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { + // WASM_SEC_ORDER_NONE + {}, + // WASM_SEC_ORDER_TYPE + {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, + // WASM_SEC_ORDER_IMPORT + {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, + // WASM_SEC_ORDER_FUNCTION + {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, + // WASM_SEC_ORDER_TABLE + {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, + // WASM_SEC_ORDER_MEMORY + {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_EVENT}, + // WASM_SEC_ORDER_EVENT + {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_GLOBAL}, + // WASM_SEC_ORDER_GLOBAL + {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, + // WASM_SEC_ORDER_EXPORT + {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, + // WASM_SEC_ORDER_START + {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, + // WASM_SEC_ORDER_ELEM + {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, + // WASM_SEC_ORDER_DATACOUNT + {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, + // WASM_SEC_ORDER_CODE + {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, + // WASM_SEC_ORDER_DATA + {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, + + // Custom Sections + // WASM_SEC_ORDER_DYLINK + {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, + // WASM_SEC_ORDER_LINKING + {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, + // WASM_SEC_ORDER_RELOC (can be repeated) + {}, + // WASM_SEC_ORDER_NAME + {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, + // WASM_SEC_ORDER_PRODUCERS + {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, + // WASM_SEC_ORDER_TARGET_FEATURES + {WASM_SEC_ORDER_TARGET_FEATURES}}; bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, StringRef CustomSectionName) { diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp index 10717718b2019..2a69c6c46b590 100644 --- a/llvm/lib/Object/WindowsResource.cpp +++ b/llvm/lib/Object/WindowsResource.cpp @@ -346,7 +346,7 @@ Error WindowsResourceParser::parse(WindowsResource *WR, ResourceEntryRef Entry = EntryOrErr.get(); uint32_t Origin = InputFilenames.size(); - InputFilenames.push_back(WR->getFileName()); + InputFilenames.push_back(std::string(WR->getFileName())); bool End = false; while (!End) { @@ -368,7 +368,7 @@ Error WindowsResourceParser::parse(ResourceSectionRef &RSR, StringRef Filename, std::vector<std::string> &Duplicates) { UNWRAP_REF_OR_RETURN(BaseTable, RSR.getBaseTable()); uint32_t Origin = InputFilenames.size(); - InputFilenames.push_back(Filename); + InputFilenames.push_back(std::string(Filename)); std::vector<StringOrID> Context; return addChildren(Root, RSR, BaseTable, Origin, Context, Duplicates); } @@ -721,8 +721,10 @@ WindowsResourceCOFFWriter::write(uint32_t TimeDateStamp) { // it's okay to *not* copy the trailing zero. static void coffnamecpy(char (&Dest)[COFF::NameSize], StringRef Src) { assert(Src.size() <= COFF::NameSize && - "Src is not larger than COFF::NameSize"); - strncpy(Dest, Src.data(), (size_t)COFF::NameSize); + "Src is larger than COFF::NameSize"); + assert((Src.size() == COFF::NameSize || Dest[Src.size()] == '\0') && + "Dest not zeroed upon initialization"); + memcpy(Dest, Src.data(), Src.size()); } void WindowsResourceCOFFWriter::writeCOFFHeader(uint32_t TimeDateStamp) { diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index f98cd69a0d379..533361666cf21 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -11,13 +11,16 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/XCOFFObjectFile.h" +#include "llvm/MC/SubtargetFeature.h" #include <cstddef> #include <cstring> namespace llvm { namespace object { -enum { FUNCTION_SYM = 0x20, SYM_TYPE_MASK = 0x07, RELOC_OVERFLOW = 65535 }; +static const uint8_t FunctionSym = 0x20; +static const uint8_t SymTypeMask = 0x07; +static const uint16_t NoRelMask = 0x0001; // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer // 'M'. Returns a pointer to the underlying object on success. @@ -25,8 +28,8 @@ template <typename T> static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, const uint64_t Size = sizeof(T)) { uintptr_t Addr = uintptr_t(Ptr); - if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) - return errorCodeToError(EC); + if (Error E = Binary::checkOffset(M, Addr, Size)) + return std::move(E); return reinterpret_cast<const T *>(Addr); } @@ -314,58 +317,98 @@ bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { } relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { - llvm_unreachable("Not yet implemented!"); - return relocation_iterator(RelocationRef()); + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); + auto RelocationsOrErr = relocations(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) + return relocation_iterator(RelocationRef()); + DataRefImpl Ret; + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); + return relocation_iterator(RelocationRef(Ret, this)); } relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { - llvm_unreachable("Not yet implemented!"); - return relocation_iterator(RelocationRef()); + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); + auto RelocationsOrErr = relocations(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) + return relocation_iterator(RelocationRef()); + DataRefImpl Ret; + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); + return relocation_iterator(RelocationRef(Ret, this)); } void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { - llvm_unreachable("Not yet implemented!"); - return; + Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); } uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { - llvm_unreachable("Not yet implemented!"); - uint64_t Result = 0; - return Result; + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); + const uint32_t RelocAddress = Reloc->VirtualAddress; + const uint16_t NumberOfSections = getNumberOfSections(); + for (uint16_t i = 0; i < NumberOfSections; ++i) { + // Find which section this relocation is belonging to, and get the + // relocation offset relative to the start of the section. + if (Sec32->VirtualAddress <= RelocAddress && + RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { + return RelocAddress - Sec32->VirtualAddress; + } + ++Sec32; + } + return InvalidRelocOffset; } symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { - llvm_unreachable("Not yet implemented!"); - return symbol_iterator(SymbolRef()); + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + const uint32_t Index = Reloc->SymbolIndex; + + if (Index >= getLogicalNumberOfSymbolTableEntries32()) + return symbol_end(); + + DataRefImpl SymDRI; + SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index); + return symbol_iterator(SymbolRef(SymDRI, this)); } uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { - llvm_unreachable("Not yet implemented!"); - uint64_t Result = 0; - return Result; + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + return viewAs<XCOFFRelocation32>(Rel.p)->Type; } void XCOFFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - llvm_unreachable("Not yet implemented!"); - return; + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type); + Result.append(Res.begin(), Res.end()); } -uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = 0; llvm_unreachable("Not yet implemented!"); return Result; } basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { - assert(!is64Bit() && "64-bit support not implemented yet."); + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); DataRefImpl SymDRI; SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); return basic_symbol_iterator(SymbolRef(SymDRI, this)); } basic_symbol_iterator XCOFFObjectFile::symbol_end() const { - assert(!is64Bit() && "64-bit support not implemented yet."); + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); DataRefImpl SymDRI; SymDRI.p = reinterpret_cast<uintptr_t>( SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); @@ -400,9 +443,9 @@ SubtargetFeatures XCOFFObjectFile::getFeatures() const { } bool XCOFFObjectFile::isRelocatableObject() const { - bool Result = false; - llvm_unreachable("Not yet implemented!"); - return Result; + if (is64Bit()) + report_fatal_error("64-bit support not implemented yet"); + return !(fileHeader32()->Flags & NoRelMask); } Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { @@ -588,7 +631,7 @@ Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries( uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1; - if (Sec.NumberOfRelocations < RELOC_OVERFLOW) + if (Sec.NumberOfRelocations < XCOFF::RelocOverflow) return Sec.NumberOfRelocations; for (const auto &Sec : sections32()) { if (Sec.Flags == XCOFF::STYP_OVRFLO && @@ -608,6 +651,7 @@ XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const { uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); + assert(sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32); auto RelocationOrErr = getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr), NumRelocEntries * sizeof(XCOFFRelocation32)); @@ -623,9 +667,11 @@ Expected<XCOFFStringTable> XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { // If there is a string table, then the buffer must contain at least 4 bytes // for the string table's size. Not having a string table is not an error. - if (auto EC = Binary::checkOffset( - Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) + if (Error E = Binary::checkOffset( + Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { + consumeError(std::move(E)); return XCOFFStringTable{0, nullptr}; + } // Read the size out of the buffer. uint32_t Size = support::endian::read32be(Obj->base() + Offset); @@ -722,6 +768,8 @@ uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const { return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries; } +// TODO: The function needs to return an error if there is no csect auxiliary +// entry. const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const { assert(!OwningObjectPtr->is64Bit() && "32-bit interface called on 64-bit object file."); @@ -747,6 +795,8 @@ int16_t XCOFFSymbolRef::getSectionNumber() const { return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber; } +// TODO: The function name needs to be changed to express the purpose of the +// function. bool XCOFFSymbolRef::hasCsectAuxEnt() const { XCOFF::StorageClass SC = getStorageClass(); return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || @@ -757,7 +807,7 @@ bool XCOFFSymbolRef::isFunction() const { if (OwningObjectPtr->is64Bit()) report_fatal_error("64-bit support is unimplemented yet."); - if (getType() & FUNCTION_SYM) + if (getType() & FunctionSym) return true; if (!hasCsectAuxEnt()) @@ -766,7 +816,7 @@ bool XCOFFSymbolRef::isFunction() const { const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32(); // A function definition should be a label definition. - if ((CsectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD) + if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD) return false; if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR) |