diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-08-22 19:00:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-13 20:39:49 +0000 |
commit | fe6060f10f634930ff71b7c50291ddc610da2475 (patch) | |
tree | 1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/llvm/lib/Object | |
parent | b61bce17f346d79cecfd8f195a64b10f77be43b1 (diff) | |
parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
20 files changed, 680 insertions, 439 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/Archive.cpp b/contrib/llvm-project/llvm/lib/Object/Archive.cpp index 11c9de4455dd..6ff896cf347e 100644 --- a/contrib/llvm-project/llvm/lib/Object/Archive.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Archive.cpp @@ -43,8 +43,7 @@ const char ThinMagic[] = "!<thin>\n"; void Archive::anchor() {} -static Error -malformedError(Twine Msg) { +static Error malformedError(Twine Msg) { std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")"; return make_error<GenericBinaryError>(std::move(StringMsg), object_error::parse_failed); @@ -77,8 +76,8 @@ ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent, if (Err) { std::string Buf; raw_string_ostream OS(Buf); - OS.write_escaped(StringRef(ArMemHdr->Terminator, - sizeof(ArMemHdr->Terminator))); + OS.write_escaped( + StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator))); OS.flush(); std::string Msg("terminator characters in archive member \"" + Buf + "\" not the correct \"`\\n\" values for the archive " @@ -102,14 +101,14 @@ Expected<StringRef> ArchiveMemberHeader::getRawName() const { auto Kind = Parent->kind(); if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) { if (ArMemHdr->Name[0] == ' ') { - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("name contains a leading space for archive member " - "header at offset " + Twine(Offset)); + "header at offset " + + Twine(Offset)); } EndCond = ' '; - } - else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#') + } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#') EndCond = ' '; else EndCond = '/'; @@ -131,8 +130,8 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const { // archive header is truncated to produce an error message with the name. // Make sure the name field is not truncated. if (Size < offsetof(ArMemHdrType, Name) + sizeof(ArMemHdr->Name)) { - uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t ArchiveOffset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("archive header truncated before the name field " "for archive member header at offset " + Twine(ArchiveOffset)); @@ -158,21 +157,22 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const { raw_string_ostream OS(Buf); OS.write_escaped(Name.substr(1).rtrim(' ')); OS.flush(); - uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t ArchiveOffset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("long name offset characters after the '/' are " - "not all decimal numbers: '" + Buf + "' for " - "archive member header at offset " + + "not all decimal numbers: '" + + Buf + "' for archive member header at offset " + Twine(ArchiveOffset)); } // Verify it. if (StringOffset >= Parent->getStringTable().size()) { - uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); - return malformedError("long name offset " + Twine(StringOffset) + " past " - "the end of the string table for archive member " - "header at offset " + Twine(ArchiveOffset)); + uint64_t ArchiveOffset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); + return malformedError("long name offset " + Twine(StringOffset) + + " past the end of the string table for archive " + "member header at offset " + + Twine(ArchiveOffset)); } // GNU long file names end with a "/\n". @@ -196,23 +196,24 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const { raw_string_ostream OS(Buf); OS.write_escaped(Name.substr(3).rtrim(' ')); OS.flush(); - uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t ArchiveOffset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("long name length characters after the #1/ are " - "not all decimal numbers: '" + Buf + "' for " - "archive member header at offset " + + "not all decimal numbers: '" + + Buf + "' for archive member header at offset " + Twine(ArchiveOffset)); } if (getSizeOf() + NameLength > Size) { - uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t ArchiveOffset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("long name length: " + Twine(NameLength) + " extends past the end of the member or archive " "for archive member header at offset " + Twine(ArchiveOffset)); } return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(), - NameLength).rtrim('\0'); + NameLength) + .rtrim('\0'); } // It is not a long name so trim the blanks at the end of the name. @@ -225,36 +226,43 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const { Expected<uint64_t> ArchiveMemberHeader::getSize() const { uint64_t Ret; - if (StringRef(ArMemHdr->Size, - sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) { + if (StringRef(ArMemHdr->Size, sizeof(ArMemHdr->Size)) + .rtrim(" ") + .getAsInteger(10, Ret)) { std::string Buf; raw_string_ostream OS(Buf); - OS.write_escaped(StringRef(ArMemHdr->Size, - sizeof(ArMemHdr->Size)).rtrim(" ")); + OS.write_escaped( + StringRef(ArMemHdr->Size, sizeof(ArMemHdr->Size)).rtrim(" ")); OS.flush(); - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("characters in size field in archive header are not " - "all decimal numbers: '" + Buf + "' for archive " - "member header at offset " + Twine(Offset)); + "all decimal numbers: '" + + Buf + + "' for archive " + "member header at offset " + + Twine(Offset)); } return Ret; } Expected<sys::fs::perms> ArchiveMemberHeader::getAccessMode() const { unsigned Ret; - if (StringRef(ArMemHdr->AccessMode, - sizeof(ArMemHdr->AccessMode)).rtrim(' ').getAsInteger(8, Ret)) { + if (StringRef(ArMemHdr->AccessMode, sizeof(ArMemHdr->AccessMode)) + .rtrim(' ') + .getAsInteger(8, Ret)) { std::string Buf; raw_string_ostream OS(Buf); - OS.write_escaped(StringRef(ArMemHdr->AccessMode, - sizeof(ArMemHdr->AccessMode)).rtrim(" ")); + OS.write_escaped( + StringRef(ArMemHdr->AccessMode, sizeof(ArMemHdr->AccessMode)) + .rtrim(" ")); OS.flush(); - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("characters in AccessMode field in archive header " - "are not all decimal numbers: '" + Buf + "' for the " - "archive member header at offset " + Twine(Offset)); + "are not all decimal numbers: '" + + Buf + "' for the archive member header at offset " + + Twine(Offset)); } return static_cast<sys::fs::perms>(Ret); } @@ -262,19 +270,21 @@ Expected<sys::fs::perms> ArchiveMemberHeader::getAccessMode() const { Expected<sys::TimePoint<std::chrono::seconds>> ArchiveMemberHeader::getLastModified() const { unsigned Seconds; - if (StringRef(ArMemHdr->LastModified, - sizeof(ArMemHdr->LastModified)).rtrim(' ') + if (StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified)) + .rtrim(' ') .getAsInteger(10, Seconds)) { std::string Buf; raw_string_ostream OS(Buf); - OS.write_escaped(StringRef(ArMemHdr->LastModified, - sizeof(ArMemHdr->LastModified)).rtrim(" ")); + OS.write_escaped( + StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified)) + .rtrim(" ")); OS.flush(); - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("characters in LastModified field in archive header " - "are not all decimal numbers: '" + Buf + "' for the " - "archive member header at offset " + Twine(Offset)); + "are not all decimal numbers: '" + + Buf + "' for the archive member header at offset " + + Twine(Offset)); } return sys::toTimePoint(Seconds); @@ -290,11 +300,12 @@ Expected<unsigned> ArchiveMemberHeader::getUID() const { raw_string_ostream OS(Buf); OS.write_escaped(User); OS.flush(); - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("characters in UID field in archive header " - "are not all decimal numbers: '" + Buf + "' for the " - "archive member header at offset " + Twine(Offset)); + "are not all decimal numbers: '" + + Buf + "' for the archive member header at offset " + + Twine(Offset)); } return Ret; } @@ -309,11 +320,12 @@ Expected<unsigned> ArchiveMemberHeader::getGID() const { raw_string_ostream OS(Buf); OS.write_escaped(Group); OS.flush(); - uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - - Parent->getData().data(); + uint64_t Offset = + reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); return malformedError("characters in GID field in archive header " - "are not all decimal numbers: '" + Buf + "' for the " - "archive member header at offset " + Twine(Offset)); + "are not all decimal numbers: '" + + Buf + "' for the archive member header at offset " + + Twine(Offset)); } return Ret; } @@ -321,15 +333,15 @@ Expected<unsigned> ArchiveMemberHeader::getGID() const { Archive::Child::Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile) : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr), - Data(Data), StartOfFile(StartOfFile) { -} + Data(Data), StartOfFile(StartOfFile) {} Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) : Parent(Parent), Header(Parent, Start, Parent - ? Parent->getData().size() - (Start - Parent->getData().data()) - : 0, Err) { + ? Parent->getData().size() - (Start - Parent->getData().data()) + : 0, + Err) { if (!Start) return; @@ -368,7 +380,7 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) StartOfFile = Header.getSizeOf(); // Don't include attached name. Expected<StringRef> NameOrErr = getRawName(); - if (!NameOrErr){ + if (!NameOrErr) { *Err = NameOrErr.takeError(); return; } @@ -382,8 +394,8 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) OS.flush(); uint64_t Offset = Start - Parent->getData().data(); *Err = malformedError("long name length characters after the #1/ are " - "not all decimal numbers: '" + Buf + "' for " - "archive member header at offset " + + "not all decimal numbers: '" + + Buf + "' for archive member header at offset " + Twine(Offset)); return; } @@ -646,8 +658,7 @@ Archive::Archive(MemoryBufferRef Source, Error &Err) SymbolTable = BufOrErr.get(); if (Increment()) return; - } - else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") { + } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") { Format = K_DARWIN64; // We know that the symbol table is not an external file, but we still // must check any Expected<> return value. diff --git a/contrib/llvm-project/llvm/lib/Object/Binary.cpp b/contrib/llvm-project/llvm/lib/Object/Binary.cpp index e741cbba2882..143554344256 100644 --- a/contrib/llvm-project/llvm/lib/Object/Binary.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Binary.cpp @@ -56,6 +56,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: + case file_magic::goff_object: case file_magic::macho_object: case file_magic::macho_executable: case file_magic::macho_fixed_virtual_memory_shared_lib: @@ -97,7 +98,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, Expected<OwningBinary<Binary>> object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) { ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, + MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/false, /*RequiresNullTerminator=*/false); if (std::error_code EC = FileOrErr.getError()) return errorCodeToError(EC); diff --git a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp index 6e9a8eb35dcf..354b3c0d5577 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp @@ -328,7 +328,14 @@ bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { // The .debug sections are the only debug sections for COFF // (\see MCObjectFileInfo.cpp). -bool COFFObjectFile::isDebugSection(StringRef SectionName) const { +bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const { + Expected<StringRef> SectionNameOrErr = getSectionName(Ref); + if (!SectionNameOrErr) { + // TODO: Report the error message properly. + consumeError(SectionNameOrErr.takeError()); + return false; + } + StringRef SectionName = SectionNameOrErr.get(); return SectionName.startswith(".debug"); } diff --git a/contrib/llvm-project/llvm/lib/Object/ELF.cpp b/contrib/llvm-project/llvm/lib/Object/ELF.cpp index 264f115ddbb5..ca2ed4449120 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELF.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELF.cpp @@ -8,7 +8,7 @@ #include "llvm/Object/ELF.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/Support/LEB128.h" +#include "llvm/Support/DataExtractor.h" using namespace llvm; using namespace object; @@ -22,6 +22,13 @@ using namespace object; StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { switch (Machine) { + case ELF::EM_68K: + switch (Type) { +#include "llvm/BinaryFormat/ELFRelocs/M68k.def" + default: + break; + } + break; case ELF::EM_X86_64: switch (Type) { #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" @@ -373,39 +380,31 @@ ELFFile<ELFT>::android_relas(const Elf_Shdr &Sec) const { Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); if (!ContentsOrErr) return ContentsOrErr.takeError(); - const uint8_t *Cur = ContentsOrErr->begin(); - const uint8_t *End = ContentsOrErr->end(); - if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' || - Cur[2] != 'S' || Cur[3] != '2') + ArrayRef<uint8_t> Content = *ContentsOrErr; + if (Content.size() < 4 || Content[0] != 'A' || Content[1] != 'P' || + Content[2] != 'S' || Content[3] != '2') return createError("invalid packed relocation header"); - Cur += 4; - - const char *ErrStr = nullptr; - auto ReadSLEB = [&]() -> int64_t { - if (ErrStr) - return 0; - unsigned Len; - int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr); - Cur += Len; - return Result; - }; + DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4); + DataExtractor::Cursor Cur(/*Offset=*/4); - uint64_t NumRelocs = ReadSLEB(); - uint64_t Offset = ReadSLEB(); + uint64_t NumRelocs = Data.getSLEB128(Cur); + uint64_t Offset = Data.getSLEB128(Cur); uint64_t Addend = 0; - if (ErrStr) - return createError(ErrStr); + if (!Cur) + return std::move(Cur.takeError()); std::vector<Elf_Rela> Relocs; Relocs.reserve(NumRelocs); while (NumRelocs) { - uint64_t NumRelocsInGroup = ReadSLEB(); + uint64_t NumRelocsInGroup = Data.getSLEB128(Cur); + if (!Cur) + return std::move(Cur.takeError()); if (NumRelocsInGroup > NumRelocs) return createError("relocation group unexpectedly large"); NumRelocs -= NumRelocsInGroup; - uint64_t GroupFlags = ReadSLEB(); + uint64_t GroupFlags = Data.getSLEB128(Cur); bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG; bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG; bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG; @@ -413,34 +412,30 @@ ELFFile<ELFT>::android_relas(const Elf_Shdr &Sec) const { uint64_t GroupOffsetDelta; if (GroupedByOffsetDelta) - GroupOffsetDelta = ReadSLEB(); + GroupOffsetDelta = Data.getSLEB128(Cur); uint64_t GroupRInfo; if (GroupedByInfo) - GroupRInfo = ReadSLEB(); + GroupRInfo = Data.getSLEB128(Cur); if (GroupedByAddend && GroupHasAddend) - Addend += ReadSLEB(); + Addend += Data.getSLEB128(Cur); if (!GroupHasAddend) Addend = 0; - for (uint64_t I = 0; I != NumRelocsInGroup; ++I) { + for (uint64_t I = 0; Cur && I != NumRelocsInGroup; ++I) { Elf_Rela R; - Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB(); + Offset += GroupedByOffsetDelta ? GroupOffsetDelta : Data.getSLEB128(Cur); R.r_offset = Offset; - R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB(); + R.r_info = GroupedByInfo ? GroupRInfo : Data.getSLEB128(Cur); if (GroupHasAddend && !GroupedByAddend) - Addend += ReadSLEB(); + Addend += Data.getSLEB128(Cur); R.r_addend = Addend; Relocs.push_back(R); - - if (ErrStr) - return createError(ErrStr); } - - if (ErrStr) - return createError(ErrStr); + if (!Cur) + return std::move(Cur.takeError()); } return Relocs; @@ -617,6 +612,58 @@ ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const { return base() + Offset; } +template <class ELFT> +Expected<std::vector<typename ELFT::BBAddrMap>> +ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { + Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); + if (!ContentsOrErr) + return ContentsOrErr.takeError(); + ArrayRef<uint8_t> Content = *ContentsOrErr; + DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4); + std::vector<Elf_BBAddrMap> FunctionEntries; + + DataExtractor::Cursor Cur(0); + Error ULEBSizeErr = Error::success(); + + // Helper to extract and decode the next ULEB128 value as uint32_t. + // Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the uint32_t + // limit. + // Also returns zero if ULEBSizeErr is already in an error state. + auto ReadULEB128AsUInt32 = [&Data, &Cur, &ULEBSizeErr]() -> uint32_t { + // Bail out and do not extract data if ULEBSizeErr is already set. + if (ULEBSizeErr) + return 0; + uint64_t Offset = Cur.tell(); + uint64_t Value = Data.getULEB128(Cur); + if (Value > UINT32_MAX) { + ULEBSizeErr = createError( + "ULEB128 value at offset 0x" + Twine::utohexstr(Offset) + + " exceeds UINT32_MAX (0x" + Twine::utohexstr(Value) + ")"); + return 0; + } + return static_cast<uint32_t>(Value); + }; + + while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) { + uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur)); + uint32_t NumBlocks = ReadULEB128AsUInt32(); + std::vector<typename Elf_BBAddrMap::BBEntry> BBEntries; + for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks); + ++BlockID) { + uint32_t Offset = ReadULEB128AsUInt32(); + uint32_t Size = ReadULEB128AsUInt32(); + uint32_t Metadata = ReadULEB128AsUInt32(); + BBEntries.push_back({Offset, Size, Metadata}); + } + FunctionEntries.push_back({Address, BBEntries}); + } + // Either Cur is in the error state, or ULEBSizeError is set (not both), but + // we join the two errors here to be safe. + if (!Cur || ULEBSizeErr) + return joinErrors(Cur.takeError(), std::move(ULEBSizeErr)); + return FunctionEntries; +} + template class llvm::object::ELFFile<ELF32LE>; template class llvm::object::ELFFile<ELF32BE>; template class llvm::object::ELFFile<ELF64LE>; diff --git a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp index 91871a6255dc..6613d79ab3d0 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp @@ -457,6 +457,8 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { return "gfx908"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX909: return "gfx909"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90A: + return "gfx90a"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90C: return "gfx90c"; @@ -467,6 +469,8 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { return "gfx1011"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1012: return "gfx1012"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1013: + return "gfx1013"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1030: return "gfx1030"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1031: @@ -475,6 +479,10 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { return "gfx1032"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1033: return "gfx1033"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1034: + return "gfx1034"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1035: + return "gfx1035"; default: llvm_unreachable("Unknown EF_AMDGPU_MACH value"); } @@ -581,6 +589,7 @@ ELFObjectFileBase::getPltAddresses() const { JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; break; case Triple::aarch64: + case Triple::aarch64_be: JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; break; default: diff --git a/contrib/llvm-project/llvm/lib/Object/FaultMapParser.cpp b/contrib/llvm-project/llvm/lib/Object/FaultMapParser.cpp new file mode 100644 index 000000000000..9e83bc1de79d --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Object/FaultMapParser.cpp @@ -0,0 +1,66 @@ +//===----------------------- FaultMapParser.cpp ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/FaultMapParser.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void printFaultType(FaultMapParser::FaultKind FT, raw_ostream &OS) { + switch (FT) { + default: + llvm_unreachable("unhandled fault type!"); + case FaultMapParser::FaultingLoad: + OS << "FaultingLoad"; + break; + case FaultMapParser::FaultingLoadStore: + OS << "FaultingLoadStore"; + break; + case FaultMapParser::FaultingStore: + OS << "FaultingStore"; + break; + } +} + +raw_ostream & +llvm::operator<<(raw_ostream &OS, + const FaultMapParser::FunctionFaultInfoAccessor &FFI) { + OS << "Fault kind: "; + printFaultType((FaultMapParser::FaultKind)FFI.getFaultKind(), OS); + OS << ", faulting PC offset: " << FFI.getFaultingPCOffset() + << ", handling PC offset: " << FFI.getHandlerPCOffset(); + return OS; +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, + const FaultMapParser::FunctionInfoAccessor &FI) { + OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8) + << ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n"; + for (unsigned I = 0, E = FI.getNumFaultingPCs(); I != E; ++I) + OS << FI.getFunctionFaultInfoAt(I) << "\n"; + return OS; +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) { + OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n"; + OS << "NumFunctions: " << FMP.getNumFunctions() << "\n"; + + if (FMP.getNumFunctions() == 0) + return OS; + + FaultMapParser::FunctionInfoAccessor FI; + + for (unsigned I = 0, E = FMP.getNumFunctions(); I != E; ++I) { + FI = (I == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo(); + OS << FI; + } + + return OS; +} diff --git a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp index e39cb732add1..746b00867157 100644 --- a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp +++ b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp @@ -108,7 +108,7 @@ struct Builder { Error addModule(Module *M); Error addSymbol(const ModuleSymbolTable &Msymtab, - const SmallPtrSet<GlobalValue *, 8> &Used, + const SmallPtrSet<GlobalValue *, 4> &Used, ModuleSymbolTable::Symbol Sym); Error build(ArrayRef<Module *> Mods); @@ -119,8 +119,21 @@ Error Builder::addModule(Module *M) { return make_error<StringError>("input module has no datalayout", inconvertibleErrorCode()); - SmallPtrSet<GlobalValue *, 8> Used; - collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); + // Symbols in the llvm.used list will get the FB_Used bit and will not be + // internalized. We do this for llvm.compiler.used as well: + // + // IR symbol table tracks module-level asm symbol references but not inline + // asm. A symbol only referenced by inline asm is not in the IR symbol table, + // so we may not know that the definition (in another translation unit) is + // referenced. That definition may have __attribute__((used)) (which lowers to + // llvm.compiler.used on ELF targets) to communicate to the compiler that it + // may be used by inline asm. The usage is perfectly fine, so we treat + // llvm.compiler.used conservatively as llvm.used to work around our own + // limitation. + SmallVector<GlobalValue *, 4> UsedV; + collectUsedGlobalVariables(*M, UsedV, /*CompilerUsed=*/false); + collectUsedGlobalVariables(*M, UsedV, /*CompilerUsed=*/true); + SmallPtrSet<GlobalValue *, 4> Used(UsedV.begin(), UsedV.end()); ModuleSymbolTable Msymtab; Msymtab.addModule(M); @@ -186,6 +199,7 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) { storage::Comdat Comdat; setStr(Comdat.Name, Saver.save(Name)); + Comdat.SelectionKind = C->getSelectionKind(); Comdats.push_back(Comdat); } @@ -193,7 +207,7 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) { } Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, - const SmallPtrSet<GlobalValue *, 8> &Used, + const SmallPtrSet<GlobalValue *, 4> &Used, ModuleSymbolTable::Symbol Msym) { Syms.emplace_back(); storage::Symbol &Sym = Syms.back(); @@ -217,7 +231,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, raw_svector_ostream OS(Name); Msymtab.printSymbolName(OS, Msym); } - setStr(Sym.Name, Saver.save(StringRef(Name))); + setStr(Sym.Name, Saver.save(Name.str())); auto Flags = Msymtab.getSymbolFlags(Msym); if (Flags & object::BasicSymbolRef::SF_Undefined) @@ -247,11 +261,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, setStr(Sym.IRName, GV->getName()); - bool IsBuiltinFunc = false; - - for (const char *LibcallName : LibcallRoutineNames) - if (GV->getName() == LibcallName) - IsBuiltinFunc = true; + bool IsBuiltinFunc = llvm::is_contained(LibcallRoutineNames, GV->getName()); if (Used.count(GV) || IsBuiltinFunc) Sym.Flags |= 1 << storage::Symbol::FB_used; @@ -268,8 +278,8 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, if (!GVar) return make_error<StringError>("Only variables can have common linkage!", inconvertibleErrorCode()); - Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize( - GV->getType()->getElementType()); + Uncommon().CommonSize = + GV->getParent()->getDataLayout().getTypeAllocSize(GV->getValueType()); Uncommon().CommonAlign = GVar->getAlignment(); } diff --git a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp index 302255926289..177314a9a790 100644 --- a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp @@ -42,7 +42,6 @@ #include <limits> #include <list> #include <memory> -#include <string> #include <system_error> using namespace llvm; @@ -1836,6 +1835,8 @@ MachOObjectFile::getSymbolType(DataRefImpl Symb) const { if (!SecOrError) return SecOrError.takeError(); section_iterator Sec = *SecOrError; + if (Sec == section_end()) + return SymbolRef::ST_Other; if (Sec->isData() || Sec->isBSS()) return SymbolRef::ST_Data; return SymbolRef::ST_Function; @@ -2033,7 +2034,14 @@ bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { SectionType == MachO::S_GB_ZEROFILL); } -bool MachOObjectFile::isDebugSection(StringRef SectionName) const { +bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const { + Expected<StringRef> SectionNameOrErr = getSectionName(Sec); + if (!SectionNameOrErr) { + // TODO: Report the error message properly. + consumeError(SectionNameOrErr.takeError()); + return false; + } + StringRef SectionName = SectionNameOrErr.get(); return SectionName.startswith("__debug") || SectionName.startswith("__zdebug") || SectionName.startswith("__apple") || SectionName == "__gdb_index" || diff --git a/contrib/llvm-project/llvm/lib/Object/MachOUniversalWriter.cpp b/contrib/llvm-project/llvm/lib/Object/MachOUniversalWriter.cpp index 4bb467e56a6f..9673c97a10f0 100644 --- a/contrib/llvm-project/llvm/lib/Object/MachOUniversalWriter.cpp +++ b/contrib/llvm-project/llvm/lib/Object/MachOUniversalWriter.cpp @@ -263,8 +263,8 @@ buildFatArchList(ArrayRef<Slice> Slices) { return FatArchList; } -static Error writeUniversalBinaryToStream(ArrayRef<Slice> Slices, - raw_ostream &Out) { +Error object::writeUniversalBinaryToStream(ArrayRef<Slice> Slices, + raw_ostream &Out) { MachO::fat_header FatHeader; FatHeader.magic = MachO::FAT_MAGIC; FatHeader.nfat_arch = Slices.size(); @@ -324,14 +324,3 @@ Error object::writeUniversalBinary(ArrayRef<Slice> Slices, } return Temp->keep(OutputFileName); } - -Expected<std::unique_ptr<MemoryBuffer>> -object::writeUniversalBinaryToBuffer(ArrayRef<Slice> Slices) { - SmallVector<char, 0> Buffer; - raw_svector_ostream Out(Buffer); - - if (Error E = writeUniversalBinaryToStream(Slices, Out)) - return std::move(E); - - return std::make_unique<SmallVectorMemoryBuffer>(std::move(Buffer)); -} diff --git a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp index 7f3055b5dcfa..9a79de77af16 100644 --- a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp @@ -99,16 +99,18 @@ initializeRecordStreamer(const Module &M, if (!MCII) return; - MCObjectFileInfo MOFI; - MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); - MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx); - MOFI.setSDKVersion(M.getSDKVersion()); - RecordStreamer Streamer(MCCtx, M); - T->createNullTargetStreamer(Streamer); - std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); + + MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr); + std::unique_ptr<MCObjectFileInfo> MOFI( + T->createMCObjectFileInfo(MCCtx, /*PIC=*/false)); + MOFI->setSDKVersion(M.getSDKVersion()); + MCCtx.setObjectFileInfo(MOFI.get()); + RecordStreamer Streamer(MCCtx, M); + T->createNullTargetStreamer(Streamer); + std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI)); diff --git a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp index cf09a66d9c7d..5c894439ff67 100644 --- a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp @@ -94,9 +94,7 @@ bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { return isSectionData(Sec); } -bool ObjectFile::isDebugSection(StringRef SectionName) const { - return false; -} +bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; } Expected<section_iterator> ObjectFile::getRelocatedSection(DataRefImpl Sec) const { @@ -147,6 +145,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type, case file_magic::windows_resource: case file_magic::pdb: case file_magic::minidump: + case file_magic::goff_object: return errorCodeToError(object_error::invalid_file_type); case file_magic::tapi_file: return errorCodeToError(object_error::invalid_file_type); diff --git a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp index b2f973eff361..2d07d34bbf97 100644 --- a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp +++ b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp @@ -123,9 +123,10 @@ RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) { return SI->second; } -void RecordStreamer::emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) { - SymverAliasMap[Aliasee].push_back(AliasName); +void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym, + StringRef Name, + bool KeepOriginalSym) { + SymverAliasMap[OriginalSym].push_back(Name); } iterator_range<RecordStreamer::const_symver_iterator> diff --git a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h index 99d15f790a15..957d80f33bf4 100644 --- a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h +++ b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h @@ -63,8 +63,8 @@ public: void EndCOFFSymbolDef() override {} /// Record .symver aliases for later processing. - void emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) override; + void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name, + bool KeepOriginalSym) override; // Emit ELF .symver aliases and ensure they have the same binding as the // defined symbol they alias with. diff --git a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp index 204577af7239..ab98a2dd2ac1 100644 --- a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp +++ b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp @@ -89,8 +89,8 @@ static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S, static bool supportsBPF(uint64_t Type) { switch (Type) { - case ELF::R_BPF_64_32: - case ELF::R_BPF_64_64: + case ELF::R_BPF_64_ABS32: + case ELF::R_BPF_64_ABS64: return true; default: return false; @@ -100,9 +100,9 @@ static bool supportsBPF(uint64_t Type) { static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S, uint64_t LocData, int64_t /*Addend*/) { switch (Type) { - case ELF::R_BPF_64_32: + case ELF::R_BPF_64_ABS32: return (S + LocData) & 0xFFFFFFFF; - case ELF::R_BPF_64_64: + case ELF::R_BPF_64_ABS64: return S + LocData; default: llvm_unreachable("Invalid relocation type"); @@ -312,12 +312,17 @@ static bool supportsARM(uint64_t Type) { } static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S, - uint64_t LocData, int64_t /*Addend*/) { + uint64_t LocData, int64_t Addend) { + // Support both RELA and REL relocations. The caller is responsible + // for supplying the correct values for LocData and Addend, i.e. + // Addend == 0 for REL and LocData == 0 for RELA. + assert((LocData == 0 || Addend == 0) && + "one of LocData and Addend must be 0"); switch (Type) { case ELF::R_ARM_ABS32: - return (S + LocData) & 0xFFFFFFFF; + return (S + LocData + Addend) & 0xFFFFFFFF; case ELF::R_ARM_REL32: - return (S + LocData - Offset) & 0xFFFFFFFF; + return (S + LocData + Addend - Offset) & 0xFFFFFFFF; } llvm_unreachable("Invalid relocation type"); } @@ -572,9 +577,10 @@ static bool supportsWasm32(uint64_t Type) { case wasm::R_WASM_GLOBAL_INDEX_LEB: 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_TAG_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: case wasm::R_WASM_TABLE_NUMBER_LEB: + case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: return true; default: return false; @@ -608,9 +614,10 @@ static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S, case wasm::R_WASM_GLOBAL_INDEX_LEB: 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_TAG_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: case wasm::R_WASM_TABLE_NUMBER_LEB: + case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: // For wasm section, its offset at 0 -- ignoring Value return LocData; default: @@ -742,8 +749,13 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; }; - if (GetRelSectionType() == ELF::SHT_RELA) + if (GetRelSectionType() == ELF::SHT_RELA) { Addend = getELFAddend(R); + // RISCV relocations use both LocData and Addend. + if (Obj->getArch() != Triple::riscv32 && + Obj->getArch() != Triple::riscv64) + LocData = 0; + } } return Resolver(R.getType(), R.getOffset(), S, LocData, Addend); diff --git a/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp b/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp index 97baabec084b..e42dbe6f47ab 100644 --- a/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp +++ b/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp @@ -12,6 +12,7 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/Wasm.h" +#include "llvm/Object/XCOFFObjectFile.h" using namespace llvm; using namespace object; @@ -30,7 +31,8 @@ static unsigned getSectionID(const ObjectFile &O, SectionRef Sec) { return M->getSectionID(Sec); if (isa<WasmObjectFile>(&O)) return Sec.getIndex(); - + if (isa<XCOFFObjectFile>(&O)) + return Sec.getIndex(); return cast<COFFObjectFile>(O).getSectionID(Sec); } @@ -39,6 +41,8 @@ static unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) { return M->getSymbolSectionID(Sym); if (const auto *M = dyn_cast<WasmObjectFile>(&O)) return M->getSymbolSectionId(Sym); + if (const auto *M = dyn_cast<XCOFFObjectFile>(&O)) + return M->getSymbolSectionID(Sym); return cast<COFFObjectFile>(O).getSymbolSectionID(Sym); } diff --git a/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp b/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp index 34a2c5e1c125..58db5b672914 100644 --- a/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp @@ -53,6 +53,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: + case file_magic::goff_object: case file_magic::macho_executable: case file_magic::macho_fixed_virtual_memory_shared_lib: case file_magic::macho_core: @@ -102,6 +103,7 @@ bool SymbolicFile::isSymbolicFile(file_magic Type, const LLVMContext *Context) { case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: + case file_magic::goff_object: case file_magic::macho_executable: case file_magic::macho_fixed_virtual_memory_shared_lib: case file_magic::macho_core: diff --git a/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp b/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp index 7a361990ba5d..6b576260bdb1 100644 --- a/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp @@ -14,17 +14,12 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/TextAPI/Symbol.h" using namespace llvm; using namespace MachO; using namespace object; -static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_"; -static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_"; -static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_"; -static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_"; -static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_"; - static uint32_t getFlags(const Symbol *Sym) { uint32_t Flags = BasicSymbolRef::SF_Global; if (Sym->isUndefined()) diff --git a/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp b/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp index 48cb949cb6f4..d73d93f6bd53 100644 --- a/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp +++ b/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp @@ -14,7 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/Error.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/TextAPI/MachO/TextAPIReader.h" +#include "llvm/TextAPI/TextAPIReader.h" using namespace llvm; using namespace MachO; diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp index 40f468881edd..a08c648358c0 100644 --- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp @@ -39,8 +39,8 @@ using namespace object; void WasmSymbol::print(raw_ostream &Out) const { Out << "Name=" << Info.Name - << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) - << ", Flags=" << Info.Flags; + << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x" + << Twine::utohexstr(Info.Flags); if (!isTypeData()) { Out << ", ElemIndex=" << Info.ElementIndex; } else if (isDefined()) { @@ -208,7 +208,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { wasm::WasmLimits Result; Result.Flags = readVaruint32(Ctx); - Result.Initial = readVaruint64(Ctx); + Result.Minimum = readVaruint64(Ctx); if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) Result.Maximum = readVaruint64(Ctx); return Result; @@ -316,8 +316,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) { return parseTableSection(Ctx); case wasm::WASM_SEC_MEMORY: return parseMemorySection(Ctx); - case wasm::WASM_SEC_EVENT: - return parseEventSection(Ctx); + case wasm::WASM_SEC_TAG: + return parseTagSection(Ctx); case wasm::WASM_SEC_GLOBAL: return parseGlobalSection(Ctx); case wasm::WASM_SEC_EXPORT: @@ -462,7 +462,7 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { for (uint32_t I = 0; I < Count; I++) { DataSegments[I].Data.Name = readString(Ctx); DataSegments[I].Data.Alignment = readVaruint32(Ctx); - DataSegments[I].Data.LinkerFlags = readVaruint32(Ctx); + DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx); } break; } @@ -507,19 +507,19 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { std::vector<wasm::WasmImport *> ImportedGlobals; std::vector<wasm::WasmImport *> ImportedFunctions; - std::vector<wasm::WasmImport *> ImportedEvents; + std::vector<wasm::WasmImport *> ImportedTags; std::vector<wasm::WasmImport *> ImportedTables; ImportedGlobals.reserve(Imports.size()); ImportedFunctions.reserve(Imports.size()); - ImportedEvents.reserve(Imports.size()); + ImportedTags.reserve(Imports.size()); ImportedTables.reserve(Imports.size()); for (auto &I : Imports) { if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) ImportedFunctions.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) ImportedGlobals.emplace_back(&I); - else if (I.Kind == wasm::WASM_EXTERNAL_EVENT) - ImportedEvents.emplace_back(&I); + else if (I.Kind == wasm::WASM_EXTERNAL_TAG) + ImportedTags.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) ImportedTables.emplace_back(&I); } @@ -529,7 +529,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { const wasm::WasmSignature *Signature = nullptr; const wasm::WasmGlobalType *GlobalType = nullptr; const wasm::WasmTableType *TableType = nullptr; - const wasm::WasmEventType *EventType = nullptr; + const wasm::WasmTagType *TagType = nullptr; Info.Kind = readUint8(Ctx); Info.Flags = readVaruint32(Ctx); @@ -598,8 +598,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { case wasm::WASM_SYMBOL_TYPE_TABLE: Info.ElementIndex = readVaruint32(Ctx); - if (!isValidTableIndex(Info.ElementIndex) || - IsDefined != isDefinedTableIndex(Info.ElementIndex)) + if (!isValidTableNumber(Info.ElementIndex) || + IsDefined != isDefinedTableNumber(Info.ElementIndex)) return make_error<GenericBinaryError>("invalid table symbol index", object_error::parse_failed); if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == @@ -608,8 +608,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { object_error::parse_failed); if (IsDefined) { Info.Name = readString(Ctx); - unsigned TableIndex = Info.ElementIndex - NumImportedTables; - wasm::WasmTable &Table = Tables[TableIndex]; + unsigned TableNumber = Info.ElementIndex - NumImportedTables; + wasm::WasmTable &Table = Tables[TableNumber]; TableType = &Table.Type; if (Table.SymbolName.empty()) Table.SymbolName = Info.Name; @@ -637,9 +637,12 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { object_error::parse_failed); 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); + size_t SegmentSize = DataSegments[Index].Data.Content.size(); + if (Offset > SegmentSize) + return make_error<GenericBinaryError>( + "invalid data symbol offset: `" + Info.Name + "` (offset: " + + Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")", + object_error::parse_failed); Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; } break; @@ -657,11 +660,11 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { break; } - case wasm::WASM_SYMBOL_TYPE_EVENT: { + case wasm::WASM_SYMBOL_TYPE_TAG: { Info.ElementIndex = readVaruint32(Ctx); - if (!isValidEventIndex(Info.ElementIndex) || - IsDefined != isDefinedEventIndex(Info.ElementIndex)) - return make_error<GenericBinaryError>("invalid event symbol index", + if (!isValidTagIndex(Info.ElementIndex) || + IsDefined != isDefinedTagIndex(Info.ElementIndex)) + return make_error<GenericBinaryError>("invalid tag symbol index", object_error::parse_failed); if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == wasm::WASM_SYMBOL_BINDING_WEAK) @@ -669,23 +672,23 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { object_error::parse_failed); if (IsDefined) { Info.Name = readString(Ctx); - unsigned EventIndex = Info.ElementIndex - NumImportedEvents; - wasm::WasmEvent &Event = Events[EventIndex]; - Signature = &Signatures[Event.Type.SigIndex]; - EventType = &Event.Type; - if (Event.SymbolName.empty()) - Event.SymbolName = Info.Name; + unsigned TagIndex = Info.ElementIndex - NumImportedTags; + wasm::WasmTag &Tag = Tags[TagIndex]; + Signature = &Signatures[Tag.Type.SigIndex]; + TagType = &Tag.Type; + if (Tag.SymbolName.empty()) + Tag.SymbolName = Info.Name; } else { - wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; + wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex]; if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); Info.ImportName = Import.Field; } else { Info.Name = Import.Field; } - EventType = &Import.Event; - Signature = &Signatures[EventType->SigIndex]; + TagType = &Import.Tag; + Signature = &Signatures[TagType->SigIndex]; if (!Import.Module.empty()) { Info.ImportModule = Import.Module; } @@ -707,7 +710,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { object_error::parse_failed); LinkingData.SymbolTable.emplace_back(Info); Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType, - EventType, Signature); + TagType, Signature); LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); } @@ -867,6 +870,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { case wasm::R_WASM_TABLE_INDEX_I32: case wasm::R_WASM_TABLE_INDEX_I64: case wasm::R_WASM_TABLE_INDEX_REL_SLEB: + case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: if (!isValidFunctionSymbol(Reloc.Index)) return make_error<GenericBinaryError>( "invalid relocation function index", object_error::parse_failed); @@ -895,9 +899,9 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { return make_error<GenericBinaryError>("invalid relocation global index", object_error::parse_failed); break; - case wasm::R_WASM_EVENT_INDEX_LEB: - if (!isValidEventSymbol(Reloc.Index)) - return make_error<GenericBinaryError>("invalid relocation event index", + case wasm::R_WASM_TAG_INDEX_LEB: + if (!isValidTagSymbol(Reloc.Index)) + return make_error<GenericBinaryError>("invalid relocation tag index", object_error::parse_failed); break; case wasm::R_WASM_MEMORY_ADDR_LEB: @@ -905,6 +909,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { case wasm::R_WASM_MEMORY_ADDR_I32: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: + case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: if (!isValidDataSymbol(Reloc.Index)) return make_error<GenericBinaryError>("invalid relocation data index", object_error::parse_failed); @@ -914,6 +919,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { case wasm::R_WASM_MEMORY_ADDR_SLEB64: case wasm::R_WASM_MEMORY_ADDR_I64: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: + case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: if (!isValidDataSymbol(Reloc.Index)) return make_error<GenericBinaryError>("invalid relocation data index", object_error::parse_failed); @@ -953,6 +959,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { Size = 10; if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || + Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 || Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) @@ -1058,10 +1065,10 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { object_error::parse_failed); break; } - case wasm::WASM_EXTERNAL_EVENT: - NumImportedEvents++; - Im.Event.Attribute = readVarint32(Ctx); - Im.Event.SigIndex = readVarint32(Ctx); + case wasm::WASM_EXTERNAL_TAG: + NumImportedTags++; + Im.Tag.Attribute = readUint8(Ctx); + Im.Tag.SigIndex = readVarint32(Ctx); break; default: return make_error<GenericBinaryError>("unexpected import kind", @@ -1130,20 +1137,20 @@ Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { return Error::success(); } -Error WasmObjectFile::parseEventSection(ReadContext &Ctx) { - EventSection = Sections.size(); - uint32_t Count = readVarint32(Ctx); - Events.reserve(Count); +Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { + TagSection = Sections.size(); + uint32_t Count = readVaruint32(Ctx); + Tags.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); + wasm::WasmTag Tag; + Tag.Index = NumImportedTags + Tags.size(); + Tag.Type.Attribute = readUint8(Ctx); + Tag.Type.SigIndex = readVaruint32(Ctx); + Tags.push_back(Tag); } if (Ctx.Ptr != Ctx.End) - return make_error<GenericBinaryError>("event section ended prematurely", + return make_error<GenericBinaryError>("tag section ended prematurely", object_error::parse_failed); return Error::success(); } @@ -1188,9 +1195,9 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { return make_error<GenericBinaryError>("invalid global export", object_error::parse_failed); break; - case wasm::WASM_EXTERNAL_EVENT: - if (!isValidEventIndex(Ex.Index)) - return make_error<GenericBinaryError>("invalid event export", + case wasm::WASM_EXTERNAL_TAG: + if (!isValidTagIndex(Ex.Index)) + return make_error<GenericBinaryError>("invalid tag export", object_error::parse_failed); break; case wasm::WASM_EXTERNAL_MEMORY: @@ -1220,7 +1227,7 @@ bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { return Index < NumImportedGlobals + Globals.size(); } -bool WasmObjectFile::isValidTableIndex(uint32_t Index) const { +bool WasmObjectFile::isValidTableNumber(uint32_t Index) const { return Index < NumImportedTables + Tables.size(); } @@ -1228,16 +1235,16 @@ bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { return Index >= NumImportedGlobals && isValidGlobalIndex(Index); } -bool WasmObjectFile::isDefinedTableIndex(uint32_t Index) const { - return Index >= NumImportedTables && isValidTableIndex(Index); +bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const { + return Index >= NumImportedTables && isValidTableNumber(Index); } -bool WasmObjectFile::isValidEventIndex(uint32_t Index) const { - return Index < NumImportedEvents + Events.size(); +bool WasmObjectFile::isValidTagIndex(uint32_t Index) const { + return Index < NumImportedTags + Tags.size(); } -bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const { - return Index >= NumImportedEvents && isValidEventIndex(Index); +bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const { + return Index >= NumImportedTags && isValidTagIndex(Index); } bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { @@ -1252,8 +1259,8 @@ bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); } -bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const { - return Index < Symbols.size() && Symbols[Index].isTypeEvent(); +bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeTag(); } bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { @@ -1280,9 +1287,9 @@ wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { return Globals[Index - NumImportedGlobals]; } -wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) { - assert(isDefinedEventIndex(Index)); - return Events[Index - NumImportedEvents]; +wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) { + assert(isDefinedTagIndex(Index)); + return Tags[Index - NumImportedTags]; } Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { @@ -1340,13 +1347,54 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { ElemSegments.reserve(Count); while (Count--) { wasm::WasmElemSegment Segment; - Segment.TableIndex = readVaruint32(Ctx); - if (Segment.TableIndex != 0) { - return make_error<GenericBinaryError>("invalid TableIndex", + Segment.Flags = readVaruint32(Ctx); + + uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER | + wasm::WASM_ELEM_SEGMENT_IS_PASSIVE | + wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS; + if (Segment.Flags & ~SupportedFlags) + return make_error<GenericBinaryError>( + "Unsupported flags for element segment", object_error::parse_failed); + + if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) + Segment.TableNumber = readVaruint32(Ctx); + else + Segment.TableNumber = 0; + if (!isValidTableNumber(Segment.TableNumber)) + return make_error<GenericBinaryError>("invalid TableNumber", object_error::parse_failed); + + if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) { + Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Offset.Value.Int32 = 0; + } else { + if (Error Err = readInitExpr(Segment.Offset, Ctx)) + return Err; } - if (Error Err = readInitExpr(Segment.Offset, Ctx)) - return Err; + + if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { + Segment.ElemKind = readUint8(Ctx); + if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) { + if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) && + Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) { + return make_error<GenericBinaryError>("invalid reference type", + object_error::parse_failed); + } + } else { + if (Segment.ElemKind != 0) + return make_error<GenericBinaryError>("invalid elemtype", + object_error::parse_failed); + Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); + } + } else { + Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); + } + + if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) + return make_error<GenericBinaryError>( + "elem segment init expressions not yet implemented", + object_error::parse_failed); + uint32_t NumElems = readVaruint32(Ctx); while (NumElems--) { Segment.Functions.push_back(readVaruint32(Ctx)); @@ -1388,7 +1436,7 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { // The rest of these Data fields are set later, when reading in the linking // metadata section. Segment.Data.Alignment = 0; - Segment.Data.LinkerFlags = 0; + Segment.Data.LinkingFlags = 0; Segment.Data.Comdat = UINT32_MAX; Segment.SectionOffset = Ctx.Ptr - Ctx.Start; Ctx.Ptr += Size; @@ -1468,7 +1516,7 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { switch (Sym.Info.Kind) { case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: - case wasm::WASM_SYMBOL_TYPE_EVENT: + case wasm::WASM_SYMBOL_TYPE_TAG: case wasm::WASM_SYMBOL_TYPE_TABLE: return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_DATA: { @@ -1517,7 +1565,7 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Data; case wasm::WASM_SYMBOL_TYPE_SECTION: return SymbolRef::ST_Debug; - case wasm::WASM_SYMBOL_TYPE_EVENT: + case wasm::WASM_SYMBOL_TYPE_TAG: return SymbolRef::ST_Other; case wasm::WASM_SYMBOL_TYPE_TABLE: return SymbolRef::ST_Other; @@ -1553,8 +1601,8 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { return DataSection; case wasm::WASM_SYMBOL_TYPE_SECTION: return Sym.Info.ElementIndex; - case wasm::WASM_SYMBOL_TYPE_EVENT: - return EventSection; + case wasm::WASM_SYMBOL_TYPE_TAG: + return TagSection; case wasm::WASM_SYMBOL_TYPE_TABLE: return TableSection; default: @@ -1576,7 +1624,7 @@ Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const { ECase(TABLE); ECase(MEMORY); ECase(GLOBAL); - ECase(EVENT); + ECase(TAG); ECase(EXPORT); ECase(START); ECase(ELEM); @@ -1775,8 +1823,8 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID, return WASM_SEC_ORDER_DATA; case wasm::WASM_SEC_DATACOUNT: return WASM_SEC_ORDER_DATACOUNT; - case wasm::WASM_SEC_EVENT: - return WASM_SEC_ORDER_EVENT; + case wasm::WASM_SEC_TAG: + return WASM_SEC_ORDER_TAG; default: return WASM_SEC_ORDER_NONE; } @@ -1798,9 +1846,9 @@ int WasmSectionOrderChecker::DisallowedPredecessors // 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_MEMORY, WASM_SEC_ORDER_TAG}, + // WASM_SEC_ORDER_TAG + {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL}, // WASM_SEC_ORDER_GLOBAL {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, // WASM_SEC_ORDER_EXPORT diff --git a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp index a16a458168d4..53447d0c97b2 100644 --- a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/XCOFFObjectFile.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/DataExtractor.h" #include <cstddef> @@ -23,8 +24,8 @@ using namespace XCOFF; namespace object { static const uint8_t FunctionSym = 0x20; -static const uint8_t SymTypeMask = 0x07; static const uint16_t NoRelMask = 0x0001; +static const size_t SymbolAuxTypeOffset = 17; // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer // 'M'. Returns a pointer to the underlying object on success. @@ -82,6 +83,19 @@ uint8_t XCOFFRelocation32::getRelocatedLength() const { return (Info & XR_BIASED_LENGTH_MASK) + 1; } +uintptr_t +XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, + uint32_t Distance) { + return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize); +} + +const XCOFF::SymbolAuxType * +XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const { + assert(is64Bit() && "64-bit interface called on a 32-bit object file."); + return viewAs<XCOFF::SymbolAuxType>( + getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset)); +} + void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, uintptr_t TableAddress) const { if (Addr < TableAddress) @@ -114,14 +128,12 @@ XCOFFObjectFile::toSection64(DataRefImpl Ref) const { return viewAs<XCOFFSectionHeader64>(Ref.p); } -const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); +XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); #ifndef NDEBUG checkSymbolEntryPointer(Ref.p); #endif - auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p); - return SymEntPtr; + return XCOFFSymbolRef(Ref, this); } const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { @@ -147,15 +159,15 @@ XCOFFObjectFile::sectionHeaderTable64() const { } void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1; + uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress( + Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); #ifndef NDEBUG // This function is used by basic_symbol_iterator, which allows to // point to the end-of-symbol-table address. - if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress()) - checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr)); + if (NextSymbolAddr != getEndOfSymbolTableAddress()) + checkSymbolEntryPointer(NextSymbolAddr); #endif - Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr); + Symb.p = NextSymbolAddr; } Expected<StringRef> @@ -175,36 +187,27 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { object_error::parse_failed); } +StringRef XCOFFObjectFile::getStringTable() const { + return StringRef(StringTable.Data, StringTable.Size); +} + Expected<StringRef> XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { - if (CFileEntPtr->NameInStrTbl.Magic != - XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) + if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); } Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - - // A storage class value with the high-order bit on indicates that the name is - // a symbolic debugger stabstring. - if (SymEntPtr->StorageClass & 0x80) - return StringRef("Unimplemented Debug Name"); - - if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) - return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName); - - return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset); + return toSymbolRef(Symb).getName(); } Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - return toSymbolEntry(Symb)->Value; + return toSymbolRef(Symb).getValue(); } uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - return toSymbolEntry(Symb)->Value; + return toSymbolRef(Symb).getValue(); } uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { @@ -215,14 +218,13 @@ uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { Expected<SymbolRef::Type> XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { - llvm_unreachable("Not yet implemented!"); + // TODO: Return the correct symbol type. return SymbolRef::ST_Other; } Expected<section_iterator> XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - int16_t SectNum = SymEntPtr->SectionNumber; + const int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); if (isReservedSectionNumber(SectNum)) return section_end(); @@ -296,9 +298,7 @@ uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { } bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { - bool Result = false; - llvm_unreachable("Not yet implemented!"); - return Result; + return false; } bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { @@ -315,6 +315,11 @@ bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); } +bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const { + uint32_t Flags = getSectionFlags(Sec); + return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF); +} + bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 : toSection32(Sec)->FileOffsetToRawData == 0; @@ -377,7 +382,7 @@ symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { return symbol_end(); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index); + SymDRI.p = getSymbolEntryAddressByIndex(Index); return symbol_iterator(SymbolRef(SymDRI, this)); } @@ -398,24 +403,20 @@ void XCOFFObjectFile::getRelocationTypeName( Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = 0; - llvm_unreachable("Not yet implemented!"); + // TODO: Return correct symbol flags. return Result; } basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { - 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 { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast<uintptr_t>( - SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); + const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); + SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); return basic_symbol_iterator(SymbolRef(SymDRI, this)); } @@ -448,7 +449,7 @@ SubtargetFeatures XCOFFObjectFile::getFeatures() const { bool XCOFFObjectFile::isRelocatableObject() const { if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); + return !(fileHeader64()->Flags & NoRelMask); return !(fileHeader32()->Flags & NoRelMask); } @@ -458,6 +459,22 @@ Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { return 0; } +StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { + return StringSwitch<StringRef>(Name) + .Case("dwinfo", "debug_info") + .Case("dwline", "debug_line") + .Case("dwpbnms", "debug_pubnames") + .Case("dwpbtyp", "debug_pubtypes") + .Case("dwarnge", "debug_aranges") + .Case("dwabrev", "debug_abbrev") + .Case("dwstr", "debug_str") + .Case("dwrnges", "debug_ranges") + .Case("dwloc", "debug_loc") + .Case("dwframe", "debug_frame") + .Case("dwmac", "debug_macinfo") + .Default(Name); +} + size_t XCOFFObjectFile::getFileHeaderSize() const { return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); } @@ -486,9 +503,8 @@ Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { } Expected<StringRef> -XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - int16_t SectionNum = SymEntPtr->SectionNumber; +XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { + const int16_t SectionNum = SymEntPtr.getSectionNumber(); switch (SectionNum) { case XCOFF::N_DEBUG: @@ -506,6 +522,11 @@ XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { } } +unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { + XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); + return XCOFFSymRef.getSectionNumber(); +} + bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { return (SectionNumber <= 0 && SectionNumber >= -2); } @@ -549,10 +570,13 @@ uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { return fileHeader64()->NumberOfSymTableEntries; } +uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { + return is64Bit() ? getNumberOfSymbolTableEntries64() + : getLogicalNumberOfSymbolTableEntries32(); +} + uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { - uint32_t NumberOfSymTableEntries = - is64Bit() ? getNumberOfSymbolTableEntries64() - : getLogicalNumberOfSymbolTableEntries32(); + const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); } @@ -578,16 +602,20 @@ uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { XCOFF::SymbolTableEntrySize; } +uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { + return getAdvancedSymbolEntryAddress( + reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); +} + Expected<StringRef> XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { - if (is64Bit()) - report_fatal_error("64-bit symbol table support not implemented yet."); + const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); - if (Index >= getLogicalNumberOfSymbolTableEntries32()) + if (Index >= NumberOfSymTableEntries) return errorCodeToError(object_error::invalid_symbol_index); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index); + SymDRI.p = getSymbolEntryAddressByIndex(Index); return getSymbolName(SymDRI); } @@ -730,20 +758,21 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { Obj->SectionHeaderTable = SecHeadersOrErr.get(); } - // 64-bit object supports only file header and section headers for now. - if (Obj->is64Bit()) - return std::move(Obj); + const uint32_t NumberOfSymbolTableEntries = + Obj->getNumberOfSymbolTableEntries(); // If there is no symbol table we are done parsing the memory buffer. - if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0) + if (NumberOfSymbolTableEntries == 0) return std::move(Obj); // Parse symbol table. - CurOffset = Obj->fileHeader32()->SymbolTableOffset; - uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) * - Obj->getLogicalNumberOfSymbolTableEntries32(); + CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() + : Obj->getSymbolTableOffset32(); + const uint64_t SymbolTableSize = + static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * + NumberOfSymbolTableEntries; auto SymTableOrErr = - getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize); + getObject<void *>(Data, Base + CurOffset, SymbolTableSize); if (Error E = SymTableOrErr.takeError()) return std::move(E); Obj->SymbolTblPtr = SymTableOrErr.get(); @@ -765,74 +794,103 @@ ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, return XCOFFObjectFile::create(FileType, MemBufRef); } -XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass; -} +bool XCOFFSymbolRef::isFunction() const { + if (!isCsectSymbol()) + return false; -uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries; -} + if (getSymbolType() & FunctionSym) + return true; -// 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."); - assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found."); + Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); + if (!ExpCsectAuxEnt) + return false; - // In XCOFF32, the csect auxilliary entry is always the last auxiliary - // entry for the symbol. - uintptr_t AuxAddr = getWithOffset( - SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries()); + const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); -#ifndef NDEBUG - OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); -#endif + // A function definition should be a label definition. + // FIXME: This is not necessarily the case when -ffunction-sections is + // enabled. + if (!CsectAuxRef.isLabel()) + return false; - return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr); -} + if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) + return false; -uint16_t XCOFFSymbolRef::getType() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType; -} + const int16_t SectNum = getSectionNumber(); + Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); + if (!SI) { + // If we could not get the section, then this symbol should not be + // a function. So consume the error and return `false` to move on. + consumeError(SI.takeError()); + return false; + } -int16_t XCOFFSymbolRef::getSectionNumber() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber; + return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); } -// TODO: The function name needs to be changed to express the purpose of the -// function. -bool XCOFFSymbolRef::hasCsectAuxEnt() const { +bool XCOFFSymbolRef::isCsectSymbol() const { XCOFF::StorageClass SC = getStorageClass(); return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || SC == XCOFF::C_HIDEXT); } -bool XCOFFSymbolRef::isFunction() const { - if (OwningObjectPtr->is64Bit()) - report_fatal_error("64-bit support is unimplemented yet."); +Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { + assert(isCsectSymbol() && + "Calling csect symbol interface with a non-csect symbol."); - if (getType() & FunctionSym) - return true; + uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); - if (!hasCsectAuxEnt()) - return false; + Expected<StringRef> NameOrErr = getName(); + if (auto Err = NameOrErr.takeError()) + return std::move(Err); - const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32(); + if (!NumberOfAuxEntries) { + return createStringError(object_error::parse_failed, + "csect symbol \"" + *NameOrErr + + "\" contains no auxiliary entry"); + } - // A function definition should be a label definition. - if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD) - return false; + if (!OwningObjectPtr->is64Bit()) { + // In XCOFF32, the csect auxilliary entry is always the last auxiliary + // entry for the symbol. + uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + getEntryAddress(), NumberOfAuxEntries); + return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); + } - if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR) - return false; + // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. + // We need to iterate through all the auxiliary entries to find it. + for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { + uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + getEntryAddress(), Index); + if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == + XCOFF::SymbolAuxType::AUX_CSECT) { +#ifndef NDEBUG + OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); +#endif + return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); + } + } - int16_t SectNum = getSectionNumber(); - Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); - if (!SI) - return false; + return createStringError( + object_error::parse_failed, + "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); +} - return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); +Expected<StringRef> XCOFFSymbolRef::getName() const { + // A storage class value with the high-order bit on indicates that the name is + // a symbolic debugger stabstring. + if (getStorageClass() & 0x80) + return StringRef("Unimplemented Debug Name"); + + if (Entry32) { + if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) + return generateXCOFFFixedNameStringRef(Entry32->SymbolName); + + return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); + } + + return OwningObjectPtr->getStringTableEntry(Entry64->Offset); } // Explictly instantiate template classes. @@ -846,15 +904,34 @@ bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { return support::endian::read32be(Bytes.data()) == 0; } -TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) { +#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) +#define GETVALUEWITHMASKSHIFT(X, S) \ + ((Data & (TracebackTable::X)) >> (TracebackTable::S)) + +Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { + Error Err = Error::success(); + TBVectorExt TBTVecExt(TBvectorStrRef, Err); + if (Err) + return std::move(Err); + return TBTVecExt; +} + +TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); Data = support::endian::read16be(Ptr); - VecParmsInfo = support::endian::read32be(Ptr + 2); + uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); + unsigned ParmsNum = + GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); + + ErrorAsOutParameter EAO(&Err); + Expected<SmallString<32>> VecParmsTypeOrError = + parseVectorParmsType(VecParmsTypeValue, ParmsNum); + if (!VecParmsTypeOrError) + Err = VecParmsTypeOrError.takeError(); + else + VecParmsInfo = VecParmsTypeOrError.get(); } -#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) -#define GETVALUEWITHMASKSHIFT(X, S) \ - ((Data & (TracebackTable::X)) >> (TracebackTable::S)) uint8_t TBVectorExt::getNumberOfVRSaved() const { return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); } @@ -866,6 +943,7 @@ bool TBVectorExt::isVRSavedOnStack() const { bool TBVectorExt::hasVarArgs() const { return GETVALUEWITHMASK(HasVarArgsMask); } + uint8_t TBVectorExt::getNumberOfVectorParms() const { return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); @@ -877,72 +955,6 @@ bool TBVectorExt::hasVMXInstruction() const { #undef GETVALUEWITHMASK #undef GETVALUEWITHMASKSHIFT -SmallString<32> TBVectorExt::getVectorParmsInfoString() const { - SmallString<32> ParmsType; - uint32_t Value = VecParmsInfo; - for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) { - if (I != 0) - ParmsType += ", "; - switch (Value & TracebackTable::ParmTypeMask) { - case TracebackTable::ParmTypeIsVectorCharBit: - ParmsType += "vc"; - break; - - case TracebackTable::ParmTypeIsVectorShortBit: - ParmsType += "vs"; - break; - - case TracebackTable::ParmTypeIsVectorIntBit: - ParmsType += "vi"; - break; - - case TracebackTable::ParmTypeIsVectorFloatBit: - ParmsType += "vf"; - break; - } - Value <<= 2; - } - return ParmsType; -} - -static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value, - unsigned int ParmsNum) { - SmallString<32> ParmsType; - unsigned I = 0; - bool Begin = false; - while (I < ParmsNum || Value) { - if (Begin) - ParmsType += ", "; - else - Begin = true; - - switch (Value & TracebackTable::ParmTypeMask) { - case TracebackTable::ParmTypeIsFixedBits: - ParmsType += "i"; - ++I; - break; - case TracebackTable::ParmTypeIsVectorBits: - ParmsType += "v"; - break; - case TracebackTable::ParmTypeIsFloatingBits: - ParmsType += "f"; - ++I; - break; - case TracebackTable::ParmTypeIsDoubleBits: - ParmsType += "d"; - ++I; - break; - default: - assert(false && "Unrecognized bits in ParmsType."); - } - Value <<= 2; - } - assert(I == ParmsNum && - "The total parameters number of fixed-point or floating-point " - "parameters not equal to the number in the parameter type!"); - return ParmsType; -} - Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size) { Error Err = Error::success(); @@ -963,21 +975,13 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, // Skip 8 bytes of mandatory fields. DE.getU64(Cur); + unsigned FixedParmsNum = getNumberOfFixedParms(); + unsigned FloatingParmsNum = getNumberOfFPParms(); + uint32_t ParamsTypeValue = 0; + // Begin to parse optional fields. - if (Cur) { - unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms(); - - // As long as there are no "fixed-point" or floating-point parameters, this - // field remains not present even when hasVectorInfo gives true and - // indicates the presence of vector parameters. - if (ParmNum > 0) { - uint32_t ParamsTypeValue = DE.getU32(Cur); - if (Cur) - ParmsType = hasVectorInfo() - ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum) - : parseParmsType(ParamsTypeValue, ParmNum); - } - } + if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) + ParamsTypeValue = DE.getU32(Cur); if (Cur && hasTraceBackTableOffset()) TraceBackTableOffset = DE.getU32(Cur); @@ -1006,10 +1010,35 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, if (Cur && isAllocaUsed()) AllocaRegister = DE.getU8(Cur); + unsigned VectorParmsNum = 0; if (Cur && hasVectorInfo()) { StringRef VectorExtRef = DE.getBytes(Cur, 6); - if (Cur) - VecExt = TBVectorExt(VectorExtRef); + if (Cur) { + Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); + if (!TBVecExtOrErr) { + Err = TBVecExtOrErr.takeError(); + return; + } + VecExt = TBVecExtOrErr.get(); + VectorParmsNum = VecExt.getValue().getNumberOfVectorParms(); + } + } + + // As long as there is no fixed-point or floating-point parameter, this + // field remains not present even when hasVectorInfo gives true and + // indicates the presence of vector parameters. + if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { + Expected<SmallString<32>> ParmsTypeOrError = + hasVectorInfo() + ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, + FloatingParmsNum, VectorParmsNum) + : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); + + if (!ParmsTypeOrError) { + Err = ParmsTypeOrError.takeError(); + return; + } + ParmsType = ParmsTypeOrError.get(); } if (Cur && hasExtensionTable()) @@ -1017,6 +1046,7 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, if (!Cur) Err = Cur.takeError(); + Size = Cur.tell(); } |