diff options
| author | orivej <[email protected]> | 2022-02-10 16:44:49 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:49 +0300 |
| commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
| tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/include/llvm/Object | |
| parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/Object')
29 files changed, 9246 insertions, 9246 deletions
diff --git a/contrib/libs/llvm12/include/llvm/Object/Archive.h b/contrib/libs/llvm12/include/llvm/Object/Archive.h index b6b1a126ac3..07cc0a13524 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Archive.h +++ b/contrib/libs/llvm12/include/llvm/Object/Archive.h @@ -1,297 +1,297 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Archive.h - ar archive file format -----------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the ar archive file format class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ARCHIVE_H -#define LLVM_OBJECT_ARCHIVE_H - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/fallible_iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Object/Binary.h" -#include "llvm/Support/Chrono.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <memory> -#include <string> -#include <vector> - -namespace llvm { -namespace object { - -class Archive; - -class ArchiveMemberHeader { -public: - friend class Archive; - - ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr, - uint64_t Size, Error *Err); - // ArchiveMemberHeader() = default; - - /// Get the name without looking up long names. - Expected<StringRef> getRawName() const; - - /// Get the name looking up long names. - Expected<StringRef> getName(uint64_t Size) const; - - Expected<uint64_t> getSize() const; - - Expected<sys::fs::perms> getAccessMode() const; - Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const; - - StringRef getRawLastModified() const { - return StringRef(ArMemHdr->LastModified, - sizeof(ArMemHdr->LastModified)).rtrim(' '); - } - - Expected<unsigned> getUID() const; - Expected<unsigned> getGID() const; - - // This returns the size of the private struct ArMemHdrType - uint64_t getSizeOf() const { - return sizeof(ArMemHdrType); - } - -private: - struct ArMemHdrType { - char Name[16]; - char LastModified[12]; - char UID[6]; - char GID[6]; - char AccessMode[8]; - char Size[10]; ///< Size of data, not including header or padding. - char Terminator[2]; - }; - Archive const *Parent; - ArMemHdrType const *ArMemHdr; -}; - -class Archive : public Binary { - virtual void anchor(); - -public: - class Child { - friend Archive; - friend ArchiveMemberHeader; - - const Archive *Parent; - ArchiveMemberHeader Header; - /// Includes header but not padding byte. - StringRef Data; - /// Offset from Data to the start of the file. - uint16_t StartOfFile; - - Expected<bool> isThinMember() const; - - public: - Child(const Archive *Parent, const char *Start, Error *Err); - Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); - - bool operator ==(const Child &other) const { - assert(!Parent || !other.Parent || Parent == other.Parent); - return Data.begin() == other.Data.begin(); - } - - const Archive *getParent() const { return Parent; } - Expected<Child> getNext() const; - - Expected<StringRef> getName() const; - Expected<std::string> getFullName() const; - Expected<StringRef> getRawName() const { return Header.getRawName(); } - - Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const { - return Header.getLastModified(); - } - - StringRef getRawLastModified() const { - return Header.getRawLastModified(); - } - - Expected<unsigned> getUID() const { return Header.getUID(); } - Expected<unsigned> getGID() const { return Header.getGID(); } - - Expected<sys::fs::perms> getAccessMode() const { - return Header.getAccessMode(); - } - - /// \return the size of the archive member without the header or padding. - Expected<uint64_t> getSize() const; - /// \return the size in the archive header for this member. - Expected<uint64_t> getRawSize() const; - - Expected<StringRef> getBuffer() const; - uint64_t getChildOffset() const; - uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; } - - Expected<MemoryBufferRef> getMemoryBufferRef() const; - - Expected<std::unique_ptr<Binary>> - getAsBinary(LLVMContext *Context = nullptr) const; - }; - - class ChildFallibleIterator { - Child C; - - public: - ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {} - ChildFallibleIterator(const Child &C) : C(C) {} - - const Child *operator->() const { return &C; } - const Child &operator*() const { return C; } - - bool operator==(const ChildFallibleIterator &other) const { - // Ignore errors here: If an error occurred during increment then getNext - // will have been set to child_end(), and the following comparison should - // do the right thing. - return C == other.C; - } - - bool operator!=(const ChildFallibleIterator &other) const { - return !(*this == other); - } - - Error inc() { - auto NextChild = C.getNext(); - if (!NextChild) - return NextChild.takeError(); - C = std::move(*NextChild); - return Error::success(); - } - }; - - using child_iterator = fallible_iterator<ChildFallibleIterator>; - - class Symbol { - const Archive *Parent; - uint32_t SymbolIndex; - uint32_t StringIndex; // Extra index to the string. - - public: - Symbol(const Archive *p, uint32_t symi, uint32_t stri) - : Parent(p) - , SymbolIndex(symi) - , StringIndex(stri) {} - - bool operator ==(const Symbol &other) const { - return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); - } - - StringRef getName() const; - Expected<Child> getMember() const; - Symbol getNext() const; - }; - - class symbol_iterator { - Symbol symbol; - - public: - symbol_iterator(const Symbol &s) : symbol(s) {} - - const Symbol *operator->() const { return &symbol; } - const Symbol &operator*() const { return symbol; } - - bool operator==(const symbol_iterator &other) const { - return symbol == other.symbol; - } - - bool operator!=(const symbol_iterator &other) const { - return !(*this == other); - } - - symbol_iterator& operator++() { // Preincrement - symbol = symbol.getNext(); - return *this; - } - }; - - Archive(MemoryBufferRef Source, Error &Err); - static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source); - - /// Size field is 10 decimal digits long - static const uint64_t MaxMemberSize = 9999999999; - - enum Kind { - K_GNU, - K_GNU64, - K_BSD, - K_DARWIN, - K_DARWIN64, - K_COFF - }; - - Kind kind() const { return (Kind)Format; } - bool isThin() const { return IsThin; } - - child_iterator child_begin(Error &Err, bool SkipInternal = true) const; - child_iterator child_end() const; - iterator_range<child_iterator> children(Error &Err, - bool SkipInternal = true) const { - return make_range(child_begin(Err, SkipInternal), child_end()); - } - - symbol_iterator symbol_begin() const; - symbol_iterator symbol_end() const; - iterator_range<symbol_iterator> symbols() const { - return make_range(symbol_begin(), symbol_end()); - } - - // Cast methods. - static bool classof(Binary const *v) { - return v->isArchive(); - } - - // check if a symbol is in the archive - Expected<Optional<Child>> findSym(StringRef name) const; - - bool isEmpty() const; - bool hasSymbolTable() const; - StringRef getSymbolTable() const { return SymbolTable; } - StringRef getStringTable() const { return StringTable; } - uint32_t getNumberOfSymbols() const; - - std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { - return std::move(ThinBuffers); - } - -private: - StringRef SymbolTable; - StringRef StringTable; - - StringRef FirstRegularData; - uint16_t FirstRegularStartOfFile = -1; - void setFirstRegular(const Child &C); - - unsigned Format : 3; - unsigned IsThin : 1; - mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; -}; - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_ARCHIVE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Archive.h - ar archive file format -----------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the ar archive file format class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ARCHIVE_H +#define LLVM_OBJECT_ARCHIVE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/fallible_iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/Chrono.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { +namespace object { + +class Archive; + +class ArchiveMemberHeader { +public: + friend class Archive; + + ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr, + uint64_t Size, Error *Err); + // ArchiveMemberHeader() = default; + + /// Get the name without looking up long names. + Expected<StringRef> getRawName() const; + + /// Get the name looking up long names. + Expected<StringRef> getName(uint64_t Size) const; + + Expected<uint64_t> getSize() const; + + Expected<sys::fs::perms> getAccessMode() const; + Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const; + + StringRef getRawLastModified() const { + return StringRef(ArMemHdr->LastModified, + sizeof(ArMemHdr->LastModified)).rtrim(' '); + } + + Expected<unsigned> getUID() const; + Expected<unsigned> getGID() const; + + // This returns the size of the private struct ArMemHdrType + uint64_t getSizeOf() const { + return sizeof(ArMemHdrType); + } + +private: + struct ArMemHdrType { + char Name[16]; + char LastModified[12]; + char UID[6]; + char GID[6]; + char AccessMode[8]; + char Size[10]; ///< Size of data, not including header or padding. + char Terminator[2]; + }; + Archive const *Parent; + ArMemHdrType const *ArMemHdr; +}; + +class Archive : public Binary { + virtual void anchor(); + +public: + class Child { + friend Archive; + friend ArchiveMemberHeader; + + const Archive *Parent; + ArchiveMemberHeader Header; + /// Includes header but not padding byte. + StringRef Data; + /// Offset from Data to the start of the file. + uint16_t StartOfFile; + + Expected<bool> isThinMember() const; + + public: + Child(const Archive *Parent, const char *Start, Error *Err); + Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); + + bool operator ==(const Child &other) const { + assert(!Parent || !other.Parent || Parent == other.Parent); + return Data.begin() == other.Data.begin(); + } + + const Archive *getParent() const { return Parent; } + Expected<Child> getNext() const; + + Expected<StringRef> getName() const; + Expected<std::string> getFullName() const; + Expected<StringRef> getRawName() const { return Header.getRawName(); } + + Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const { + return Header.getLastModified(); + } + + StringRef getRawLastModified() const { + return Header.getRawLastModified(); + } + + Expected<unsigned> getUID() const { return Header.getUID(); } + Expected<unsigned> getGID() const { return Header.getGID(); } + + Expected<sys::fs::perms> getAccessMode() const { + return Header.getAccessMode(); + } + + /// \return the size of the archive member without the header or padding. + Expected<uint64_t> getSize() const; + /// \return the size in the archive header for this member. + Expected<uint64_t> getRawSize() const; + + Expected<StringRef> getBuffer() const; + uint64_t getChildOffset() const; + uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; } + + Expected<MemoryBufferRef> getMemoryBufferRef() const; + + Expected<std::unique_ptr<Binary>> + getAsBinary(LLVMContext *Context = nullptr) const; + }; + + class ChildFallibleIterator { + Child C; + + public: + ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {} + ChildFallibleIterator(const Child &C) : C(C) {} + + const Child *operator->() const { return &C; } + const Child &operator*() const { return C; } + + bool operator==(const ChildFallibleIterator &other) const { + // Ignore errors here: If an error occurred during increment then getNext + // will have been set to child_end(), and the following comparison should + // do the right thing. + return C == other.C; + } + + bool operator!=(const ChildFallibleIterator &other) const { + return !(*this == other); + } + + Error inc() { + auto NextChild = C.getNext(); + if (!NextChild) + return NextChild.takeError(); + C = std::move(*NextChild); + return Error::success(); + } + }; + + using child_iterator = fallible_iterator<ChildFallibleIterator>; + + class Symbol { + const Archive *Parent; + uint32_t SymbolIndex; + uint32_t StringIndex; // Extra index to the string. + + public: + Symbol(const Archive *p, uint32_t symi, uint32_t stri) + : Parent(p) + , SymbolIndex(symi) + , StringIndex(stri) {} + + bool operator ==(const Symbol &other) const { + return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); + } + + StringRef getName() const; + Expected<Child> getMember() const; + Symbol getNext() const; + }; + + class symbol_iterator { + Symbol symbol; + + public: + symbol_iterator(const Symbol &s) : symbol(s) {} + + const Symbol *operator->() const { return &symbol; } + const Symbol &operator*() const { return symbol; } + + bool operator==(const symbol_iterator &other) const { + return symbol == other.symbol; + } + + bool operator!=(const symbol_iterator &other) const { + return !(*this == other); + } + + symbol_iterator& operator++() { // Preincrement + symbol = symbol.getNext(); + return *this; + } + }; + + Archive(MemoryBufferRef Source, Error &Err); + static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source); + + /// Size field is 10 decimal digits long + static const uint64_t MaxMemberSize = 9999999999; + + enum Kind { + K_GNU, + K_GNU64, + K_BSD, + K_DARWIN, + K_DARWIN64, + K_COFF + }; + + Kind kind() const { return (Kind)Format; } + bool isThin() const { return IsThin; } + + child_iterator child_begin(Error &Err, bool SkipInternal = true) const; + child_iterator child_end() const; + iterator_range<child_iterator> children(Error &Err, + bool SkipInternal = true) const { + return make_range(child_begin(Err, SkipInternal), child_end()); + } + + symbol_iterator symbol_begin() const; + symbol_iterator symbol_end() const; + iterator_range<symbol_iterator> symbols() const { + return make_range(symbol_begin(), symbol_end()); + } + + // Cast methods. + static bool classof(Binary const *v) { + return v->isArchive(); + } + + // check if a symbol is in the archive + Expected<Optional<Child>> findSym(StringRef name) const; + + bool isEmpty() const; + bool hasSymbolTable() const; + StringRef getSymbolTable() const { return SymbolTable; } + StringRef getStringTable() const { return StringTable; } + uint32_t getNumberOfSymbols() const; + + std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { + return std::move(ThinBuffers); + } + +private: + StringRef SymbolTable; + StringRef StringTable; + + StringRef FirstRegularData; + uint16_t FirstRegularStartOfFile = -1; + void setFirstRegular(const Child &C); + + unsigned Format : 3; + unsigned IsThin : 1; + mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; +}; + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_ARCHIVE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h b/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h index a2c582c4804..777cf2f3337 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h +++ b/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h @@ -1,61 +1,61 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Declares the writeArchive function for writing an archive file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ARCHIVEWRITER_H -#define LLVM_OBJECT_ARCHIVEWRITER_H - -#include "llvm/Object/Archive.h" - -namespace llvm { - -struct NewArchiveMember { - std::unique_ptr<MemoryBuffer> Buf; - StringRef MemberName; - sys::TimePoint<std::chrono::seconds> ModTime; - unsigned UID = 0, GID = 0, Perms = 0644; - - NewArchiveMember() = default; - NewArchiveMember(MemoryBufferRef BufRef); - - static Expected<NewArchiveMember> - getOldMember(const object::Archive::Child &OldMember, bool Deterministic); - - static Expected<NewArchiveMember> getFile(StringRef FileName, - bool Deterministic); -}; - -Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To); - -Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, - bool Deterministic, bool Thin, - std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr); +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Declares the writeArchive function for writing an archive file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ARCHIVEWRITER_H +#define LLVM_OBJECT_ARCHIVEWRITER_H + +#include "llvm/Object/Archive.h" + +namespace llvm { + +struct NewArchiveMember { + std::unique_ptr<MemoryBuffer> Buf; + StringRef MemberName; + sys::TimePoint<std::chrono::seconds> ModTime; + unsigned UID = 0, GID = 0, Perms = 0644; + + NewArchiveMember() = default; + NewArchiveMember(MemoryBufferRef BufRef); + + static Expected<NewArchiveMember> + getOldMember(const object::Archive::Child &OldMember, bool Deterministic); + + static Expected<NewArchiveMember> getFile(StringRef FileName, + bool Deterministic); +}; + +Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To); + +Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin, + std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr); // writeArchiveToBuffer is similar to writeArchive but returns the Archive in a // buffer instead of writing it out to a file. Expected<std::unique_ptr<MemoryBuffer>> writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin); -} - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/Binary.h b/contrib/libs/llvm12/include/llvm/Object/Binary.h index 0b1ee8456bb..cc0ce62f6d2 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Binary.h +++ b/contrib/libs/llvm12/include/llvm/Object/Binary.h @@ -1,253 +1,253 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Binary.h - A generic binary file -------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the Binary class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_BINARY_H -#define LLVM_OBJECT_BINARY_H - -#include "llvm-c/Types.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Object/Error.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include <algorithm> -#include <memory> -#include <utility> - -namespace llvm { - -class LLVMContext; -class StringRef; - -namespace object { - -class Binary { -private: - unsigned int TypeID; - -protected: - MemoryBufferRef Data; - - Binary(unsigned int Type, MemoryBufferRef Source); - - enum { - ID_Archive, - ID_MachOUniversalBinary, - ID_COFFImportFile, - ID_IR, // LLVM IR - ID_TapiUniversal, // Text-based Dynamic Library Stub file. - ID_TapiFile, // Text-based Dynamic Library Stub file. - - ID_Minidump, - - ID_WinRes, // Windows resource (.res) file. - - // Object and children. - ID_StartObjects, - ID_COFF, - - ID_XCOFF32, // AIX XCOFF 32-bit - ID_XCOFF64, // AIX XCOFF 64-bit - - ID_ELF32L, // ELF 32-bit, little endian - ID_ELF32B, // ELF 32-bit, big endian - ID_ELF64L, // ELF 64-bit, little endian - ID_ELF64B, // ELF 64-bit, big endian - - ID_MachO32L, // MachO 32-bit, little endian - ID_MachO32B, // MachO 32-bit, big endian - ID_MachO64L, // MachO 64-bit, little endian - ID_MachO64B, // MachO 64-bit, big endian - - ID_Wasm, - - ID_EndObjects - }; - - static inline unsigned int getELFType(bool isLE, bool is64Bits) { - if (isLE) - return is64Bits ? ID_ELF64L : ID_ELF32L; - else - return is64Bits ? ID_ELF64B : ID_ELF32B; - } - - static unsigned int getMachOType(bool isLE, bool is64Bits) { - if (isLE) - return is64Bits ? ID_MachO64L : ID_MachO32L; - else - return is64Bits ? ID_MachO64B : ID_MachO32B; - } - -public: - Binary() = delete; - Binary(const Binary &other) = delete; - virtual ~Binary(); - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Binary.h - A generic binary file -------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the Binary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_BINARY_H +#define LLVM_OBJECT_BINARY_H + +#include "llvm-c/Types.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include <algorithm> +#include <memory> +#include <utility> + +namespace llvm { + +class LLVMContext; +class StringRef; + +namespace object { + +class Binary { +private: + unsigned int TypeID; + +protected: + MemoryBufferRef Data; + + Binary(unsigned int Type, MemoryBufferRef Source); + + enum { + ID_Archive, + ID_MachOUniversalBinary, + ID_COFFImportFile, + ID_IR, // LLVM IR + ID_TapiUniversal, // Text-based Dynamic Library Stub file. + ID_TapiFile, // Text-based Dynamic Library Stub file. + + ID_Minidump, + + ID_WinRes, // Windows resource (.res) file. + + // Object and children. + ID_StartObjects, + ID_COFF, + + ID_XCOFF32, // AIX XCOFF 32-bit + ID_XCOFF64, // AIX XCOFF 64-bit + + ID_ELF32L, // ELF 32-bit, little endian + ID_ELF32B, // ELF 32-bit, big endian + ID_ELF64L, // ELF 64-bit, little endian + ID_ELF64B, // ELF 64-bit, big endian + + ID_MachO32L, // MachO 32-bit, little endian + ID_MachO32B, // MachO 32-bit, big endian + ID_MachO64L, // MachO 64-bit, little endian + ID_MachO64B, // MachO 64-bit, big endian + + ID_Wasm, + + ID_EndObjects + }; + + static inline unsigned int getELFType(bool isLE, bool is64Bits) { + if (isLE) + return is64Bits ? ID_ELF64L : ID_ELF32L; + else + return is64Bits ? ID_ELF64B : ID_ELF32B; + } + + static unsigned int getMachOType(bool isLE, bool is64Bits) { + if (isLE) + return is64Bits ? ID_MachO64L : ID_MachO32L; + else + return is64Bits ? ID_MachO64B : ID_MachO32B; + } + +public: + Binary() = delete; + Binary(const Binary &other) = delete; + virtual ~Binary(); + virtual Error initContent() { return Error::success(); }; - StringRef getData() const; - StringRef getFileName() const; - MemoryBufferRef getMemoryBufferRef() const; - - // Cast methods. - unsigned int getType() const { return TypeID; } - - // Convenience methods - bool isObject() const { - return TypeID > ID_StartObjects && TypeID < ID_EndObjects; - } - - bool isSymbolic() const { - return isIR() || isObject() || isCOFFImportFile() || isTapiFile(); - } - - bool isArchive() const { return TypeID == ID_Archive; } - - bool isMachOUniversalBinary() const { - return TypeID == ID_MachOUniversalBinary; - } - - bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; } - - bool isELF() const { - return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B; - } - - bool isMachO() const { - return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B; - } - - bool isCOFF() const { - return TypeID == ID_COFF; - } - - bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; } - - bool isWasm() const { return TypeID == ID_Wasm; } - - bool isCOFFImportFile() const { - return TypeID == ID_COFFImportFile; - } - - bool isIR() const { - return TypeID == ID_IR; - } - - bool isMinidump() const { return TypeID == ID_Minidump; } - - bool isTapiFile() const { return TypeID == ID_TapiFile; } - - bool isLittleEndian() const { - return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || - TypeID == ID_MachO32B || TypeID == ID_MachO64B); - } - - bool isWinRes() const { return TypeID == ID_WinRes; } - - Triple::ObjectFormatType getTripleObjectFormat() const { - if (isCOFF()) - return Triple::COFF; - if (isMachO()) - return Triple::MachO; - if (isELF()) - return Triple::ELF; - return Triple::UnknownObjectFormat; - } - - static Error checkOffset(MemoryBufferRef M, uintptr_t Addr, - const uint64_t Size) { - if (Addr + Size < Addr || Addr + Size < Size || + StringRef getData() const; + StringRef getFileName() const; + MemoryBufferRef getMemoryBufferRef() const; + + // Cast methods. + unsigned int getType() const { return TypeID; } + + // Convenience methods + bool isObject() const { + return TypeID > ID_StartObjects && TypeID < ID_EndObjects; + } + + bool isSymbolic() const { + return isIR() || isObject() || isCOFFImportFile() || isTapiFile(); + } + + bool isArchive() const { return TypeID == ID_Archive; } + + bool isMachOUniversalBinary() const { + return TypeID == ID_MachOUniversalBinary; + } + + bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; } + + bool isELF() const { + return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B; + } + + bool isMachO() const { + return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B; + } + + bool isCOFF() const { + return TypeID == ID_COFF; + } + + bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; } + + bool isWasm() const { return TypeID == ID_Wasm; } + + bool isCOFFImportFile() const { + return TypeID == ID_COFFImportFile; + } + + bool isIR() const { + return TypeID == ID_IR; + } + + bool isMinidump() const { return TypeID == ID_Minidump; } + + bool isTapiFile() const { return TypeID == ID_TapiFile; } + + bool isLittleEndian() const { + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || + TypeID == ID_MachO32B || TypeID == ID_MachO64B); + } + + bool isWinRes() const { return TypeID == ID_WinRes; } + + Triple::ObjectFormatType getTripleObjectFormat() const { + if (isCOFF()) + return Triple::COFF; + if (isMachO()) + return Triple::MachO; + if (isELF()) + return Triple::ELF; + return Triple::UnknownObjectFormat; + } + + static Error checkOffset(MemoryBufferRef M, uintptr_t Addr, + const uint64_t Size) { + if (Addr + Size < Addr || Addr + Size < Size || Addr + Size > reinterpret_cast<uintptr_t>(M.getBufferEnd()) || Addr < reinterpret_cast<uintptr_t>(M.getBufferStart())) { - return errorCodeToError(object_error::unexpected_eof); - } - return Error::success(); - } -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef) - -/// Create a Binary from Source, autodetecting the file type. -/// -/// @param Source The data to create the Binary from. -Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, + return errorCodeToError(object_error::unexpected_eof); + } + return Error::success(); + } +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef) + +/// Create a Binary from Source, autodetecting the file type. +/// +/// @param Source The data to create the Binary from. +Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, LLVMContext *Context = nullptr, bool InitContent = true); - -template <typename T> class OwningBinary { - std::unique_ptr<T> Bin; - std::unique_ptr<MemoryBuffer> Buf; - -public: - OwningBinary(); - OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf); - OwningBinary(OwningBinary<T>&& Other); - OwningBinary<T> &operator=(OwningBinary<T> &&Other); - - std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary(); - - T* getBinary(); - const T* getBinary() const; -}; - -template <typename T> -OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin, - std::unique_ptr<MemoryBuffer> Buf) - : Bin(std::move(Bin)), Buf(std::move(Buf)) {} - -template <typename T> OwningBinary<T>::OwningBinary() = default; - -template <typename T> -OwningBinary<T>::OwningBinary(OwningBinary &&Other) - : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {} - -template <typename T> -OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) { - Bin = std::move(Other.Bin); - Buf = std::move(Other.Buf); - return *this; -} - -template <typename T> -std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> -OwningBinary<T>::takeBinary() { - return std::make_pair(std::move(Bin), std::move(Buf)); -} - -template <typename T> T* OwningBinary<T>::getBinary() { - return Bin.get(); -} - -template <typename T> const T* OwningBinary<T>::getBinary() const { - return Bin.get(); -} - + +template <typename T> class OwningBinary { + std::unique_ptr<T> Bin; + std::unique_ptr<MemoryBuffer> Buf; + +public: + OwningBinary(); + OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf); + OwningBinary(OwningBinary<T>&& Other); + OwningBinary<T> &operator=(OwningBinary<T> &&Other); + + std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary(); + + T* getBinary(); + const T* getBinary() const; +}; + +template <typename T> +OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin, + std::unique_ptr<MemoryBuffer> Buf) + : Bin(std::move(Bin)), Buf(std::move(Buf)) {} + +template <typename T> OwningBinary<T>::OwningBinary() = default; + +template <typename T> +OwningBinary<T>::OwningBinary(OwningBinary &&Other) + : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {} + +template <typename T> +OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) { + Bin = std::move(Other.Bin); + Buf = std::move(Other.Buf); + return *this; +} + +template <typename T> +std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> +OwningBinary<T>::takeBinary() { + return std::make_pair(std::move(Bin), std::move(Buf)); +} + +template <typename T> T* OwningBinary<T>::getBinary() { + return Bin.get(); +} + +template <typename T> const T* OwningBinary<T>::getBinary() const { + return Bin.get(); +} + Expected<OwningBinary<Binary>> createBinary(StringRef Path, LLVMContext *Context = nullptr, bool InitContent = true); - -} // end namespace object - -} // end namespace llvm - -#endif // LLVM_OBJECT_BINARY_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + +} // end namespace object + +} // end namespace llvm + +#endif // LLVM_OBJECT_BINARY_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/COFF.h b/contrib/libs/llvm12/include/llvm/Object/COFF.h index 816a078cfcd..3b7fbb1a991 100644 --- a/contrib/libs/llvm12/include/llvm/Object/COFF.h +++ b/contrib/libs/llvm12/include/llvm/Object/COFF.h @@ -1,593 +1,593 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the COFFObjectFile class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_COFF_H -#define LLVM_OBJECT_COFF_H - -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/CVDebugRecord.h" -#include "llvm/Object/Error.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/ErrorHandling.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <system_error> - -namespace llvm { - -template <typename T> class ArrayRef; - -namespace object { - -class BaseRelocRef; -class DelayImportDirectoryEntryRef; -class ExportDirectoryEntryRef; -class ImportDirectoryEntryRef; -class ImportedSymbolRef; -class ResourceSectionRef; - -using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; -using delay_import_directory_iterator = - content_iterator<DelayImportDirectoryEntryRef>; -using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>; -using imported_symbol_iterator = content_iterator<ImportedSymbolRef>; -using base_reloc_iterator = content_iterator<BaseRelocRef>; - -/// The DOS compatible header at the front of all PE/COFF executables. -struct dos_header { - char Magic[2]; - support::ulittle16_t UsedBytesInTheLastPage; - support::ulittle16_t FileSizeInPages; - support::ulittle16_t NumberOfRelocationItems; - support::ulittle16_t HeaderSizeInParagraphs; - support::ulittle16_t MinimumExtraParagraphs; - support::ulittle16_t MaximumExtraParagraphs; - support::ulittle16_t InitialRelativeSS; - support::ulittle16_t InitialSP; - support::ulittle16_t Checksum; - support::ulittle16_t InitialIP; - support::ulittle16_t InitialRelativeCS; - support::ulittle16_t AddressOfRelocationTable; - support::ulittle16_t OverlayNumber; - support::ulittle16_t Reserved[4]; - support::ulittle16_t OEMid; - support::ulittle16_t OEMinfo; - support::ulittle16_t Reserved2[10]; - support::ulittle32_t AddressOfNewExeHeader; -}; - -struct coff_file_header { - support::ulittle16_t Machine; - support::ulittle16_t NumberOfSections; - support::ulittle32_t TimeDateStamp; - support::ulittle32_t PointerToSymbolTable; - support::ulittle32_t NumberOfSymbols; - support::ulittle16_t SizeOfOptionalHeader; - support::ulittle16_t Characteristics; - - bool isImportLibrary() const { return NumberOfSections == 0xffff; } -}; - -struct coff_bigobj_file_header { - support::ulittle16_t Sig1; - support::ulittle16_t Sig2; - support::ulittle16_t Version; - support::ulittle16_t Machine; - support::ulittle32_t TimeDateStamp; - uint8_t UUID[16]; - support::ulittle32_t unused1; - support::ulittle32_t unused2; - support::ulittle32_t unused3; - support::ulittle32_t unused4; - support::ulittle32_t NumberOfSections; - support::ulittle32_t PointerToSymbolTable; - support::ulittle32_t NumberOfSymbols; -}; - -/// The 32-bit PE header that follows the COFF header. -struct pe32_header { - support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; - support::ulittle32_t SizeOfCode; - support::ulittle32_t SizeOfInitializedData; - support::ulittle32_t SizeOfUninitializedData; - support::ulittle32_t AddressOfEntryPoint; - support::ulittle32_t BaseOfCode; - support::ulittle32_t BaseOfData; - support::ulittle32_t ImageBase; - support::ulittle32_t SectionAlignment; - support::ulittle32_t FileAlignment; - support::ulittle16_t MajorOperatingSystemVersion; - support::ulittle16_t MinorOperatingSystemVersion; - support::ulittle16_t MajorImageVersion; - support::ulittle16_t MinorImageVersion; - support::ulittle16_t MajorSubsystemVersion; - support::ulittle16_t MinorSubsystemVersion; - support::ulittle32_t Win32VersionValue; - support::ulittle32_t SizeOfImage; - support::ulittle32_t SizeOfHeaders; - support::ulittle32_t CheckSum; - support::ulittle16_t Subsystem; - // FIXME: This should be DllCharacteristics. - support::ulittle16_t DLLCharacteristics; - support::ulittle32_t SizeOfStackReserve; - support::ulittle32_t SizeOfStackCommit; - support::ulittle32_t SizeOfHeapReserve; - support::ulittle32_t SizeOfHeapCommit; - support::ulittle32_t LoaderFlags; - // FIXME: This should be NumberOfRvaAndSizes. - support::ulittle32_t NumberOfRvaAndSize; -}; - -/// The 64-bit PE header that follows the COFF header. -struct pe32plus_header { - support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; - support::ulittle32_t SizeOfCode; - support::ulittle32_t SizeOfInitializedData; - support::ulittle32_t SizeOfUninitializedData; - support::ulittle32_t AddressOfEntryPoint; - support::ulittle32_t BaseOfCode; - support::ulittle64_t ImageBase; - support::ulittle32_t SectionAlignment; - support::ulittle32_t FileAlignment; - support::ulittle16_t MajorOperatingSystemVersion; - support::ulittle16_t MinorOperatingSystemVersion; - support::ulittle16_t MajorImageVersion; - support::ulittle16_t MinorImageVersion; - support::ulittle16_t MajorSubsystemVersion; - support::ulittle16_t MinorSubsystemVersion; - support::ulittle32_t Win32VersionValue; - support::ulittle32_t SizeOfImage; - support::ulittle32_t SizeOfHeaders; - support::ulittle32_t CheckSum; - support::ulittle16_t Subsystem; - support::ulittle16_t DLLCharacteristics; - support::ulittle64_t SizeOfStackReserve; - support::ulittle64_t SizeOfStackCommit; - support::ulittle64_t SizeOfHeapReserve; - support::ulittle64_t SizeOfHeapCommit; - support::ulittle32_t LoaderFlags; - support::ulittle32_t NumberOfRvaAndSize; -}; - -struct data_directory { - support::ulittle32_t RelativeVirtualAddress; - support::ulittle32_t Size; -}; - -struct debug_directory { - support::ulittle32_t Characteristics; - support::ulittle32_t TimeDateStamp; - support::ulittle16_t MajorVersion; - support::ulittle16_t MinorVersion; - support::ulittle32_t Type; - support::ulittle32_t SizeOfData; - support::ulittle32_t AddressOfRawData; - support::ulittle32_t PointerToRawData; -}; - -template <typename IntTy> -struct import_lookup_table_entry { - IntTy Data; - - bool isOrdinal() const { return Data < 0; } - - uint16_t getOrdinal() const { - assert(isOrdinal() && "ILT entry is not an ordinal!"); - return Data & 0xFFFF; - } - - uint32_t getHintNameRVA() const { - assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); - return Data & 0xFFFFFFFF; - } -}; - -using import_lookup_table_entry32 = - import_lookup_table_entry<support::little32_t>; -using import_lookup_table_entry64 = - import_lookup_table_entry<support::little64_t>; - -struct delay_import_directory_table_entry { - // dumpbin reports this field as "Characteristics" instead of "Attributes". - support::ulittle32_t Attributes; - support::ulittle32_t Name; - support::ulittle32_t ModuleHandle; - support::ulittle32_t DelayImportAddressTable; - support::ulittle32_t DelayImportNameTable; - support::ulittle32_t BoundDelayImportTable; - support::ulittle32_t UnloadDelayImportTable; - support::ulittle32_t TimeStamp; -}; - -struct export_directory_table_entry { - support::ulittle32_t ExportFlags; - support::ulittle32_t TimeDateStamp; - support::ulittle16_t MajorVersion; - support::ulittle16_t MinorVersion; - support::ulittle32_t NameRVA; - support::ulittle32_t OrdinalBase; - support::ulittle32_t AddressTableEntries; - support::ulittle32_t NumberOfNamePointers; - support::ulittle32_t ExportAddressTableRVA; - support::ulittle32_t NamePointerRVA; - support::ulittle32_t OrdinalTableRVA; -}; - -union export_address_table_entry { - support::ulittle32_t ExportRVA; - support::ulittle32_t ForwarderRVA; -}; - -using export_name_pointer_table_entry = support::ulittle32_t; -using export_ordinal_table_entry = support::ulittle16_t; - -struct StringTableOffset { - support::ulittle32_t Zeroes; - support::ulittle32_t Offset; -}; - -template <typename SectionNumberType> -struct coff_symbol { - union { - char ShortName[COFF::NameSize]; - StringTableOffset Offset; - } Name; - - support::ulittle32_t Value; - SectionNumberType SectionNumber; - - support::ulittle16_t Type; - - uint8_t StorageClass; - uint8_t NumberOfAuxSymbols; -}; - -using coff_symbol16 = coff_symbol<support::ulittle16_t>; -using coff_symbol32 = coff_symbol<support::ulittle32_t>; - -// Contains only common parts of coff_symbol16 and coff_symbol32. -struct coff_symbol_generic { - union { - char ShortName[COFF::NameSize]; - StringTableOffset Offset; - } Name; - support::ulittle32_t Value; -}; - -struct coff_aux_section_definition; -struct coff_aux_weak_external; - -class COFFSymbolRef { -public: - COFFSymbolRef() = default; - COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} - COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} - - const void *getRawPtr() const { - return CS16 ? static_cast<const void *>(CS16) : CS32; - } - - const coff_symbol_generic *getGeneric() const { - if (CS16) - return reinterpret_cast<const coff_symbol_generic *>(CS16); - return reinterpret_cast<const coff_symbol_generic *>(CS32); - } - - friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { - return A.getRawPtr() < B.getRawPtr(); - } - - bool isBigObj() const { - if (CS16) - return false; - if (CS32) - return true; - llvm_unreachable("COFFSymbolRef points to nothing!"); - } - - const char *getShortName() const { - return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; - } - - const StringTableOffset &getStringTableOffset() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - return CS16 ? CS16->Name.Offset : CS32->Name.Offset; - } - - uint32_t getValue() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - return CS16 ? CS16->Value : CS32->Value; - } - - int32_t getSectionNumber() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - if (CS16) { - // Reserved sections are returned as negative numbers. - if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) - return CS16->SectionNumber; - return static_cast<int16_t>(CS16->SectionNumber); - } - return static_cast<int32_t>(CS32->SectionNumber); - } - - uint16_t getType() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - return CS16 ? CS16->Type : CS32->Type; - } - - uint8_t getStorageClass() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - return CS16 ? CS16->StorageClass : CS32->StorageClass; - } - - uint8_t getNumberOfAuxSymbols() const { - assert(isSet() && "COFFSymbolRef points to nothing!"); - return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; - } - - uint8_t getBaseType() const { return getType() & 0x0F; } - - uint8_t getComplexType() const { - return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; - } - - template <typename T> const T *getAux() const { - return CS16 ? reinterpret_cast<const T *>(CS16 + 1) - : reinterpret_cast<const T *>(CS32 + 1); - } - - const coff_aux_section_definition *getSectionDefinition() const { - if (!getNumberOfAuxSymbols() || - getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) - return nullptr; - return getAux<coff_aux_section_definition>(); - } - - const coff_aux_weak_external *getWeakExternal() const { - if (!getNumberOfAuxSymbols() || - getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) - return nullptr; - return getAux<coff_aux_weak_external>(); - } - - bool isAbsolute() const { - return getSectionNumber() == -1; - } - - bool isExternal() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; - } - - bool isCommon() const { - return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && - getValue() != 0; - } - - bool isUndefined() const { - return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && - getValue() == 0; - } - - bool isWeakExternal() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - } - - bool isFunctionDefinition() const { - return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && - getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && - !COFF::isReservedSectionNumber(getSectionNumber()); - } - - bool isFunctionLineInfo() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; - } - - bool isAnyUndefined() const { - return isUndefined() || isWeakExternal(); - } - - bool isFileRecord() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; - } - - bool isSection() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; - } - - bool isSectionDefinition() const { - // C++/CLI creates external ABS symbols for non-const appdomain globals. - // These are also followed by an auxiliary section definition. - bool isAppdomainGlobal = - getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && - getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; - bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; - if (!getNumberOfAuxSymbols()) - return false; - return isAppdomainGlobal || isOrdinarySection; - } - - bool isCLRToken() const { - return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; - } - -private: - bool isSet() const { return CS16 || CS32; } - - const coff_symbol16 *CS16 = nullptr; - const coff_symbol32 *CS32 = nullptr; -}; - -struct coff_section { - char Name[COFF::NameSize]; - support::ulittle32_t VirtualSize; - support::ulittle32_t VirtualAddress; - support::ulittle32_t SizeOfRawData; - support::ulittle32_t PointerToRawData; - support::ulittle32_t PointerToRelocations; - support::ulittle32_t PointerToLinenumbers; - support::ulittle16_t NumberOfRelocations; - support::ulittle16_t NumberOfLinenumbers; - support::ulittle32_t Characteristics; - - // Returns true if the actual number of relocations is stored in - // VirtualAddress field of the first relocation table entry. - bool hasExtendedRelocations() const { - return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && - NumberOfRelocations == UINT16_MAX; - } - - uint32_t getAlignment() const { - // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to - // IMAGE_SCN_ALIGN_1BYTES. - if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) - return 1; - - // Bit [20:24] contains section alignment. 0 means use a default alignment - // of 16. - uint32_t Shift = (Characteristics >> 20) & 0xF; - if (Shift > 0) - return 1U << (Shift - 1); - return 16; - } -}; - -struct coff_relocation { - support::ulittle32_t VirtualAddress; - support::ulittle32_t SymbolTableIndex; - support::ulittle16_t Type; -}; - -struct coff_aux_function_definition { - support::ulittle32_t TagIndex; - support::ulittle32_t TotalSize; - support::ulittle32_t PointerToLinenumber; - support::ulittle32_t PointerToNextFunction; - char Unused1[2]; -}; - -static_assert(sizeof(coff_aux_function_definition) == 18, - "auxiliary entry must be 18 bytes"); - -struct coff_aux_bf_and_ef_symbol { - char Unused1[4]; - support::ulittle16_t Linenumber; - char Unused2[6]; - support::ulittle32_t PointerToNextFunction; - char Unused3[2]; -}; - -static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, - "auxiliary entry must be 18 bytes"); - -struct coff_aux_weak_external { - support::ulittle32_t TagIndex; - support::ulittle32_t Characteristics; - char Unused1[10]; -}; - -static_assert(sizeof(coff_aux_weak_external) == 18, - "auxiliary entry must be 18 bytes"); - -struct coff_aux_section_definition { - support::ulittle32_t Length; - support::ulittle16_t NumberOfRelocations; - support::ulittle16_t NumberOfLinenumbers; - support::ulittle32_t CheckSum; - support::ulittle16_t NumberLowPart; - uint8_t Selection; - uint8_t Unused; - support::ulittle16_t NumberHighPart; - int32_t getNumber(bool IsBigObj) const { - uint32_t Number = static_cast<uint32_t>(NumberLowPart); - if (IsBigObj) - Number |= static_cast<uint32_t>(NumberHighPart) << 16; - return static_cast<int32_t>(Number); - } -}; - -static_assert(sizeof(coff_aux_section_definition) == 18, - "auxiliary entry must be 18 bytes"); - -struct coff_aux_clr_token { - uint8_t AuxType; - uint8_t Reserved; - support::ulittle32_t SymbolTableIndex; - char MBZ[12]; -}; - -static_assert(sizeof(coff_aux_clr_token) == 18, - "auxiliary entry must be 18 bytes"); - -struct coff_import_header { - support::ulittle16_t Sig1; - support::ulittle16_t Sig2; - support::ulittle16_t Version; - support::ulittle16_t Machine; - support::ulittle32_t TimeDateStamp; - support::ulittle32_t SizeOfData; - support::ulittle16_t OrdinalHint; - support::ulittle16_t TypeInfo; - - int getType() const { return TypeInfo & 0x3; } - int getNameType() const { return (TypeInfo >> 2) & 0x7; } -}; - -struct coff_import_directory_table_entry { - support::ulittle32_t ImportLookupTableRVA; - support::ulittle32_t TimeDateStamp; - support::ulittle32_t ForwarderChain; - support::ulittle32_t NameRVA; - support::ulittle32_t ImportAddressTableRVA; - - bool isNull() const { - return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && - ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; - } -}; - -template <typename IntTy> -struct coff_tls_directory { - IntTy StartAddressOfRawData; - IntTy EndAddressOfRawData; - IntTy AddressOfIndex; - IntTy AddressOfCallBacks; - support::ulittle32_t SizeOfZeroFill; - support::ulittle32_t Characteristics; - - uint32_t getAlignment() const { - // Bit [20:24] contains section alignment. +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the COFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_H +#define LLVM_OBJECT_COFF_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/CVDebugRecord.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <system_error> + +namespace llvm { + +template <typename T> class ArrayRef; + +namespace object { + +class BaseRelocRef; +class DelayImportDirectoryEntryRef; +class ExportDirectoryEntryRef; +class ImportDirectoryEntryRef; +class ImportedSymbolRef; +class ResourceSectionRef; + +using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; +using delay_import_directory_iterator = + content_iterator<DelayImportDirectoryEntryRef>; +using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>; +using imported_symbol_iterator = content_iterator<ImportedSymbolRef>; +using base_reloc_iterator = content_iterator<BaseRelocRef>; + +/// The DOS compatible header at the front of all PE/COFF executables. +struct dos_header { + char Magic[2]; + support::ulittle16_t UsedBytesInTheLastPage; + support::ulittle16_t FileSizeInPages; + support::ulittle16_t NumberOfRelocationItems; + support::ulittle16_t HeaderSizeInParagraphs; + support::ulittle16_t MinimumExtraParagraphs; + support::ulittle16_t MaximumExtraParagraphs; + support::ulittle16_t InitialRelativeSS; + support::ulittle16_t InitialSP; + support::ulittle16_t Checksum; + support::ulittle16_t InitialIP; + support::ulittle16_t InitialRelativeCS; + support::ulittle16_t AddressOfRelocationTable; + support::ulittle16_t OverlayNumber; + support::ulittle16_t Reserved[4]; + support::ulittle16_t OEMid; + support::ulittle16_t OEMinfo; + support::ulittle16_t Reserved2[10]; + support::ulittle32_t AddressOfNewExeHeader; +}; + +struct coff_file_header { + support::ulittle16_t Machine; + support::ulittle16_t NumberOfSections; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; + support::ulittle16_t SizeOfOptionalHeader; + support::ulittle16_t Characteristics; + + bool isImportLibrary() const { return NumberOfSections == 0xffff; } +}; + +struct coff_bigobj_file_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + uint8_t UUID[16]; + support::ulittle32_t unused1; + support::ulittle32_t unused2; + support::ulittle32_t unused3; + support::ulittle32_t unused4; + support::ulittle32_t NumberOfSections; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; +}; + +/// The 32-bit PE header that follows the COFF header. +struct pe32_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle32_t BaseOfData; + support::ulittle32_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + // FIXME: This should be DllCharacteristics. + support::ulittle16_t DLLCharacteristics; + support::ulittle32_t SizeOfStackReserve; + support::ulittle32_t SizeOfStackCommit; + support::ulittle32_t SizeOfHeapReserve; + support::ulittle32_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes. + support::ulittle32_t NumberOfRvaAndSize; +}; + +/// The 64-bit PE header that follows the COFF header. +struct pe32plus_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle64_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle64_t SizeOfStackReserve; + support::ulittle64_t SizeOfStackCommit; + support::ulittle64_t SizeOfHeapReserve; + support::ulittle64_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +struct data_directory { + support::ulittle32_t RelativeVirtualAddress; + support::ulittle32_t Size; +}; + +struct debug_directory { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t Type; + support::ulittle32_t SizeOfData; + support::ulittle32_t AddressOfRawData; + support::ulittle32_t PointerToRawData; +}; + +template <typename IntTy> +struct import_lookup_table_entry { + IntTy Data; + + bool isOrdinal() const { return Data < 0; } + + uint16_t getOrdinal() const { + assert(isOrdinal() && "ILT entry is not an ordinal!"); + return Data & 0xFFFF; + } + + uint32_t getHintNameRVA() const { + assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); + return Data & 0xFFFFFFFF; + } +}; + +using import_lookup_table_entry32 = + import_lookup_table_entry<support::little32_t>; +using import_lookup_table_entry64 = + import_lookup_table_entry<support::little64_t>; + +struct delay_import_directory_table_entry { + // dumpbin reports this field as "Characteristics" instead of "Attributes". + support::ulittle32_t Attributes; + support::ulittle32_t Name; + support::ulittle32_t ModuleHandle; + support::ulittle32_t DelayImportAddressTable; + support::ulittle32_t DelayImportNameTable; + support::ulittle32_t BoundDelayImportTable; + support::ulittle32_t UnloadDelayImportTable; + support::ulittle32_t TimeStamp; +}; + +struct export_directory_table_entry { + support::ulittle32_t ExportFlags; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t NameRVA; + support::ulittle32_t OrdinalBase; + support::ulittle32_t AddressTableEntries; + support::ulittle32_t NumberOfNamePointers; + support::ulittle32_t ExportAddressTableRVA; + support::ulittle32_t NamePointerRVA; + support::ulittle32_t OrdinalTableRVA; +}; + +union export_address_table_entry { + support::ulittle32_t ExportRVA; + support::ulittle32_t ForwarderRVA; +}; + +using export_name_pointer_table_entry = support::ulittle32_t; +using export_ordinal_table_entry = support::ulittle16_t; + +struct StringTableOffset { + support::ulittle32_t Zeroes; + support::ulittle32_t Offset; +}; + +template <typename SectionNumberType> +struct coff_symbol { + union { + char ShortName[COFF::NameSize]; + StringTableOffset Offset; + } Name; + + support::ulittle32_t Value; + SectionNumberType SectionNumber; + + support::ulittle16_t Type; + + uint8_t StorageClass; + uint8_t NumberOfAuxSymbols; +}; + +using coff_symbol16 = coff_symbol<support::ulittle16_t>; +using coff_symbol32 = coff_symbol<support::ulittle32_t>; + +// Contains only common parts of coff_symbol16 and coff_symbol32. +struct coff_symbol_generic { + union { + char ShortName[COFF::NameSize]; + StringTableOffset Offset; + } Name; + support::ulittle32_t Value; +}; + +struct coff_aux_section_definition; +struct coff_aux_weak_external; + +class COFFSymbolRef { +public: + COFFSymbolRef() = default; + COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} + COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} + + const void *getRawPtr() const { + return CS16 ? static_cast<const void *>(CS16) : CS32; + } + + const coff_symbol_generic *getGeneric() const { + if (CS16) + return reinterpret_cast<const coff_symbol_generic *>(CS16); + return reinterpret_cast<const coff_symbol_generic *>(CS32); + } + + friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { + return A.getRawPtr() < B.getRawPtr(); + } + + bool isBigObj() const { + if (CS16) + return false; + if (CS32) + return true; + llvm_unreachable("COFFSymbolRef points to nothing!"); + } + + const char *getShortName() const { + return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; + } + + const StringTableOffset &getStringTableOffset() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Name.Offset : CS32->Name.Offset; + } + + uint32_t getValue() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Value : CS32->Value; + } + + int32_t getSectionNumber() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + if (CS16) { + // Reserved sections are returned as negative numbers. + if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) + return CS16->SectionNumber; + return static_cast<int16_t>(CS16->SectionNumber); + } + return static_cast<int32_t>(CS32->SectionNumber); + } + + uint16_t getType() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Type : CS32->Type; + } + + uint8_t getStorageClass() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->StorageClass : CS32->StorageClass; + } + + uint8_t getNumberOfAuxSymbols() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; + } + + uint8_t getBaseType() const { return getType() & 0x0F; } + + uint8_t getComplexType() const { + return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; + } + + template <typename T> const T *getAux() const { + return CS16 ? reinterpret_cast<const T *>(CS16 + 1) + : reinterpret_cast<const T *>(CS32 + 1); + } + + const coff_aux_section_definition *getSectionDefinition() const { + if (!getNumberOfAuxSymbols() || + getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) + return nullptr; + return getAux<coff_aux_section_definition>(); + } + + const coff_aux_weak_external *getWeakExternal() const { + if (!getNumberOfAuxSymbols() || + getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + return nullptr; + return getAux<coff_aux_weak_external>(); + } + + bool isAbsolute() const { + return getSectionNumber() == -1; + } + + bool isExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; + } + + bool isCommon() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() != 0; + } + + bool isUndefined() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() == 0; + } + + bool isWeakExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + } + + bool isFunctionDefinition() const { + return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && + !COFF::isReservedSectionNumber(getSectionNumber()); + } + + bool isFunctionLineInfo() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; + } + + bool isAnyUndefined() const { + return isUndefined() || isWeakExternal(); + } + + bool isFileRecord() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; + } + + bool isSection() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; + } + + bool isSectionDefinition() const { + // C++/CLI creates external ABS symbols for non-const appdomain globals. + // These are also followed by an auxiliary section definition. + bool isAppdomainGlobal = + getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; + if (!getNumberOfAuxSymbols()) + return false; + return isAppdomainGlobal || isOrdinarySection; + } + + bool isCLRToken() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; + } + +private: + bool isSet() const { return CS16 || CS32; } + + const coff_symbol16 *CS16 = nullptr; + const coff_symbol32 *CS32 = nullptr; +}; + +struct coff_section { + char Name[COFF::NameSize]; + support::ulittle32_t VirtualSize; + support::ulittle32_t VirtualAddress; + support::ulittle32_t SizeOfRawData; + support::ulittle32_t PointerToRawData; + support::ulittle32_t PointerToRelocations; + support::ulittle32_t PointerToLinenumbers; + support::ulittle16_t NumberOfRelocations; + support::ulittle16_t NumberOfLinenumbers; + support::ulittle32_t Characteristics; + + // Returns true if the actual number of relocations is stored in + // VirtualAddress field of the first relocation table entry. + bool hasExtendedRelocations() const { + return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && + NumberOfRelocations == UINT16_MAX; + } + + uint32_t getAlignment() const { + // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to + // IMAGE_SCN_ALIGN_1BYTES. + if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) + return 1; + + // Bit [20:24] contains section alignment. 0 means use a default alignment + // of 16. + uint32_t Shift = (Characteristics >> 20) & 0xF; + if (Shift > 0) + return 1U << (Shift - 1); + return 16; + } +}; + +struct coff_relocation { + support::ulittle32_t VirtualAddress; + support::ulittle32_t SymbolTableIndex; + support::ulittle16_t Type; +}; + +struct coff_aux_function_definition { + support::ulittle32_t TagIndex; + support::ulittle32_t TotalSize; + support::ulittle32_t PointerToLinenumber; + support::ulittle32_t PointerToNextFunction; + char Unused1[2]; +}; + +static_assert(sizeof(coff_aux_function_definition) == 18, + "auxiliary entry must be 18 bytes"); + +struct coff_aux_bf_and_ef_symbol { + char Unused1[4]; + support::ulittle16_t Linenumber; + char Unused2[6]; + support::ulittle32_t PointerToNextFunction; + char Unused3[2]; +}; + +static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, + "auxiliary entry must be 18 bytes"); + +struct coff_aux_weak_external { + support::ulittle32_t TagIndex; + support::ulittle32_t Characteristics; + char Unused1[10]; +}; + +static_assert(sizeof(coff_aux_weak_external) == 18, + "auxiliary entry must be 18 bytes"); + +struct coff_aux_section_definition { + support::ulittle32_t Length; + support::ulittle16_t NumberOfRelocations; + support::ulittle16_t NumberOfLinenumbers; + support::ulittle32_t CheckSum; + support::ulittle16_t NumberLowPart; + uint8_t Selection; + uint8_t Unused; + support::ulittle16_t NumberHighPart; + int32_t getNumber(bool IsBigObj) const { + uint32_t Number = static_cast<uint32_t>(NumberLowPart); + if (IsBigObj) + Number |= static_cast<uint32_t>(NumberHighPart) << 16; + return static_cast<int32_t>(Number); + } +}; + +static_assert(sizeof(coff_aux_section_definition) == 18, + "auxiliary entry must be 18 bytes"); + +struct coff_aux_clr_token { + uint8_t AuxType; + uint8_t Reserved; + support::ulittle32_t SymbolTableIndex; + char MBZ[12]; +}; + +static_assert(sizeof(coff_aux_clr_token) == 18, + "auxiliary entry must be 18 bytes"); + +struct coff_import_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t SizeOfData; + support::ulittle16_t OrdinalHint; + support::ulittle16_t TypeInfo; + + int getType() const { return TypeInfo & 0x3; } + int getNameType() const { return (TypeInfo >> 2) & 0x7; } +}; + +struct coff_import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; + + bool isNull() const { + return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && + ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; + } +}; + +template <typename IntTy> +struct coff_tls_directory { + IntTy StartAddressOfRawData; + IntTy EndAddressOfRawData; + IntTy AddressOfIndex; + IntTy AddressOfCallBacks; + support::ulittle32_t SizeOfZeroFill; + support::ulittle32_t Characteristics; + + uint32_t getAlignment() const { + // Bit [20:24] contains section alignment. uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20; - if (Shift > 0) - return 1U << (Shift - 1); - return 0; - } + if (Shift > 0) + return 1U << (Shift - 1); + return 0; + } void setAlignment(uint32_t Align) { uint32_t AlignBits = 0; @@ -599,404 +599,404 @@ struct coff_tls_directory { Characteristics = (Characteristics & ~COFF::IMAGE_SCN_ALIGN_MASK) | AlignBits; } -}; - -using coff_tls_directory32 = coff_tls_directory<support::little32_t>; -using coff_tls_directory64 = coff_tls_directory<support::little64_t>; - -/// Bits in control flow guard flags as we understand them. -enum class coff_guard_flags : uint32_t { - CFInstrumented = 0x00000100, - HasFidTable = 0x00000400, - ProtectDelayLoadIAT = 0x00001000, - DelayLoadIATSection = 0x00002000, // Delay load in separate section - HasLongJmpTable = 0x00010000, - FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes -}; - -enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 }; - -struct coff_load_config_code_integrity { - support::ulittle16_t Flags; - support::ulittle16_t Catalog; - support::ulittle32_t CatalogOffset; - support::ulittle32_t Reserved; -}; - -/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) -struct coff_load_configuration32 { - support::ulittle32_t Size; - support::ulittle32_t TimeDateStamp; - support::ulittle16_t MajorVersion; - support::ulittle16_t MinorVersion; - support::ulittle32_t GlobalFlagsClear; - support::ulittle32_t GlobalFlagsSet; - support::ulittle32_t CriticalSectionDefaultTimeout; - support::ulittle32_t DeCommitFreeBlockThreshold; - support::ulittle32_t DeCommitTotalFreeThreshold; - support::ulittle32_t LockPrefixTable; - support::ulittle32_t MaximumAllocationSize; - support::ulittle32_t VirtualMemoryThreshold; - support::ulittle32_t ProcessAffinityMask; - support::ulittle32_t ProcessHeapFlags; - support::ulittle16_t CSDVersion; - support::ulittle16_t DependentLoadFlags; - support::ulittle32_t EditList; - support::ulittle32_t SecurityCookie; - support::ulittle32_t SEHandlerTable; - support::ulittle32_t SEHandlerCount; - - // Added in MSVC 2015 for /guard:cf. - support::ulittle32_t GuardCFCheckFunction; - support::ulittle32_t GuardCFCheckDispatch; - support::ulittle32_t GuardCFFunctionTable; - support::ulittle32_t GuardCFFunctionCount; - support::ulittle32_t GuardFlags; // coff_guard_flags - - // Added in MSVC 2017 - coff_load_config_code_integrity CodeIntegrity; - support::ulittle32_t GuardAddressTakenIatEntryTable; - support::ulittle32_t GuardAddressTakenIatEntryCount; - support::ulittle32_t GuardLongJumpTargetTable; - support::ulittle32_t GuardLongJumpTargetCount; - support::ulittle32_t DynamicValueRelocTable; - support::ulittle32_t CHPEMetadataPointer; - support::ulittle32_t GuardRFFailureRoutine; - support::ulittle32_t GuardRFFailureRoutineFunctionPointer; - support::ulittle32_t DynamicValueRelocTableOffset; - support::ulittle16_t DynamicValueRelocTableSection; - support::ulittle16_t Reserved2; - support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; - support::ulittle32_t HotPatchTableOffset; -}; - -/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) -struct coff_load_configuration64 { - support::ulittle32_t Size; - support::ulittle32_t TimeDateStamp; - support::ulittle16_t MajorVersion; - support::ulittle16_t MinorVersion; - support::ulittle32_t GlobalFlagsClear; - support::ulittle32_t GlobalFlagsSet; - support::ulittle32_t CriticalSectionDefaultTimeout; - support::ulittle64_t DeCommitFreeBlockThreshold; - support::ulittle64_t DeCommitTotalFreeThreshold; - support::ulittle64_t LockPrefixTable; - support::ulittle64_t MaximumAllocationSize; - support::ulittle64_t VirtualMemoryThreshold; - support::ulittle64_t ProcessAffinityMask; - support::ulittle32_t ProcessHeapFlags; - support::ulittle16_t CSDVersion; - support::ulittle16_t DependentLoadFlags; - support::ulittle64_t EditList; - support::ulittle64_t SecurityCookie; - support::ulittle64_t SEHandlerTable; - support::ulittle64_t SEHandlerCount; - - // Added in MSVC 2015 for /guard:cf. - support::ulittle64_t GuardCFCheckFunction; - support::ulittle64_t GuardCFCheckDispatch; - support::ulittle64_t GuardCFFunctionTable; - support::ulittle64_t GuardCFFunctionCount; - support::ulittle32_t GuardFlags; - - // Added in MSVC 2017 - coff_load_config_code_integrity CodeIntegrity; - support::ulittle64_t GuardAddressTakenIatEntryTable; - support::ulittle64_t GuardAddressTakenIatEntryCount; - support::ulittle64_t GuardLongJumpTargetTable; - support::ulittle64_t GuardLongJumpTargetCount; - support::ulittle64_t DynamicValueRelocTable; - support::ulittle64_t CHPEMetadataPointer; - support::ulittle64_t GuardRFFailureRoutine; - support::ulittle64_t GuardRFFailureRoutineFunctionPointer; - support::ulittle32_t DynamicValueRelocTableOffset; - support::ulittle16_t DynamicValueRelocTableSection; - support::ulittle16_t Reserved2; - support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; - support::ulittle32_t HotPatchTableOffset; -}; - -struct coff_runtime_function_x64 { - support::ulittle32_t BeginAddress; - support::ulittle32_t EndAddress; - support::ulittle32_t UnwindInformation; -}; - -struct coff_base_reloc_block_header { - support::ulittle32_t PageRVA; - support::ulittle32_t BlockSize; -}; - -struct coff_base_reloc_block_entry { - support::ulittle16_t Data; - - int getType() const { return Data >> 12; } - int getOffset() const { return Data & ((1 << 12) - 1); } -}; - -struct coff_resource_dir_entry { - union { - support::ulittle32_t NameOffset; - support::ulittle32_t ID; - uint32_t getNameOffset() const { - return maskTrailingOnes<uint32_t>(31) & NameOffset; - } - // Even though the PE/COFF spec doesn't mention this, the high bit of a name - // offset is set. - void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } - } Identifier; - union { - support::ulittle32_t DataEntryOffset; - support::ulittle32_t SubdirOffset; - - bool isSubDir() const { return SubdirOffset >> 31; } - uint32_t value() const { - return maskTrailingOnes<uint32_t>(31) & SubdirOffset; - } - - } Offset; -}; - -struct coff_resource_data_entry { - support::ulittle32_t DataRVA; - support::ulittle32_t DataSize; - support::ulittle32_t Codepage; - support::ulittle32_t Reserved; -}; - -struct coff_resource_dir_table { - support::ulittle32_t Characteristics; - support::ulittle32_t TimeDateStamp; - support::ulittle16_t MajorVersion; - support::ulittle16_t MinorVersion; - support::ulittle16_t NumberOfNameEntries; - support::ulittle16_t NumberOfIDEntries; -}; - -struct debug_h_header { - support::ulittle32_t Magic; - support::ulittle16_t Version; - support::ulittle16_t HashAlgorithm; -}; - -class COFFObjectFile : public ObjectFile { -private: - COFFObjectFile(MemoryBufferRef Object); - - friend class ImportDirectoryEntryRef; - friend class ExportDirectoryEntryRef; - const coff_file_header *COFFHeader; - const coff_bigobj_file_header *COFFBigObjHeader; - const pe32_header *PE32Header; - const pe32plus_header *PE32PlusHeader; - const data_directory *DataDirectory; - const coff_section *SectionTable; - const coff_symbol16 *SymbolTable16; - const coff_symbol32 *SymbolTable32; - const char *StringTable; - uint32_t StringTableSize; - const coff_import_directory_table_entry *ImportDirectory; - const delay_import_directory_table_entry *DelayImportDirectory; - uint32_t NumberOfDelayImportDirectory; - const export_directory_table_entry *ExportDirectory; - const coff_base_reloc_block_header *BaseRelocHeader; - const coff_base_reloc_block_header *BaseRelocEnd; - const debug_directory *DebugDirectoryBegin; - const debug_directory *DebugDirectoryEnd; +}; + +using coff_tls_directory32 = coff_tls_directory<support::little32_t>; +using coff_tls_directory64 = coff_tls_directory<support::little64_t>; + +/// Bits in control flow guard flags as we understand them. +enum class coff_guard_flags : uint32_t { + CFInstrumented = 0x00000100, + HasFidTable = 0x00000400, + ProtectDelayLoadIAT = 0x00001000, + DelayLoadIATSection = 0x00002000, // Delay load in separate section + HasLongJmpTable = 0x00010000, + FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes +}; + +enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 }; + +struct coff_load_config_code_integrity { + support::ulittle16_t Flags; + support::ulittle16_t Catalog; + support::ulittle32_t CatalogOffset; + support::ulittle32_t Reserved; +}; + +/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) +struct coff_load_configuration32 { + support::ulittle32_t Size; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t GlobalFlagsClear; + support::ulittle32_t GlobalFlagsSet; + support::ulittle32_t CriticalSectionDefaultTimeout; + support::ulittle32_t DeCommitFreeBlockThreshold; + support::ulittle32_t DeCommitTotalFreeThreshold; + support::ulittle32_t LockPrefixTable; + support::ulittle32_t MaximumAllocationSize; + support::ulittle32_t VirtualMemoryThreshold; + support::ulittle32_t ProcessAffinityMask; + support::ulittle32_t ProcessHeapFlags; + support::ulittle16_t CSDVersion; + support::ulittle16_t DependentLoadFlags; + support::ulittle32_t EditList; + support::ulittle32_t SecurityCookie; + support::ulittle32_t SEHandlerTable; + support::ulittle32_t SEHandlerCount; + + // Added in MSVC 2015 for /guard:cf. + support::ulittle32_t GuardCFCheckFunction; + support::ulittle32_t GuardCFCheckDispatch; + support::ulittle32_t GuardCFFunctionTable; + support::ulittle32_t GuardCFFunctionCount; + support::ulittle32_t GuardFlags; // coff_guard_flags + + // Added in MSVC 2017 + coff_load_config_code_integrity CodeIntegrity; + support::ulittle32_t GuardAddressTakenIatEntryTable; + support::ulittle32_t GuardAddressTakenIatEntryCount; + support::ulittle32_t GuardLongJumpTargetTable; + support::ulittle32_t GuardLongJumpTargetCount; + support::ulittle32_t DynamicValueRelocTable; + support::ulittle32_t CHPEMetadataPointer; + support::ulittle32_t GuardRFFailureRoutine; + support::ulittle32_t GuardRFFailureRoutineFunctionPointer; + support::ulittle32_t DynamicValueRelocTableOffset; + support::ulittle16_t DynamicValueRelocTableSection; + support::ulittle16_t Reserved2; + support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; + support::ulittle32_t HotPatchTableOffset; +}; + +/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) +struct coff_load_configuration64 { + support::ulittle32_t Size; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t GlobalFlagsClear; + support::ulittle32_t GlobalFlagsSet; + support::ulittle32_t CriticalSectionDefaultTimeout; + support::ulittle64_t DeCommitFreeBlockThreshold; + support::ulittle64_t DeCommitTotalFreeThreshold; + support::ulittle64_t LockPrefixTable; + support::ulittle64_t MaximumAllocationSize; + support::ulittle64_t VirtualMemoryThreshold; + support::ulittle64_t ProcessAffinityMask; + support::ulittle32_t ProcessHeapFlags; + support::ulittle16_t CSDVersion; + support::ulittle16_t DependentLoadFlags; + support::ulittle64_t EditList; + support::ulittle64_t SecurityCookie; + support::ulittle64_t SEHandlerTable; + support::ulittle64_t SEHandlerCount; + + // Added in MSVC 2015 for /guard:cf. + support::ulittle64_t GuardCFCheckFunction; + support::ulittle64_t GuardCFCheckDispatch; + support::ulittle64_t GuardCFFunctionTable; + support::ulittle64_t GuardCFFunctionCount; + support::ulittle32_t GuardFlags; + + // Added in MSVC 2017 + coff_load_config_code_integrity CodeIntegrity; + support::ulittle64_t GuardAddressTakenIatEntryTable; + support::ulittle64_t GuardAddressTakenIatEntryCount; + support::ulittle64_t GuardLongJumpTargetTable; + support::ulittle64_t GuardLongJumpTargetCount; + support::ulittle64_t DynamicValueRelocTable; + support::ulittle64_t CHPEMetadataPointer; + support::ulittle64_t GuardRFFailureRoutine; + support::ulittle64_t GuardRFFailureRoutineFunctionPointer; + support::ulittle32_t DynamicValueRelocTableOffset; + support::ulittle16_t DynamicValueRelocTableSection; + support::ulittle16_t Reserved2; + support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; + support::ulittle32_t HotPatchTableOffset; +}; + +struct coff_runtime_function_x64 { + support::ulittle32_t BeginAddress; + support::ulittle32_t EndAddress; + support::ulittle32_t UnwindInformation; +}; + +struct coff_base_reloc_block_header { + support::ulittle32_t PageRVA; + support::ulittle32_t BlockSize; +}; + +struct coff_base_reloc_block_entry { + support::ulittle16_t Data; + + int getType() const { return Data >> 12; } + int getOffset() const { return Data & ((1 << 12) - 1); } +}; + +struct coff_resource_dir_entry { + union { + support::ulittle32_t NameOffset; + support::ulittle32_t ID; + uint32_t getNameOffset() const { + return maskTrailingOnes<uint32_t>(31) & NameOffset; + } + // Even though the PE/COFF spec doesn't mention this, the high bit of a name + // offset is set. + void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } + } Identifier; + union { + support::ulittle32_t DataEntryOffset; + support::ulittle32_t SubdirOffset; + + bool isSubDir() const { return SubdirOffset >> 31; } + uint32_t value() const { + return maskTrailingOnes<uint32_t>(31) & SubdirOffset; + } + + } Offset; +}; + +struct coff_resource_data_entry { + support::ulittle32_t DataRVA; + support::ulittle32_t DataSize; + support::ulittle32_t Codepage; + support::ulittle32_t Reserved; +}; + +struct coff_resource_dir_table { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle16_t NumberOfNameEntries; + support::ulittle16_t NumberOfIDEntries; +}; + +struct debug_h_header { + support::ulittle32_t Magic; + support::ulittle16_t Version; + support::ulittle16_t HashAlgorithm; +}; + +class COFFObjectFile : public ObjectFile { +private: + COFFObjectFile(MemoryBufferRef Object); + + friend class ImportDirectoryEntryRef; + friend class ExportDirectoryEntryRef; + const coff_file_header *COFFHeader; + const coff_bigobj_file_header *COFFBigObjHeader; + const pe32_header *PE32Header; + const pe32plus_header *PE32PlusHeader; + const data_directory *DataDirectory; + const coff_section *SectionTable; + const coff_symbol16 *SymbolTable16; + const coff_symbol32 *SymbolTable32; + const char *StringTable; + uint32_t StringTableSize; + const coff_import_directory_table_entry *ImportDirectory; + const delay_import_directory_table_entry *DelayImportDirectory; + uint32_t NumberOfDelayImportDirectory; + const export_directory_table_entry *ExportDirectory; + const coff_base_reloc_block_header *BaseRelocHeader; + const coff_base_reloc_block_header *BaseRelocEnd; + const debug_directory *DebugDirectoryBegin; + const debug_directory *DebugDirectoryEnd; const coff_tls_directory32 *TLSDirectory32; const coff_tls_directory64 *TLSDirectory64; - // Either coff_load_configuration32 or coff_load_configuration64. - const void *LoadConfig = nullptr; - - Expected<StringRef> getString(uint32_t offset) const; - - template <typename coff_symbol_type> - const coff_symbol_type *toSymb(DataRefImpl Symb) const; - const coff_section *toSec(DataRefImpl Sec) const; - const coff_relocation *toRel(DataRefImpl Rel) const; - - // Finish initializing the object and return success or an error. - Error initialize(); - - Error initSymbolTablePtr(); - Error initImportTablePtr(); - Error initDelayImportTablePtr(); - Error initExportTablePtr(); - Error initBaseRelocPtr(); - Error initDebugDirectoryPtr(); + // Either coff_load_configuration32 or coff_load_configuration64. + const void *LoadConfig = nullptr; + + Expected<StringRef> getString(uint32_t offset) const; + + template <typename coff_symbol_type> + const coff_symbol_type *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) const; + const coff_relocation *toRel(DataRefImpl Rel) const; + + // Finish initializing the object and return success or an error. + Error initialize(); + + Error initSymbolTablePtr(); + Error initImportTablePtr(); + Error initDelayImportTablePtr(); + Error initExportTablePtr(); + Error initBaseRelocPtr(); + Error initDebugDirectoryPtr(); Error initTLSDirectoryPtr(); - Error initLoadConfigPtr(); - -public: - static Expected<std::unique_ptr<COFFObjectFile>> - create(MemoryBufferRef Object); - - uintptr_t getSymbolTable() const { - if (SymbolTable16) - return reinterpret_cast<uintptr_t>(SymbolTable16); - if (SymbolTable32) - return reinterpret_cast<uintptr_t>(SymbolTable32); - return uintptr_t(0); - } - - uint16_t getMachine() const { - if (COFFHeader) - return COFFHeader->Machine; - if (COFFBigObjHeader) - return COFFBigObjHeader->Machine; - llvm_unreachable("no COFF header!"); - } - - uint16_t getSizeOfOptionalHeader() const { - if (COFFHeader) - return COFFHeader->isImportLibrary() ? 0 - : COFFHeader->SizeOfOptionalHeader; - // bigobj doesn't have this field. - if (COFFBigObjHeader) - return 0; - llvm_unreachable("no COFF header!"); - } - - uint16_t getCharacteristics() const { - if (COFFHeader) - return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; - // bigobj doesn't have characteristics to speak of, - // editbin will silently lie to you if you attempt to set any. - if (COFFBigObjHeader) - return 0; - llvm_unreachable("no COFF header!"); - } - - uint32_t getTimeDateStamp() const { - if (COFFHeader) - return COFFHeader->TimeDateStamp; - if (COFFBigObjHeader) - return COFFBigObjHeader->TimeDateStamp; - llvm_unreachable("no COFF header!"); - } - - uint32_t getNumberOfSections() const { - if (COFFHeader) - return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; - if (COFFBigObjHeader) - return COFFBigObjHeader->NumberOfSections; - llvm_unreachable("no COFF header!"); - } - - uint32_t getPointerToSymbolTable() const { - if (COFFHeader) - return COFFHeader->isImportLibrary() ? 0 - : COFFHeader->PointerToSymbolTable; - if (COFFBigObjHeader) - return COFFBigObjHeader->PointerToSymbolTable; - llvm_unreachable("no COFF header!"); - } - - uint32_t getRawNumberOfSymbols() const { - if (COFFHeader) - return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; - if (COFFBigObjHeader) - return COFFBigObjHeader->NumberOfSymbols; - llvm_unreachable("no COFF header!"); - } - - uint32_t getNumberOfSymbols() const { - if (!SymbolTable16 && !SymbolTable32) - return 0; - return getRawNumberOfSymbols(); - } - - uint32_t getStringTableSize() const { return StringTableSize; } - - const coff_load_configuration32 *getLoadConfig32() const { - assert(!is64()); - return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); - } - - const coff_load_configuration64 *getLoadConfig64() const { - assert(is64()); - return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); - } - StringRef getRelocationTypeName(uint16_t Type) const; - -protected: - void moveSymbolNext(DataRefImpl &Symb) const override; - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint32_t getSymbolAlignment(DataRefImpl Symb) const override; - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionVirtual(DataRefImpl Sec) const override; - bool isDebugSection(StringRef SectionName) const override; - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - - void moveRelocationNext(DataRefImpl &Rel) const override; - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - -public: - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - section_iterator section_begin() const override; - section_iterator section_end() const override; - - const coff_section *getCOFFSection(const SectionRef &Section) const; - COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; - COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; - const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; - unsigned getSectionID(SectionRef Sec) const; - unsigned getSymbolSectionID(SymbolRef Sym) const; - - uint8_t getBytesInAddress() const override; - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - Expected<uint64_t> getStartAddress() const override; - SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } - - import_directory_iterator import_directory_begin() const; - import_directory_iterator import_directory_end() const; - delay_import_directory_iterator delay_import_directory_begin() const; - delay_import_directory_iterator delay_import_directory_end() const; - export_directory_iterator export_directory_begin() const; - export_directory_iterator export_directory_end() const; - base_reloc_iterator base_reloc_begin() const; - base_reloc_iterator base_reloc_end() const; - const debug_directory *debug_directory_begin() const { - return DebugDirectoryBegin; - } - const debug_directory *debug_directory_end() const { - return DebugDirectoryEnd; - } - - iterator_range<import_directory_iterator> import_directories() const; - iterator_range<delay_import_directory_iterator> - delay_import_directories() const; - iterator_range<export_directory_iterator> export_directories() const; - iterator_range<base_reloc_iterator> base_relocs() const; - iterator_range<const debug_directory *> debug_directories() const { - return make_range(debug_directory_begin(), debug_directory_end()); - } - + Error initLoadConfigPtr(); + +public: + static Expected<std::unique_ptr<COFFObjectFile>> + create(MemoryBufferRef Object); + + uintptr_t getSymbolTable() const { + if (SymbolTable16) + return reinterpret_cast<uintptr_t>(SymbolTable16); + if (SymbolTable32) + return reinterpret_cast<uintptr_t>(SymbolTable32); + return uintptr_t(0); + } + + uint16_t getMachine() const { + if (COFFHeader) + return COFFHeader->Machine; + if (COFFBigObjHeader) + return COFFBigObjHeader->Machine; + llvm_unreachable("no COFF header!"); + } + + uint16_t getSizeOfOptionalHeader() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->SizeOfOptionalHeader; + // bigobj doesn't have this field. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + + uint16_t getCharacteristics() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; + // bigobj doesn't have characteristics to speak of, + // editbin will silently lie to you if you attempt to set any. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + + uint32_t getTimeDateStamp() const { + if (COFFHeader) + return COFFHeader->TimeDateStamp; + if (COFFBigObjHeader) + return COFFBigObjHeader->TimeDateStamp; + llvm_unreachable("no COFF header!"); + } + + uint32_t getNumberOfSections() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSections; + llvm_unreachable("no COFF header!"); + } + + uint32_t getPointerToSymbolTable() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->PointerToSymbolTable; + if (COFFBigObjHeader) + return COFFBigObjHeader->PointerToSymbolTable; + llvm_unreachable("no COFF header!"); + } + + uint32_t getRawNumberOfSymbols() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSymbols; + llvm_unreachable("no COFF header!"); + } + + uint32_t getNumberOfSymbols() const { + if (!SymbolTable16 && !SymbolTable32) + return 0; + return getRawNumberOfSymbols(); + } + + uint32_t getStringTableSize() const { return StringTableSize; } + + const coff_load_configuration32 *getLoadConfig32() const { + assert(!is64()); + return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); + } + + const coff_load_configuration64 *getLoadConfig64() const { + assert(is64()); + return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); + } + StringRef getRelocationTypeName(uint16_t Type) const; + +protected: + void moveSymbolNext(DataRefImpl &Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isDebugSection(StringRef SectionName) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + +public: + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + section_iterator section_begin() const override; + section_iterator section_end() const override; + + const coff_section *getCOFFSection(const SectionRef &Section) const; + COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; + COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; + const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; + unsigned getSectionID(SectionRef Sec) const; + unsigned getSymbolSectionID(SymbolRef Sym) const; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + Expected<uint64_t> getStartAddress() const override; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + + import_directory_iterator import_directory_begin() const; + import_directory_iterator import_directory_end() const; + delay_import_directory_iterator delay_import_directory_begin() const; + delay_import_directory_iterator delay_import_directory_end() const; + export_directory_iterator export_directory_begin() const; + export_directory_iterator export_directory_end() const; + base_reloc_iterator base_reloc_begin() const; + base_reloc_iterator base_reloc_end() const; + const debug_directory *debug_directory_begin() const { + return DebugDirectoryBegin; + } + const debug_directory *debug_directory_end() const { + return DebugDirectoryEnd; + } + + iterator_range<import_directory_iterator> import_directories() const; + iterator_range<delay_import_directory_iterator> + delay_import_directories() const; + iterator_range<export_directory_iterator> export_directories() const; + iterator_range<base_reloc_iterator> base_relocs() const; + iterator_range<const debug_directory *> debug_directories() const { + return make_range(debug_directory_begin(), debug_directory_end()); + } + const coff_tls_directory32 *getTLSDirectory32() const { return TLSDirectory32; } @@ -1004,288 +1004,288 @@ public: return TLSDirectory64; } - const dos_header *getDOSHeader() const { - if (!PE32Header && !PE32PlusHeader) - return nullptr; - return reinterpret_cast<const dos_header *>(base()); - } - - const coff_file_header *getCOFFHeader() const { return COFFHeader; } - const coff_bigobj_file_header *getCOFFBigObjHeader() const { - return COFFBigObjHeader; - } - const pe32_header *getPE32Header() const { return PE32Header; } - const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; } - - const data_directory *getDataDirectory(uint32_t index) const; - Expected<const coff_section *> getSection(int32_t index) const; - - Expected<COFFSymbolRef> getSymbol(uint32_t index) const { - if (index >= getNumberOfSymbols()) - return errorCodeToError(object_error::parse_failed); - if (SymbolTable16) - return COFFSymbolRef(SymbolTable16 + index); - if (SymbolTable32) - return COFFSymbolRef(SymbolTable32 + index); - return errorCodeToError(object_error::parse_failed); - } - - template <typename T> - Error getAuxSymbol(uint32_t index, const T *&Res) const { - Expected<COFFSymbolRef> S = getSymbol(index); - if (Error E = S.takeError()) - return E; - Res = reinterpret_cast<const T *>(S->getRawPtr()); - return Error::success(); - } - - Expected<StringRef> getSymbolName(COFFSymbolRef Symbol) const; - Expected<StringRef> getSymbolName(const coff_symbol_generic *Symbol) const; - - ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; - - uint32_t getSymbolIndex(COFFSymbolRef Symbol) const; - - size_t getSymbolTableEntrySize() const { - if (COFFHeader) - return sizeof(coff_symbol16); - if (COFFBigObjHeader) - return sizeof(coff_symbol32); - llvm_unreachable("null symbol table pointer!"); - } - - ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; - - Expected<StringRef> getSectionName(const coff_section *Sec) const; - uint64_t getSectionSize(const coff_section *Sec) const; - Error getSectionContents(const coff_section *Sec, - ArrayRef<uint8_t> &Res) const; - - uint64_t getImageBase() const; - Error getVaPtr(uint64_t VA, uintptr_t &Res) const; - Error getRvaPtr(uint32_t Rva, uintptr_t &Res) const; - - /// Given an RVA base and size, returns a valid array of bytes or an error - /// code if the RVA and size is not contained completely within a valid - /// section. - Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, - ArrayRef<uint8_t> &Contents) const; - - Error getHintName(uint32_t Rva, uint16_t &Hint, - StringRef &Name) const; - - /// Get PDB information out of a codeview debug directory entry. - Error getDebugPDBInfo(const debug_directory *DebugDir, - const codeview::DebugInfo *&Info, - StringRef &PDBFileName) const; - - /// Get PDB information from an executable. If the information is not present, - /// Info will be set to nullptr and PDBFileName will be empty. An error is - /// returned only on corrupt object files. Convenience accessor that can be - /// used if the debug directory is not already handy. - Error getDebugPDBInfo(const codeview::DebugInfo *&Info, - StringRef &PDBFileName) const; - - bool isRelocatableObject() const override; - bool is64() const { return PE32PlusHeader; } - - StringRef mapDebugSectionName(StringRef Name) const override; - - static bool classof(const Binary *v) { return v->isCOFF(); } -}; - -// The iterator for the import directory table. -class ImportDirectoryEntryRef { -public: - ImportDirectoryEntryRef() = default; - ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, - uint32_t I, const COFFObjectFile *Owner) - : ImportTable(Table), Index(I), OwningObject(Owner) {} - - bool operator==(const ImportDirectoryEntryRef &Other) const; - void moveNext(); - - imported_symbol_iterator imported_symbol_begin() const; - imported_symbol_iterator imported_symbol_end() const; - iterator_range<imported_symbol_iterator> imported_symbols() const; - - imported_symbol_iterator lookup_table_begin() const; - imported_symbol_iterator lookup_table_end() const; - iterator_range<imported_symbol_iterator> lookup_table_symbols() const; - - Error getName(StringRef &Result) const; - Error getImportLookupTableRVA(uint32_t &Result) const; - Error getImportAddressTableRVA(uint32_t &Result) const; - - Error - getImportTableEntry(const coff_import_directory_table_entry *&Result) const; - -private: - const coff_import_directory_table_entry *ImportTable; - uint32_t Index; - const COFFObjectFile *OwningObject = nullptr; -}; - -class DelayImportDirectoryEntryRef { -public: - DelayImportDirectoryEntryRef() = default; - DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, - uint32_t I, const COFFObjectFile *Owner) - : Table(T), Index(I), OwningObject(Owner) {} - - bool operator==(const DelayImportDirectoryEntryRef &Other) const; - void moveNext(); - - imported_symbol_iterator imported_symbol_begin() const; - imported_symbol_iterator imported_symbol_end() const; - iterator_range<imported_symbol_iterator> imported_symbols() const; - - Error getName(StringRef &Result) const; - Error getDelayImportTable( - const delay_import_directory_table_entry *&Result) const; - Error getImportAddress(int AddrIndex, uint64_t &Result) const; - -private: - const delay_import_directory_table_entry *Table; - uint32_t Index; - const COFFObjectFile *OwningObject = nullptr; -}; - -// The iterator for the export directory table entry. -class ExportDirectoryEntryRef { -public: - ExportDirectoryEntryRef() = default; - ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, - const COFFObjectFile *Owner) - : ExportTable(Table), Index(I), OwningObject(Owner) {} - - bool operator==(const ExportDirectoryEntryRef &Other) const; - void moveNext(); - - Error getDllName(StringRef &Result) const; - Error getOrdinalBase(uint32_t &Result) const; - Error getOrdinal(uint32_t &Result) const; - Error getExportRVA(uint32_t &Result) const; - Error getSymbolName(StringRef &Result) const; - - Error isForwarder(bool &Result) const; - Error getForwardTo(StringRef &Result) const; - -private: - const export_directory_table_entry *ExportTable; - uint32_t Index; - const COFFObjectFile *OwningObject = nullptr; -}; - -class ImportedSymbolRef { -public: - ImportedSymbolRef() = default; - ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, - const COFFObjectFile *Owner) - : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} - ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, - const COFFObjectFile *Owner) - : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} - - bool operator==(const ImportedSymbolRef &Other) const; - void moveNext(); - - Error getSymbolName(StringRef &Result) const; - Error isOrdinal(bool &Result) const; - Error getOrdinal(uint16_t &Result) const; - Error getHintNameRVA(uint32_t &Result) const; - -private: - const import_lookup_table_entry32 *Entry32; - const import_lookup_table_entry64 *Entry64; - uint32_t Index; - const COFFObjectFile *OwningObject = nullptr; -}; - -class BaseRelocRef { -public: - BaseRelocRef() = default; - BaseRelocRef(const coff_base_reloc_block_header *Header, - const COFFObjectFile *Owner) - : Header(Header), Index(0) {} - - bool operator==(const BaseRelocRef &Other) const; - void moveNext(); - - Error getType(uint8_t &Type) const; - Error getRVA(uint32_t &Result) const; - -private: - const coff_base_reloc_block_header *Header; - uint32_t Index; -}; - -class ResourceSectionRef { -public: - ResourceSectionRef() = default; - explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} - - Error load(const COFFObjectFile *O); - Error load(const COFFObjectFile *O, const SectionRef &S); - - Expected<ArrayRef<UTF16>> - getEntryNameString(const coff_resource_dir_entry &Entry); - Expected<const coff_resource_dir_table &> - getEntrySubDir(const coff_resource_dir_entry &Entry); - Expected<const coff_resource_data_entry &> - getEntryData(const coff_resource_dir_entry &Entry); - Expected<const coff_resource_dir_table &> getBaseTable(); - Expected<const coff_resource_dir_entry &> - getTableEntry(const coff_resource_dir_table &Table, uint32_t Index); - - Expected<StringRef> getContents(const coff_resource_data_entry &Entry); - -private: - BinaryByteStream BBS; - - SectionRef Section; - const COFFObjectFile *Obj; - - std::vector<const coff_relocation *> Relocs; - - Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); - Expected<const coff_resource_dir_entry &> - getTableEntryAtOffset(uint32_t Offset); - Expected<const coff_resource_data_entry &> - getDataEntryAtOffset(uint32_t Offset); - Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); -}; - -// Corresponds to `_FPO_DATA` structure in the PE/COFF spec. -struct FpoData { - support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code - support::ulittle32_t Size; // cbProcSize: # bytes in function - support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 - support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 - support::ulittle16_t Attributes; - - // cbProlog: # bytes in prolog - int getPrologSize() const { return Attributes & 0xF; } - - // cbRegs: # regs saved - int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } - - // fHasSEH: true if seh is func - bool hasSEH() const { return (Attributes >> 9) & 1; } - - // fUseBP: true if EBP has been allocated - bool useBP() const { return (Attributes >> 10) & 1; } - - // cbFrame: frame pointer - frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); } -}; - -} // end namespace object - -} // end namespace llvm - -#endif // LLVM_OBJECT_COFF_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + const dos_header *getDOSHeader() const { + if (!PE32Header && !PE32PlusHeader) + return nullptr; + return reinterpret_cast<const dos_header *>(base()); + } + + const coff_file_header *getCOFFHeader() const { return COFFHeader; } + const coff_bigobj_file_header *getCOFFBigObjHeader() const { + return COFFBigObjHeader; + } + const pe32_header *getPE32Header() const { return PE32Header; } + const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; } + + const data_directory *getDataDirectory(uint32_t index) const; + Expected<const coff_section *> getSection(int32_t index) const; + + Expected<COFFSymbolRef> getSymbol(uint32_t index) const { + if (index >= getNumberOfSymbols()) + return errorCodeToError(object_error::parse_failed); + if (SymbolTable16) + return COFFSymbolRef(SymbolTable16 + index); + if (SymbolTable32) + return COFFSymbolRef(SymbolTable32 + index); + return errorCodeToError(object_error::parse_failed); + } + + template <typename T> + Error getAuxSymbol(uint32_t index, const T *&Res) const { + Expected<COFFSymbolRef> S = getSymbol(index); + if (Error E = S.takeError()) + return E; + Res = reinterpret_cast<const T *>(S->getRawPtr()); + return Error::success(); + } + + Expected<StringRef> getSymbolName(COFFSymbolRef Symbol) const; + Expected<StringRef> getSymbolName(const coff_symbol_generic *Symbol) const; + + ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; + + uint32_t getSymbolIndex(COFFSymbolRef Symbol) const; + + size_t getSymbolTableEntrySize() const { + if (COFFHeader) + return sizeof(coff_symbol16); + if (COFFBigObjHeader) + return sizeof(coff_symbol32); + llvm_unreachable("null symbol table pointer!"); + } + + ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; + + Expected<StringRef> getSectionName(const coff_section *Sec) const; + uint64_t getSectionSize(const coff_section *Sec) const; + Error getSectionContents(const coff_section *Sec, + ArrayRef<uint8_t> &Res) const; + + uint64_t getImageBase() const; + Error getVaPtr(uint64_t VA, uintptr_t &Res) const; + Error getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + + /// Given an RVA base and size, returns a valid array of bytes or an error + /// code if the RVA and size is not contained completely within a valid + /// section. + Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const; + + Error getHintName(uint32_t Rva, uint16_t &Hint, + StringRef &Name) const; + + /// Get PDB information out of a codeview debug directory entry. + Error getDebugPDBInfo(const debug_directory *DebugDir, + const codeview::DebugInfo *&Info, + StringRef &PDBFileName) const; + + /// Get PDB information from an executable. If the information is not present, + /// Info will be set to nullptr and PDBFileName will be empty. An error is + /// returned only on corrupt object files. Convenience accessor that can be + /// used if the debug directory is not already handy. + Error getDebugPDBInfo(const codeview::DebugInfo *&Info, + StringRef &PDBFileName) const; + + bool isRelocatableObject() const override; + bool is64() const { return PE32PlusHeader; } + + StringRef mapDebugSectionName(StringRef Name) const override; + + static bool classof(const Binary *v) { return v->isCOFF(); } +}; + +// The iterator for the import directory table. +class ImportDirectoryEntryRef { +public: + ImportDirectoryEntryRef() = default; + ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, + uint32_t I, const COFFObjectFile *Owner) + : ImportTable(Table), Index(I), OwningObject(Owner) {} + + bool operator==(const ImportDirectoryEntryRef &Other) const; + void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range<imported_symbol_iterator> imported_symbols() const; + + imported_symbol_iterator lookup_table_begin() const; + imported_symbol_iterator lookup_table_end() const; + iterator_range<imported_symbol_iterator> lookup_table_symbols() const; + + Error getName(StringRef &Result) const; + Error getImportLookupTableRVA(uint32_t &Result) const; + Error getImportAddressTableRVA(uint32_t &Result) const; + + Error + getImportTableEntry(const coff_import_directory_table_entry *&Result) const; + +private: + const coff_import_directory_table_entry *ImportTable; + uint32_t Index; + const COFFObjectFile *OwningObject = nullptr; +}; + +class DelayImportDirectoryEntryRef { +public: + DelayImportDirectoryEntryRef() = default; + DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, + uint32_t I, const COFFObjectFile *Owner) + : Table(T), Index(I), OwningObject(Owner) {} + + bool operator==(const DelayImportDirectoryEntryRef &Other) const; + void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range<imported_symbol_iterator> imported_symbols() const; + + Error getName(StringRef &Result) const; + Error getDelayImportTable( + const delay_import_directory_table_entry *&Result) const; + Error getImportAddress(int AddrIndex, uint64_t &Result) const; + +private: + const delay_import_directory_table_entry *Table; + uint32_t Index; + const COFFObjectFile *OwningObject = nullptr; +}; + +// The iterator for the export directory table entry. +class ExportDirectoryEntryRef { +public: + ExportDirectoryEntryRef() = default; + ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, + const COFFObjectFile *Owner) + : ExportTable(Table), Index(I), OwningObject(Owner) {} + + bool operator==(const ExportDirectoryEntryRef &Other) const; + void moveNext(); + + Error getDllName(StringRef &Result) const; + Error getOrdinalBase(uint32_t &Result) const; + Error getOrdinal(uint32_t &Result) const; + Error getExportRVA(uint32_t &Result) const; + Error getSymbolName(StringRef &Result) const; + + Error isForwarder(bool &Result) const; + Error getForwardTo(StringRef &Result) const; + +private: + const export_directory_table_entry *ExportTable; + uint32_t Index; + const COFFObjectFile *OwningObject = nullptr; +}; + +class ImportedSymbolRef { +public: + ImportedSymbolRef() = default; + ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} + ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} + + bool operator==(const ImportedSymbolRef &Other) const; + void moveNext(); + + Error getSymbolName(StringRef &Result) const; + Error isOrdinal(bool &Result) const; + Error getOrdinal(uint16_t &Result) const; + Error getHintNameRVA(uint32_t &Result) const; + +private: + const import_lookup_table_entry32 *Entry32; + const import_lookup_table_entry64 *Entry64; + uint32_t Index; + const COFFObjectFile *OwningObject = nullptr; +}; + +class BaseRelocRef { +public: + BaseRelocRef() = default; + BaseRelocRef(const coff_base_reloc_block_header *Header, + const COFFObjectFile *Owner) + : Header(Header), Index(0) {} + + bool operator==(const BaseRelocRef &Other) const; + void moveNext(); + + Error getType(uint8_t &Type) const; + Error getRVA(uint32_t &Result) const; + +private: + const coff_base_reloc_block_header *Header; + uint32_t Index; +}; + +class ResourceSectionRef { +public: + ResourceSectionRef() = default; + explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} + + Error load(const COFFObjectFile *O); + Error load(const COFFObjectFile *O, const SectionRef &S); + + Expected<ArrayRef<UTF16>> + getEntryNameString(const coff_resource_dir_entry &Entry); + Expected<const coff_resource_dir_table &> + getEntrySubDir(const coff_resource_dir_entry &Entry); + Expected<const coff_resource_data_entry &> + getEntryData(const coff_resource_dir_entry &Entry); + Expected<const coff_resource_dir_table &> getBaseTable(); + Expected<const coff_resource_dir_entry &> + getTableEntry(const coff_resource_dir_table &Table, uint32_t Index); + + Expected<StringRef> getContents(const coff_resource_data_entry &Entry); + +private: + BinaryByteStream BBS; + + SectionRef Section; + const COFFObjectFile *Obj; + + std::vector<const coff_relocation *> Relocs; + + Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); + Expected<const coff_resource_dir_entry &> + getTableEntryAtOffset(uint32_t Offset); + Expected<const coff_resource_data_entry &> + getDataEntryAtOffset(uint32_t Offset); + Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); +}; + +// Corresponds to `_FPO_DATA` structure in the PE/COFF spec. +struct FpoData { + support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code + support::ulittle32_t Size; // cbProcSize: # bytes in function + support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 + support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 + support::ulittle16_t Attributes; + + // cbProlog: # bytes in prolog + int getPrologSize() const { return Attributes & 0xF; } + + // cbRegs: # regs saved + int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } + + // fHasSEH: true if seh is func + bool hasSEH() const { return (Attributes >> 9) & 1; } + + // fUseBP: true if EBP has been allocated + bool useBP() const { return (Attributes >> 10) & 1; } + + // cbFrame: frame pointer + frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); } +}; + +} // end namespace object + +} // end namespace llvm + +#endif // LLVM_OBJECT_COFF_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h b/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h index d5d5a369dff..e45fa29270d 100644 --- a/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h @@ -1,124 +1,124 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// COFF short import file is a special kind of file which contains -// only symbol names for DLL-exported symbols. This class implements -// exporting of Symbols to create libraries and a SymbolicFile -// interface for the file type. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_COFF_IMPORT_FILE_H -#define LLVM_OBJECT_COFF_IMPORT_FILE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/IRObjectFile.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { -namespace object { - -class COFFImportFile : public SymbolicFile { -public: - COFFImportFile(MemoryBufferRef Source) - : SymbolicFile(ID_COFFImportFile, Source) {} - - static bool classof(Binary const *V) { return V->isCOFFImportFile(); } - - void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } - - Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override { - if (Symb.p == 0) - OS << "__imp_"; - OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header)); - return Error::success(); - } - - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override { - return SymbolRef::SF_Global; - } - - basic_symbol_iterator symbol_begin() const override { - return BasicSymbolRef(DataRefImpl(), this); - } - - basic_symbol_iterator symbol_end() const override { - DataRefImpl Symb; - Symb.p = isData() ? 1 : 2; - return BasicSymbolRef(Symb, this); - } - - const coff_import_header *getCOFFImportHeader() const { - return reinterpret_cast<const object::coff_import_header *>( - Data.getBufferStart()); - } - -private: - bool isData() const { - return getCOFFImportHeader()->getType() == COFF::IMPORT_DATA; - } -}; - -struct COFFShortExport { - /// The name of the export as specified in the .def file or on the command - /// line, i.e. "foo" in "/EXPORT:foo", and "bar" in "/EXPORT:foo=bar". This - /// may lack mangling, such as underscore prefixing and stdcall suffixing. - std::string Name; - - /// The external, exported name. Only non-empty when export renaming is in - /// effect, i.e. "foo" in "/EXPORT:foo=bar". - std::string ExtName; - - /// The real, mangled symbol name from the object file. Given - /// "/export:foo=bar", this could be "_bar@8" if bar is stdcall. - std::string SymbolName; - - /// Creates a weak alias. This is the name of the weak aliasee. In a .def - /// file, this is "baz" in "EXPORTS\nfoo = bar == baz". - std::string AliasTarget; - - uint16_t Ordinal = 0; - bool Noname = false; - bool Data = false; - bool Private = false; - bool Constant = false; - - friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) { - return L.Name == R.Name && L.ExtName == R.ExtName && - L.Ordinal == R.Ordinal && L.Noname == R.Noname && - L.Data == R.Data && L.Private == R.Private; - } - - friend bool operator!=(const COFFShortExport &L, const COFFShortExport &R) { - return !(L == R); - } -}; - -Error writeImportLibrary(StringRef ImportName, StringRef Path, - ArrayRef<COFFShortExport> Exports, - COFF::MachineTypes Machine, bool MinGW); - -} // namespace object -} // namespace llvm - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// COFF short import file is a special kind of file which contains +// only symbol names for DLL-exported symbols. This class implements +// exporting of Symbols to create libraries and a SymbolicFile +// interface for the file type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_IMPORT_FILE_H +#define LLVM_OBJECT_COFF_IMPORT_FILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace object { + +class COFFImportFile : public SymbolicFile { +public: + COFFImportFile(MemoryBufferRef Source) + : SymbolicFile(ID_COFFImportFile, Source) {} + + static bool classof(Binary const *V) { return V->isCOFFImportFile(); } + + void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } + + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override { + if (Symb.p == 0) + OS << "__imp_"; + OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header)); + return Error::success(); + } + + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override { + return SymbolRef::SF_Global; + } + + basic_symbol_iterator symbol_begin() const override { + return BasicSymbolRef(DataRefImpl(), this); + } + + basic_symbol_iterator symbol_end() const override { + DataRefImpl Symb; + Symb.p = isData() ? 1 : 2; + return BasicSymbolRef(Symb, this); + } + + const coff_import_header *getCOFFImportHeader() const { + return reinterpret_cast<const object::coff_import_header *>( + Data.getBufferStart()); + } + +private: + bool isData() const { + return getCOFFImportHeader()->getType() == COFF::IMPORT_DATA; + } +}; + +struct COFFShortExport { + /// The name of the export as specified in the .def file or on the command + /// line, i.e. "foo" in "/EXPORT:foo", and "bar" in "/EXPORT:foo=bar". This + /// may lack mangling, such as underscore prefixing and stdcall suffixing. + std::string Name; + + /// The external, exported name. Only non-empty when export renaming is in + /// effect, i.e. "foo" in "/EXPORT:foo=bar". + std::string ExtName; + + /// The real, mangled symbol name from the object file. Given + /// "/export:foo=bar", this could be "_bar@8" if bar is stdcall. + std::string SymbolName; + + /// Creates a weak alias. This is the name of the weak aliasee. In a .def + /// file, this is "baz" in "EXPORTS\nfoo = bar == baz". + std::string AliasTarget; + + uint16_t Ordinal = 0; + bool Noname = false; + bool Data = false; + bool Private = false; + bool Constant = false; + + friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) { + return L.Name == R.Name && L.ExtName == R.ExtName && + L.Ordinal == R.Ordinal && L.Noname == R.Noname && + L.Data == R.Data && L.Private == R.Private; + } + + friend bool operator!=(const COFFShortExport &L, const COFFShortExport &R) { + return !(L == R); + } +}; + +Error writeImportLibrary(StringRef ImportName, StringRef Path, + ArrayRef<COFFShortExport> Exports, + COFF::MachineTypes Machine, bool MinGW); + +} // namespace object +} // namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h b/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h index 3661c193331..3168d9cc9ee 100644 --- a/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h +++ b/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h @@ -1,63 +1,63 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===--- COFFModuleDefinition.h ---------------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Windows-specific. -// A parser for the module-definition file (.def file). -// Parsed results are directly written to Config global variable. -// -// The format of module-definition files are described in this document: -// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_COFF_MODULE_DEFINITION_H -#define LLVM_OBJECT_COFF_MODULE_DEFINITION_H - -#include "llvm/Object/COFF.h" -#include "llvm/Object/COFFImportFile.h" - -namespace llvm { -namespace object { - -struct COFFModuleDefinition { - std::vector<COFFShortExport> Exports; - std::string OutputFile; - std::string ImportName; - uint64_t ImageBase = 0; - uint64_t StackReserve = 0; - uint64_t StackCommit = 0; - uint64_t HeapReserve = 0; - uint64_t HeapCommit = 0; - uint32_t MajorImageVersion = 0; - uint32_t MinorImageVersion = 0; - uint32_t MajorOSVersion = 0; - uint32_t MinorOSVersion = 0; -}; - -// mingw and wine def files do not mangle _ for x86 which -// is a consequence of legacy binutils' dlltool functionality. -// This MingwDef flag should be removed once mingw stops this pratice. -Expected<COFFModuleDefinition> -parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine, - bool MingwDef = false); - -} // End namespace object. -} // End namespace llvm. - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- COFFModuleDefinition.h ---------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Windows-specific. +// A parser for the module-definition file (.def file). +// Parsed results are directly written to Config global variable. +// +// The format of module-definition files are described in this document: +// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_MODULE_DEFINITION_H +#define LLVM_OBJECT_COFF_MODULE_DEFINITION_H + +#include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" + +namespace llvm { +namespace object { + +struct COFFModuleDefinition { + std::vector<COFFShortExport> Exports; + std::string OutputFile; + std::string ImportName; + uint64_t ImageBase = 0; + uint64_t StackReserve = 0; + uint64_t StackCommit = 0; + uint64_t HeapReserve = 0; + uint64_t HeapCommit = 0; + uint32_t MajorImageVersion = 0; + uint32_t MinorImageVersion = 0; + uint32_t MajorOSVersion = 0; + uint32_t MinorOSVersion = 0; +}; + +// mingw and wine def files do not mangle _ for x86 which +// is a consequence of legacy binutils' dlltool functionality. +// This MingwDef flag should be removed once mingw stops this pratice. +Expected<COFFModuleDefinition> +parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine, + bool MingwDef = false); + +} // End namespace object. +} // End namespace llvm. + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h b/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h index 17685635bfd..973975c4e36 100644 --- a/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h +++ b/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h @@ -1,65 +1,65 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- CVDebugRecord.h ------------------------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_CVDEBUGRECORD_H -#define LLVM_OBJECT_CVDEBUGRECORD_H - -#include "llvm/Support/Endian.h" - -namespace llvm { -namespace OMF { -struct Signature { - enum ID : uint32_t { - PDB70 = 0x53445352, // RSDS - PDB20 = 0x3031424e, // NB10 - CV50 = 0x3131424e, // NB11 - CV41 = 0x3930424e, // NB09 - }; - - support::ulittle32_t CVSignature; - support::ulittle32_t Offset; -}; -} - -namespace codeview { -struct PDB70DebugInfo { - support::ulittle32_t CVSignature; - uint8_t Signature[16]; - support::ulittle32_t Age; - // char PDBFileName[]; -}; - -struct PDB20DebugInfo { - support::ulittle32_t CVSignature; - support::ulittle32_t Offset; - support::ulittle32_t Signature; - support::ulittle32_t Age; - // char PDBFileName[]; -}; - -union DebugInfo { - struct OMF::Signature Signature; - struct PDB20DebugInfo PDB20; - struct PDB70DebugInfo PDB70; -}; -} -} - -#endif - - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- CVDebugRecord.h ------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_CVDEBUGRECORD_H +#define LLVM_OBJECT_CVDEBUGRECORD_H + +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace OMF { +struct Signature { + enum ID : uint32_t { + PDB70 = 0x53445352, // RSDS + PDB20 = 0x3031424e, // NB10 + CV50 = 0x3131424e, // NB11 + CV41 = 0x3930424e, // NB09 + }; + + support::ulittle32_t CVSignature; + support::ulittle32_t Offset; +}; +} + +namespace codeview { +struct PDB70DebugInfo { + support::ulittle32_t CVSignature; + uint8_t Signature[16]; + support::ulittle32_t Age; + // char PDBFileName[]; +}; + +struct PDB20DebugInfo { + support::ulittle32_t CVSignature; + support::ulittle32_t Offset; + support::ulittle32_t Signature; + support::ulittle32_t Age; + // char PDBFileName[]; +}; + +union DebugInfo { + struct OMF::Signature Signature; + struct PDB20DebugInfo PDB20; + struct PDB70DebugInfo PDB70; +}; +} +} + +#endif + + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/Decompressor.h b/contrib/libs/llvm12/include/llvm/Object/Decompressor.h index 92409641e48..b488ef5b4c5 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Decompressor.h +++ b/contrib/libs/llvm12/include/llvm/Object/Decompressor.h @@ -1,77 +1,77 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===-- Decompressor.h ------------------------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===/ - -#ifndef LLVM_OBJECT_DECOMPRESSOR_H -#define LLVM_OBJECT_DECOMPRESSOR_H - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { -namespace object { - -/// Decompressor helps to handle decompression of compressed sections. -class Decompressor { -public: - /// Create decompressor object. - /// @param Name Section name. - /// @param Data Section content. - /// @param IsLE Flag determines if Data is in little endian form. - /// @param Is64Bit Flag determines if object is 64 bit. - static Expected<Decompressor> create(StringRef Name, StringRef Data, - bool IsLE, bool Is64Bit); - - /// Resize the buffer and uncompress section data into it. - /// @param Out Destination buffer. - template <class T> Error resizeAndDecompress(T &Out) { - Out.resize(DecompressedSize); - return decompress({Out.data(), (size_t)DecompressedSize}); - } - - /// Uncompress section data to raw buffer provided. - /// @param Buffer Destination buffer. - Error decompress(MutableArrayRef<char> Buffer); - - /// Return memory buffer size required for decompression. - uint64_t getDecompressedSize() { return DecompressedSize; } - - /// Return true if section is compressed, including gnu-styled case. - static bool isCompressed(const object::SectionRef &Section); - - /// Return true if section is a ELF compressed one. - static bool isCompressedELFSection(uint64_t Flags, StringRef Name); - - /// Return true if section name matches gnu style compressed one. - static bool isGnuStyle(StringRef Name); - -private: - Decompressor(StringRef Data); - - Error consumeCompressedGnuHeader(); - Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); - - StringRef SectionData; - uint64_t DecompressedSize; -}; - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_DECOMPRESSOR_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- Decompressor.h ------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_OBJECT_DECOMPRESSOR_H +#define LLVM_OBJECT_DECOMPRESSOR_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { + +/// Decompressor helps to handle decompression of compressed sections. +class Decompressor { +public: + /// Create decompressor object. + /// @param Name Section name. + /// @param Data Section content. + /// @param IsLE Flag determines if Data is in little endian form. + /// @param Is64Bit Flag determines if object is 64 bit. + static Expected<Decompressor> create(StringRef Name, StringRef Data, + bool IsLE, bool Is64Bit); + + /// Resize the buffer and uncompress section data into it. + /// @param Out Destination buffer. + template <class T> Error resizeAndDecompress(T &Out) { + Out.resize(DecompressedSize); + return decompress({Out.data(), (size_t)DecompressedSize}); + } + + /// Uncompress section data to raw buffer provided. + /// @param Buffer Destination buffer. + Error decompress(MutableArrayRef<char> Buffer); + + /// Return memory buffer size required for decompression. + uint64_t getDecompressedSize() { return DecompressedSize; } + + /// Return true if section is compressed, including gnu-styled case. + static bool isCompressed(const object::SectionRef &Section); + + /// Return true if section is a ELF compressed one. + static bool isCompressedELFSection(uint64_t Flags, StringRef Name); + + /// Return true if section name matches gnu style compressed one. + static bool isGnuStyle(StringRef Name); + +private: + Decompressor(StringRef Data); + + Error consumeCompressedGnuHeader(); + Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); + + StringRef SectionData; + uint64_t DecompressedSize; +}; + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_DECOMPRESSOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ELF.h b/contrib/libs/llvm12/include/llvm/Object/ELF.h index 20e25a9ee28..9d96941ec12 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ELF.h +++ b/contrib/libs/llvm12/include/llvm/Object/ELF.h @@ -1,42 +1,42 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the ELFFile template class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ELF_H -#define LLVM_OBJECT_ELF_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Object/Error.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <limits> -#include <utility> - -namespace llvm { -namespace object { - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_H +#define LLVM_OBJECT_ELF_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <utility> + +namespace llvm { +namespace object { + struct VerdAux { unsigned Offset; std::string Name; @@ -74,24 +74,24 @@ struct VersionEntry { bool IsVerDef; }; -StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); -uint32_t getELFRelativeRelocationType(uint32_t Machine); -StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); - -// Subclasses of ELFFile may need this for template instantiation -inline std::pair<unsigned char, unsigned char> -getElfArchType(StringRef Object) { - if (Object.size() < ELF::EI_NIDENT) - return std::make_pair((uint8_t)ELF::ELFCLASSNONE, - (uint8_t)ELF::ELFDATANONE); - return std::make_pair((uint8_t)Object[ELF::EI_CLASS], - (uint8_t)Object[ELF::EI_DATA]); -} - -static inline Error createError(const Twine &Err) { - return make_error<StringError>(Err, object_error::parse_failed); -} - +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); +uint32_t getELFRelativeRelocationType(uint32_t Machine); +StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); + +// Subclasses of ELFFile may need this for template instantiation +inline std::pair<unsigned char, unsigned char> +getElfArchType(StringRef Object) { + if (Object.size() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE, + (uint8_t)ELF::ELFDATANONE); + return std::make_pair((uint8_t)Object[ELF::EI_CLASS], + (uint8_t)Object[ELF::EI_DATA]); +} + +static inline Error createError(const Twine &Err) { + return make_error<StringError>(Err, object_error::parse_failed); +} + enum PPCInstrMasks : uint64_t { PADDI_R12_NO_DISP = 0x0610000039800000, PLD_R12_NO_DISP = 0x04100000E5800000, @@ -99,8 +99,8 @@ enum PPCInstrMasks : uint64_t { BCTR = 0x4E800420, }; -template <class ELFT> class ELFFile; - +template <class ELFT> class ELFFile; + template <class T> struct DataRegion { // This constructor is used when we know the start and the size of a data // region. We assume that Arr does not go past the end of the file. @@ -131,21 +131,21 @@ template <class T> struct DataRegion { const uint8_t *BufEnd = nullptr; }; -template <class ELFT> +template <class ELFT> std::string getSecIndexForError(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) { auto TableOrErr = Obj.sections(); - if (TableOrErr) + if (TableOrErr) return "[index " + std::to_string(&Sec - &TableOrErr->front()) + "]"; - // To make this helper be more convenient for error reporting purposes we - // drop the error. But really it should never be triggered. Before this point, - // our code should have called 'sections()' and reported a proper error on - // failure. - llvm::consumeError(TableOrErr.takeError()); - return "[unknown index]"; -} - -template <class ELFT> + // To make this helper be more convenient for error reporting purposes we + // drop the error. But really it should never be triggered. Before this point, + // our code should have called 'sections()' and reported a proper error on + // failure. + llvm::consumeError(TableOrErr.takeError()); + return "[unknown index]"; +} + +template <class ELFT> static std::string describe(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) { unsigned SecNdx = &Sec - &cantFail(Obj.sections()).front(); @@ -159,436 +159,436 @@ template <class ELFT> std::string getPhdrIndexForError(const ELFFile<ELFT> &Obj, const typename ELFT::Phdr &Phdr) { auto Headers = Obj.program_headers(); - if (Headers) + if (Headers) return ("[index " + Twine(&Phdr - &Headers->front()) + "]").str(); - // See comment in the getSecIndexForError() above. - llvm::consumeError(Headers.takeError()); - return "[unknown index]"; -} - -static inline Error defaultWarningHandler(const Twine &Msg) { - return createError(Msg); -} - -template <class ELFT> -class ELFFile { -public: - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - - // This is a callback that can be passed to a number of functions. - // It can be used to ignore non-critical errors (warnings), which is - // useful for dumpers, like llvm-readobj. - // It accepts a warning message string and returns a success - // when the warning should be ignored or an error otherwise. - using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>; - - const uint8_t *base() const { return Buf.bytes_begin(); } + // See comment in the getSecIndexForError() above. + llvm::consumeError(Headers.takeError()); + return "[unknown index]"; +} + +static inline Error defaultWarningHandler(const Twine &Msg) { + return createError(Msg); +} + +template <class ELFT> +class ELFFile { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + // This is a callback that can be passed to a number of functions. + // It can be used to ignore non-critical errors (warnings), which is + // useful for dumpers, like llvm-readobj. + // It accepts a warning message string and returns a success + // when the warning should be ignored or an error otherwise. + using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>; + + const uint8_t *base() const { return Buf.bytes_begin(); } const uint8_t *end() const { return base() + getBufSize(); } - - size_t getBufSize() const { return Buf.size(); } - -private: - StringRef Buf; - - ELFFile(StringRef Object); - -public: + + size_t getBufSize() const { return Buf.size(); } + +private: + StringRef Buf; + + ELFFile(StringRef Object); + +public: const Elf_Ehdr &getHeader() const { return *reinterpret_cast<const Elf_Ehdr *>(base()); - } - - template <typename T> - Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; - template <typename T> + } + + template <typename T> + Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const; + template <typename T> Expected<const T *> getEntry(const Elf_Shdr &Section, uint32_t Entry) const; - + Expected<std::vector<VerDef>> getVersionDefinitions(const Elf_Shdr &Sec) const; Expected<std::vector<VerNeed>> getVersionDependencies( const Elf_Shdr &Sec, WarningHandler WarnHandler = &defaultWarningHandler) const; - Expected<StringRef> + Expected<StringRef> getSymbolVersionByIndex(uint32_t SymbolVersionIndex, bool &IsDefault, SmallVector<Optional<VersionEntry>, 0> &VersionMap, Optional<bool> IsSymHidden) const; Expected<StringRef> getStringTable(const Elf_Shdr &Section, - WarningHandler WarnHandler = &defaultWarningHandler) const; - Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; - Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, - Elf_Shdr_Range Sections) const; + WarningHandler WarnHandler = &defaultWarningHandler) const; + Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const; + Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const; Expected<StringRef> getLinkAsStrtab(const typename ELFT::Shdr &Sec) const; - - Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; - Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, - Elf_Shdr_Range Sections) const; - + + Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const; + Expected<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const; + Expected<uint64_t> getDynSymtabSize() const; - StringRef getRelocationTypeName(uint32_t Type) const; - void getRelocationTypeName(uint32_t Type, - SmallVectorImpl<char> &Result) const; - uint32_t getRelativeRelocationType() const; - - std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const; - std::string getDynamicTagAsString(uint64_t Type) const; - - /// Get the symbol for a given relocation. + StringRef getRelocationTypeName(uint32_t Type) const; + void getRelocationTypeName(uint32_t Type, + SmallVectorImpl<char> &Result) const; + uint32_t getRelativeRelocationType() const; + + std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const; + std::string getDynamicTagAsString(uint64_t Type) const; + + /// Get the symbol for a given relocation. Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel &Rel, - const Elf_Shdr *SymTab) const; - + const Elf_Shdr *SymTab) const; + Expected<SmallVector<Optional<VersionEntry>, 0>> loadVersionMap(const Elf_Shdr *VerNeedSec, const Elf_Shdr *VerDefSec) const; - static Expected<ELFFile> create(StringRef Object); - - bool isLE() const { + static Expected<ELFFile> create(StringRef Object); + + bool isLE() const { return getHeader().getDataEncoding() == ELF::ELFDATA2LSB; - } - - bool isMipsELF64() const { + } + + bool isMipsELF64() const { return getHeader().e_machine == ELF::EM_MIPS && getHeader().getFileClass() == ELF::ELFCLASS64; - } - - bool isMips64EL() const { return isMipsELF64() && isLE(); } - - Expected<Elf_Shdr_Range> sections() const; - - Expected<Elf_Dyn_Range> dynamicEntries() const; - + } + + bool isMips64EL() const { return isMipsELF64() && isLE(); } + + Expected<Elf_Shdr_Range> sections() const; + + Expected<Elf_Dyn_Range> dynamicEntries() const; + Expected<const uint8_t *> toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler = &defaultWarningHandler) const; - - Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { - if (!Sec) - return makeArrayRef<Elf_Sym>(nullptr, nullptr); + + Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { + if (!Sec) + return makeArrayRef<Elf_Sym>(nullptr, nullptr); return getSectionContentsAsArray<Elf_Sym>(*Sec); - } - + } + Expected<Elf_Rela_Range> relas(const Elf_Shdr &Sec) const { - return getSectionContentsAsArray<Elf_Rela>(Sec); - } - + return getSectionContentsAsArray<Elf_Rela>(Sec); + } + Expected<Elf_Rel_Range> rels(const Elf_Shdr &Sec) const { - return getSectionContentsAsArray<Elf_Rel>(Sec); - } - + return getSectionContentsAsArray<Elf_Rel>(Sec); + } + Expected<Elf_Relr_Range> relrs(const Elf_Shdr &Sec) const { - return getSectionContentsAsArray<Elf_Relr>(Sec); - } - + return getSectionContentsAsArray<Elf_Relr>(Sec); + } + std::vector<Elf_Rel> decode_relrs(Elf_Relr_Range relrs) const; - + Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr &Sec) const; - - /// Iterate over program header table. - Expected<Elf_Phdr_Range> program_headers() const { + + /// Iterate over program header table. + Expected<Elf_Phdr_Range> program_headers() const { if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr)) - return createError("invalid e_phentsize: " + + return createError("invalid e_phentsize: " + Twine(getHeader().e_phentsize)); - - uint64_t HeadersSize = + + uint64_t HeadersSize = (uint64_t)getHeader().e_phnum * getHeader().e_phentsize; uint64_t PhOff = getHeader().e_phoff; - if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize()) - return createError("program headers are longer than binary of size " + - Twine(getBufSize()) + ": e_phoff = 0x" + + if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize()) + return createError("program headers are longer than binary of size " + + Twine(getBufSize()) + ": e_phoff = 0x" + Twine::utohexstr(getHeader().e_phoff) + ", e_phnum = " + Twine(getHeader().e_phnum) + ", e_phentsize = " + Twine(getHeader().e_phentsize)); - - auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff); + + auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff); return makeArrayRef(Begin, Begin + getHeader().e_phnum); - } - - /// Get an iterator over notes in a program header. - /// - /// The program header must be of type \c PT_NOTE. - /// - /// \param Phdr the program header to iterate over. - /// \param Err [out] an error to support fallible iteration, which should - /// be checked after iteration ends. - Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { - assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE"); - ErrorAsOutParameter ErrAsOutParam(&Err); - if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { + } + + /// Get an iterator over notes in a program header. + /// + /// The program header must be of type \c PT_NOTE. + /// + /// \param Phdr the program header to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { + assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE"); + ErrorAsOutParameter ErrAsOutParam(&Err); + if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { Err = createError("invalid offset (0x" + Twine::utohexstr(Phdr.p_offset) + ") or size (0x" + Twine::utohexstr(Phdr.p_filesz) + ")"); - return Elf_Note_Iterator(Err); - } - return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); - } - - /// Get an iterator over notes in a section. - /// - /// The section must be of type \c SHT_NOTE. - /// - /// \param Shdr the section to iterate over. - /// \param Err [out] an error to support fallible iteration, which should - /// be checked after iteration ends. - Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { - assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE"); - ErrorAsOutParameter ErrAsOutParam(&Err); - if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { + return Elf_Note_Iterator(Err); + } + return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); + } + + /// Get an iterator over notes in a section. + /// + /// The section must be of type \c SHT_NOTE. + /// + /// \param Shdr the section to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { + assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE"); + ErrorAsOutParameter ErrAsOutParam(&Err); + if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { Err = createError("invalid offset (0x" + Twine::utohexstr(Shdr.sh_offset) + ") or size (0x" + Twine::utohexstr(Shdr.sh_size) + ")"); - return Elf_Note_Iterator(Err); - } - return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); - } - - /// Get the end iterator for notes. - Elf_Note_Iterator notes_end() const { - return Elf_Note_Iterator(); - } - - /// Get an iterator range over notes of a program header. - /// - /// The program header must be of type \c PT_NOTE. - /// - /// \param Phdr the program header to iterate over. - /// \param Err [out] an error to support fallible iteration, which should - /// be checked after iteration ends. - iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, - Error &Err) const { - return make_range(notes_begin(Phdr, Err), notes_end()); - } - - /// Get an iterator range over notes of a section. - /// - /// The section must be of type \c SHT_NOTE. - /// - /// \param Shdr the section to iterate over. - /// \param Err [out] an error to support fallible iteration, which should - /// be checked after iteration ends. - iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, - Error &Err) const { - return make_range(notes_begin(Shdr, Err), notes_end()); - } - - Expected<StringRef> getSectionStringTable( - Elf_Shdr_Range Sections, - WarningHandler WarnHandler = &defaultWarningHandler) const; + return Elf_Note_Iterator(Err); + } + return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); + } + + /// Get the end iterator for notes. + Elf_Note_Iterator notes_end() const { + return Elf_Note_Iterator(); + } + + /// Get an iterator range over notes of a program header. + /// + /// The program header must be of type \c PT_NOTE. + /// + /// \param Phdr the program header to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, + Error &Err) const { + return make_range(notes_begin(Phdr, Err), notes_end()); + } + + /// Get an iterator range over notes of a section. + /// + /// The section must be of type \c SHT_NOTE. + /// + /// \param Shdr the section to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, + Error &Err) const { + return make_range(notes_begin(Shdr, Err), notes_end()); + } + + Expected<StringRef> getSectionStringTable( + Elf_Shdr_Range Sections, + WarningHandler WarnHandler = &defaultWarningHandler) const; Expected<uint32_t> getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms, DataRegion<Elf_Word> ShndxTable) const; Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym, - const Elf_Shdr *SymTab, + const Elf_Shdr *SymTab, DataRegion<Elf_Word> ShndxTable) const; Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym, - Elf_Sym_Range Symtab, + Elf_Sym_Range Symtab, DataRegion<Elf_Word> ShndxTable) const; - Expected<const Elf_Shdr *> getSection(uint32_t Index) const; - - Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, - uint32_t Index) const; - - Expected<StringRef> + Expected<const Elf_Shdr *> getSection(uint32_t Index) const; + + Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, + uint32_t Index) const; + + Expected<StringRef> getSectionName(const Elf_Shdr &Section, - WarningHandler WarnHandler = &defaultWarningHandler) const; + WarningHandler WarnHandler = &defaultWarningHandler) const; Expected<StringRef> getSectionName(const Elf_Shdr &Section, - StringRef DotShstrtab) const; - template <typename T> + StringRef DotShstrtab) const; + template <typename T> Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr &Sec) const; Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr &Sec) const; Expected<ArrayRef<uint8_t>> getSegmentContents(const Elf_Phdr &Phdr) const; -}; - -using ELF32LEFile = ELFFile<ELF32LE>; -using ELF64LEFile = ELFFile<ELF64LE>; -using ELF32BEFile = ELFFile<ELF32BE>; -using ELF64BEFile = ELFFile<ELF64BE>; - -template <class ELFT> -inline Expected<const typename ELFT::Shdr *> -getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { - if (Index >= Sections.size()) - return createError("invalid section index: " + Twine(Index)); - return &Sections[Index]; -} - -template <class ELFT> -inline Expected<uint32_t> +}; + +using ELF32LEFile = ELFFile<ELF32LE>; +using ELF64LEFile = ELFFile<ELF64LE>; +using ELF32BEFile = ELFFile<ELF32BE>; +using ELF64BEFile = ELFFile<ELF64BE>; + +template <class ELFT> +inline Expected<const typename ELFT::Shdr *> +getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { + if (Index >= Sections.size()) + return createError("invalid section index: " + Twine(Index)); + return &Sections[Index]; +} + +template <class ELFT> +inline Expected<uint32_t> getExtendedSymbolTableIndex(const typename ELFT::Sym &Sym, unsigned SymIndex, DataRegion<typename ELFT::Word> ShndxTable) { assert(Sym.st_shndx == ELF::SHN_XINDEX); if (!ShndxTable.First) - return createError( + return createError( "found an extended symbol index (" + Twine(SymIndex) + "), but unable to locate the extended symbol index table"); - + Expected<typename ELFT::Word> TableOrErr = ShndxTable[SymIndex]; if (!TableOrErr) return createError("unable to read an extended symbol table at index " + Twine(SymIndex) + ": " + toString(TableOrErr.takeError())); return *TableOrErr; -} - -template <class ELFT> -Expected<uint32_t> +} + +template <class ELFT> +Expected<uint32_t> ELFFile<ELFT>::getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms, DataRegion<Elf_Word> ShndxTable) const { uint32_t Index = Sym.st_shndx; - if (Index == ELF::SHN_XINDEX) { + if (Index == ELF::SHN_XINDEX) { Expected<uint32_t> ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>(Sym, &Sym - Syms.begin(), ShndxTable); - if (!ErrorOrIndex) - return ErrorOrIndex.takeError(); - return *ErrorOrIndex; - } - if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) - return 0; - return Index; -} - -template <class ELFT> -Expected<const typename ELFT::Shdr *> + if (!ErrorOrIndex) + return ErrorOrIndex.takeError(); + return *ErrorOrIndex; + } + if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) + return 0; + return Index; +} + +template <class ELFT> +Expected<const typename ELFT::Shdr *> ELFFile<ELFT>::getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab, DataRegion<Elf_Word> ShndxTable) const { - auto SymsOrErr = symbols(SymTab); - if (!SymsOrErr) - return SymsOrErr.takeError(); - return getSection(Sym, *SymsOrErr, ShndxTable); -} - -template <class ELFT> -Expected<const typename ELFT::Shdr *> + auto SymsOrErr = symbols(SymTab); + if (!SymsOrErr) + return SymsOrErr.takeError(); + return getSection(Sym, *SymsOrErr, ShndxTable); +} + +template <class ELFT> +Expected<const typename ELFT::Shdr *> ELFFile<ELFT>::getSection(const Elf_Sym &Sym, Elf_Sym_Range Symbols, DataRegion<Elf_Word> ShndxTable) const { - auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); - if (!IndexOrErr) - return IndexOrErr.takeError(); - uint32_t Index = *IndexOrErr; - if (Index == 0) - return nullptr; - return getSection(Index); -} - -template <class ELFT> -Expected<const typename ELFT::Sym *> -ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { - auto SymsOrErr = symbols(Sec); - if (!SymsOrErr) - return SymsOrErr.takeError(); - - Elf_Sym_Range Symbols = *SymsOrErr; - if (Index >= Symbols.size()) - return createError("unable to get symbol from section " + + auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable); + if (!IndexOrErr) + return IndexOrErr.takeError(); + uint32_t Index = *IndexOrErr; + if (Index == 0) + return nullptr; + return getSection(Index); +} + +template <class ELFT> +Expected<const typename ELFT::Sym *> +ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { + auto SymsOrErr = symbols(Sec); + if (!SymsOrErr) + return SymsOrErr.takeError(); + + Elf_Sym_Range Symbols = *SymsOrErr; + if (Index >= Symbols.size()) + return createError("unable to get symbol from section " + getSecIndexForError(*this, *Sec) + - ": invalid symbol index (" + Twine(Index) + ")"); - return &Symbols[Index]; -} - -template <class ELFT> -template <typename T> -Expected<ArrayRef<T>> + ": invalid symbol index (" + Twine(Index) + ")"); + return &Symbols[Index]; +} + +template <class ELFT> +template <typename T> +Expected<ArrayRef<T>> ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr &Sec) const { if (Sec.sh_entsize != sizeof(T) && sizeof(T) != 1) return createError("section " + getSecIndexForError(*this, Sec) + " has invalid sh_entsize: expected " + Twine(sizeof(T)) + ", but got " + Twine(Sec.sh_entsize)); - + uintX_t Offset = Sec.sh_offset; uintX_t Size = Sec.sh_size; - - if (Size % sizeof(T)) + + if (Size % sizeof(T)) return createError("section " + getSecIndexForError(*this, Sec) + - " has an invalid sh_size (" + Twine(Size) + - ") which is not a multiple of its sh_entsize (" + + " has an invalid sh_size (" + Twine(Size) + + ") which is not a multiple of its sh_entsize (" + Twine(Sec.sh_entsize) + ")"); - if (std::numeric_limits<uintX_t>::max() - Offset < Size) + if (std::numeric_limits<uintX_t>::max() - Offset < Size) return createError("section " + getSecIndexForError(*this, Sec) + - " has a sh_offset (0x" + Twine::utohexstr(Offset) + - ") + sh_size (0x" + Twine::utohexstr(Size) + - ") that cannot be represented"); - if (Offset + Size > Buf.size()) + " has a sh_offset (0x" + Twine::utohexstr(Offset) + + ") + sh_size (0x" + Twine::utohexstr(Size) + + ") that cannot be represented"); + if (Offset + Size > Buf.size()) return createError("section " + getSecIndexForError(*this, Sec) + - " has a sh_offset (0x" + Twine::utohexstr(Offset) + - ") + sh_size (0x" + Twine::utohexstr(Size) + - ") that is greater than the file size (0x" + - Twine::utohexstr(Buf.size()) + ")"); - - if (Offset % alignof(T)) - // TODO: this error is untested. - return createError("unaligned data"); - - const T *Start = reinterpret_cast<const T *>(base() + Offset); - return makeArrayRef(Start, Size / sizeof(T)); -} - -template <class ELFT> -Expected<ArrayRef<uint8_t>> + " has a sh_offset (0x" + Twine::utohexstr(Offset) + + ") + sh_size (0x" + Twine::utohexstr(Size) + + ") that is greater than the file size (0x" + + Twine::utohexstr(Buf.size()) + ")"); + + if (Offset % alignof(T)) + // TODO: this error is untested. + return createError("unaligned data"); + + const T *Start = reinterpret_cast<const T *>(base() + Offset); + return makeArrayRef(Start, Size / sizeof(T)); +} + +template <class ELFT> +Expected<ArrayRef<uint8_t>> ELFFile<ELFT>::getSegmentContents(const Elf_Phdr &Phdr) const { uintX_t Offset = Phdr.p_offset; uintX_t Size = Phdr.p_filesz; - - if (std::numeric_limits<uintX_t>::max() - Offset < Size) + + if (std::numeric_limits<uintX_t>::max() - Offset < Size) return createError("program header " + getPhdrIndexForError(*this, Phdr) + - " has a p_offset (0x" + Twine::utohexstr(Offset) + - ") + p_filesz (0x" + Twine::utohexstr(Size) + - ") that cannot be represented"); - if (Offset + Size > Buf.size()) + " has a p_offset (0x" + Twine::utohexstr(Offset) + + ") + p_filesz (0x" + Twine::utohexstr(Size) + + ") that cannot be represented"); + if (Offset + Size > Buf.size()) return createError("program header " + getPhdrIndexForError(*this, Phdr) + - " has a p_offset (0x" + Twine::utohexstr(Offset) + - ") + p_filesz (0x" + Twine::utohexstr(Size) + - ") that is greater than the file size (0x" + - Twine::utohexstr(Buf.size()) + ")"); - return makeArrayRef(base() + Offset, Size); -} - -template <class ELFT> -Expected<ArrayRef<uint8_t>> + " has a p_offset (0x" + Twine::utohexstr(Offset) + + ") + p_filesz (0x" + Twine::utohexstr(Size) + + ") that is greater than the file size (0x" + + Twine::utohexstr(Buf.size()) + ")"); + return makeArrayRef(base() + Offset, Size); +} + +template <class ELFT> +Expected<ArrayRef<uint8_t>> ELFFile<ELFT>::getSectionContents(const Elf_Shdr &Sec) const { - return getSectionContentsAsArray<uint8_t>(Sec); -} - -template <class ELFT> -StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + return getSectionContentsAsArray<uint8_t>(Sec); +} + +template <class ELFT> +StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { return getELFRelocationTypeName(getHeader().e_machine, Type); -} - -template <class ELFT> -void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, - SmallVectorImpl<char> &Result) const { - if (!isMipsELF64()) { - StringRef Name = getRelocationTypeName(Type); - Result.append(Name.begin(), Name.end()); - } else { - // The Mips N64 ABI allows up to three operations to be specified per - // relocation record. Unfortunately there's no easy way to test for the - // presence of N64 ELFs as they have no special flag that identifies them - // as being N64. We can safely assume at the moment that all Mips - // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough - // information to disambiguate between old vs new ABIs. - uint8_t Type1 = (Type >> 0) & 0xFF; - uint8_t Type2 = (Type >> 8) & 0xFF; - uint8_t Type3 = (Type >> 16) & 0xFF; - - // Concat all three relocation type names. - StringRef Name = getRelocationTypeName(Type1); - Result.append(Name.begin(), Name.end()); - - Name = getRelocationTypeName(Type2); - Result.append(1, '/'); - Result.append(Name.begin(), Name.end()); - - Name = getRelocationTypeName(Type3); - Result.append(1, '/'); - Result.append(Name.begin(), Name.end()); - } -} - -template <class ELFT> -uint32_t ELFFile<ELFT>::getRelativeRelocationType() const { +} + +template <class ELFT> +void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, + SmallVectorImpl<char> &Result) const { + if (!isMipsELF64()) { + StringRef Name = getRelocationTypeName(Type); + Result.append(Name.begin(), Name.end()); + } else { + // The Mips N64 ABI allows up to three operations to be specified per + // relocation record. Unfortunately there's no easy way to test for the + // presence of N64 ELFs as they have no special flag that identifies them + // as being N64. We can safely assume at the moment that all Mips + // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough + // information to disambiguate between old vs new ABIs. + uint8_t Type1 = (Type >> 0) & 0xFF; + uint8_t Type2 = (Type >> 8) & 0xFF; + uint8_t Type3 = (Type >> 16) & 0xFF; + + // Concat all three relocation type names. + StringRef Name = getRelocationTypeName(Type1); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type2); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type3); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + } +} + +template <class ELFT> +uint32_t ELFFile<ELFT>::getRelativeRelocationType() const { return getELFRelativeRelocationType(getHeader().e_machine); -} - -template <class ELFT> +} + +template <class ELFT> Expected<SmallVector<Optional<VersionEntry>, 0>> ELFFile<ELFT>::loadVersionMap(const Elf_Shdr *VerNeedSec, const Elf_Shdr *VerDefSec) const { @@ -626,40 +626,40 @@ ELFFile<ELFT>::loadVersionMap(const Elf_Shdr *VerNeedSec, } template <class ELFT> -Expected<const typename ELFT::Sym *> +Expected<const typename ELFT::Sym *> ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel &Rel, - const Elf_Shdr *SymTab) const { + const Elf_Shdr *SymTab) const { uint32_t Index = Rel.getSymbol(isMips64EL()); - if (Index == 0) - return nullptr; + if (Index == 0) + return nullptr; return getEntry<Elf_Sym>(*SymTab, Index); -} - -template <class ELFT> -Expected<StringRef> -ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections, - WarningHandler WarnHandler) const { +} + +template <class ELFT> +Expected<StringRef> +ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections, + WarningHandler WarnHandler) const { uint32_t Index = getHeader().e_shstrndx; - if (Index == ELF::SHN_XINDEX) { - // If the section name string table section index is greater than - // or equal to SHN_LORESERVE, then the actual index of the section name - // string table section is contained in the sh_link field of the section - // header at index 0. - if (Sections.empty()) - return createError( - "e_shstrndx == SHN_XINDEX, but the section header table is empty"); - - Index = Sections[0].sh_link; - } - - if (!Index) // no section string table. - return ""; - if (Index >= Sections.size()) - return createError("section header string table index " + Twine(Index) + - " does not exist"); + if (Index == ELF::SHN_XINDEX) { + // If the section name string table section index is greater than + // or equal to SHN_LORESERVE, then the actual index of the section name + // string table section is contained in the sh_link field of the section + // header at index 0. + if (Sections.empty()) + return createError( + "e_shstrndx == SHN_XINDEX, but the section header table is empty"); + + Index = Sections[0].sh_link; + } + + if (!Index) // no section string table. + return ""; + if (Index >= Sections.size()) + return createError("section header string table index " + Twine(Index) + + " does not exist"); return getStringTable(Sections[Index], WarnHandler); -} - +} + /// This function finds the number of dynamic symbols using a GNU hash table. /// /// @param Table The GNU hash table for .dynsym. @@ -753,80 +753,80 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const { return 0; } -template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} - -template <class ELFT> -Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { - if (sizeof(Elf_Ehdr) > Object.size()) - return createError("invalid buffer: the size (" + Twine(Object.size()) + - ") is smaller than an ELF header (" + - Twine(sizeof(Elf_Ehdr)) + ")"); - return ELFFile(Object); -} - -template <class ELFT> -Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { +template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} + +template <class ELFT> +Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { + if (sizeof(Elf_Ehdr) > Object.size()) + return createError("invalid buffer: the size (" + Twine(Object.size()) + + ") is smaller than an ELF header (" + + Twine(sizeof(Elf_Ehdr)) + ")"); + return ELFFile(Object); +} + +template <class ELFT> +Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { const uintX_t SectionTableOffset = getHeader().e_shoff; - if (SectionTableOffset == 0) - return ArrayRef<Elf_Shdr>(); - + if (SectionTableOffset == 0) + return ArrayRef<Elf_Shdr>(); + if (getHeader().e_shentsize != sizeof(Elf_Shdr)) - return createError("invalid e_shentsize in ELF header: " + + return createError("invalid e_shentsize in ELF header: " + Twine(getHeader().e_shentsize)); - - const uint64_t FileSize = Buf.size(); - if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || - SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) - return createError( - "section header table goes past the end of the file: e_shoff = 0x" + - Twine::utohexstr(SectionTableOffset)); - - // Invalid address alignment of section headers - if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) - // TODO: this error is untested. - return createError("invalid alignment of section headers"); - - const Elf_Shdr *First = - reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); - + + const uint64_t FileSize = Buf.size(); + if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || + SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) + return createError( + "section header table goes past the end of the file: e_shoff = 0x" + + Twine::utohexstr(SectionTableOffset)); + + // Invalid address alignment of section headers + if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) + // TODO: this error is untested. + return createError("invalid alignment of section headers"); + + const Elf_Shdr *First = + reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); + uintX_t NumSections = getHeader().e_shnum; - if (NumSections == 0) - NumSections = First->sh_size; - - if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) - return createError("invalid number of sections specified in the NULL " - "section's sh_size field (" + - Twine(NumSections) + ")"); - - const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); - if (SectionTableOffset + SectionTableSize < SectionTableOffset) - return createError( - "invalid section header table offset (e_shoff = 0x" + - Twine::utohexstr(SectionTableOffset) + - ") or invalid number of sections specified in the first section " - "header's sh_size field (0x" + - Twine::utohexstr(NumSections) + ")"); - - // Section table goes past end of file! - if (SectionTableOffset + SectionTableSize > FileSize) - return createError("section table goes past the end of file"); - return makeArrayRef(First, NumSections); -} - -template <class ELFT> -template <typename T> -Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, - uint32_t Entry) const { - auto SecOrErr = getSection(Section); - if (!SecOrErr) - return SecOrErr.takeError(); + if (NumSections == 0) + NumSections = First->sh_size; + + if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) + return createError("invalid number of sections specified in the NULL " + "section's sh_size field (" + + Twine(NumSections) + ")"); + + const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); + if (SectionTableOffset + SectionTableSize < SectionTableOffset) + return createError( + "invalid section header table offset (e_shoff = 0x" + + Twine::utohexstr(SectionTableOffset) + + ") or invalid number of sections specified in the first section " + "header's sh_size field (0x" + + Twine::utohexstr(NumSections) + ")"); + + // Section table goes past end of file! + if (SectionTableOffset + SectionTableSize > FileSize) + return createError("section table goes past the end of file"); + return makeArrayRef(First, NumSections); +} + +template <class ELFT> +template <typename T> +Expected<const T *> ELFFile<ELFT>::getEntry(uint32_t Section, + uint32_t Entry) const { + auto SecOrErr = getSection(Section); + if (!SecOrErr) + return SecOrErr.takeError(); return getEntry<T>(**SecOrErr, Entry); -} - -template <class ELFT> -template <typename T> +} + +template <class ELFT> +template <typename T> Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr &Section, - uint32_t Entry) const { + uint32_t Entry) const { Expected<ArrayRef<T>> EntriesOrErr = getSectionContentsAsArray<T>(Section); if (!EntriesOrErr) return EntriesOrErr.takeError(); @@ -839,8 +839,8 @@ Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr &Section, ": it goes past the end of the section (0x" + Twine::utohexstr(Section.sh_size) + ")"); return &Arr[Entry]; -} - +} + template <typename ELFT> Expected<StringRef> ELFFile<ELFT>::getSymbolVersionByIndex( uint32_t SymbolVersionIndex, bool &IsDefault, @@ -869,7 +869,7 @@ Expected<StringRef> ELFFile<ELFT>::getSymbolVersionByIndex( return Entry.Name.c_str(); } -template <class ELFT> +template <class ELFT> Expected<std::vector<VerDef>> ELFFile<ELFT>::getVersionDefinitions(const Elf_Shdr &Sec) const { Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Sec); @@ -1045,104 +1045,104 @@ ELFFile<ELFT>::getVersionDependencies(const Elf_Shdr &Sec, } template <class ELFT> -Expected<const typename ELFT::Shdr *> -ELFFile<ELFT>::getSection(uint32_t Index) const { - auto TableOrErr = sections(); - if (!TableOrErr) - return TableOrErr.takeError(); - return object::getSection<ELFT>(*TableOrErr, Index); -} - -template <class ELFT> -Expected<StringRef> +Expected<const typename ELFT::Shdr *> +ELFFile<ELFT>::getSection(uint32_t Index) const { + auto TableOrErr = sections(); + if (!TableOrErr) + return TableOrErr.takeError(); + return object::getSection<ELFT>(*TableOrErr, Index); +} + +template <class ELFT> +Expected<StringRef> ELFFile<ELFT>::getStringTable(const Elf_Shdr &Section, - WarningHandler WarnHandler) const { + WarningHandler WarnHandler) const { if (Section.sh_type != ELF::SHT_STRTAB) - if (Error E = WarnHandler("invalid sh_type for string table section " + + if (Error E = WarnHandler("invalid sh_type for string table section " + getSecIndexForError(*this, Section) + - ": expected SHT_STRTAB, but got " + - object::getELFSectionTypeName( + ": expected SHT_STRTAB, but got " + + object::getELFSectionTypeName( getHeader().e_machine, Section.sh_type))) - return std::move(E); - - auto V = getSectionContentsAsArray<char>(Section); - if (!V) - return V.takeError(); - ArrayRef<char> Data = *V; - if (Data.empty()) - return createError("SHT_STRTAB string table section " + + return std::move(E); + + auto V = getSectionContentsAsArray<char>(Section); + if (!V) + return V.takeError(); + ArrayRef<char> Data = *V; + if (Data.empty()) + return createError("SHT_STRTAB string table section " + getSecIndexForError(*this, Section) + " is empty"); - if (Data.back() != '\0') - return createError("SHT_STRTAB string table section " + + if (Data.back() != '\0') + return createError("SHT_STRTAB string table section " + getSecIndexForError(*this, Section) + - " is non-null terminated"); - return StringRef(Data.begin(), Data.size()); -} - -template <class ELFT> -Expected<ArrayRef<typename ELFT::Word>> -ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { - auto SectionsOrErr = sections(); - if (!SectionsOrErr) - return SectionsOrErr.takeError(); - return getSHNDXTable(Section, *SectionsOrErr); -} - -template <class ELFT> -Expected<ArrayRef<typename ELFT::Word>> -ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, - Elf_Shdr_Range Sections) const { - assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); + " is non-null terminated"); + return StringRef(Data.begin(), Data.size()); +} + +template <class ELFT> +Expected<ArrayRef<typename ELFT::Word>> +ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + return getSHNDXTable(Section, *SectionsOrErr); +} + +template <class ELFT> +Expected<ArrayRef<typename ELFT::Word>> +ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, + Elf_Shdr_Range Sections) const { + assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); auto VOrErr = getSectionContentsAsArray<Elf_Word>(Section); - if (!VOrErr) - return VOrErr.takeError(); - ArrayRef<Elf_Word> V = *VOrErr; - auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); - if (!SymTableOrErr) - return SymTableOrErr.takeError(); - const Elf_Shdr &SymTable = **SymTableOrErr; - if (SymTable.sh_type != ELF::SHT_SYMTAB && - SymTable.sh_type != ELF::SHT_DYNSYM) + if (!VOrErr) + return VOrErr.takeError(); + ArrayRef<Elf_Word> V = *VOrErr; + auto SymTableOrErr = object::getSection<ELFT>(Sections, Section.sh_link); + if (!SymTableOrErr) + return SymTableOrErr.takeError(); + const Elf_Shdr &SymTable = **SymTableOrErr; + if (SymTable.sh_type != ELF::SHT_SYMTAB && + SymTable.sh_type != ELF::SHT_DYNSYM) return createError( "SHT_SYMTAB_SHNDX section is linked with " + object::getELFSectionTypeName(getHeader().e_machine, SymTable.sh_type) + " section (expected SHT_SYMTAB/SHT_DYNSYM)"); - - uint64_t Syms = SymTable.sh_size / sizeof(Elf_Sym); - if (V.size() != Syms) - return createError("SHT_SYMTAB_SHNDX has " + Twine(V.size()) + - " entries, but the symbol table associated has " + - Twine(Syms)); - - return V; -} - -template <class ELFT> -Expected<StringRef> -ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { - auto SectionsOrErr = sections(); - if (!SectionsOrErr) - return SectionsOrErr.takeError(); - return getStringTableForSymtab(Sec, *SectionsOrErr); -} - -template <class ELFT> -Expected<StringRef> -ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, - Elf_Shdr_Range Sections) const { - - if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) - return createError( - "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); + + uint64_t Syms = SymTable.sh_size / sizeof(Elf_Sym); + if (V.size() != Syms) + return createError("SHT_SYMTAB_SHNDX has " + Twine(V.size()) + + " entries, but the symbol table associated has " + + Twine(Syms)); + + return V; +} + +template <class ELFT> +Expected<StringRef> +ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + return getStringTableForSymtab(Sec, *SectionsOrErr); +} + +template <class ELFT> +Expected<StringRef> +ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, + Elf_Shdr_Range Sections) const { + + if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) + return createError( + "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); Expected<const Elf_Shdr *> SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); - if (!SectionOrErr) - return SectionOrErr.takeError(); + if (!SectionOrErr) + return SectionOrErr.takeError(); return getStringTable(**SectionOrErr); -} - -template <class ELFT> -Expected<StringRef> +} + +template <class ELFT> +Expected<StringRef> ELFFile<ELFT>::getLinkAsStrtab(const typename ELFT::Shdr &Sec) const { Expected<const typename ELFT::Shdr *> StrTabSecOrErr = getSection(Sec.sh_link); @@ -1161,51 +1161,51 @@ ELFFile<ELFT>::getLinkAsStrtab(const typename ELFT::Shdr &Sec) const { template <class ELFT> Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section, - WarningHandler WarnHandler) const { - auto SectionsOrErr = sections(); - if (!SectionsOrErr) - return SectionsOrErr.takeError(); - auto Table = getSectionStringTable(*SectionsOrErr, WarnHandler); - if (!Table) - return Table.takeError(); - return getSectionName(Section, *Table); -} - -template <class ELFT> + WarningHandler WarnHandler) const { + auto SectionsOrErr = sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + auto Table = getSectionStringTable(*SectionsOrErr, WarnHandler); + if (!Table) + return Table.takeError(); + return getSectionName(Section, *Table); +} + +template <class ELFT> Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section, - StringRef DotShstrtab) const { + StringRef DotShstrtab) const { uint32_t Offset = Section.sh_name; - if (Offset == 0) - return StringRef(); - if (Offset >= DotShstrtab.size()) + if (Offset == 0) + return StringRef(); + if (Offset >= DotShstrtab.size()) return createError("a section " + getSecIndexForError(*this, Section) + - " has an invalid sh_name (0x" + - Twine::utohexstr(Offset) + - ") offset which goes past the end of the " - "section name string table"); - return StringRef(DotShstrtab.data() + Offset); -} - -/// This function returns the hash value for a symbol in the .dynsym section -/// Name of the API remains consistent as specified in the libelf -/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash -inline unsigned hashSysV(StringRef SymbolName) { - unsigned h = 0, g; - for (char C : SymbolName) { - h = (h << 4) + C; - g = h & 0xf0000000L; - if (g != 0) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_ELF_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + " has an invalid sh_name (0x" + + Twine::utohexstr(Offset) + + ") offset which goes past the end of the " + "section name string table"); + return StringRef(DotShstrtab.data() + Offset); +} + +/// This function returns the hash value for a symbol in the .dynsym section +/// Name of the API remains consistent as specified in the libelf +/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash +inline unsigned hashSysV(StringRef SymbolName) { + unsigned h = 0, g; + for (char C : SymbolName) { + h = (h << 4) + C; + g = h & 0xf0000000L; + if (g != 0) + h ^= g >> 24; + h &= ~g; + } + return h; +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_ELF_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h index 28c6ec9bfc8..40bd4150202 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h @@ -1,415 +1,415 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the ELFObjectFile template class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ELFOBJECTFILE_H -#define LLVM_OBJECT_ELFOBJECTFILE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ELF.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Object/Error.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/ARMAttributeParser.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ELFAttributes.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include <cassert> -#include <cstdint> -#include <system_error> - -namespace llvm { -namespace object { - -constexpr int NumElfSymbolTypes = 16; -extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes]; - -class elf_symbol_iterator; - -class ELFObjectFileBase : public ObjectFile { - friend class ELFRelocationRef; - friend class ELFSectionRef; - friend class ELFSymbolRef; - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELFOBJECTFILE_H +#define LLVM_OBJECT_ELFOBJECTFILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/ARMAttributeParser.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELFAttributes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cassert> +#include <cstdint> +#include <system_error> + +namespace llvm { +namespace object { + +constexpr int NumElfSymbolTypes = 16; +extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes]; + +class elf_symbol_iterator; + +class ELFObjectFileBase : public ObjectFile { + friend class ELFRelocationRef; + friend class ELFSectionRef; + friend class ELFSymbolRef; + SubtargetFeatures getMIPSFeatures() const; SubtargetFeatures getARMFeatures() const; SubtargetFeatures getRISCVFeatures() const; StringRef getAMDGPUCPUName() const; -protected: - ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); - - virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; - - virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; - - virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; - virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const = 0; - -public: - using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; - - virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; - - /// Returns platform-specific object flags, if any. - virtual unsigned getPlatformFlags() const = 0; - - elf_symbol_iterator_range symbols() const; - - static bool classof(const Binary *v) { return v->isELF(); } - - SubtargetFeatures getFeatures() const override; - +protected: + ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + + virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; + + virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; + + virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; + virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const = 0; + +public: + using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; + + virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; + + /// Returns platform-specific object flags, if any. + virtual unsigned getPlatformFlags() const = 0; + + elf_symbol_iterator_range symbols() const; + + static bool classof(const Binary *v) { return v->isELF(); } + + SubtargetFeatures getFeatures() const override; + Optional<StringRef> tryGetCPUName() const override; - - void setARMSubArch(Triple &TheTriple) const override; - - virtual uint16_t getEType() const = 0; - - virtual uint16_t getEMachine() const = 0; - + + void setARMSubArch(Triple &TheTriple) const override; + + virtual uint16_t getEType() const = 0; + + virtual uint16_t getEMachine() const = 0; + std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> getPltAddresses() const; -}; - -class ELFSectionRef : public SectionRef { -public: - ELFSectionRef(const SectionRef &B) : SectionRef(B) { - assert(isa<ELFObjectFileBase>(SectionRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(SectionRef::getObject()); - } - - uint32_t getType() const { - return getObject()->getSectionType(getRawDataRefImpl()); - } - - uint64_t getFlags() const { - return getObject()->getSectionFlags(getRawDataRefImpl()); - } - - uint64_t getOffset() const { - return getObject()->getSectionOffset(getRawDataRefImpl()); - } -}; - -class elf_section_iterator : public section_iterator { -public: - elf_section_iterator(const section_iterator &B) : section_iterator(B) { - assert(isa<ELFObjectFileBase>(B->getObject())); - } - - const ELFSectionRef *operator->() const { - return static_cast<const ELFSectionRef *>(section_iterator::operator->()); - } - - const ELFSectionRef &operator*() const { - return static_cast<const ELFSectionRef &>(section_iterator::operator*()); - } -}; - -class ELFSymbolRef : public SymbolRef { -public: - ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { - assert(isa<ELFObjectFileBase>(SymbolRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(BasicSymbolRef::getObject()); - } - - uint64_t getSize() const { - return getObject()->getSymbolSize(getRawDataRefImpl()); - } - - uint8_t getBinding() const { - return getObject()->getSymbolBinding(getRawDataRefImpl()); - } - - uint8_t getOther() const { - return getObject()->getSymbolOther(getRawDataRefImpl()); - } - - uint8_t getELFType() const { - return getObject()->getSymbolELFType(getRawDataRefImpl()); - } - - StringRef getELFTypeName() const { - uint8_t Type = getELFType(); - for (auto &EE : ElfSymbolTypes) { - if (EE.Value == Type) { - return EE.AltName; - } - } - return ""; - } -}; - -class elf_symbol_iterator : public symbol_iterator { -public: - elf_symbol_iterator(const basic_symbol_iterator &B) - : symbol_iterator(SymbolRef(B->getRawDataRefImpl(), - cast<ELFObjectFileBase>(B->getObject()))) {} - - const ELFSymbolRef *operator->() const { - return static_cast<const ELFSymbolRef *>(symbol_iterator::operator->()); - } - - const ELFSymbolRef &operator*() const { - return static_cast<const ELFSymbolRef &>(symbol_iterator::operator*()); - } -}; - -class ELFRelocationRef : public RelocationRef { -public: - ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { - assert(isa<ELFObjectFileBase>(RelocationRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(RelocationRef::getObject()); - } - - Expected<int64_t> getAddend() const { - return getObject()->getRelocationAddend(getRawDataRefImpl()); - } -}; - -class elf_relocation_iterator : public relocation_iterator { -public: - elf_relocation_iterator(const relocation_iterator &B) - : relocation_iterator(RelocationRef( - B->getRawDataRefImpl(), cast<ELFObjectFileBase>(B->getObject()))) {} - - const ELFRelocationRef *operator->() const { - return static_cast<const ELFRelocationRef *>( - relocation_iterator::operator->()); - } - - const ELFRelocationRef &operator*() const { - return static_cast<const ELFRelocationRef &>( - relocation_iterator::operator*()); - } -}; - -inline ELFObjectFileBase::elf_symbol_iterator_range -ELFObjectFileBase::symbols() const { - return elf_symbol_iterator_range(symbol_begin(), symbol_end()); -} - -template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { - uint16_t getEMachine() const override; - uint16_t getEType() const override; - uint64_t getSymbolSize(DataRefImpl Sym) const override; - -public: - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - - SectionRef toSectionRef(const Elf_Shdr *Sec) const { - return SectionRef(toDRI(Sec), this); - } - +}; + +class ELFSectionRef : public SectionRef { +public: + ELFSectionRef(const SectionRef &B) : SectionRef(B) { + assert(isa<ELFObjectFileBase>(SectionRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(SectionRef::getObject()); + } + + uint32_t getType() const { + return getObject()->getSectionType(getRawDataRefImpl()); + } + + uint64_t getFlags() const { + return getObject()->getSectionFlags(getRawDataRefImpl()); + } + + uint64_t getOffset() const { + return getObject()->getSectionOffset(getRawDataRefImpl()); + } +}; + +class elf_section_iterator : public section_iterator { +public: + elf_section_iterator(const section_iterator &B) : section_iterator(B) { + assert(isa<ELFObjectFileBase>(B->getObject())); + } + + const ELFSectionRef *operator->() const { + return static_cast<const ELFSectionRef *>(section_iterator::operator->()); + } + + const ELFSectionRef &operator*() const { + return static_cast<const ELFSectionRef &>(section_iterator::operator*()); + } +}; + +class ELFSymbolRef : public SymbolRef { +public: + ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { + assert(isa<ELFObjectFileBase>(SymbolRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(BasicSymbolRef::getObject()); + } + + uint64_t getSize() const { + return getObject()->getSymbolSize(getRawDataRefImpl()); + } + + uint8_t getBinding() const { + return getObject()->getSymbolBinding(getRawDataRefImpl()); + } + + uint8_t getOther() const { + return getObject()->getSymbolOther(getRawDataRefImpl()); + } + + uint8_t getELFType() const { + return getObject()->getSymbolELFType(getRawDataRefImpl()); + } + + StringRef getELFTypeName() const { + uint8_t Type = getELFType(); + for (auto &EE : ElfSymbolTypes) { + if (EE.Value == Type) { + return EE.AltName; + } + } + return ""; + } +}; + +class elf_symbol_iterator : public symbol_iterator { +public: + elf_symbol_iterator(const basic_symbol_iterator &B) + : symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast<ELFObjectFileBase>(B->getObject()))) {} + + const ELFSymbolRef *operator->() const { + return static_cast<const ELFSymbolRef *>(symbol_iterator::operator->()); + } + + const ELFSymbolRef &operator*() const { + return static_cast<const ELFSymbolRef &>(symbol_iterator::operator*()); + } +}; + +class ELFRelocationRef : public RelocationRef { +public: + ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { + assert(isa<ELFObjectFileBase>(RelocationRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(RelocationRef::getObject()); + } + + Expected<int64_t> getAddend() const { + return getObject()->getRelocationAddend(getRawDataRefImpl()); + } +}; + +class elf_relocation_iterator : public relocation_iterator { +public: + elf_relocation_iterator(const relocation_iterator &B) + : relocation_iterator(RelocationRef( + B->getRawDataRefImpl(), cast<ELFObjectFileBase>(B->getObject()))) {} + + const ELFRelocationRef *operator->() const { + return static_cast<const ELFRelocationRef *>( + relocation_iterator::operator->()); + } + + const ELFRelocationRef &operator*() const { + return static_cast<const ELFRelocationRef &>( + relocation_iterator::operator*()); + } +}; + +inline ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFileBase::symbols() const { + return elf_symbol_iterator_range(symbol_begin(), symbol_end()); +} + +template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { + uint16_t getEMachine() const override; + uint16_t getEType() const override; + uint64_t getSymbolSize(DataRefImpl Sym) const override; + +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + SectionRef toSectionRef(const Elf_Shdr *Sec) const { + return SectionRef(toDRI(Sec), this); + } + ELFSymbolRef toSymbolRef(const Elf_Shdr *SymTable, unsigned SymbolNum) const { return ELFSymbolRef({toDRI(SymTable, SymbolNum), this}); } bool IsContentValid() const { return ContentValid; } -private: - ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, - const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, +private: + ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndxSec); - + bool ContentValid = false; -protected: - ELFFile<ELFT> EF; - - const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. - const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. +protected: + ELFFile<ELFT> EF; + + const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. + const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section. - + Error initContent() override; - void moveSymbolNext(DataRefImpl &Symb) const override; - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - uint32_t getSymbolAlignment(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - uint8_t getSymbolBinding(DataRefImpl Symb) const override; - uint8_t getSymbolOther(DataRefImpl Symb) const override; - uint8_t getSymbolELFType(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, - const Elf_Shdr *SymTab) const; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionVirtual(DataRefImpl Sec) const override; - bool isBerkeleyText(DataRefImpl Sec) const override; - bool isBerkeleyData(DataRefImpl Sec) const override; - bool isDebugSection(StringRef SectionName) const override; - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - std::vector<SectionRef> dynamic_relocation_sections() const override; - Expected<section_iterator> - getRelocatedSection(DataRefImpl Sec) const override; - - void moveRelocationNext(DataRefImpl &Rel) const override; - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - - uint32_t getSectionType(DataRefImpl Sec) const override; - uint64_t getSectionFlags(DataRefImpl Sec) const override; - uint64_t getSectionOffset(DataRefImpl Sec) const override; - StringRef getRelocationTypeName(uint32_t Type) const; - - DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { - DataRefImpl DRI; - if (!SymTable) { - DRI.d.a = 0; - DRI.d.b = 0; - return DRI; - } - assert(SymTable->sh_type == ELF::SHT_SYMTAB || - SymTable->sh_type == ELF::SHT_DYNSYM); - - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) { - DRI.d.a = 0; - DRI.d.b = 0; - return DRI; - } - uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); - unsigned SymTableIndex = - (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr); - - DRI.d.a = SymTableIndex; - DRI.d.b = SymbolNum; - return DRI; - } - - const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { - return reinterpret_cast<const Elf_Shdr *>(Sec.p); - } - - DataRefImpl toDRI(const Elf_Shdr *Sec) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(Sec); - return DRI; - } - - DataRefImpl toDRI(const Elf_Dyn *Dyn) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(Dyn); - return DRI; - } - - bool isExportedToOtherDSO(const Elf_Sym *ESym) const { - unsigned char Binding = ESym->getBinding(); - unsigned char Visibility = ESym->getVisibility(); - - // A symbol is exported if its binding is either GLOBAL or WEAK, and its - // visibility is either DEFAULT or PROTECTED. All other symbols are not - // exported. - return ( - (Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK || - Binding == ELF::STB_GNU_UNIQUE) && - (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)); - } - - Error getBuildAttributes(ELFAttributeParser &Attributes) const override { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return SectionsOrErr.takeError(); - - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || - Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { + void moveSymbolNext(DataRefImpl &Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + uint8_t getSymbolBinding(DataRefImpl Symb) const override; + uint8_t getSymbolOther(DataRefImpl Symb) const override; + uint8_t getSymbolELFType(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, + const Elf_Shdr *SymTab) const; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isBerkeleyText(DataRefImpl Sec) const override; + bool isBerkeleyData(DataRefImpl Sec) const override; + bool isDebugSection(StringRef SectionName) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + std::vector<SectionRef> dynamic_relocation_sections() const override; + Expected<section_iterator> + getRelocatedSection(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + uint32_t getSectionType(DataRefImpl Sec) const override; + uint64_t getSectionFlags(DataRefImpl Sec) const override; + uint64_t getSectionOffset(DataRefImpl Sec) const override; + StringRef getRelocationTypeName(uint32_t Type) const; + + DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { + DataRefImpl DRI; + if (!SymTable) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + assert(SymTable->sh_type == ELF::SHT_SYMTAB || + SymTable->sh_type == ELF::SHT_DYNSYM); + + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); + unsigned SymTableIndex = + (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr); + + DRI.d.a = SymTableIndex; + DRI.d.b = SymbolNum; + return DRI; + } + + const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { + return reinterpret_cast<const Elf_Shdr *>(Sec.p); + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Sec); + return DRI; + } + + DataRefImpl toDRI(const Elf_Dyn *Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Dyn); + return DRI; + } + + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + // A symbol is exported if its binding is either GLOBAL or WEAK, and its + // visibility is either DEFAULT or PROTECTED. All other symbols are not + // exported. + return ( + (Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK || + Binding == ELF::STB_GNU_UNIQUE) && + (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)); + } + + Error getBuildAttributes(ELFAttributeParser &Attributes) const override { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || + Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { auto ErrorOrContents = EF.getSectionContents(Sec); - if (!ErrorOrContents) - return ErrorOrContents.takeError(); - - auto Contents = ErrorOrContents.get(); - if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) - return Error::success(); - - if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) - return E; - break; - } - } - return Error::success(); - } - - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; - -public: - ELFObjectFile(ELFObjectFile<ELFT> &&Other); + if (!ErrorOrContents) + return ErrorOrContents.takeError(); + + auto Contents = ErrorOrContents.get(); + if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) + return Error::success(); + + if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) + return E; + break; + } + } + return Error::success(); + } + + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +public: + ELFObjectFile(ELFObjectFile<ELFT> &&Other); static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object, bool InitContent = true); - - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; - + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const { return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b); - } - + } + /// Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { auto RelSecOrErr = EF.getSection(Rel.d.a); @@ -418,51 +418,51 @@ public: return *RelSecOrErr; } - const Elf_Shdr *getSection(DataRefImpl Sec) const { - return reinterpret_cast<const Elf_Shdr *>(Sec.p); - } - - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - - elf_symbol_iterator dynamic_symbol_begin() const; - elf_symbol_iterator dynamic_symbol_end() const; - - section_iterator section_begin() const override; - section_iterator section_end() const override; - - Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const override; - - uint8_t getBytesInAddress() const override; - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - Expected<uint64_t> getStartAddress() const override; - + const Elf_Shdr *getSection(DataRefImpl Sec) const { + return reinterpret_cast<const Elf_Shdr *>(Sec.p); + } + + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + elf_symbol_iterator dynamic_symbol_begin() const; + elf_symbol_iterator dynamic_symbol_end() const; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + + Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const override; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + Expected<uint64_t> getStartAddress() const override; + unsigned getPlatformFlags() const override { return EF.getHeader().e_flags; } - + const ELFFile<ELFT> &getELFFile() const { return EF; } - - bool isDyldType() const { return isDyldELFObject; } - static bool classof(const Binary *v) { - return v->getType() == getELFType(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } - - elf_symbol_iterator_range getDynamicSymbolIterators() const override; - - bool isRelocatableObject() const override; -}; - -using ELF32LEObjectFile = ELFObjectFile<ELF32LE>; -using ELF64LEObjectFile = ELFObjectFile<ELF64LE>; -using ELF32BEObjectFile = ELFObjectFile<ELF32BE>; -using ELF64BEObjectFile = ELFObjectFile<ELF64BE>; - -template <class ELFT> -void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { - ++Sym.d.b; -} - + + bool isDyldType() const { return isDyldELFObject; } + static bool classof(const Binary *v) { + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); + } + + elf_symbol_iterator_range getDynamicSymbolIterators() const override; + + bool isRelocatableObject() const override; +}; + +using ELF32LEObjectFile = ELFObjectFile<ELF32LE>; +using ELF64LEObjectFile = ELFObjectFile<ELF64LE>; +using ELF32BEObjectFile = ELFObjectFile<ELF32BE>; +using ELF64BEObjectFile = ELFObjectFile<ELF64BE>; + +template <class ELFT> +void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { + ++Sym.d.b; +} + template <class ELFT> Error ELFObjectFile<ELFT>::initContent() { auto SectionsOrErr = EF.sections(); if (!SectionsOrErr) @@ -492,94 +492,94 @@ template <class ELFT> Error ELFObjectFile<ELFT>::initContent() { return Error::success(); } -template <class ELFT> -Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { +template <class ELFT> +Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) return SymOrErr.takeError(); - auto SymTabOrErr = EF.getSection(Sym.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); - const Elf_Shdr *SymTableSec = *SymTabOrErr; - auto StrTabOrErr = EF.getSection(SymTableSec->sh_link); - if (!StrTabOrErr) - return StrTabOrErr.takeError(); - const Elf_Shdr *StringTableSec = *StrTabOrErr; + auto SymTabOrErr = EF.getSection(Sym.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + const Elf_Shdr *SymTableSec = *SymTabOrErr; + auto StrTabOrErr = EF.getSection(SymTableSec->sh_link); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + const Elf_Shdr *StringTableSec = *StrTabOrErr; auto SymStrTabOrErr = EF.getStringTable(*StringTableSec); - if (!SymStrTabOrErr) - return SymStrTabOrErr.takeError(); + if (!SymStrTabOrErr) + return SymStrTabOrErr.takeError(); Expected<StringRef> Name = (*SymOrErr)->getName(*SymStrTabOrErr); - if (Name && !Name->empty()) - return Name; - - // If the symbol name is empty use the section name. + if (Name && !Name->empty()) + return Name; + + // If the symbol name is empty use the section name. if ((*SymOrErr)->getType() == ELF::STT_SECTION) { - if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) { - consumeError(Name.takeError()); - return (*SecOrErr)->getName(); - } - } - return Name; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags; -} - -template <class ELFT> -uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { - return getSection(Sec)->sh_type; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionOffset(DataRefImpl Sec) const { - return getSection(Sec)->sh_offset; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { + if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) { + consumeError(Name.takeError()); + return (*SecOrErr)->getName(); + } + } + return Name; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags; +} + +template <class ELFT> +uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { + return getSection(Sec)->sh_type; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionOffset(DataRefImpl Sec) const { + return getSection(Sec)->sh_offset; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); uint64_t Ret = (*SymOrErr)->st_value; if ((*SymOrErr)->st_shndx == ELF::SHN_ABS) - return Ret; - + return Ret; + const Elf_Ehdr &Header = EF.getHeader(); - // Clear the ARM/Thumb or microMIPS indicator flag. + // Clear the ARM/Thumb or microMIPS indicator flag. if ((Header.e_machine == ELF::EM_ARM || Header.e_machine == ELF::EM_MIPS) && (*SymOrErr)->getType() == ELF::STT_FUNC) - Ret &= ~1; - - return Ret; -} - -template <class ELFT> -Expected<uint64_t> -ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { - Expected<uint64_t> SymbolValueOrErr = getSymbolValue(Symb); - if (!SymbolValueOrErr) - // TODO: Test this error. - return SymbolValueOrErr.takeError(); - - uint64_t Result = *SymbolValueOrErr; + Ret &= ~1; + + return Ret; +} + +template <class ELFT> +Expected<uint64_t> +ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { + Expected<uint64_t> SymbolValueOrErr = getSymbolValue(Symb); + if (!SymbolValueOrErr) + // TODO: Test this error. + return SymbolValueOrErr.takeError(); + + uint64_t Result = *SymbolValueOrErr; Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); switch ((*SymOrErr)->st_shndx) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - case ELF::SHN_ABS: - return Result; - } - - auto SymTabOrErr = EF.getSection(Symb.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); - + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + case ELF::SHN_ABS: + return Result; + } + + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + if (EF.getHeader().e_type == ELF::ET_REL) { ArrayRef<Elf_Word> ShndxTable; if (DotSymtabShndxSec) { @@ -593,169 +593,169 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { Expected<const Elf_Shdr *> SectionOrErr = EF.getSection(**SymOrErr, *SymTabOrErr, ShndxTable); - if (!SectionOrErr) - return SectionOrErr.takeError(); - const Elf_Shdr *Section = *SectionOrErr; - if (Section) - Result += Section->sh_addr; - } - - return Result; -} - -template <class ELFT> -uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { + if (!SectionOrErr) + return SectionOrErr.takeError(); + const Elf_Shdr *Section = *SectionOrErr; + if (Section) + Result += Section->sh_addr; + } + + return Result; +} + +template <class ELFT> +uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); if ((*SymOrErr)->st_shndx == ELF::SHN_COMMON) return (*SymOrErr)->st_value; - return 0; -} - -template <class ELFT> -uint16_t ELFObjectFile<ELFT>::getEMachine() const { + return 0; +} + +template <class ELFT> +uint16_t ELFObjectFile<ELFT>::getEMachine() const { return EF.getHeader().e_machine; -} - -template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const { +} + +template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const { return EF.getHeader().e_type; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->st_size; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const { +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const { return getSymbolSize(Symb); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->getBinding(); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->st_other; -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->getType(); -} - -template <class ELFT> -Expected<SymbolRef::Type> -ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { +} + +template <class ELFT> +Expected<SymbolRef::Type> +ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); - + switch ((*SymOrErr)->getType()) { - case ELF::STT_NOTYPE: - return SymbolRef::ST_Unknown; - case ELF::STT_SECTION: - return SymbolRef::ST_Debug; - case ELF::STT_FILE: - return SymbolRef::ST_File; - case ELF::STT_FUNC: - return SymbolRef::ST_Function; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - return SymbolRef::ST_Data; - default: - return SymbolRef::ST_Other; - } -} - -template <class ELFT> -Expected<uint32_t> ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { + case ELF::STT_NOTYPE: + return SymbolRef::ST_Unknown; + case ELF::STT_SECTION: + return SymbolRef::ST_Debug; + case ELF::STT_FILE: + return SymbolRef::ST_File; + case ELF::STT_FUNC: + return SymbolRef::ST_Function; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + return SymbolRef::ST_Data; + default: + return SymbolRef::ST_Other; + } +} + +template <class ELFT> +Expected<uint32_t> ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) return SymOrErr.takeError(); - + const Elf_Sym *ESym = *SymOrErr; - uint32_t Result = SymbolRef::SF_None; - - if (ESym->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (ESym->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (ESym->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) - Result |= SymbolRef::SF_FormatSpecific; - - if (Expected<typename ELFT::SymRange> SymbolsOrErr = - EF.symbols(DotSymtabSec)) { - // Set the SF_FormatSpecific flag for the 0-index null symbol. - if (ESym == SymbolsOrErr->begin()) - Result |= SymbolRef::SF_FormatSpecific; - } else - // TODO: Test this error. - return SymbolsOrErr.takeError(); - - if (Expected<typename ELFT::SymRange> SymbolsOrErr = - EF.symbols(DotDynSymSec)) { - // Set the SF_FormatSpecific flag for the 0-index null symbol. - if (ESym == SymbolsOrErr->begin()) - Result |= SymbolRef::SF_FormatSpecific; - } else - // TODO: Test this error. - return SymbolsOrErr.takeError(); - + uint32_t Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) + Result |= SymbolRef::SF_FormatSpecific; + + if (Expected<typename ELFT::SymRange> SymbolsOrErr = + EF.symbols(DotSymtabSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); + + if (Expected<typename ELFT::SymRange> SymbolsOrErr = + EF.symbols(DotDynSymSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); + if (EF.getHeader().e_machine == ELF::EM_ARM) { - if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { - StringRef Name = *NameOrErr; - if (Name.startswith("$d") || Name.startswith("$t") || - Name.startswith("$a")) - Result |= SymbolRef::SF_FormatSpecific; - } else { - // TODO: Actually report errors helpfully. - consumeError(NameOrErr.takeError()); - } - if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) - Result |= SymbolRef::SF_Thumb; - } - - if (ESym->st_shndx == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (isExportedToOtherDSO(ESym)) - Result |= SymbolRef::SF_Exported; - - if (ESym->getVisibility() == ELF::STV_HIDDEN) - Result |= SymbolRef::SF_Hidden; - - return Result; -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, - const Elf_Shdr *SymTab) const { + if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { + StringRef Name = *NameOrErr; + if (Name.startswith("$d") || Name.startswith("$t") || + Name.startswith("$a")) + Result |= SymbolRef::SF_FormatSpecific; + } else { + // TODO: Actually report errors helpfully. + consumeError(NameOrErr.takeError()); + } + if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) + Result |= SymbolRef::SF_Thumb; + } + + if (ESym->st_shndx == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + + if (ESym->getVisibility() == ELF::STV_HIDDEN) + Result |= SymbolRef::SF_Hidden; + + return Result; +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, + const Elf_Shdr *SymTab) const { ArrayRef<Elf_Word> ShndxTable; if (DotSymtabShndxSec) { // TODO: Test this error. @@ -767,550 +767,550 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, } auto ESecOrErr = EF.getSection(*ESym, SymTab, ShndxTable); - if (!ESecOrErr) - return ESecOrErr.takeError(); - - const Elf_Shdr *ESec = *ESecOrErr; - if (!ESec) - return section_end(); - - DataRefImpl Sec; - Sec.p = reinterpret_cast<intptr_t>(ESec); - return section_iterator(SectionRef(Sec, this)); -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { + if (!ESecOrErr) + return ESecOrErr.takeError(); + + const Elf_Shdr *ESec = *ESecOrErr; + if (!ESec) + return section_end(); + + DataRefImpl Sec; + Sec.p = reinterpret_cast<intptr_t>(ESec); + return section_iterator(SectionRef(Sec, this)); +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); - auto SymTabOrErr = EF.getSection(Symb.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); return getSymbolSection(*SymOrErr, *SymTabOrErr); -} - -template <class ELFT> -void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { - const Elf_Shdr *ESec = getSection(Sec); - Sec = toDRI(++ESec); -} - -template <class ELFT> -Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const { +} + +template <class ELFT> +void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { + const Elf_Shdr *ESec = getSection(Sec); + Sec = toDRI(++ESec); +} + +template <class ELFT> +Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const { return EF.getSectionName(*getSection(Sec)); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const { - return getSection(Sec)->sh_addr; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionIndex(DataRefImpl Sec) const { - auto SectionsOrErr = EF.sections(); - handleAllErrors(std::move(SectionsOrErr.takeError()), - [](const ErrorInfoBase &) { - llvm_unreachable("unable to get section index"); - }); - const Elf_Shdr *First = SectionsOrErr->begin(); - return getSection(Sec) - First; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { - return getSection(Sec)->sh_size; -} - -template <class ELFT> -Expected<ArrayRef<uint8_t>> -ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - if (EShdr->sh_type == ELF::SHT_NOBITS) - return makeArrayRef((const uint8_t *)base(), 0); - if (Error E = - checkOffset(getMemoryBufferRef(), - (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) - return std::move(E); - return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset, - EShdr->sh_size); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { - return getSection(Sec)->sh_addralign; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return EShdr->sh_type == ELF::SHT_PROGBITS && - EShdr->sh_flags & ELF::SHF_ALLOC && - !(EShdr->sh_flags & ELF::SHF_EXECINSTR); -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_NOBITS; -} - -template <class ELFT> -std::vector<SectionRef> -ELFObjectFile<ELFT>::dynamic_relocation_sections() const { - std::vector<SectionRef> Res; - std::vector<uintptr_t> Offsets; - - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return Res; - - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type != ELF::SHT_DYNAMIC) - continue; - Elf_Dyn *Dynamic = - reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset); - for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) { - if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA || - Dynamic->d_tag == ELF::DT_JMPREL) { - Offsets.push_back(Dynamic->d_un.d_val); - } - } - } - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (is_contained(Offsets, Sec.sh_addr)) - Res.emplace_back(toDRI(&Sec), this); - } - return Res; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { - return getSection(Sec)->sh_type == ELF::SHT_NOBITS; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isBerkeleyText(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_ALLOC && - (getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR || - !(getSection(Sec)->sh_flags & ELF::SHF_WRITE)); -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isBerkeleyData(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return !isBerkeleyText(Sec) && EShdr->sh_type != ELF::SHT_NOBITS && - EShdr->sh_flags & ELF::SHF_ALLOC; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isDebugSection(StringRef SectionName) const { - return SectionName.startswith(".debug") || - SectionName.startswith(".zdebug") || SectionName == ".gdb_index"; -} - -template <class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { - DataRefImpl RelData; - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return relocation_iterator(RelocationRef()); - uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const { + return getSection(Sec)->sh_addr; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionIndex(DataRefImpl Sec) const { + auto SectionsOrErr = EF.sections(); + handleAllErrors(std::move(SectionsOrErr.takeError()), + [](const ErrorInfoBase &) { + llvm_unreachable("unable to get section index"); + }); + const Elf_Shdr *First = SectionsOrErr->begin(); + return getSection(Sec) - First; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { + return getSection(Sec)->sh_size; +} + +template <class ELFT> +Expected<ArrayRef<uint8_t>> +ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + if (EShdr->sh_type == ELF::SHT_NOBITS) + return makeArrayRef((const uint8_t *)base(), 0); + if (Error E = + checkOffset(getMemoryBufferRef(), + (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) + return std::move(E); + return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset, + EShdr->sh_size); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { + return getSection(Sec)->sh_addralign; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_type == ELF::SHT_PROGBITS && + EShdr->sh_flags & ELF::SHF_ALLOC && + !(EShdr->sh_flags & ELF::SHF_EXECINSTR); +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; +} + +template <class ELFT> +std::vector<SectionRef> +ELFObjectFile<ELFT>::dynamic_relocation_sections() const { + std::vector<SectionRef> Res; + std::vector<uintptr_t> Offsets; + + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return Res; + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type != ELF::SHT_DYNAMIC) + continue; + Elf_Dyn *Dynamic = + reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset); + for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) { + if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA || + Dynamic->d_tag == ELF::DT_JMPREL) { + Offsets.push_back(Dynamic->d_un.d_val); + } + } + } + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (is_contained(Offsets, Sec.sh_addr)) + Res.emplace_back(toDRI(&Sec), this); + } + return Res; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { + return getSection(Sec)->sh_type == ELF::SHT_NOBITS; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isBerkeleyText(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_ALLOC && + (getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR || + !(getSection(Sec)->sh_flags & ELF::SHF_WRITE)); +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isBerkeleyData(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return !isBerkeleyText(Sec) && EShdr->sh_type != ELF::SHT_NOBITS && + EShdr->sh_flags & ELF::SHF_ALLOC; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isDebugSection(StringRef SectionName) const { + return SectionName.startswith(".debug") || + SectionName.startswith(".zdebug") || SectionName == ".gdb_index"; +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { + DataRefImpl RelData; + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return relocation_iterator(RelocationRef()); + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize; - RelData.d.b = 0; - return relocation_iterator(RelocationRef(RelData, this)); -} - -template <class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); - relocation_iterator Begin = section_rel_begin(Sec); - if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) - return Begin; - DataRefImpl RelData = Begin->getRawDataRefImpl(); - const Elf_Shdr *RelSec = getRelSection(RelData); - - // Error check sh_link here so that getRelocationSymbol can just use it. - auto SymSecOrErr = EF.getSection(RelSec->sh_link); - if (!SymSecOrErr) - report_fatal_error(errorToErrorCode(SymSecOrErr.takeError()).message()); - - RelData.d.b += S->sh_size / S->sh_entsize; - return relocation_iterator(RelocationRef(RelData, this)); -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + relocation_iterator Begin = section_rel_begin(Sec); + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + return Begin; + DataRefImpl RelData = Begin->getRawDataRefImpl(); + const Elf_Shdr *RelSec = getRelSection(RelData); + + // Error check sh_link here so that getRelocationSymbol can just use it. + auto SymSecOrErr = EF.getSection(RelSec->sh_link); + if (!SymSecOrErr) + report_fatal_error(errorToErrorCode(SymSecOrErr.takeError()).message()); + + RelData.d.b += S->sh_size / S->sh_entsize; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader().e_type != ELF::ET_REL) - return section_end(); - - const Elf_Shdr *EShdr = getSection(Sec); - uintX_t Type = EShdr->sh_type; - if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) - return section_end(); - - Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info); - if (!SecOrErr) - return SecOrErr.takeError(); - return section_iterator(SectionRef(toDRI(*SecOrErr), this)); -} - -// Relocations -template <class ELFT> -void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { - ++Rel.d.b; -} - -template <class ELFT> -symbol_iterator -ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); - else - symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); - if (!symbolIdx) - return symbol_end(); - - // FIXME: error check symbolIdx - DataRefImpl SymbolData; - SymbolData.d.a = sec->sh_link; - SymbolData.d.b = symbolIdx; - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - return getRel(Rel)->r_offset; - - return getRela(Rel)->r_offset; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const { - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - return getRel(Rel)->getType(EF.isMips64EL()); - else - return getRela(Rel)->getType(EF.isMips64EL()); -} - -template <class ELFT> -StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + return section_end(); + + const Elf_Shdr *EShdr = getSection(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return section_end(); + + Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info); + if (!SecOrErr) + return SecOrErr.takeError(); + return section_iterator(SectionRef(toDRI(*SecOrErr), this)); +} + +// Relocations +template <class ELFT> +void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { + ++Rel.d.b; +} + +template <class ELFT> +symbol_iterator +ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); + else + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + if (!symbolIdx) + return symbol_end(); + + // FIXME: error check symbolIdx + DataRefImpl SymbolData; + SymbolData.d.a = sec->sh_link; + SymbolData.d.b = symbolIdx; + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->r_offset; + + return getRela(Rel)->r_offset; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->getType(EF.isMips64EL()); + else + return getRela(Rel)->getType(EF.isMips64EL()); +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { return getELFRelocationTypeName(EF.getHeader().e_machine, Type); -} - -template <class ELFT> -void ELFObjectFile<ELFT>::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - uint32_t type = getRelocationType(Rel); - EF.getRelocationTypeName(type, Result); -} - -template <class ELFT> -Expected<int64_t> -ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const { - if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) - return createError("Section is not SHT_RELA"); - return (int64_t)getRela(Rel)->r_addend; -} - -template <class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rel * -ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { - assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); - auto Ret = EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); - if (!Ret) - report_fatal_error(errorToErrorCode(Ret.takeError()).message()); - return *Ret; -} - -template <class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rela * -ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { - assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); - auto Ret = EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); - if (!Ret) - report_fatal_error(errorToErrorCode(Ret.takeError()).message()); - return *Ret; -} - -template <class ELFT> -Expected<ELFObjectFile<ELFT>> +} + +template <class ELFT> +void ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + uint32_t type = getRelocationType(Rel); + EF.getRelocationTypeName(type, Result); +} + +template <class ELFT> +Expected<int64_t> +ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const { + if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) + return createError("Section is not SHT_RELA"); + return (int64_t)getRela(Rel)->r_addend; +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rel * +ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { + assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); + auto Ret = EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rela * +ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { + assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); + auto Ret = EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; +} + +template <class ELFT> +Expected<ELFObjectFile<ELFT>> ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) { - auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer()); - if (Error E = EFOrErr.takeError()) - return std::move(E); - + auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer()); + if (Error E = EFOrErr.takeError()) + return std::move(E); + ELFObjectFile<ELFT> Obj = {Object, std::move(*EFOrErr), nullptr, nullptr, nullptr}; if (InitContent) if (Error E = Obj.initContent()) return std::move(E); return std::move(Obj); -} - -template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, - const Elf_Shdr *DotDynSymSec, - const Elf_Shdr *DotSymtabSec, +} + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, + const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndx) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), - Object), - EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), + : ELFObjectFileBase( + getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), + Object), + EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), DotSymtabShndxSec(DotSymtabShndx) {} - -template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) - : ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec, + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) + : ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec, Other.DotSymtabSec, Other.DotSymtabShndxSec) {} - -template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { - DataRefImpl Sym = - toDRI(DotSymtabSec, - DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const { - const Elf_Shdr *SymTab = DotSymtabSec; - if (!SymTab) - return symbol_begin(); - DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { - if (!DotDynSymSec || DotDynSymSec->sh_size < sizeof(Elf_Sym)) - // Ignore errors here where the dynsym is empty or sh_size less than the - // size of one symbol. These should be handled elsewhere. - return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 0), this)); - // Skip 0-index NULL symbol. - return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 1), this)); -} - -template <class ELFT> -elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { - const Elf_Shdr *SymTab = DotDynSymSec; - if (!SymTab) - return dynamic_symbol_begin(); - DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -section_iterator ELFObjectFile<ELFT>::section_begin() const { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return section_iterator(SectionRef()); - return section_iterator(SectionRef(toDRI((*SectionsOrErr).begin()), this)); -} - -template <class ELFT> -section_iterator ELFObjectFile<ELFT>::section_end() const { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return section_iterator(SectionRef()); - return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this)); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { - return ELFT::Is64Bits ? 8 : 4; -} - -template <class ELFT> -StringRef ELFObjectFile<ELFT>::getFileFormatName() const { - bool IsLittleEndian = ELFT::TargetEndianness == support::little; + +template <class ELFT> +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { + DataRefImpl Sym = + toDRI(DotSymtabSec, + DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const { + const Elf_Shdr *SymTab = DotSymtabSec; + if (!SymTab) + return symbol_begin(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { + if (!DotDynSymSec || DotDynSymSec->sh_size < sizeof(Elf_Sym)) + // Ignore errors here where the dynsym is empty or sh_size less than the + // size of one symbol. These should be handled elsewhere. + return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 0), this)); + // Skip 0-index NULL symbol. + return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 1), this)); +} + +template <class ELFT> +elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { + const Elf_Shdr *SymTab = DotDynSymSec; + if (!SymTab) + return dynamic_symbol_begin(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::section_begin() const { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).begin()), this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::section_end() const { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this)); +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getFileFormatName() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: + case ELF::ELFCLASS32: switch (EF.getHeader().e_machine) { - case ELF::EM_386: - return "elf32-i386"; - case ELF::EM_IAMCU: - return "elf32-iamcu"; - case ELF::EM_X86_64: - return "elf32-x86-64"; - case ELF::EM_ARM: - return (IsLittleEndian ? "elf32-littlearm" : "elf32-bigarm"); - case ELF::EM_AVR: - return "elf32-avr"; - case ELF::EM_HEXAGON: - return "elf32-hexagon"; - case ELF::EM_LANAI: - return "elf32-lanai"; - case ELF::EM_MIPS: - return "elf32-mips"; - case ELF::EM_MSP430: - return "elf32-msp430"; - case ELF::EM_PPC: + case ELF::EM_386: + return "elf32-i386"; + case ELF::EM_IAMCU: + return "elf32-iamcu"; + case ELF::EM_X86_64: + return "elf32-x86-64"; + case ELF::EM_ARM: + return (IsLittleEndian ? "elf32-littlearm" : "elf32-bigarm"); + case ELF::EM_AVR: + return "elf32-avr"; + case ELF::EM_HEXAGON: + return "elf32-hexagon"; + case ELF::EM_LANAI: + return "elf32-lanai"; + case ELF::EM_MIPS: + return "elf32-mips"; + case ELF::EM_MSP430: + return "elf32-msp430"; + case ELF::EM_PPC: return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc"); - case ELF::EM_RISCV: - return "elf32-littleriscv"; + case ELF::EM_RISCV: + return "elf32-littleriscv"; case ELF::EM_CSKY: return "elf32-csky"; - case ELF::EM_SPARC: - case ELF::EM_SPARC32PLUS: - return "elf32-sparc"; - case ELF::EM_AMDGPU: - return "elf32-amdgpu"; - default: - return "elf32-unknown"; - } - case ELF::ELFCLASS64: + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return "elf32-sparc"; + case ELF::EM_AMDGPU: + return "elf32-amdgpu"; + default: + return "elf32-unknown"; + } + case ELF::ELFCLASS64: switch (EF.getHeader().e_machine) { - case ELF::EM_386: - return "elf64-i386"; - case ELF::EM_X86_64: - return "elf64-x86-64"; - case ELF::EM_AARCH64: - return (IsLittleEndian ? "elf64-littleaarch64" : "elf64-bigaarch64"); - case ELF::EM_PPC64: - return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); - case ELF::EM_RISCV: - return "elf64-littleriscv"; - case ELF::EM_S390: - return "elf64-s390"; - case ELF::EM_SPARCV9: - return "elf64-sparc"; - case ELF::EM_MIPS: - return "elf64-mips"; - case ELF::EM_AMDGPU: - return "elf64-amdgpu"; - case ELF::EM_BPF: - return "elf64-bpf"; - case ELF::EM_VE: - return "elf64-ve"; - default: - return "elf64-unknown"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { - bool IsLittleEndian = ELFT::TargetEndianness == support::little; + case ELF::EM_386: + return "elf64-i386"; + case ELF::EM_X86_64: + return "elf64-x86-64"; + case ELF::EM_AARCH64: + return (IsLittleEndian ? "elf64-littleaarch64" : "elf64-bigaarch64"); + case ELF::EM_PPC64: + return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); + case ELF::EM_RISCV: + return "elf64-littleriscv"; + case ELF::EM_S390: + return "elf64-s390"; + case ELF::EM_SPARCV9: + return "elf64-sparc"; + case ELF::EM_MIPS: + return "elf64-mips"; + case ELF::EM_AMDGPU: + return "elf64-amdgpu"; + case ELF::EM_BPF: + return "elf64-bpf"; + case ELF::EM_VE: + return "elf64-ve"; + default: + return "elf64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader().e_machine) { - case ELF::EM_386: - case ELF::EM_IAMCU: - return Triple::x86; - case ELF::EM_X86_64: - return Triple::x86_64; - case ELF::EM_AARCH64: - return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; - case ELF::EM_ARM: - return Triple::arm; - case ELF::EM_AVR: - return Triple::avr; - case ELF::EM_HEXAGON: - return Triple::hexagon; - case ELF::EM_LANAI: - return Triple::lanai; - case ELF::EM_MIPS: + case ELF::EM_386: + case ELF::EM_IAMCU: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: + return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_AVR: + return Triple::avr; + case ELF::EM_HEXAGON: + return Triple::hexagon; + case ELF::EM_LANAI: + return Triple::lanai; + case ELF::EM_MIPS: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - return IsLittleEndian ? Triple::mipsel : Triple::mips; - case ELF::ELFCLASS64: - return IsLittleEndian ? Triple::mips64el : Triple::mips64; - default: - report_fatal_error("Invalid ELFCLASS!"); - } - case ELF::EM_MSP430: - return Triple::msp430; - case ELF::EM_PPC: + case ELF::ELFCLASS32: + return IsLittleEndian ? Triple::mipsel : Triple::mips; + case ELF::ELFCLASS64: + return IsLittleEndian ? Triple::mips64el : Triple::mips64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } + case ELF::EM_MSP430: + return Triple::msp430; + case ELF::EM_PPC: return IsLittleEndian ? Triple::ppcle : Triple::ppc; - case ELF::EM_PPC64: - return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; - case ELF::EM_RISCV: + case ELF::EM_PPC64: + return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; + case ELF::EM_RISCV: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - return Triple::riscv32; - case ELF::ELFCLASS64: - return Triple::riscv64; - default: - report_fatal_error("Invalid ELFCLASS!"); - } - case ELF::EM_S390: - return Triple::systemz; - - case ELF::EM_SPARC: - case ELF::EM_SPARC32PLUS: - return IsLittleEndian ? Triple::sparcel : Triple::sparc; - case ELF::EM_SPARCV9: - return Triple::sparcv9; - - case ELF::EM_AMDGPU: { - if (!IsLittleEndian) - return Triple::UnknownArch; - + case ELF::ELFCLASS32: + return Triple::riscv32; + case ELF::ELFCLASS64: + return Triple::riscv64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } + case ELF::EM_S390: + return Triple::systemz; + + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return IsLittleEndian ? Triple::sparcel : Triple::sparc; + case ELF::EM_SPARCV9: + return Triple::sparcv9; + + case ELF::EM_AMDGPU: { + if (!IsLittleEndian) + return Triple::UnknownArch; + unsigned MACH = EF.getHeader().e_flags & ELF::EF_AMDGPU_MACH; - if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && - MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) - return Triple::r600; - if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST && - MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST) - return Triple::amdgcn; - - return Triple::UnknownArch; - } - - case ELF::EM_BPF: - return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; - - case ELF::EM_VE: - return Triple::ve; + if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) + return Triple::r600; + if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST) + return Triple::amdgcn; + + return Triple::UnknownArch; + } + + case ELF::EM_BPF: + return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; + + case ELF::EM_VE: + return Triple::ve; case ELF::EM_CSKY: return Triple::csky; - default: - return Triple::UnknownArch; - } -} - -template <class ELFT> -Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const { + default: + return Triple::UnknownArch; + } +} + +template <class ELFT> +Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const { return EF.getHeader().e_entry; -} - -template <class ELFT> -ELFObjectFileBase::elf_symbol_iterator_range -ELFObjectFile<ELFT>::getDynamicSymbolIterators() const { - return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); -} - -template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { +} + +template <class ELFT> +ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFile<ELFT>::getDynamicSymbolIterators() const { + return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { return EF.getHeader().e_type == ELF::ET_REL; -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_ELFOBJECTFILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_ELFOBJECTFILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h b/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h index 320dfaa573e..501ba000cfb 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h +++ b/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h @@ -1,119 +1,119 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ELFTYPES_H -#define LLVM_OBJECT_ELFTYPES_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/Object/Error.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <cassert> -#include <cstdint> -#include <cstring> -#include <type_traits> - -namespace llvm { -namespace object { - -using support::endianness; - -template <class ELFT> struct Elf_Ehdr_Impl; -template <class ELFT> struct Elf_Shdr_Impl; -template <class ELFT> struct Elf_Sym_Impl; -template <class ELFT> struct Elf_Dyn_Impl; -template <class ELFT> struct Elf_Phdr_Impl; -template <class ELFT, bool isRela> struct Elf_Rel_Impl; -template <class ELFT> struct Elf_Verdef_Impl; -template <class ELFT> struct Elf_Verdaux_Impl; -template <class ELFT> struct Elf_Verneed_Impl; -template <class ELFT> struct Elf_Vernaux_Impl; -template <class ELFT> struct Elf_Versym_Impl; -template <class ELFT> struct Elf_Hash_Impl; -template <class ELFT> struct Elf_GnuHash_Impl; -template <class ELFT> struct Elf_Chdr_Impl; -template <class ELFT> struct Elf_Nhdr_Impl; -template <class ELFT> class Elf_Note_Impl; -template <class ELFT> class Elf_Note_Iterator_Impl; -template <class ELFT> struct Elf_CGProfile_Impl; - -template <endianness E, bool Is64> struct ELFType { -private: - template <typename Ty> - using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>; - -public: - static const endianness TargetEndianness = E; - static const bool Is64Bits = Is64; - - using uint = std::conditional_t<Is64, uint64_t, uint32_t>; - using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>; - using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>; - using Sym = Elf_Sym_Impl<ELFType<E, Is64>>; - using Dyn = Elf_Dyn_Impl<ELFType<E, Is64>>; - using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>; - using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>; - using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>; - using Relr = packed<uint>; - using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>; - using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>; - using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>; - using Vernaux = Elf_Vernaux_Impl<ELFType<E, Is64>>; - using Versym = Elf_Versym_Impl<ELFType<E, Is64>>; - using Hash = Elf_Hash_Impl<ELFType<E, Is64>>; - using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>; - using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>; - using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>; - using Note = Elf_Note_Impl<ELFType<E, Is64>>; - using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>; - using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>; - using DynRange = ArrayRef<Dyn>; - using ShdrRange = ArrayRef<Shdr>; - using SymRange = ArrayRef<Sym>; - using RelRange = ArrayRef<Rel>; - using RelaRange = ArrayRef<Rela>; - using RelrRange = ArrayRef<Relr>; - using PhdrRange = ArrayRef<Phdr>; - - using Half = packed<uint16_t>; - using Word = packed<uint32_t>; - using Sword = packed<int32_t>; - using Xword = packed<uint64_t>; - using Sxword = packed<int64_t>; - using Addr = packed<uint>; - using Off = packed<uint>; -}; - -using ELF32LE = ELFType<support::little, false>; -using ELF32BE = ELFType<support::big, false>; -using ELF64LE = ELFType<support::little, true>; -using ELF64BE = ELFType<support::big, true>; - -// Use an alignment of 2 for the typedefs since that is the worst case for -// ELF files in archives. - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - using Elf_Addr = typename ELFT::Addr; \ - using Elf_Off = typename ELFT::Off; \ - using Elf_Half = typename ELFT::Half; \ - using Elf_Word = typename ELFT::Word; \ - using Elf_Sword = typename ELFT::Sword; \ - using Elf_Xword = typename ELFT::Xword; \ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELFTYPES_H +#define LLVM_OBJECT_ELFTYPES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <cstring> +#include <type_traits> + +namespace llvm { +namespace object { + +using support::endianness; + +template <class ELFT> struct Elf_Ehdr_Impl; +template <class ELFT> struct Elf_Shdr_Impl; +template <class ELFT> struct Elf_Sym_Impl; +template <class ELFT> struct Elf_Dyn_Impl; +template <class ELFT> struct Elf_Phdr_Impl; +template <class ELFT, bool isRela> struct Elf_Rel_Impl; +template <class ELFT> struct Elf_Verdef_Impl; +template <class ELFT> struct Elf_Verdaux_Impl; +template <class ELFT> struct Elf_Verneed_Impl; +template <class ELFT> struct Elf_Vernaux_Impl; +template <class ELFT> struct Elf_Versym_Impl; +template <class ELFT> struct Elf_Hash_Impl; +template <class ELFT> struct Elf_GnuHash_Impl; +template <class ELFT> struct Elf_Chdr_Impl; +template <class ELFT> struct Elf_Nhdr_Impl; +template <class ELFT> class Elf_Note_Impl; +template <class ELFT> class Elf_Note_Iterator_Impl; +template <class ELFT> struct Elf_CGProfile_Impl; + +template <endianness E, bool Is64> struct ELFType { +private: + template <typename Ty> + using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>; + +public: + static const endianness TargetEndianness = E; + static const bool Is64Bits = Is64; + + using uint = std::conditional_t<Is64, uint64_t, uint32_t>; + using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>; + using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>; + using Sym = Elf_Sym_Impl<ELFType<E, Is64>>; + using Dyn = Elf_Dyn_Impl<ELFType<E, Is64>>; + using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>; + using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>; + using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>; + using Relr = packed<uint>; + using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>; + using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>; + using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>; + using Vernaux = Elf_Vernaux_Impl<ELFType<E, Is64>>; + using Versym = Elf_Versym_Impl<ELFType<E, Is64>>; + using Hash = Elf_Hash_Impl<ELFType<E, Is64>>; + using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>; + using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>; + using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>; + using Note = Elf_Note_Impl<ELFType<E, Is64>>; + using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>; + using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>; + using DynRange = ArrayRef<Dyn>; + using ShdrRange = ArrayRef<Shdr>; + using SymRange = ArrayRef<Sym>; + using RelRange = ArrayRef<Rel>; + using RelaRange = ArrayRef<Rela>; + using RelrRange = ArrayRef<Relr>; + using PhdrRange = ArrayRef<Phdr>; + + using Half = packed<uint16_t>; + using Word = packed<uint32_t>; + using Sword = packed<int32_t>; + using Xword = packed<uint64_t>; + using Sxword = packed<int64_t>; + using Addr = packed<uint>; + using Off = packed<uint>; +}; + +using ELF32LE = ELFType<support::little, false>; +using ELF32BE = ELFType<support::big, false>; +using ELF64LE = ELFType<support::little, true>; +using ELF64BE = ELFType<support::big, true>; + +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. + +// I really don't like doing this, but the alternative is copypasta. +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + using Elf_Addr = typename ELFT::Addr; \ + using Elf_Off = typename ELFT::Off; \ + using Elf_Half = typename ELFT::Half; \ + using Elf_Word = typename ELFT::Word; \ + using Elf_Sword = typename ELFT::Sword; \ + using Elf_Xword = typename ELFT::Xword; \ using Elf_Sxword = typename ELFT::Sxword; \ using uintX_t = typename ELFT::uint; \ using Elf_Ehdr = typename ELFT::Ehdr; \ @@ -142,664 +142,664 @@ using ELF64BE = ELFType<support::big, true>; using Elf_Rela_Range = typename ELFT::RelaRange; \ using Elf_Relr_Range = typename ELFT::RelrRange; \ using Elf_Phdr_Range = typename ELFT::PhdrRange; \ - -#define LLVM_ELF_COMMA , -#define LLVM_ELF_IMPORT_TYPES(E, W) \ - LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>) - -// Section header. -template <class ELFT> struct Elf_Shdr_Base; - -template <endianness TargetEndianness> -struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Word sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Word sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Word sh_addralign; // Section address alignment - Elf_Word sh_entsize; // Size of records contained within the section -}; - -template <endianness TargetEndianness> -struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Xword sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Xword sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Xword sh_addralign; // Section address alignment - Elf_Xword sh_entsize; // Size of records contained within the section -}; - -template <class ELFT> -struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { - using Elf_Shdr_Base<ELFT>::sh_entsize; - using Elf_Shdr_Base<ELFT>::sh_size; - - /// Get the number of entities this section contains if it has any. - unsigned getEntityCount() const { - if (sh_entsize == 0) - return 0; - return sh_size / sh_entsize; - } -}; - -template <class ELFT> struct Elf_Sym_Base; - -template <endianness TargetEndianness> -struct Elf_Sym_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Word st_name; // Symbol name (index into string table) - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Word st_size; // Size of the symbol - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in -}; - -template <endianness TargetEndianness> -struct Elf_Sym_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Word st_name; // Symbol name (index into string table) - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Xword st_size; // Size of the symbol -}; - -template <class ELFT> -struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { - using Elf_Sym_Base<ELFT>::st_info; - using Elf_Sym_Base<ELFT>::st_shndx; - using Elf_Sym_Base<ELFT>::st_other; - using Elf_Sym_Base<ELFT>::st_value; - - // These accessors and mutators correspond to the ELF32_ST_BIND, - // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: - unsigned char getBinding() const { return st_info >> 4; } - unsigned char getType() const { return st_info & 0x0f; } - uint64_t getValue() const { return st_value; } - void setBinding(unsigned char b) { setBindingAndType(b, getType()); } - void setType(unsigned char t) { setBindingAndType(getBinding(), t); } - - void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (b << 4) + (t & 0x0f); - } - - /// Access to the STV_xxx flag stored in the first two bits of st_other. - /// STV_DEFAULT: 0 - /// STV_INTERNAL: 1 - /// STV_HIDDEN: 2 - /// STV_PROTECTED: 3 - unsigned char getVisibility() const { return st_other & 0x3; } - void setVisibility(unsigned char v) { - assert(v < 4 && "Invalid value for visibility"); - st_other = (st_other & ~0x3) | v; - } - - bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; } - - bool isCommon() const { - return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON; - } - - bool isDefined() const { return !isUndefined(); } - - bool isProcessorSpecific() const { - return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC; - } - - bool isOSSpecific() const { - return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS; - } - - bool isReserved() const { - // ELF::SHN_HIRESERVE is 0xffff so st_shndx <= ELF::SHN_HIRESERVE is always - // true and some compilers warn about it. - return st_shndx >= ELF::SHN_LORESERVE; - } - - bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; } - - bool isExternal() const { - return getBinding() != ELF::STB_LOCAL; - } - - Expected<StringRef> getName(StringRef StrTab) const; -}; - -template <class ELFT> -Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const { - uint32_t Offset = this->st_name; - if (Offset >= StrTab.size()) - return createStringError(object_error::parse_failed, - "st_name (0x%" PRIx32 - ") is past the end of the string table" - " of size 0x%zx", - Offset, StrTab.size()); - return StringRef(StrTab.data() + Offset); -} - -/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section -/// (.gnu.version). This structure is identical for ELF32 and ELF64. -template <class ELFT> -struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) -}; - -/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section -/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template <class ELFT> -struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) - Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) - Elf_Half vd_ndx; // Version index, used in .gnu.version entries - Elf_Half vd_cnt; // Number of Verdaux entries - Elf_Word vd_hash; // Hash of name - Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) - Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) - - /// Get the first Verdaux entry for this Verdef. - const Elf_Verdaux *getAux() const { - return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux); - } -}; - -/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef -/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template <class ELFT> -struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vda_name; // Version name (offset in string table) - Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) -}; - -/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template <class ELFT> -struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) - Elf_Half vn_cnt; // Number of associated Vernaux entries - Elf_Word vn_file; // Library name (string table offset) - Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) - Elf_Word vn_next; // Offset to next Verneed entry (in bytes) -}; - -/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template <class ELFT> -struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vna_hash; // Hash of dependency name - Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) - Elf_Half vna_other; // Version index, used in .gnu.version entries - Elf_Word vna_name; // Dependency name - Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) -}; - -/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic -/// table section (.dynamic) look like. -template <class ELFT> struct Elf_Dyn_Base; - -template <endianness TargetEndianness> -struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - } d_un; -}; - -template <endianness TargetEndianness> -struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Sxword d_tag; - union { - Elf_Xword d_val; - Elf_Addr d_ptr; - } d_un; -}; - -/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters. -template <class ELFT> -struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { - using Elf_Dyn_Base<ELFT>::d_tag; - using Elf_Dyn_Base<ELFT>::d_un; - using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>; - using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_t>; - intX_t getTag() const { return d_tag; } - uintX_t getVal() const { return d_un.d_val; } - uintX_t getPtr() const { return d_un.d_ptr; } -}; - -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - static const bool IsRela = false; - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R, bool IsMips64EL) { - assert(!IsMips64EL); - r_info = R; - } - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return this->getRInfo(isMips64EL) >> 8; - } - unsigned char getType(bool isMips64EL) const { - return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); - } - void setSymbol(uint32_t s, bool IsMips64EL) { - setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); - } - void setType(unsigned char t, bool IsMips64EL) { - setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); - } - void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { - this->setRInfo((s << 8) + t, IsMips64EL); - } -}; - -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true> - : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - static const bool IsRela = true; - Elf_Sword r_addend; // Compute value for relocatable field by adding this -}; - -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - static const bool IsRela = false; - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - - uint64_t getRInfo(bool isMips64EL) const { - uint64_t t = r_info; - if (!isMips64EL) - return t; - // Mips64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little endian 32 bit number followed - // by a 32 bit big endian number. - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - } - - void setRInfo(uint64_t R, bool IsMips64EL) { - if (IsMips64EL) - r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | - ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); - else - r_info = R; - } - - // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, - // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return (uint32_t)(this->getRInfo(isMips64EL) >> 32); - } - uint32_t getType(bool isMips64EL) const { - return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); - } - void setSymbol(uint32_t s, bool IsMips64EL) { - setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); - } - void setType(uint32_t t, bool IsMips64EL) { - setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); - } - void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { - this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); - } -}; - -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true> - : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - static const bool IsRela = true; - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. -}; - -template <class ELFT> -struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes - Elf_Half e_type; // Type of file (see ET_*) - Elf_Half e_machine; // Required architecture for this file (see EM_*) - Elf_Word e_version; // Must be equal to 1 - Elf_Addr e_entry; // Address to jump to in order to start program - Elf_Off e_phoff; // Program header table's file offset, in bytes - Elf_Off e_shoff; // Section header table's file offset, in bytes - Elf_Word e_flags; // Processor-specific flags - Elf_Half e_ehsize; // Size of ELF header, in bytes - Elf_Half e_phentsize; // Size of an entry in the program header table - Elf_Half e_phnum; // Number of entries in the program header table - Elf_Half e_shentsize; // Size of an entry in the section header table - Elf_Half e_shnum; // Number of entries in the section header table - Elf_Half e_shstrndx; // Section header table index of section name - // string table - - bool checkMagic() const { - return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; - } - - unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } - unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } -}; - -template <endianness TargetEndianness> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Word p_type; // Type of segment - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Word p_flags; // Segment flags - Elf_Word p_align; // Segment alignment constraint -}; - -template <endianness TargetEndianness> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Word p_type; // Type of segment - Elf_Word p_flags; // Segment flags - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Xword p_align; // Segment alignment constraint -}; - -// ELFT needed for endianness. -template <class ELFT> -struct Elf_Hash_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word nbucket; - Elf_Word nchain; - - ArrayRef<Elf_Word> buckets() const { - return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket); - } - - ArrayRef<Elf_Word> chains() const { - return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket, - &nbucket + 2 + nbucket + nchain); - } -}; - -// .gnu.hash section -template <class ELFT> -struct Elf_GnuHash_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word nbuckets; - Elf_Word symndx; - Elf_Word maskwords; - Elf_Word shift2; - - ArrayRef<Elf_Off> filter() const { - return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1), - maskwords); - } - - ArrayRef<Elf_Word> buckets() const { - return ArrayRef<Elf_Word>( - reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets); - } - - ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const { - assert(DynamicSymCount >= symndx); - return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx); - } -}; - -// Compressed section headers. -// http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header -template <endianness TargetEndianness> -struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Word ch_type; - Elf_Word ch_size; - Elf_Word ch_addralign; -}; - -template <endianness TargetEndianness> -struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Word ch_type; - Elf_Word ch_reserved; - Elf_Xword ch_size; - Elf_Xword ch_addralign; -}; - -/// Note header -template <class ELFT> -struct Elf_Nhdr_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word n_namesz; - Elf_Word n_descsz; - Elf_Word n_type; - - /// The alignment of the name and descriptor. - /// - /// Implementations differ from the specification here: in practice all - /// variants align both the name and descriptor to 4-bytes. - static const unsigned int Align = 4; - - /// Get the size of the note, including name, descriptor, and padding. - size_t getSize() const { - return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz); - } -}; - -/// An ELF note. -/// -/// Wraps a note header, providing methods for accessing the name and -/// descriptor safely. -template <class ELFT> -class Elf_Note_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - - const Elf_Nhdr_Impl<ELFT> &Nhdr; - - template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl; - -public: - Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {} - - /// Get the note's name, excluding the terminating null byte. - StringRef getName() const { - if (!Nhdr.n_namesz) - return StringRef(); - return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr), - Nhdr.n_namesz - 1); - } - - /// Get the note's descriptor. - ArrayRef<uint8_t> getDesc() const { - if (!Nhdr.n_descsz) - return ArrayRef<uint8_t>(); - return ArrayRef<uint8_t>( - reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) + - alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz), - Nhdr.n_descsz); - } - - /// Get the note's descriptor as StringRef - StringRef getDescAsStringRef() const { - ArrayRef<uint8_t> Desc = getDesc(); - return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); - } - - /// Get the note's type. - Elf_Word getType() const { return Nhdr.n_type; } -}; - -template <class ELFT> -class Elf_Note_Iterator_Impl - : std::iterator<std::forward_iterator_tag, Elf_Note_Impl<ELFT>> { - // Nhdr being a nullptr marks the end of iteration. - const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr; - size_t RemainingSize = 0u; - Error *Err = nullptr; - - template <class ELFFileELFT> friend class ELFFile; - - // Stop iteration and indicate an overflow. - void stopWithOverflowError() { - Nhdr = nullptr; - *Err = make_error<StringError>("ELF note overflows container", - object_error::parse_failed); - } - - // Advance Nhdr by NoteSize bytes, starting from NhdrPos. - // - // Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize - // upon returning. Handles stopping iteration when reaching the end of the - // container, either cleanly or with an overflow error. - void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) { - RemainingSize -= NoteSize; - if (RemainingSize == 0u) { - // Ensure that if the iterator walks to the end, the error is checked - // afterwards. - *Err = Error::success(); - Nhdr = nullptr; - } else if (sizeof(*Nhdr) > RemainingSize) - stopWithOverflowError(); - else { - Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize); - if (Nhdr->getSize() > RemainingSize) - stopWithOverflowError(); - else - *Err = Error::success(); - } - } - - Elf_Note_Iterator_Impl() {} - explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {} - Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err) - : RemainingSize(Size), Err(&Err) { - consumeError(std::move(Err)); - assert(Start && "ELF note iterator starting at NULL"); - advanceNhdr(Start, 0u); - } - -public: - Elf_Note_Iterator_Impl &operator++() { - assert(Nhdr && "incremented ELF note end iterator"); - const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr); - size_t NoteSize = Nhdr->getSize(); - advanceNhdr(NhdrPos, NoteSize); - return *this; - } - bool operator==(Elf_Note_Iterator_Impl Other) const { - if (!Nhdr && Other.Err) - (void)(bool)(*Other.Err); - if (!Other.Nhdr && Err) - (void)(bool)(*Err); - return Nhdr == Other.Nhdr; - } - bool operator!=(Elf_Note_Iterator_Impl Other) const { - return !(*this == Other); - } - Elf_Note_Impl<ELFT> operator*() const { - assert(Nhdr && "dereferenced ELF note end iterator"); - return Elf_Note_Impl<ELFT>(*Nhdr); - } -}; - -template <class ELFT> struct Elf_CGProfile_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word cgp_from; - Elf_Word cgp_to; - Elf_Xword cgp_weight; -}; - -// MIPS .reginfo section -template <class ELFT> -struct Elf_Mips_RegInfo; - -template <support::endianness TargetEndianness> -struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) - Elf_Word ri_gprmask; // bit-mask of used general registers - Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers - Elf_Addr ri_gp_value; // gp register value -}; - -template <support::endianness TargetEndianness> -struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) - Elf_Word ri_gprmask; // bit-mask of used general registers - Elf_Word ri_pad; // unused padding field - Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers - Elf_Addr ri_gp_value; // gp register value -}; - -// .MIPS.options section -template <class ELFT> struct Elf_Mips_Options { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - uint8_t kind; // Determines interpretation of variable part of descriptor - uint8_t size; // Byte size of descriptor, including this header - Elf_Half section; // Section header index of section affected, - // or 0 for global options - Elf_Word info; // Kind-specific information - - Elf_Mips_RegInfo<ELFT> &getRegInfo() { - assert(kind == ELF::ODK_REGINFO); - return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>( - (uint8_t *)this + sizeof(Elf_Mips_Options)); - } - const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { - return const_cast<Elf_Mips_Options *>(this)->getRegInfo(); - } -}; - -// .MIPS.abiflags section content -template <class ELFT> struct Elf_Mips_ABIFlags { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half version; // Version of the structure - uint8_t isa_level; // ISA level: 1-5, 32, and 64 - uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V) - uint8_t gpr_size; // General purpose registers size - uint8_t cpr1_size; // Co-processor 1 registers size - uint8_t cpr2_size; // Co-processor 2 registers size - uint8_t fp_abi; // Floating-point ABI flag - Elf_Word isa_ext; // Processor-specific extension - Elf_Word ases; // ASEs flags - Elf_Word flags1; // General flags - Elf_Word flags2; // General flags -}; - -} // end namespace object. -} // end namespace llvm. - -#endif // LLVM_OBJECT_ELFTYPES_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + +#define LLVM_ELF_COMMA , +#define LLVM_ELF_IMPORT_TYPES(E, W) \ + LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>) + +// Section header. +template <class ELFT> struct Elf_Shdr_Base; + +template <endianness TargetEndianness> +struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Word sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Word sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Word sh_addralign; // Section address alignment + Elf_Word sh_entsize; // Size of records contained within the section +}; + +template <endianness TargetEndianness> +struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Xword sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Xword sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Xword sh_addralign; // Section address alignment + Elf_Xword sh_entsize; // Size of records contained within the section +}; + +template <class ELFT> +struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { + using Elf_Shdr_Base<ELFT>::sh_entsize; + using Elf_Shdr_Base<ELFT>::sh_size; + + /// Get the number of entities this section contains if it has any. + unsigned getEntityCount() const { + if (sh_entsize == 0) + return 0; + return sh_size / sh_entsize; + } +}; + +template <class ELFT> struct Elf_Sym_Base; + +template <endianness TargetEndianness> +struct Elf_Sym_Base<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word st_name; // Symbol name (index into string table) + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in +}; + +template <endianness TargetEndianness> +struct Elf_Sym_Base<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Xword st_size; // Size of the symbol +}; + +template <class ELFT> +struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { + using Elf_Sym_Base<ELFT>::st_info; + using Elf_Sym_Base<ELFT>::st_shndx; + using Elf_Sym_Base<ELFT>::st_other; + using Elf_Sym_Base<ELFT>::st_value; + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + uint64_t getValue() const { return st_value; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } + + /// Access to the STV_xxx flag stored in the first two bits of st_other. + /// STV_DEFAULT: 0 + /// STV_INTERNAL: 1 + /// STV_HIDDEN: 2 + /// STV_PROTECTED: 3 + unsigned char getVisibility() const { return st_other & 0x3; } + void setVisibility(unsigned char v) { + assert(v < 4 && "Invalid value for visibility"); + st_other = (st_other & ~0x3) | v; + } + + bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; } + + bool isCommon() const { + return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON; + } + + bool isDefined() const { return !isUndefined(); } + + bool isProcessorSpecific() const { + return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC; + } + + bool isOSSpecific() const { + return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS; + } + + bool isReserved() const { + // ELF::SHN_HIRESERVE is 0xffff so st_shndx <= ELF::SHN_HIRESERVE is always + // true and some compilers warn about it. + return st_shndx >= ELF::SHN_LORESERVE; + } + + bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; } + + bool isExternal() const { + return getBinding() != ELF::STB_LOCAL; + } + + Expected<StringRef> getName(StringRef StrTab) const; +}; + +template <class ELFT> +Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const { + uint32_t Offset = this->st_name; + if (Offset >= StrTab.size()) + return createStringError(object_error::parse_failed, + "st_name (0x%" PRIx32 + ") is past the end of the string table" + " of size 0x%zx", + Offset, StrTab.size()); + return StringRef(StrTab.data() + Offset); +} + +/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section +/// (.gnu.version). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Versym_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) +}; + +/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section +/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verdef_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) + Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) + Elf_Half vd_ndx; // Version index, used in .gnu.version entries + Elf_Half vd_cnt; // Number of Verdaux entries + Elf_Word vd_hash; // Hash of name + Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) + Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) + + /// Get the first Verdaux entry for this Verdef. + const Elf_Verdaux *getAux() const { + return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux); + } +}; + +/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef +/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verdaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vda_name; // Version name (offset in string table) + Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) +}; + +/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verneed_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) + Elf_Half vn_cnt; // Number of associated Vernaux entries + Elf_Word vn_file; // Library name (string table offset) + Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) + Elf_Word vn_next; // Offset to next Verneed entry (in bytes) +}; + +/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Vernaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vna_hash; // Hash of dependency name + Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) + Elf_Half vna_other; // Version index, used in .gnu.version entries + Elf_Word vna_name; // Dependency name + Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) +}; + +/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic +/// table section (.dynamic) look like. +template <class ELFT> struct Elf_Dyn_Base; + +template <endianness TargetEndianness> +struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template <endianness TargetEndianness> +struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters. +template <class ELFT> +struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { + using Elf_Dyn_Base<ELFT>::d_tag; + using Elf_Dyn_Base<ELFT>::d_un; + using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>; + using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_t>; + intX_t getTag() const { return d_tag; } + uintX_t getVal() const { return d_un.d_val; } + uintX_t getPtr() const { return d_un.d_ptr; } +}; + +template <endianness TargetEndianness> +struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + static const bool IsRela = false; + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + unsigned char getType(bool isMips64EL) const { + return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); + } + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); + } +}; + +template <endianness TargetEndianness> +struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true> + : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + static const bool IsRela = true; + Elf_Sword r_addend; // Compute value for relocatable field by adding this +}; + +template <endianness TargetEndianness> +struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + static const bool IsRela = false; + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; + } + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) >> 32); + } + uint32_t getType(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); + } + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(IsMips64EL), IsMips64EL); + } + void setType(uint32_t t, bool IsMips64EL) { + setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); + } +}; + +template <endianness TargetEndianness> +struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true> + : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + static const bool IsRela = true; + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. +}; + +template <class ELFT> +struct Elf_Ehdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes + Elf_Half e_type; // Type of file (see ET_*) + Elf_Half e_machine; // Required architecture for this file (see EM_*) + Elf_Word e_version; // Must be equal to 1 + Elf_Addr e_entry; // Address to jump to in order to start program + Elf_Off e_phoff; // Program header table's file offset, in bytes + Elf_Off e_shoff; // Section header table's file offset, in bytes + Elf_Word e_flags; // Processor-specific flags + Elf_Half e_ehsize; // Size of ELF header, in bytes + Elf_Half e_phentsize; // Size of an entry in the program header table + Elf_Half e_phnum; // Number of entries in the program header table + Elf_Half e_shentsize; // Size of an entry in the section header table + Elf_Half e_shnum; // Number of entries in the section header table + Elf_Half e_shstrndx; // Section header table index of section name + // string table + + bool checkMagic() const { + return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + } + + unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } +}; + +template <endianness TargetEndianness> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word p_type; // Type of segment + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Word p_flags; // Segment flags + Elf_Word p_align; // Segment alignment constraint +}; + +template <endianness TargetEndianness> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word p_type; // Type of segment + Elf_Word p_flags; // Segment flags + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Xword p_align; // Segment alignment constraint +}; + +// ELFT needed for endianness. +template <class ELFT> +struct Elf_Hash_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word nbucket; + Elf_Word nchain; + + ArrayRef<Elf_Word> buckets() const { + return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket); + } + + ArrayRef<Elf_Word> chains() const { + return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket, + &nbucket + 2 + nbucket + nchain); + } +}; + +// .gnu.hash section +template <class ELFT> +struct Elf_GnuHash_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word nbuckets; + Elf_Word symndx; + Elf_Word maskwords; + Elf_Word shift2; + + ArrayRef<Elf_Off> filter() const { + return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1), + maskwords); + } + + ArrayRef<Elf_Word> buckets() const { + return ArrayRef<Elf_Word>( + reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets); + } + + ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const { + assert(DynamicSymCount >= symndx); + return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx); + } +}; + +// Compressed section headers. +// http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header +template <endianness TargetEndianness> +struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word ch_type; + Elf_Word ch_size; + Elf_Word ch_addralign; +}; + +template <endianness TargetEndianness> +struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word ch_type; + Elf_Word ch_reserved; + Elf_Xword ch_size; + Elf_Xword ch_addralign; +}; + +/// Note header +template <class ELFT> +struct Elf_Nhdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word n_namesz; + Elf_Word n_descsz; + Elf_Word n_type; + + /// The alignment of the name and descriptor. + /// + /// Implementations differ from the specification here: in practice all + /// variants align both the name and descriptor to 4-bytes. + static const unsigned int Align = 4; + + /// Get the size of the note, including name, descriptor, and padding. + size_t getSize() const { + return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz); + } +}; + +/// An ELF note. +/// +/// Wraps a note header, providing methods for accessing the name and +/// descriptor safely. +template <class ELFT> +class Elf_Note_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + const Elf_Nhdr_Impl<ELFT> &Nhdr; + + template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl; + +public: + Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {} + + /// Get the note's name, excluding the terminating null byte. + StringRef getName() const { + if (!Nhdr.n_namesz) + return StringRef(); + return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr), + Nhdr.n_namesz - 1); + } + + /// Get the note's descriptor. + ArrayRef<uint8_t> getDesc() const { + if (!Nhdr.n_descsz) + return ArrayRef<uint8_t>(); + return ArrayRef<uint8_t>( + reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) + + alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz), + Nhdr.n_descsz); + } + + /// Get the note's descriptor as StringRef + StringRef getDescAsStringRef() const { + ArrayRef<uint8_t> Desc = getDesc(); + return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); + } + + /// Get the note's type. + Elf_Word getType() const { return Nhdr.n_type; } +}; + +template <class ELFT> +class Elf_Note_Iterator_Impl + : std::iterator<std::forward_iterator_tag, Elf_Note_Impl<ELFT>> { + // Nhdr being a nullptr marks the end of iteration. + const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr; + size_t RemainingSize = 0u; + Error *Err = nullptr; + + template <class ELFFileELFT> friend class ELFFile; + + // Stop iteration and indicate an overflow. + void stopWithOverflowError() { + Nhdr = nullptr; + *Err = make_error<StringError>("ELF note overflows container", + object_error::parse_failed); + } + + // Advance Nhdr by NoteSize bytes, starting from NhdrPos. + // + // Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize + // upon returning. Handles stopping iteration when reaching the end of the + // container, either cleanly or with an overflow error. + void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) { + RemainingSize -= NoteSize; + if (RemainingSize == 0u) { + // Ensure that if the iterator walks to the end, the error is checked + // afterwards. + *Err = Error::success(); + Nhdr = nullptr; + } else if (sizeof(*Nhdr) > RemainingSize) + stopWithOverflowError(); + else { + Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize); + if (Nhdr->getSize() > RemainingSize) + stopWithOverflowError(); + else + *Err = Error::success(); + } + } + + Elf_Note_Iterator_Impl() {} + explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {} + Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err) + : RemainingSize(Size), Err(&Err) { + consumeError(std::move(Err)); + assert(Start && "ELF note iterator starting at NULL"); + advanceNhdr(Start, 0u); + } + +public: + Elf_Note_Iterator_Impl &operator++() { + assert(Nhdr && "incremented ELF note end iterator"); + const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr); + size_t NoteSize = Nhdr->getSize(); + advanceNhdr(NhdrPos, NoteSize); + return *this; + } + bool operator==(Elf_Note_Iterator_Impl Other) const { + if (!Nhdr && Other.Err) + (void)(bool)(*Other.Err); + if (!Other.Nhdr && Err) + (void)(bool)(*Err); + return Nhdr == Other.Nhdr; + } + bool operator!=(Elf_Note_Iterator_Impl Other) const { + return !(*this == Other); + } + Elf_Note_Impl<ELFT> operator*() const { + assert(Nhdr && "dereferenced ELF note end iterator"); + return Elf_Note_Impl<ELFT>(*Nhdr); + } +}; + +template <class ELFT> struct Elf_CGProfile_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word cgp_from; + Elf_Word cgp_to; + Elf_Xword cgp_weight; +}; + +// MIPS .reginfo section +template <class ELFT> +struct Elf_Mips_RegInfo; + +template <support::endianness TargetEndianness> +struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +template <support::endianness TargetEndianness> +struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_pad; // unused padding field + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +// .MIPS.options section +template <class ELFT> struct Elf_Mips_Options { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + uint8_t kind; // Determines interpretation of variable part of descriptor + uint8_t size; // Byte size of descriptor, including this header + Elf_Half section; // Section header index of section affected, + // or 0 for global options + Elf_Word info; // Kind-specific information + + Elf_Mips_RegInfo<ELFT> &getRegInfo() { + assert(kind == ELF::ODK_REGINFO); + return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>( + (uint8_t *)this + sizeof(Elf_Mips_Options)); + } + const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { + return const_cast<Elf_Mips_Options *>(this)->getRegInfo(); + } +}; + +// .MIPS.abiflags section content +template <class ELFT> struct Elf_Mips_ABIFlags { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half version; // Version of the structure + uint8_t isa_level; // ISA level: 1-5, 32, and 64 + uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V) + uint8_t gpr_size; // General purpose registers size + uint8_t cpr1_size; // Co-processor 1 registers size + uint8_t cpr2_size; // Co-processor 2 registers size + uint8_t fp_abi; // Floating-point ABI flag + Elf_Word isa_ext; // Processor-specific extension + Elf_Word ases; // ASEs flags + Elf_Word flags1; // General flags + Elf_Word flags2; // General flags +}; + +} // end namespace object. +} // end namespace llvm. + +#endif // LLVM_OBJECT_ELFTYPES_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/Error.h b/contrib/libs/llvm12/include/llvm/Object/Error.h index 8cfaa1a87cb..55033fb6b5e 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Error.h +++ b/contrib/libs/llvm12/include/llvm/Object/Error.h @@ -1,105 +1,105 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Error.h - system_error extensions for Object -------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This declares a new error_category for the Object library. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ERROR_H -#define LLVM_OBJECT_ERROR_H - -#include "llvm/Support/Error.h" -#include <system_error> - -namespace llvm { - -class Twine; - -namespace object { - -class Binary; - -const std::error_category &object_category(); - -enum class object_error { - // Error code 0 is absent. Use std::error_code() instead. - arch_not_found = 1, - invalid_file_type, - parse_failed, - unexpected_eof, - string_table_non_null_end, - invalid_section_index, - bitcode_section_not_found, - invalid_symbol_index, -}; - -inline std::error_code make_error_code(object_error e) { - return std::error_code(static_cast<int>(e), object_category()); -} - -/// Base class for all errors indicating malformed binary files. -/// -/// Having a subclass for all malformed binary files allows archive-walking -/// code to skip malformed files without having to understand every possible -/// way that a binary file might be malformed. -/// -/// Currently inherits from ECError for easy interoperability with -/// std::error_code, but this will be removed in the future. -class BinaryError : public ErrorInfo<BinaryError, ECError> { - void anchor() override; -public: - static char ID; - BinaryError() { - // Default to parse_failed, can be overridden with setErrorCode. - setErrorCode(make_error_code(object_error::parse_failed)); - } -}; - -/// Generic binary error. -/// -/// For errors that don't require their own specific sub-error (most errors) -/// this class can be used to describe the error via a string message. -class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> { -public: - static char ID; - GenericBinaryError(const Twine &Msg); - GenericBinaryError(const Twine &Msg, object_error ECOverride); - const std::string &getMessage() const { return Msg; } - void log(raw_ostream &OS) const override; -private: - std::string Msg; -}; - -/// isNotObjectErrorInvalidFileType() is used when looping through the children -/// of an archive after calling getAsBinary() on the child and it returns an -/// llvm::Error. In the cases we want to loop through the children and ignore the -/// non-objects in the archive this is used to test the error to see if an -/// error() function needs to called on the llvm::Error. -Error isNotObjectErrorInvalidFileType(llvm::Error Err); - -} // end namespace object. - -} // end namespace llvm. - -namespace std { -template <> -struct is_error_code_enum<llvm::object::object_error> : std::true_type {}; -} - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Error.h - system_error extensions for Object -------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This declares a new error_category for the Object library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ERROR_H +#define LLVM_OBJECT_ERROR_H + +#include "llvm/Support/Error.h" +#include <system_error> + +namespace llvm { + +class Twine; + +namespace object { + +class Binary; + +const std::error_category &object_category(); + +enum class object_error { + // Error code 0 is absent. Use std::error_code() instead. + arch_not_found = 1, + invalid_file_type, + parse_failed, + unexpected_eof, + string_table_non_null_end, + invalid_section_index, + bitcode_section_not_found, + invalid_symbol_index, +}; + +inline std::error_code make_error_code(object_error e) { + return std::error_code(static_cast<int>(e), object_category()); +} + +/// Base class for all errors indicating malformed binary files. +/// +/// Having a subclass for all malformed binary files allows archive-walking +/// code to skip malformed files without having to understand every possible +/// way that a binary file might be malformed. +/// +/// Currently inherits from ECError for easy interoperability with +/// std::error_code, but this will be removed in the future. +class BinaryError : public ErrorInfo<BinaryError, ECError> { + void anchor() override; +public: + static char ID; + BinaryError() { + // Default to parse_failed, can be overridden with setErrorCode. + setErrorCode(make_error_code(object_error::parse_failed)); + } +}; + +/// Generic binary error. +/// +/// For errors that don't require their own specific sub-error (most errors) +/// this class can be used to describe the error via a string message. +class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> { +public: + static char ID; + GenericBinaryError(const Twine &Msg); + GenericBinaryError(const Twine &Msg, object_error ECOverride); + const std::string &getMessage() const { return Msg; } + void log(raw_ostream &OS) const override; +private: + std::string Msg; +}; + +/// isNotObjectErrorInvalidFileType() is used when looping through the children +/// of an archive after calling getAsBinary() on the child and it returns an +/// llvm::Error. In the cases we want to loop through the children and ignore the +/// non-objects in the archive this is used to test the error to see if an +/// error() function needs to called on the llvm::Error. +Error isNotObjectErrorInvalidFileType(llvm::Error Err); + +} // end namespace object. + +} // end namespace llvm. + +namespace std { +template <> +struct is_error_code_enum<llvm::object::object_error> : std::true_type {}; +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h index da4a9d74aaa..548cea58d18 100644 --- a/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h @@ -1,102 +1,102 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the IRObjectFile template class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_IROBJECTFILE_H -#define LLVM_OBJECT_IROBJECTFILE_H - -#include "llvm/ADT/PointerUnion.h" -#include "llvm/Object/IRSymtab.h" -#include "llvm/Object/ModuleSymbolTable.h" -#include "llvm/Object/SymbolicFile.h" - -namespace llvm { -class BitcodeModule; -class Mangler; -class Module; -class GlobalValue; -class Triple; - -namespace object { -class ObjectFile; - -class IRObjectFile : public SymbolicFile { - std::vector<std::unique_ptr<Module>> Mods; - ModuleSymbolTable SymTab; - IRObjectFile(MemoryBufferRef Object, - std::vector<std::unique_ptr<Module>> Mods); - -public: - ~IRObjectFile() override; - void moveSymbolNext(DataRefImpl &Symb) const override; - Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - - StringRef getTargetTriple() const; - - static bool classof(const Binary *v) { - return v->isIR(); - } - - using module_iterator = - pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator, - const Module>; - - module_iterator module_begin() const { return module_iterator(Mods.begin()); } - module_iterator module_end() const { return module_iterator(Mods.end()); } - - iterator_range<module_iterator> modules() const { - return make_range(module_begin(), module_end()); - } - - /// Finds and returns bitcode embedded in the given object file, or an - /// error code if not found. - static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); - - /// Finds and returns bitcode in the given memory buffer (which may - /// be either a bitcode file or a native object file with embedded bitcode), - /// or an error code if not found. - static Expected<MemoryBufferRef> - findBitcodeInMemBuffer(MemoryBufferRef Object); - - static Expected<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, - LLVMContext &Context); -}; - -/// The contents of a bitcode file and its irsymtab. Any underlying data -/// for the irsymtab are owned by Symtab and Strtab. -struct IRSymtabFile { - std::vector<BitcodeModule> Mods; - SmallVector<char, 0> Symtab, Strtab; - irsymtab::Reader TheReader; -}; - -/// Reads a bitcode file, creating its irsymtab if necessary. -Expected<IRSymtabFile> readIRSymtab(MemoryBufferRef MBRef); - -} - -} - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the IRObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_IROBJECTFILE_H +#define LLVM_OBJECT_IROBJECTFILE_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Object/IRSymtab.h" +#include "llvm/Object/ModuleSymbolTable.h" +#include "llvm/Object/SymbolicFile.h" + +namespace llvm { +class BitcodeModule; +class Mangler; +class Module; +class GlobalValue; +class Triple; + +namespace object { +class ObjectFile; + +class IRObjectFile : public SymbolicFile { + std::vector<std::unique_ptr<Module>> Mods; + ModuleSymbolTable SymTab; + IRObjectFile(MemoryBufferRef Object, + std::vector<std::unique_ptr<Module>> Mods); + +public: + ~IRObjectFile() override; + void moveSymbolNext(DataRefImpl &Symb) const override; + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + StringRef getTargetTriple() const; + + static bool classof(const Binary *v) { + return v->isIR(); + } + + using module_iterator = + pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator, + const Module>; + + module_iterator module_begin() const { return module_iterator(Mods.begin()); } + module_iterator module_end() const { return module_iterator(Mods.end()); } + + iterator_range<module_iterator> modules() const { + return make_range(module_begin(), module_end()); + } + + /// Finds and returns bitcode embedded in the given object file, or an + /// error code if not found. + static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); + + /// Finds and returns bitcode in the given memory buffer (which may + /// be either a bitcode file or a native object file with embedded bitcode), + /// or an error code if not found. + static Expected<MemoryBufferRef> + findBitcodeInMemBuffer(MemoryBufferRef Object); + + static Expected<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object, + LLVMContext &Context); +}; + +/// The contents of a bitcode file and its irsymtab. Any underlying data +/// for the irsymtab are owned by Symtab and Strtab. +struct IRSymtabFile { + std::vector<BitcodeModule> Mods; + SmallVector<char, 0> Symtab, Strtab; + irsymtab::Reader TheReader; +}; + +/// Reads a bitcode file, creating its irsymtab if necessary. +Expected<IRSymtabFile> readIRSymtab(MemoryBufferRef MBRef); + +} + +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h b/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h index 59a6817bd5d..5aec93d8eb9 100644 --- a/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h +++ b/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h @@ -1,385 +1,385 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file contains data definitions and a reader and builder for a symbol -// table for LLVM IR. Its purpose is to allow linkers and other consumers of -// bitcode files to efficiently read the symbol table for symbol resolution -// purposes without needing to construct a module in memory. -// -// As with most object files the symbol table has two parts: the symbol table -// itself and a string table which is referenced by the symbol table. -// -// A symbol table corresponds to a single bitcode file, which may consist of -// multiple modules, so symbol tables may likewise contain symbols for multiple -// modules. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_IRSYMTAB_H -#define LLVM_OBJECT_IRSYMTAB_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <cassert> -#include <cstdint> -#include <vector> - -namespace llvm { - -struct BitcodeFileContents; -class StringTableBuilder; - -namespace irsymtab { - -namespace storage { - -// The data structures in this namespace define the low-level serialization -// format. Clients that just want to read a symbol table should use the -// irsymtab::Reader class. - -using Word = support::ulittle32_t; - -/// A reference to a string in the string table. -struct Str { - Word Offset, Size; - - StringRef get(StringRef Strtab) const { - return {Strtab.data() + Offset, Size}; - } -}; - -/// A reference to a range of objects in the symbol table. -template <typename T> struct Range { - Word Offset, Size; - - ArrayRef<T> get(StringRef Symtab) const { - return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; - } -}; - -/// Describes the range of a particular module's symbols within the symbol -/// table. -struct Module { - Word Begin, End; - - /// The index of the first Uncommon for this Module. - Word UncBegin; -}; - -/// This is equivalent to an IR comdat. -struct Comdat { - Str Name; -}; - -/// Contains the information needed by linkers for symbol resolution, as well as -/// by the LTO implementation itself. -struct Symbol { - /// The mangled symbol name. - Str Name; - - /// The unmangled symbol name, or the empty string if this is not an IR - /// symbol. - Str IRName; - - /// The index into Header::Comdats, or -1 if not a comdat member. - Word ComdatIndex; - - Word Flags; - enum FlagBits { - FB_visibility, // 2 bits - FB_has_uncommon = FB_visibility + 2, - FB_undefined, - FB_weak, - FB_common, - FB_indirect, - FB_used, - FB_tls, - FB_may_omit, - FB_global, - FB_format_specific, - FB_unnamed_addr, - FB_executable, - }; -}; - -/// This data structure contains rarely used symbol fields and is optionally -/// referenced by a Symbol. -struct Uncommon { - Word CommonSize, CommonAlign; - - /// COFF-specific: the name of the symbol that a weak external resolves to - /// if not defined. - Str COFFWeakExternFallbackName; - - /// Specified section name, if any. - Str SectionName; -}; - - -struct Header { - /// Version number of the symtab format. This number should be incremented - /// when the format changes, but it does not need to be incremented if a - /// change to LLVM would cause it to create a different symbol table. - Word Version; - enum { kCurrentVersion = 2 }; - - /// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION). - /// Consumers should rebuild the symbol table from IR if the producer's - /// version does not match the consumer's version due to potential differences - /// in symbol table format, symbol enumeration order and so on. - Str Producer; - - Range<Module> Modules; - Range<Comdat> Comdats; - Range<Symbol> Symbols; - Range<Uncommon> Uncommons; - - Str TargetTriple, SourceFileName; - - /// COFF-specific: linker directives. - Str COFFLinkerOpts; - - /// Dependent Library Specifiers - Range<Str> DependentLibraries; -}; - -} // end namespace storage - -/// Fills in Symtab and StrtabBuilder with a valid symbol and string table for -/// Mods. -Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab, - StringTableBuilder &StrtabBuilder, BumpPtrAllocator &Alloc); - -/// This represents a symbol that has been read from a storage::Symbol and -/// possibly a storage::Uncommon. -struct Symbol { - // Copied from storage::Symbol. - StringRef Name, IRName; - int ComdatIndex; - uint32_t Flags; - - // Copied from storage::Uncommon. - uint32_t CommonSize, CommonAlign; - StringRef COFFWeakExternFallbackName; - StringRef SectionName; - - /// Returns the mangled symbol name. - StringRef getName() const { return Name; } - - /// Returns the unmangled symbol name, or the empty string if this is not an - /// IR symbol. - StringRef getIRName() const { return IRName; } - - /// Returns the index into the comdat table (see Reader::getComdatTable()), or - /// -1 if not a comdat member. - int getComdatIndex() const { return ComdatIndex; } - - using S = storage::Symbol; - - GlobalValue::VisibilityTypes getVisibility() const { - return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3); - } - - bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; } - bool isWeak() const { return (Flags >> S::FB_weak) & 1; } - bool isCommon() const { return (Flags >> S::FB_common) & 1; } - bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; } - bool isUsed() const { return (Flags >> S::FB_used) & 1; } - bool isTLS() const { return (Flags >> S::FB_tls) & 1; } - - bool canBeOmittedFromSymbolTable() const { - return (Flags >> S::FB_may_omit) & 1; - } - - bool isGlobal() const { return (Flags >> S::FB_global) & 1; } - bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; } - bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; } - bool isExecutable() const { return (Flags >> S::FB_executable) & 1; } - - uint64_t getCommonSize() const { - assert(isCommon()); - return CommonSize; - } - - uint32_t getCommonAlignment() const { - assert(isCommon()); - return CommonAlign; - } - - /// COFF-specific: for weak externals, returns the name of the symbol that is - /// used as a fallback if the weak external remains undefined. - StringRef getCOFFWeakExternalFallback() const { - assert(isWeak() && isIndirect()); - return COFFWeakExternFallbackName; - } - - StringRef getSectionName() const { return SectionName; } -}; - -/// This class can be used to read a Symtab and Strtab produced by -/// irsymtab::build. -class Reader { - StringRef Symtab, Strtab; - - ArrayRef<storage::Module> Modules; - ArrayRef<storage::Comdat> Comdats; - ArrayRef<storage::Symbol> Symbols; - ArrayRef<storage::Uncommon> Uncommons; - ArrayRef<storage::Str> DependentLibraries; - - StringRef str(storage::Str S) const { return S.get(Strtab); } - - template <typename T> ArrayRef<T> range(storage::Range<T> R) const { - return R.get(Symtab); - } - - const storage::Header &header() const { - return *reinterpret_cast<const storage::Header *>(Symtab.data()); - } - -public: - class SymbolRef; - - Reader() = default; - Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) { - Modules = range(header().Modules); - Comdats = range(header().Comdats); - Symbols = range(header().Symbols); - Uncommons = range(header().Uncommons); - DependentLibraries = range(header().DependentLibraries); - } - - using symbol_range = iterator_range<object::content_iterator<SymbolRef>>; - - /// Returns the symbol table for the entire bitcode file. - /// The symbols enumerated by this method are ephemeral, but they can be - /// copied into an irsymtab::Symbol object. - symbol_range symbols() const; - - size_t getNumModules() const { return Modules.size(); } - - /// Returns a slice of the symbol table for the I'th module in the file. - /// The symbols enumerated by this method are ephemeral, but they can be - /// copied into an irsymtab::Symbol object. - symbol_range module_symbols(unsigned I) const; - - StringRef getTargetTriple() const { return str(header().TargetTriple); } - - /// Returns the source file path specified at compile time. - StringRef getSourceFileName() const { return str(header().SourceFileName); } - - /// Returns a table with all the comdats used by this file. - std::vector<StringRef> getComdatTable() const { - std::vector<StringRef> ComdatTable; - ComdatTable.reserve(Comdats.size()); - for (auto C : Comdats) - ComdatTable.push_back(str(C.Name)); - return ComdatTable; - } - - /// COFF-specific: returns linker options specified in the input file. - StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); } - - /// Returns dependent library specifiers - std::vector<StringRef> getDependentLibraries() const { - std::vector<StringRef> Specifiers; - Specifiers.reserve(DependentLibraries.size()); - for (auto S : DependentLibraries) { - Specifiers.push_back(str(S)); - } - return Specifiers; - } -}; - -/// Ephemeral symbols produced by Reader::symbols() and -/// Reader::module_symbols(). -class Reader::SymbolRef : public Symbol { - const storage::Symbol *SymI, *SymE; - const storage::Uncommon *UncI; - const Reader *R; - - void read() { - if (SymI == SymE) - return; - - Name = R->str(SymI->Name); - IRName = R->str(SymI->IRName); - ComdatIndex = SymI->ComdatIndex; - Flags = SymI->Flags; - - if (Flags & (1 << storage::Symbol::FB_has_uncommon)) { - CommonSize = UncI->CommonSize; - CommonAlign = UncI->CommonAlign; - COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName); - SectionName = R->str(UncI->SectionName); - } else - // Reset this field so it can be queried unconditionally for all symbols. - SectionName = ""; - } - -public: - SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE, - const storage::Uncommon *UncI, const Reader *R) - : SymI(SymI), SymE(SymE), UncI(UncI), R(R) { - read(); - } - - void moveNext() { - ++SymI; - if (Flags & (1 << storage::Symbol::FB_has_uncommon)) - ++UncI; - read(); - } - - bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; } -}; - -inline Reader::symbol_range Reader::symbols() const { - return {SymbolRef(Symbols.begin(), Symbols.end(), Uncommons.begin(), this), - SymbolRef(Symbols.end(), Symbols.end(), nullptr, this)}; -} - -inline Reader::symbol_range Reader::module_symbols(unsigned I) const { - const storage::Module &M = Modules[I]; - const storage::Symbol *MBegin = Symbols.begin() + M.Begin, - *MEnd = Symbols.begin() + M.End; - return {SymbolRef(MBegin, MEnd, Uncommons.begin() + M.UncBegin, this), - SymbolRef(MEnd, MEnd, nullptr, this)}; -} - -/// The contents of the irsymtab in a bitcode file. Any underlying data for the -/// irsymtab are owned by Symtab and Strtab. -struct FileContents { - SmallVector<char, 0> Symtab, Strtab; - Reader TheReader; -}; - -/// Reads the contents of a bitcode file, creating its irsymtab if necessary. -Expected<FileContents> readBitcode(const BitcodeFileContents &BFC); - -} // end namespace irsymtab -} // end namespace llvm - -#endif // LLVM_OBJECT_IRSYMTAB_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains data definitions and a reader and builder for a symbol +// table for LLVM IR. Its purpose is to allow linkers and other consumers of +// bitcode files to efficiently read the symbol table for symbol resolution +// purposes without needing to construct a module in memory. +// +// As with most object files the symbol table has two parts: the symbol table +// itself and a string table which is referenced by the symbol table. +// +// A symbol table corresponds to a single bitcode file, which may consist of +// multiple modules, so symbol tables may likewise contain symbols for multiple +// modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_IRSYMTAB_H +#define LLVM_OBJECT_IRSYMTAB_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <vector> + +namespace llvm { + +struct BitcodeFileContents; +class StringTableBuilder; + +namespace irsymtab { + +namespace storage { + +// The data structures in this namespace define the low-level serialization +// format. Clients that just want to read a symbol table should use the +// irsymtab::Reader class. + +using Word = support::ulittle32_t; + +/// A reference to a string in the string table. +struct Str { + Word Offset, Size; + + StringRef get(StringRef Strtab) const { + return {Strtab.data() + Offset, Size}; + } +}; + +/// A reference to a range of objects in the symbol table. +template <typename T> struct Range { + Word Offset, Size; + + ArrayRef<T> get(StringRef Symtab) const { + return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; + } +}; + +/// Describes the range of a particular module's symbols within the symbol +/// table. +struct Module { + Word Begin, End; + + /// The index of the first Uncommon for this Module. + Word UncBegin; +}; + +/// This is equivalent to an IR comdat. +struct Comdat { + Str Name; +}; + +/// Contains the information needed by linkers for symbol resolution, as well as +/// by the LTO implementation itself. +struct Symbol { + /// The mangled symbol name. + Str Name; + + /// The unmangled symbol name, or the empty string if this is not an IR + /// symbol. + Str IRName; + + /// The index into Header::Comdats, or -1 if not a comdat member. + Word ComdatIndex; + + Word Flags; + enum FlagBits { + FB_visibility, // 2 bits + FB_has_uncommon = FB_visibility + 2, + FB_undefined, + FB_weak, + FB_common, + FB_indirect, + FB_used, + FB_tls, + FB_may_omit, + FB_global, + FB_format_specific, + FB_unnamed_addr, + FB_executable, + }; +}; + +/// This data structure contains rarely used symbol fields and is optionally +/// referenced by a Symbol. +struct Uncommon { + Word CommonSize, CommonAlign; + + /// COFF-specific: the name of the symbol that a weak external resolves to + /// if not defined. + Str COFFWeakExternFallbackName; + + /// Specified section name, if any. + Str SectionName; +}; + + +struct Header { + /// Version number of the symtab format. This number should be incremented + /// when the format changes, but it does not need to be incremented if a + /// change to LLVM would cause it to create a different symbol table. + Word Version; + enum { kCurrentVersion = 2 }; + + /// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION). + /// Consumers should rebuild the symbol table from IR if the producer's + /// version does not match the consumer's version due to potential differences + /// in symbol table format, symbol enumeration order and so on. + Str Producer; + + Range<Module> Modules; + Range<Comdat> Comdats; + Range<Symbol> Symbols; + Range<Uncommon> Uncommons; + + Str TargetTriple, SourceFileName; + + /// COFF-specific: linker directives. + Str COFFLinkerOpts; + + /// Dependent Library Specifiers + Range<Str> DependentLibraries; +}; + +} // end namespace storage + +/// Fills in Symtab and StrtabBuilder with a valid symbol and string table for +/// Mods. +Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab, + StringTableBuilder &StrtabBuilder, BumpPtrAllocator &Alloc); + +/// This represents a symbol that has been read from a storage::Symbol and +/// possibly a storage::Uncommon. +struct Symbol { + // Copied from storage::Symbol. + StringRef Name, IRName; + int ComdatIndex; + uint32_t Flags; + + // Copied from storage::Uncommon. + uint32_t CommonSize, CommonAlign; + StringRef COFFWeakExternFallbackName; + StringRef SectionName; + + /// Returns the mangled symbol name. + StringRef getName() const { return Name; } + + /// Returns the unmangled symbol name, or the empty string if this is not an + /// IR symbol. + StringRef getIRName() const { return IRName; } + + /// Returns the index into the comdat table (see Reader::getComdatTable()), or + /// -1 if not a comdat member. + int getComdatIndex() const { return ComdatIndex; } + + using S = storage::Symbol; + + GlobalValue::VisibilityTypes getVisibility() const { + return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3); + } + + bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; } + bool isWeak() const { return (Flags >> S::FB_weak) & 1; } + bool isCommon() const { return (Flags >> S::FB_common) & 1; } + bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; } + bool isUsed() const { return (Flags >> S::FB_used) & 1; } + bool isTLS() const { return (Flags >> S::FB_tls) & 1; } + + bool canBeOmittedFromSymbolTable() const { + return (Flags >> S::FB_may_omit) & 1; + } + + bool isGlobal() const { return (Flags >> S::FB_global) & 1; } + bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; } + bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; } + bool isExecutable() const { return (Flags >> S::FB_executable) & 1; } + + uint64_t getCommonSize() const { + assert(isCommon()); + return CommonSize; + } + + uint32_t getCommonAlignment() const { + assert(isCommon()); + return CommonAlign; + } + + /// COFF-specific: for weak externals, returns the name of the symbol that is + /// used as a fallback if the weak external remains undefined. + StringRef getCOFFWeakExternalFallback() const { + assert(isWeak() && isIndirect()); + return COFFWeakExternFallbackName; + } + + StringRef getSectionName() const { return SectionName; } +}; + +/// This class can be used to read a Symtab and Strtab produced by +/// irsymtab::build. +class Reader { + StringRef Symtab, Strtab; + + ArrayRef<storage::Module> Modules; + ArrayRef<storage::Comdat> Comdats; + ArrayRef<storage::Symbol> Symbols; + ArrayRef<storage::Uncommon> Uncommons; + ArrayRef<storage::Str> DependentLibraries; + + StringRef str(storage::Str S) const { return S.get(Strtab); } + + template <typename T> ArrayRef<T> range(storage::Range<T> R) const { + return R.get(Symtab); + } + + const storage::Header &header() const { + return *reinterpret_cast<const storage::Header *>(Symtab.data()); + } + +public: + class SymbolRef; + + Reader() = default; + Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) { + Modules = range(header().Modules); + Comdats = range(header().Comdats); + Symbols = range(header().Symbols); + Uncommons = range(header().Uncommons); + DependentLibraries = range(header().DependentLibraries); + } + + using symbol_range = iterator_range<object::content_iterator<SymbolRef>>; + + /// Returns the symbol table for the entire bitcode file. + /// The symbols enumerated by this method are ephemeral, but they can be + /// copied into an irsymtab::Symbol object. + symbol_range symbols() const; + + size_t getNumModules() const { return Modules.size(); } + + /// Returns a slice of the symbol table for the I'th module in the file. + /// The symbols enumerated by this method are ephemeral, but they can be + /// copied into an irsymtab::Symbol object. + symbol_range module_symbols(unsigned I) const; + + StringRef getTargetTriple() const { return str(header().TargetTriple); } + + /// Returns the source file path specified at compile time. + StringRef getSourceFileName() const { return str(header().SourceFileName); } + + /// Returns a table with all the comdats used by this file. + std::vector<StringRef> getComdatTable() const { + std::vector<StringRef> ComdatTable; + ComdatTable.reserve(Comdats.size()); + for (auto C : Comdats) + ComdatTable.push_back(str(C.Name)); + return ComdatTable; + } + + /// COFF-specific: returns linker options specified in the input file. + StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); } + + /// Returns dependent library specifiers + std::vector<StringRef> getDependentLibraries() const { + std::vector<StringRef> Specifiers; + Specifiers.reserve(DependentLibraries.size()); + for (auto S : DependentLibraries) { + Specifiers.push_back(str(S)); + } + return Specifiers; + } +}; + +/// Ephemeral symbols produced by Reader::symbols() and +/// Reader::module_symbols(). +class Reader::SymbolRef : public Symbol { + const storage::Symbol *SymI, *SymE; + const storage::Uncommon *UncI; + const Reader *R; + + void read() { + if (SymI == SymE) + return; + + Name = R->str(SymI->Name); + IRName = R->str(SymI->IRName); + ComdatIndex = SymI->ComdatIndex; + Flags = SymI->Flags; + + if (Flags & (1 << storage::Symbol::FB_has_uncommon)) { + CommonSize = UncI->CommonSize; + CommonAlign = UncI->CommonAlign; + COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName); + SectionName = R->str(UncI->SectionName); + } else + // Reset this field so it can be queried unconditionally for all symbols. + SectionName = ""; + } + +public: + SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE, + const storage::Uncommon *UncI, const Reader *R) + : SymI(SymI), SymE(SymE), UncI(UncI), R(R) { + read(); + } + + void moveNext() { + ++SymI; + if (Flags & (1 << storage::Symbol::FB_has_uncommon)) + ++UncI; + read(); + } + + bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; } +}; + +inline Reader::symbol_range Reader::symbols() const { + return {SymbolRef(Symbols.begin(), Symbols.end(), Uncommons.begin(), this), + SymbolRef(Symbols.end(), Symbols.end(), nullptr, this)}; +} + +inline Reader::symbol_range Reader::module_symbols(unsigned I) const { + const storage::Module &M = Modules[I]; + const storage::Symbol *MBegin = Symbols.begin() + M.Begin, + *MEnd = Symbols.begin() + M.End; + return {SymbolRef(MBegin, MEnd, Uncommons.begin() + M.UncBegin, this), + SymbolRef(MEnd, MEnd, nullptr, this)}; +} + +/// The contents of the irsymtab in a bitcode file. Any underlying data for the +/// irsymtab are owned by Symtab and Strtab. +struct FileContents { + SmallVector<char, 0> Symtab, Strtab; + Reader TheReader; +}; + +/// Reads the contents of a bitcode file, creating its irsymtab if necessary. +Expected<FileContents> readBitcode(const BitcodeFileContents &BFC); + +} // end namespace irsymtab +} // end namespace llvm + +#endif // LLVM_OBJECT_IRSYMTAB_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/MachO.h b/contrib/libs/llvm12/include/llvm/Object/MachO.h index bbc0a233ee1..7c8004f6883 100644 --- a/contrib/libs/llvm12/include/llvm/Object/MachO.h +++ b/contrib/libs/llvm12/include/llvm/Object/MachO.h @@ -1,750 +1,750 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- MachO.h - MachO object file implementation ---------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the MachOObjectFile class, which implement the ObjectFile -// interface for MachO files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHO_H -#define LLVM_OBJECT_MACHO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include <cstdint> -#include <memory> -#include <string> -#include <system_error> - -namespace llvm { -namespace object { - -/// DiceRef - This is a value type class that represents a single -/// data in code entry in the table in a Mach-O object file. -class DiceRef { - DataRefImpl DicePimpl; - const ObjectFile *OwningObject = nullptr; - -public: - DiceRef() = default; - DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); - - bool operator==(const DiceRef &Other) const; - bool operator<(const DiceRef &Other) const; - - void moveNext(); - - std::error_code getOffset(uint32_t &Result) const; - std::error_code getLength(uint16_t &Result) const; - std::error_code getKind(uint16_t &Result) const; - - DataRefImpl getRawDataRefImpl() const; - const ObjectFile *getObjectFile() const; -}; -using dice_iterator = content_iterator<DiceRef>; - -/// ExportEntry encapsulates the current-state-of-the-walk used when doing a -/// non-recursive walk of the trie data structure. This allows you to iterate -/// across all exported symbols using: -/// Error Err = Error::success(); -/// for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) { -/// } -/// if (Err) { report error ... -class ExportEntry { -public: - ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie); - - StringRef name() const; - uint64_t flags() const; - uint64_t address() const; - uint64_t other() const; - StringRef otherName() const; - uint32_t nodeOffset() const; - - bool operator==(const ExportEntry &) const; - - void moveNext(); - -private: - friend class MachOObjectFile; - - void moveToFirst(); - void moveToEnd(); - uint64_t readULEB128(const uint8_t *&p, const char **error); - void pushDownUntilBottom(); - void pushNode(uint64_t Offset); - - // Represents a node in the mach-o exports trie. - struct NodeState { - NodeState(const uint8_t *Ptr); - - const uint8_t *Start; - const uint8_t *Current; - uint64_t Flags = 0; - uint64_t Address = 0; - uint64_t Other = 0; - const char *ImportName = nullptr; - unsigned ChildCount = 0; - unsigned NextChildIndex = 0; - unsigned ParentStringLength = 0; - bool IsExportNode = false; - }; - using NodeList = SmallVector<NodeState, 16>; - using node_iterator = NodeList::const_iterator; - - Error *E; - const MachOObjectFile *O; - ArrayRef<uint8_t> Trie; - SmallString<256> CumulativeString; - NodeList Stack; - bool Done = false; - - iterator_range<node_iterator> nodes() const { - return make_range(Stack.begin(), Stack.end()); - } -}; -using export_iterator = content_iterator<ExportEntry>; - -// Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry -// can be checked and translated. Only the SegIndex/SegOffset pairs from -// checked entries are to be used with the segmentName(), sectionName() and -// address() methods below. -class BindRebaseSegInfo { -public: - BindRebaseSegInfo(const MachOObjectFile *Obj); - - // Used to check a Mach-O Bind or Rebase entry for errors when iterating. - const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, - uint8_t PointerSize, uint32_t Count=1, - uint32_t Skip=0); - // Used with valid SegIndex/SegOffset values from checked entries. - StringRef segmentName(int32_t SegIndex); - StringRef sectionName(int32_t SegIndex, uint64_t SegOffset); - uint64_t address(uint32_t SegIndex, uint64_t SegOffset); - -private: - struct SectionInfo { - uint64_t Address; - uint64_t Size; - StringRef SectionName; - StringRef SegmentName; - uint64_t OffsetInSegment; - uint64_t SegmentStartAddress; - int32_t SegmentIndex; - }; - const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset); - - SmallVector<SectionInfo, 32> Sections; - int32_t MaxSegIndex; -}; - -/// MachORebaseEntry encapsulates the current state in the decompression of -/// rebasing opcodes. This allows you to iterate through the compressed table of -/// rebasing using: -/// Error Err = Error::success(); -/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) { -/// } -/// if (Err) { report error ... -class MachORebaseEntry { -public: - MachORebaseEntry(Error *Err, const MachOObjectFile *O, - ArrayRef<uint8_t> opcodes, bool is64Bit); - - int32_t segmentIndex() const; - uint64_t segmentOffset() const; - StringRef typeName() const; - StringRef segmentName() const; - StringRef sectionName() const; - uint64_t address() const; - - bool operator==(const MachORebaseEntry &) const; - - void moveNext(); - -private: - friend class MachOObjectFile; - - void moveToFirst(); - void moveToEnd(); - uint64_t readULEB128(const char **error); - - Error *E; - const MachOObjectFile *O; - ArrayRef<uint8_t> Opcodes; - const uint8_t *Ptr; - uint64_t SegmentOffset = 0; - int32_t SegmentIndex = -1; - uint64_t RemainingLoopCount = 0; - uint64_t AdvanceAmount = 0; - uint8_t RebaseType = 0; - uint8_t PointerSize; - bool Done = false; -}; -using rebase_iterator = content_iterator<MachORebaseEntry>; - -/// MachOBindEntry encapsulates the current state in the decompression of -/// binding opcodes. This allows you to iterate through the compressed table of -/// bindings using: -/// Error Err = Error::success(); -/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) { -/// } -/// if (Err) { report error ... -class MachOBindEntry { -public: - enum class Kind { Regular, Lazy, Weak }; - - MachOBindEntry(Error *Err, const MachOObjectFile *O, - ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); - - int32_t segmentIndex() const; - uint64_t segmentOffset() const; - StringRef typeName() const; - StringRef symbolName() const; - uint32_t flags() const; - int64_t addend() const; - int ordinal() const; - - StringRef segmentName() const; - StringRef sectionName() const; - uint64_t address() const; - - bool operator==(const MachOBindEntry &) const; - - void moveNext(); - -private: - friend class MachOObjectFile; - - void moveToFirst(); - void moveToEnd(); - uint64_t readULEB128(const char **error); - int64_t readSLEB128(const char **error); - - Error *E; - const MachOObjectFile *O; - ArrayRef<uint8_t> Opcodes; - const uint8_t *Ptr; - uint64_t SegmentOffset = 0; - int32_t SegmentIndex = -1; - StringRef SymbolName; - bool LibraryOrdinalSet = false; - int Ordinal = 0; - uint32_t Flags = 0; - int64_t Addend = 0; - uint64_t RemainingLoopCount = 0; - uint64_t AdvanceAmount = 0; - uint8_t BindType = 0; - uint8_t PointerSize; - Kind TableKind; - bool Done = false; -}; -using bind_iterator = content_iterator<MachOBindEntry>; - -class MachOObjectFile : public ObjectFile { -public: - struct LoadCommandInfo { - const char *Ptr; // Where in memory the load command is. - MachO::load_command C; // The command itself. - }; - using LoadCommandList = SmallVector<LoadCommandInfo, 4>; - using load_command_iterator = LoadCommandList::const_iterator; - - static Expected<std::unique_ptr<MachOObjectFile>> - create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, - uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0); - - void moveSymbolNext(DataRefImpl &Symb) const override; - - uint64_t getNValue(DataRefImpl Sym) const; - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - - // MachO specific. - Error checkSymbolTable() const; - - std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; - unsigned getSectionType(SectionRef Sec) const; - - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint32_t getSymbolAlignment(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - unsigned getSymbolSectionID(SymbolRef Symb) const; - unsigned getSectionID(SectionRef Sec) const; - - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - Expected<SectionRef> getSection(unsigned SectionIndex) const; - Expected<SectionRef> getSection(StringRef SectionName) const; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionBitcode(DataRefImpl Sec) const override; - bool isDebugSection(StringRef SectionName) const override; - - /// When dsymutil generates the companion file, it strips all unnecessary - /// sections (e.g. everything in the _TEXT segment) by omitting their body - /// and setting the offset in their corresponding load command to zero. - /// - /// While the load command itself is valid, reading the section corresponds - /// to reading the number of bytes specified in the load command, starting - /// from offset 0 (i.e. the Mach-O header at the beginning of the file). - bool isSectionStripped(DataRefImpl Sec) const override; - - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - - relocation_iterator extrel_begin() const; - relocation_iterator extrel_end() const; - iterator_range<relocation_iterator> external_relocations() const { - return make_range(extrel_begin(), extrel_end()); - } - - relocation_iterator locrel_begin() const; - relocation_iterator locrel_end() const; - - void moveRelocationNext(DataRefImpl &Rel) const override; - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - section_iterator getRelocationSection(DataRefImpl Rel) const; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - uint8_t getRelocationLength(DataRefImpl Rel) const; - - // MachO specific. - std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; - uint32_t getLibraryCount() const; - - section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; - - // TODO: Would be useful to have an iterator based version - // of the load command interface too. - - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - - // MachO specific. - symbol_iterator getSymbolByIndex(unsigned Index) const; - uint64_t getSymbolIndex(DataRefImpl Symb) const; - - section_iterator section_begin() const override; - section_iterator section_end() const override; - - uint8_t getBytesInAddress() const override; - - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } - Triple getArchTriple(const char **McpuDefault = nullptr) const; - - relocation_iterator section_rel_begin(unsigned Index) const; - relocation_iterator section_rel_end(unsigned Index) const; - - dice_iterator begin_dices() const; - dice_iterator end_dices() const; - - load_command_iterator begin_load_commands() const; - load_command_iterator end_load_commands() const; - iterator_range<load_command_iterator> load_commands() const; - - /// For use iterating over all exported symbols. - iterator_range<export_iterator> exports(Error &Err) const; - - /// For use examining a trie not in a MachOObjectFile. - static iterator_range<export_iterator> exports(Error &Err, - ArrayRef<uint8_t> Trie, - const MachOObjectFile *O = - nullptr); - - /// For use iterating over all rebase table entries. - iterator_range<rebase_iterator> rebaseTable(Error &Err); - - /// For use examining rebase opcodes in a MachOObjectFile. - static iterator_range<rebase_iterator> rebaseTable(Error &Err, - MachOObjectFile *O, - ArrayRef<uint8_t> Opcodes, - bool is64); - - /// For use iterating over all bind table entries. - iterator_range<bind_iterator> bindTable(Error &Err); - - /// For use iterating over all lazy bind table entries. - iterator_range<bind_iterator> lazyBindTable(Error &Err); - - /// For use iterating over all weak bind table entries. - iterator_range<bind_iterator> weakBindTable(Error &Err); - - /// For use examining bind opcodes in a MachOObjectFile. - static iterator_range<bind_iterator> bindTable(Error &Err, - MachOObjectFile *O, - ArrayRef<uint8_t> Opcodes, - bool is64, - MachOBindEntry::Kind); - - // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists - // that fully contains a pointer at that location. Multiple fixups in a bind - // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can - // be tested via the Count and Skip parameters. - // - // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry. - const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, - uint8_t PointerSize, uint32_t Count=1, - uint32_t Skip=0) const { - return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, - PointerSize, Count, Skip); - } - - // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists - // that fully contains a pointer at that location. Multiple fixups in a rebase - // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the - // Count and Skip parameters. - // - // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry - const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex, - uint64_t SegOffset, - uint8_t PointerSize, - uint32_t Count=1, - uint32_t Skip=0) const { - return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, - PointerSize, Count, Skip); - } - - /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to - /// get the segment name. - StringRef BindRebaseSegmentName(int32_t SegIndex) const { - return BindRebaseSectionTable->segmentName(SegIndex); - } - - /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or - /// Rebase entry to get the section name. - StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const { - return BindRebaseSectionTable->sectionName(SegIndex, SegOffset); - } - - /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or - /// Rebase entry to get the address. - uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const { - return BindRebaseSectionTable->address(SegIndex, SegOffset); - } - - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in the final object. - StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - - // Names are stored as 16 bytes. These returns the raw 16 bytes without - // interpreting them as a C string. - ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; - ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; - - // MachO specific Info about relocations. - bool isRelocationScattered(const MachO::any_relocation_info &RE) const; - unsigned getPlainRelocationSymbolNum( - const MachO::any_relocation_info &RE) const; - bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const; - bool getScatteredRelocationScattered( - const MachO::any_relocation_info &RE) const; - uint32_t getScatteredRelocationValue( - const MachO::any_relocation_info &RE) const; - uint32_t getScatteredRelocationType( - const MachO::any_relocation_info &RE) const; - unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; - unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; - unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; - unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; - SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; - - // MachO specific structures. - MachO::section getSection(DataRefImpl DRI) const; - MachO::section_64 getSection64(DataRefImpl DRI) const; - MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; - MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; - MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; - MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; - - MachO::linkedit_data_command - getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; - MachO::segment_command - getSegmentLoadCommand(const LoadCommandInfo &L) const; - MachO::segment_command_64 - getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_option_command - getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; - MachO::version_min_command - getVersionMinLoadCommand(const LoadCommandInfo &L) const; - MachO::note_command - getNoteLoadCommand(const LoadCommandInfo &L) const; - MachO::build_version_command - getBuildVersionLoadCommand(const LoadCommandInfo &L) const; - MachO::build_tool_version - getBuildToolVersion(unsigned index) const; - MachO::dylib_command - getDylibIDLoadCommand(const LoadCommandInfo &L) const; - MachO::dyld_info_command - getDyldInfoLoadCommand(const LoadCommandInfo &L) const; - MachO::dylinker_command - getDylinkerCommand(const LoadCommandInfo &L) const; - MachO::uuid_command - getUuidCommand(const LoadCommandInfo &L) const; - MachO::rpath_command - getRpathCommand(const LoadCommandInfo &L) const; - MachO::source_version_command - getSourceVersionCommand(const LoadCommandInfo &L) const; - MachO::entry_point_command - getEntryPointCommand(const LoadCommandInfo &L) const; - MachO::encryption_info_command - getEncryptionInfoCommand(const LoadCommandInfo &L) const; - MachO::encryption_info_command_64 - getEncryptionInfoCommand64(const LoadCommandInfo &L) const; - MachO::sub_framework_command - getSubFrameworkCommand(const LoadCommandInfo &L) const; - MachO::sub_umbrella_command - getSubUmbrellaCommand(const LoadCommandInfo &L) const; - MachO::sub_library_command - getSubLibraryCommand(const LoadCommandInfo &L) const; - MachO::sub_client_command - getSubClientCommand(const LoadCommandInfo &L) const; - MachO::routines_command - getRoutinesCommand(const LoadCommandInfo &L) const; - MachO::routines_command_64 - getRoutinesCommand64(const LoadCommandInfo &L) const; - MachO::thread_command - getThreadCommand(const LoadCommandInfo &L) const; - - MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; - MachO::data_in_code_entry getDice(DataRefImpl Rel) const; - const MachO::mach_header &getHeader() const; - const MachO::mach_header_64 &getHeader64() const; - uint32_t - getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, - unsigned Index) const; - MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const; - MachO::symtab_command getSymtabLoadCommand() const; - MachO::dysymtab_command getDysymtabLoadCommand() const; - MachO::linkedit_data_command getDataInCodeLoadCommand() const; - MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; - ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const; - ArrayRef<uint8_t> getDyldInfoBindOpcodes() const; - ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const; - ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const; - ArrayRef<uint8_t> getDyldInfoExportsTrie() const; - ArrayRef<uint8_t> getUuid() const; - - StringRef getStringTableData() const; - bool is64Bit() const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - - static StringRef guessLibraryShortName(StringRef Name, bool &isFramework, - StringRef &Suffix); - - static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType); - static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault = nullptr, - const char **ArchFlag = nullptr); - static bool isValidArch(StringRef ArchFlag); - static ArrayRef<StringRef> getValidArchs(); - static Triple getHostArch(); - - bool isRelocatableObject() const override; - - StringRef mapDebugSectionName(StringRef Name) const override; - - bool hasPageZeroSegment() const { return HasPageZeroSegment; } - - static bool classof(const Binary *v) { - return v->isMachO(); - } - - static uint32_t - getVersionMinMajor(MachO::version_min_command &C, bool SDK) { - uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; - return (VersionOrSDK >> 16) & 0xffff; - } - - static uint32_t - getVersionMinMinor(MachO::version_min_command &C, bool SDK) { - uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; - return (VersionOrSDK >> 8) & 0xff; - } - - static uint32_t - getVersionMinUpdate(MachO::version_min_command &C, bool SDK) { - uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; - return VersionOrSDK & 0xff; - } - - static std::string getBuildPlatform(uint32_t platform) { - switch (platform) { - case MachO::PLATFORM_MACOS: return "macos"; - case MachO::PLATFORM_IOS: return "ios"; - case MachO::PLATFORM_TVOS: return "tvos"; - case MachO::PLATFORM_WATCHOS: return "watchos"; - case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; - case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; - case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; - case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; - case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- MachO.h - MachO object file implementation ---------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the MachOObjectFile class, which implement the ObjectFile +// interface for MachO files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHO_H +#define LLVM_OBJECT_MACHO_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> +#include <memory> +#include <string> +#include <system_error> + +namespace llvm { +namespace object { + +/// DiceRef - This is a value type class that represents a single +/// data in code entry in the table in a Mach-O object file. +class DiceRef { + DataRefImpl DicePimpl; + const ObjectFile *OwningObject = nullptr; + +public: + DiceRef() = default; + DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); + + bool operator==(const DiceRef &Other) const; + bool operator<(const DiceRef &Other) const; + + void moveNext(); + + std::error_code getOffset(uint32_t &Result) const; + std::error_code getLength(uint16_t &Result) const; + std::error_code getKind(uint16_t &Result) const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; +}; +using dice_iterator = content_iterator<DiceRef>; + +/// ExportEntry encapsulates the current-state-of-the-walk used when doing a +/// non-recursive walk of the trie data structure. This allows you to iterate +/// across all exported symbols using: +/// Error Err = Error::success(); +/// for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) { +/// } +/// if (Err) { report error ... +class ExportEntry { +public: + ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie); + + StringRef name() const; + uint64_t flags() const; + uint64_t address() const; + uint64_t other() const; + StringRef otherName() const; + uint32_t nodeOffset() const; + + bool operator==(const ExportEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(const uint8_t *&p, const char **error); + void pushDownUntilBottom(); + void pushNode(uint64_t Offset); + + // Represents a node in the mach-o exports trie. + struct NodeState { + NodeState(const uint8_t *Ptr); + + const uint8_t *Start; + const uint8_t *Current; + uint64_t Flags = 0; + uint64_t Address = 0; + uint64_t Other = 0; + const char *ImportName = nullptr; + unsigned ChildCount = 0; + unsigned NextChildIndex = 0; + unsigned ParentStringLength = 0; + bool IsExportNode = false; + }; + using NodeList = SmallVector<NodeState, 16>; + using node_iterator = NodeList::const_iterator; + + Error *E; + const MachOObjectFile *O; + ArrayRef<uint8_t> Trie; + SmallString<256> CumulativeString; + NodeList Stack; + bool Done = false; + + iterator_range<node_iterator> nodes() const { + return make_range(Stack.begin(), Stack.end()); + } +}; +using export_iterator = content_iterator<ExportEntry>; + +// Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry +// can be checked and translated. Only the SegIndex/SegOffset pairs from +// checked entries are to be used with the segmentName(), sectionName() and +// address() methods below. +class BindRebaseSegInfo { +public: + BindRebaseSegInfo(const MachOObjectFile *Obj); + + // Used to check a Mach-O Bind or Rebase entry for errors when iterating. + const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, + uint8_t PointerSize, uint32_t Count=1, + uint32_t Skip=0); + // Used with valid SegIndex/SegOffset values from checked entries. + StringRef segmentName(int32_t SegIndex); + StringRef sectionName(int32_t SegIndex, uint64_t SegOffset); + uint64_t address(uint32_t SegIndex, uint64_t SegOffset); + +private: + struct SectionInfo { + uint64_t Address; + uint64_t Size; + StringRef SectionName; + StringRef SegmentName; + uint64_t OffsetInSegment; + uint64_t SegmentStartAddress; + int32_t SegmentIndex; + }; + const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset); + + SmallVector<SectionInfo, 32> Sections; + int32_t MaxSegIndex; +}; + +/// MachORebaseEntry encapsulates the current state in the decompression of +/// rebasing opcodes. This allows you to iterate through the compressed table of +/// rebasing using: +/// Error Err = Error::success(); +/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) { +/// } +/// if (Err) { report error ... +class MachORebaseEntry { +public: + MachORebaseEntry(Error *Err, const MachOObjectFile *O, + ArrayRef<uint8_t> opcodes, bool is64Bit); + + int32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + StringRef segmentName() const; + StringRef sectionName() const; + uint64_t address() const; + + bool operator==(const MachORebaseEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(const char **error); + + Error *E; + const MachOObjectFile *O; + ArrayRef<uint8_t> Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset = 0; + int32_t SegmentIndex = -1; + uint64_t RemainingLoopCount = 0; + uint64_t AdvanceAmount = 0; + uint8_t RebaseType = 0; + uint8_t PointerSize; + bool Done = false; +}; +using rebase_iterator = content_iterator<MachORebaseEntry>; + +/// MachOBindEntry encapsulates the current state in the decompression of +/// binding opcodes. This allows you to iterate through the compressed table of +/// bindings using: +/// Error Err = Error::success(); +/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) { +/// } +/// if (Err) { report error ... +class MachOBindEntry { +public: + enum class Kind { Regular, Lazy, Weak }; + + MachOBindEntry(Error *Err, const MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); + + int32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + StringRef symbolName() const; + uint32_t flags() const; + int64_t addend() const; + int ordinal() const; + + StringRef segmentName() const; + StringRef sectionName() const; + uint64_t address() const; + + bool operator==(const MachOBindEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(const char **error); + int64_t readSLEB128(const char **error); + + Error *E; + const MachOObjectFile *O; + ArrayRef<uint8_t> Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset = 0; + int32_t SegmentIndex = -1; + StringRef SymbolName; + bool LibraryOrdinalSet = false; + int Ordinal = 0; + uint32_t Flags = 0; + int64_t Addend = 0; + uint64_t RemainingLoopCount = 0; + uint64_t AdvanceAmount = 0; + uint8_t BindType = 0; + uint8_t PointerSize; + Kind TableKind; + bool Done = false; +}; +using bind_iterator = content_iterator<MachOBindEntry>; + +class MachOObjectFile : public ObjectFile { +public: + struct LoadCommandInfo { + const char *Ptr; // Where in memory the load command is. + MachO::load_command C; // The command itself. + }; + using LoadCommandList = SmallVector<LoadCommandInfo, 4>; + using load_command_iterator = LoadCommandList::const_iterator; + + static Expected<std::unique_ptr<MachOObjectFile>> + create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0); + + void moveSymbolNext(DataRefImpl &Symb) const override; + + uint64_t getNValue(DataRefImpl Sym) const; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + + // MachO specific. + Error checkSymbolTable() const; + + std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + unsigned getSectionType(SectionRef Sec) const; + + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + unsigned getSymbolSectionID(SymbolRef Symb) const; + unsigned getSectionID(SectionRef Sec) const; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + Expected<SectionRef> getSection(unsigned SectionIndex) const; + Expected<SectionRef> getSection(StringRef SectionName) const; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isSectionBitcode(DataRefImpl Sec) const override; + bool isDebugSection(StringRef SectionName) const override; + + /// When dsymutil generates the companion file, it strips all unnecessary + /// sections (e.g. everything in the _TEXT segment) by omitting their body + /// and setting the offset in their corresponding load command to zero. + /// + /// While the load command itself is valid, reading the section corresponds + /// to reading the number of bytes specified in the load command, starting + /// from offset 0 (i.e. the Mach-O header at the beginning of the file). + bool isSectionStripped(DataRefImpl Sec) const override; + + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + relocation_iterator extrel_begin() const; + relocation_iterator extrel_end() const; + iterator_range<relocation_iterator> external_relocations() const { + return make_range(extrel_begin(), extrel_end()); + } + + relocation_iterator locrel_begin() const; + relocation_iterator locrel_end() const; + + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + uint8_t getRelocationLength(DataRefImpl Rel) const; + + // MachO specific. + std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; + uint32_t getLibraryCount() const; + + section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; + + // TODO: Would be useful to have an iterator based version + // of the load command interface too. + + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + // MachO specific. + symbol_iterator getSymbolByIndex(unsigned Index) const; + uint64_t getSymbolIndex(DataRefImpl Symb) const; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + + uint8_t getBytesInAddress() const override; + + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + Triple getArchTriple(const char **McpuDefault = nullptr) const; + + relocation_iterator section_rel_begin(unsigned Index) const; + relocation_iterator section_rel_end(unsigned Index) const; + + dice_iterator begin_dices() const; + dice_iterator end_dices() const; + + load_command_iterator begin_load_commands() const; + load_command_iterator end_load_commands() const; + iterator_range<load_command_iterator> load_commands() const; + + /// For use iterating over all exported symbols. + iterator_range<export_iterator> exports(Error &Err) const; + + /// For use examining a trie not in a MachOObjectFile. + static iterator_range<export_iterator> exports(Error &Err, + ArrayRef<uint8_t> Trie, + const MachOObjectFile *O = + nullptr); + + /// For use iterating over all rebase table entries. + iterator_range<rebase_iterator> rebaseTable(Error &Err); + + /// For use examining rebase opcodes in a MachOObjectFile. + static iterator_range<rebase_iterator> rebaseTable(Error &Err, + MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, + bool is64); + + /// For use iterating over all bind table entries. + iterator_range<bind_iterator> bindTable(Error &Err); + + /// For use iterating over all lazy bind table entries. + iterator_range<bind_iterator> lazyBindTable(Error &Err); + + /// For use iterating over all weak bind table entries. + iterator_range<bind_iterator> weakBindTable(Error &Err); + + /// For use examining bind opcodes in a MachOObjectFile. + static iterator_range<bind_iterator> bindTable(Error &Err, + MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, + bool is64, + MachOBindEntry::Kind); + + // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists + // that fully contains a pointer at that location. Multiple fixups in a bind + // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can + // be tested via the Count and Skip parameters. + // + // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry. + const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, + uint8_t PointerSize, uint32_t Count=1, + uint32_t Skip=0) const { + return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, + PointerSize, Count, Skip); + } + + // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists + // that fully contains a pointer at that location. Multiple fixups in a rebase + // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the + // Count and Skip parameters. + // + // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry + const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex, + uint64_t SegOffset, + uint8_t PointerSize, + uint32_t Count=1, + uint32_t Skip=0) const { + return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, + PointerSize, Count, Skip); + } + + /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to + /// get the segment name. + StringRef BindRebaseSegmentName(int32_t SegIndex) const { + return BindRebaseSectionTable->segmentName(SegIndex); + } + + /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or + /// Rebase entry to get the section name. + StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const { + return BindRebaseSectionTable->sectionName(SegIndex, SegOffset); + } + + /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or + /// Rebase entry to get the address. + uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const { + return BindRebaseSectionTable->address(SegIndex, SegOffset); + } + + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in the final object. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; + ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; + + // MachO specific Info about relocations. + bool isRelocationScattered(const MachO::any_relocation_info &RE) const; + unsigned getPlainRelocationSymbolNum( + const MachO::any_relocation_info &RE) const; + bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const; + bool getScatteredRelocationScattered( + const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationValue( + const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationType( + const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; + SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; + + // MachO specific structures. + MachO::section getSection(DataRefImpl DRI) const; + MachO::section_64 getSection64(DataRefImpl DRI) const; + MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; + MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; + MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; + MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; + + MachO::linkedit_data_command + getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; + MachO::segment_command + getSegmentLoadCommand(const LoadCommandInfo &L) const; + MachO::segment_command_64 + getSegment64LoadCommand(const LoadCommandInfo &L) const; + MachO::linker_option_command + getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; + MachO::version_min_command + getVersionMinLoadCommand(const LoadCommandInfo &L) const; + MachO::note_command + getNoteLoadCommand(const LoadCommandInfo &L) const; + MachO::build_version_command + getBuildVersionLoadCommand(const LoadCommandInfo &L) const; + MachO::build_tool_version + getBuildToolVersion(unsigned index) const; + MachO::dylib_command + getDylibIDLoadCommand(const LoadCommandInfo &L) const; + MachO::dyld_info_command + getDyldInfoLoadCommand(const LoadCommandInfo &L) const; + MachO::dylinker_command + getDylinkerCommand(const LoadCommandInfo &L) const; + MachO::uuid_command + getUuidCommand(const LoadCommandInfo &L) const; + MachO::rpath_command + getRpathCommand(const LoadCommandInfo &L) const; + MachO::source_version_command + getSourceVersionCommand(const LoadCommandInfo &L) const; + MachO::entry_point_command + getEntryPointCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command + getEncryptionInfoCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command_64 + getEncryptionInfoCommand64(const LoadCommandInfo &L) const; + MachO::sub_framework_command + getSubFrameworkCommand(const LoadCommandInfo &L) const; + MachO::sub_umbrella_command + getSubUmbrellaCommand(const LoadCommandInfo &L) const; + MachO::sub_library_command + getSubLibraryCommand(const LoadCommandInfo &L) const; + MachO::sub_client_command + getSubClientCommand(const LoadCommandInfo &L) const; + MachO::routines_command + getRoutinesCommand(const LoadCommandInfo &L) const; + MachO::routines_command_64 + getRoutinesCommand64(const LoadCommandInfo &L) const; + MachO::thread_command + getThreadCommand(const LoadCommandInfo &L) const; + + MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; + MachO::data_in_code_entry getDice(DataRefImpl Rel) const; + const MachO::mach_header &getHeader() const; + const MachO::mach_header_64 &getHeader64() const; + uint32_t + getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, + unsigned Index) const; + MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + MachO::symtab_command getSymtabLoadCommand() const; + MachO::dysymtab_command getDysymtabLoadCommand() const; + MachO::linkedit_data_command getDataInCodeLoadCommand() const; + MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; + ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const; + ArrayRef<uint8_t> getDyldInfoBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const; + ArrayRef<uint8_t> getDyldInfoExportsTrie() const; + ArrayRef<uint8_t> getUuid() const; + + StringRef getStringTableData() const; + bool is64Bit() const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; + + static StringRef guessLibraryShortName(StringRef Name, bool &isFramework, + StringRef &Suffix); + + static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType); + static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr, + const char **ArchFlag = nullptr); + static bool isValidArch(StringRef ArchFlag); + static ArrayRef<StringRef> getValidArchs(); + static Triple getHostArch(); + + bool isRelocatableObject() const override; + + StringRef mapDebugSectionName(StringRef Name) const override; + + bool hasPageZeroSegment() const { return HasPageZeroSegment; } + + static bool classof(const Binary *v) { + return v->isMachO(); + } + + static uint32_t + getVersionMinMajor(MachO::version_min_command &C, bool SDK) { + uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; + return (VersionOrSDK >> 16) & 0xffff; + } + + static uint32_t + getVersionMinMinor(MachO::version_min_command &C, bool SDK) { + uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; + return (VersionOrSDK >> 8) & 0xff; + } + + static uint32_t + getVersionMinUpdate(MachO::version_min_command &C, bool SDK) { + uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version; + return VersionOrSDK & 0xff; + } + + static std::string getBuildPlatform(uint32_t platform) { + switch (platform) { + case MachO::PLATFORM_MACOS: return "macos"; + case MachO::PLATFORM_IOS: return "ios"; + case MachO::PLATFORM_TVOS: return "tvos"; + case MachO::PLATFORM_WATCHOS: return "watchos"; + case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; + case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; + case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; + case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; + case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; case MachO::PLATFORM_DRIVERKIT: return "driverkit"; - default: - std::string ret; - raw_string_ostream ss(ret); - ss << format_hex(platform, 8, true); - return ss.str(); - } - } - - static std::string getBuildTool(uint32_t tools) { - switch (tools) { - case MachO::TOOL_CLANG: return "clang"; - case MachO::TOOL_SWIFT: return "swift"; - case MachO::TOOL_LD: return "ld"; - default: - std::string ret; - raw_string_ostream ss(ret); - ss << format_hex(tools, 8, true); - return ss.str(); - } - } - - static std::string getVersionString(uint32_t version) { - uint32_t major = (version >> 16) & 0xffff; - uint32_t minor = (version >> 8) & 0xff; - uint32_t update = version & 0xff; - - SmallString<32> Version; - Version = utostr(major) + "." + utostr(minor); - if (update != 0) - Version += "." + utostr(update); - return std::string(std::string(Version.str())); - } - -private: - MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, - Error &Err, uint32_t UniversalCputype = 0, - uint32_t UniversalIndex = 0); - - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - - union { - MachO::mach_header_64 Header64; - MachO::mach_header Header; - }; - using SectionList = SmallVector<const char*, 1>; - SectionList Sections; - using LibraryList = SmallVector<const char*, 1>; - LibraryList Libraries; - LoadCommandList LoadCommands; - using LibraryShortName = SmallVector<StringRef, 1>; - using BuildToolList = SmallVector<const char*, 1>; - BuildToolList BuildTools; - mutable LibraryShortName LibrariesShortNames; - std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable; - const char *SymtabLoadCmd = nullptr; - const char *DysymtabLoadCmd = nullptr; - const char *DataInCodeLoadCmd = nullptr; - const char *LinkOptHintsLoadCmd = nullptr; - const char *DyldInfoLoadCmd = nullptr; - const char *UuidLoadCmd = nullptr; - bool HasPageZeroSegment = false; -}; - -/// DiceRef -inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner) - : DicePimpl(DiceP) , OwningObject(Owner) {} - -inline bool DiceRef::operator==(const DiceRef &Other) const { - return DicePimpl == Other.DicePimpl; -} - -inline bool DiceRef::operator<(const DiceRef &Other) const { - return DicePimpl < Other.DicePimpl; -} - -inline void DiceRef::moveNext() { - const MachO::data_in_code_entry *P = - reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p); - DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1); -} - -// Since a Mach-O data in code reference, a DiceRef, can only be created when -// the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for -// the methods that get the values of the fields of the reference. - -inline std::error_code DiceRef::getOffset(uint32_t &Result) const { - const MachOObjectFile *MachOOF = - static_cast<const MachOObjectFile *>(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.offset; - return std::error_code(); -} - -inline std::error_code DiceRef::getLength(uint16_t &Result) const { - const MachOObjectFile *MachOOF = - static_cast<const MachOObjectFile *>(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.length; - return std::error_code(); -} - -inline std::error_code DiceRef::getKind(uint16_t &Result) const { - const MachOObjectFile *MachOOF = - static_cast<const MachOObjectFile *>(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.kind; - return std::error_code(); -} - -inline DataRefImpl DiceRef::getRawDataRefImpl() const { - return DicePimpl; -} - -inline const ObjectFile *DiceRef::getObjectFile() const { - return OwningObject; -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_MACHO_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + default: + std::string ret; + raw_string_ostream ss(ret); + ss << format_hex(platform, 8, true); + return ss.str(); + } + } + + static std::string getBuildTool(uint32_t tools) { + switch (tools) { + case MachO::TOOL_CLANG: return "clang"; + case MachO::TOOL_SWIFT: return "swift"; + case MachO::TOOL_LD: return "ld"; + default: + std::string ret; + raw_string_ostream ss(ret); + ss << format_hex(tools, 8, true); + return ss.str(); + } + } + + static std::string getVersionString(uint32_t version) { + uint32_t major = (version >> 16) & 0xffff; + uint32_t minor = (version >> 8) & 0xff; + uint32_t update = version & 0xff; + + SmallString<32> Version; + Version = utostr(major) + "." + utostr(minor); + if (update != 0) + Version += "." + utostr(update); + return std::string(std::string(Version.str())); + } + +private: + MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + Error &Err, uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); + + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + + union { + MachO::mach_header_64 Header64; + MachO::mach_header Header; + }; + using SectionList = SmallVector<const char*, 1>; + SectionList Sections; + using LibraryList = SmallVector<const char*, 1>; + LibraryList Libraries; + LoadCommandList LoadCommands; + using LibraryShortName = SmallVector<StringRef, 1>; + using BuildToolList = SmallVector<const char*, 1>; + BuildToolList BuildTools; + mutable LibraryShortName LibrariesShortNames; + std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable; + const char *SymtabLoadCmd = nullptr; + const char *DysymtabLoadCmd = nullptr; + const char *DataInCodeLoadCmd = nullptr; + const char *LinkOptHintsLoadCmd = nullptr; + const char *DyldInfoLoadCmd = nullptr; + const char *UuidLoadCmd = nullptr; + bool HasPageZeroSegment = false; +}; + +/// DiceRef +inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner) + : DicePimpl(DiceP) , OwningObject(Owner) {} + +inline bool DiceRef::operator==(const DiceRef &Other) const { + return DicePimpl == Other.DicePimpl; +} + +inline bool DiceRef::operator<(const DiceRef &Other) const { + return DicePimpl < Other.DicePimpl; +} + +inline void DiceRef::moveNext() { + const MachO::data_in_code_entry *P = + reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p); + DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1); +} + +// Since a Mach-O data in code reference, a DiceRef, can only be created when +// the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for +// the methods that get the values of the fields of the reference. + +inline std::error_code DiceRef::getOffset(uint32_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.offset; + return std::error_code(); +} + +inline std::error_code DiceRef::getLength(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.length; + return std::error_code(); +} + +inline std::error_code DiceRef::getKind(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.kind; + return std::error_code(); +} + +inline DataRefImpl DiceRef::getRawDataRefImpl() const { + return DicePimpl; +} + +inline const ObjectFile *DiceRef::getObjectFile() const { + return OwningObject; +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_MACHO_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h b/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h index 2f34b6a71ba..089d4cdbd42 100644 --- a/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h +++ b/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h @@ -1,183 +1,183 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- MachOUniversal.h - Mach-O universal binaries -------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares Mach-O fat/universal binaries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H -#define LLVM_OBJECT_MACHOUNIVERSAL_H - -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Object/Archive.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/MachO.h" - -namespace llvm { -class StringRef; +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- MachOUniversal.h - Mach-O universal binaries -------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares Mach-O fat/universal binaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H +#define LLVM_OBJECT_MACHOUNIVERSAL_H + +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/MachO.h" + +namespace llvm { +class StringRef; class Module; class LLVMContext; - -namespace object { + +namespace object { class IRObjectFile; - -class MachOUniversalBinary : public Binary { - virtual void anchor(); - - uint32_t Magic; - uint32_t NumberOfObjects; -public: - static constexpr uint32_t MaxSectionAlignment = 15; /* 2**15 or 0x8000 */ - - class ObjectForArch { - const MachOUniversalBinary *Parent; - /// Index of object in the universal binary. - uint32_t Index; - /// Descriptor of the object. - MachO::fat_arch Header; - MachO::fat_arch_64 Header64; - - public: - ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); - - void clear() { - Parent = nullptr; - Index = 0; - } - - bool operator==(const ObjectForArch &Other) const { - return (Parent == Other.Parent) && (Index == Other.Index); - } - - ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } - uint32_t getCPUType() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return Header.cputype; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.cputype; - } - uint32_t getCPUSubType() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return Header.cpusubtype; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.cpusubtype; - } - uint64_t getOffset() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return Header.offset; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.offset; - } - uint64_t getSize() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return Header.size; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.size; - } - uint32_t getAlign() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return Header.align; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.align; - } - uint32_t getReserved() const { - if (Parent->getMagic() == MachO::FAT_MAGIC) - return 0; - else // Parent->getMagic() == MachO::FAT_MAGIC_64 - return Header64.reserved; - } - Triple getTriple() const { - return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType()); - } - std::string getArchFlagName() const { - const char *McpuDefault, *ArchFlag; - MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(), - &McpuDefault, &ArchFlag); - return ArchFlag ? ArchFlag : std::string(); - } - - Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; + +class MachOUniversalBinary : public Binary { + virtual void anchor(); + + uint32_t Magic; + uint32_t NumberOfObjects; +public: + static constexpr uint32_t MaxSectionAlignment = 15; /* 2**15 or 0x8000 */ + + class ObjectForArch { + const MachOUniversalBinary *Parent; + /// Index of object in the universal binary. + uint32_t Index; + /// Descriptor of the object. + MachO::fat_arch Header; + MachO::fat_arch_64 Header64; + + public: + ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); + + void clear() { + Parent = nullptr; + Index = 0; + } + + bool operator==(const ObjectForArch &Other) const { + return (Parent == Other.Parent) && (Index == Other.Index); + } + + ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } + uint32_t getCPUType() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.cputype; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.cputype; + } + uint32_t getCPUSubType() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.cpusubtype; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.cpusubtype; + } + uint64_t getOffset() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.offset; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.offset; + } + uint64_t getSize() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.size; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.size; + } + uint32_t getAlign() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.align; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.align; + } + uint32_t getReserved() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return 0; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.reserved; + } + Triple getTriple() const { + return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType()); + } + std::string getArchFlagName() const { + const char *McpuDefault, *ArchFlag; + MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(), + &McpuDefault, &ArchFlag); + return ArchFlag ? ArchFlag : std::string(); + } + + Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; Expected<std::unique_ptr<IRObjectFile>> getAsIRObject(LLVMContext &Ctx) const; - - Expected<std::unique_ptr<Archive>> getAsArchive() const; - }; - - class object_iterator { - ObjectForArch Obj; - public: - object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} - const ObjectForArch *operator->() const { return &Obj; } - const ObjectForArch &operator*() const { return Obj; } - - bool operator==(const object_iterator &Other) const { - return Obj == Other.Obj; - } - bool operator!=(const object_iterator &Other) const { - return !(*this == Other); - } - - object_iterator& operator++() { // Preincrement - Obj = Obj.getNext(); - return *this; - } - }; - - MachOUniversalBinary(MemoryBufferRef Souce, Error &Err); - static Expected<std::unique_ptr<MachOUniversalBinary>> - create(MemoryBufferRef Source); - - object_iterator begin_objects() const { - return ObjectForArch(this, 0); - } - object_iterator end_objects() const { - return ObjectForArch(nullptr, 0); - } - - iterator_range<object_iterator> objects() const { - return make_range(begin_objects(), end_objects()); - } - - uint32_t getMagic() const { return Magic; } - uint32_t getNumberOfObjects() const { return NumberOfObjects; } - - // Cast methods. - static bool classof(Binary const *V) { - return V->isMachOUniversalBinary(); - } - - Expected<ObjectForArch> - getObjectForArch(StringRef ArchName) const; - - Expected<std::unique_ptr<MachOObjectFile>> - getMachOObjectForArch(StringRef ArchName) const; - + + Expected<std::unique_ptr<Archive>> getAsArchive() const; + }; + + class object_iterator { + ObjectForArch Obj; + public: + object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} + const ObjectForArch *operator->() const { return &Obj; } + const ObjectForArch &operator*() const { return Obj; } + + bool operator==(const object_iterator &Other) const { + return Obj == Other.Obj; + } + bool operator!=(const object_iterator &Other) const { + return !(*this == Other); + } + + object_iterator& operator++() { // Preincrement + Obj = Obj.getNext(); + return *this; + } + }; + + MachOUniversalBinary(MemoryBufferRef Souce, Error &Err); + static Expected<std::unique_ptr<MachOUniversalBinary>> + create(MemoryBufferRef Source); + + object_iterator begin_objects() const { + return ObjectForArch(this, 0); + } + object_iterator end_objects() const { + return ObjectForArch(nullptr, 0); + } + + iterator_range<object_iterator> objects() const { + return make_range(begin_objects(), end_objects()); + } + + uint32_t getMagic() const { return Magic; } + uint32_t getNumberOfObjects() const { return NumberOfObjects; } + + // Cast methods. + static bool classof(Binary const *V) { + return V->isMachOUniversalBinary(); + } + + Expected<ObjectForArch> + getObjectForArch(StringRef ArchName) const; + + Expected<std::unique_ptr<MachOObjectFile>> + getMachOObjectForArch(StringRef ArchName) const; + Expected<std::unique_ptr<IRObjectFile>> getIRObjectForArch(StringRef ArchName, LLVMContext &Ctx) const; - Expected<std::unique_ptr<Archive>> - getArchiveForArch(StringRef ArchName) const; -}; - -} -} - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + Expected<std::unique_ptr<Archive>> + getArchiveForArch(StringRef ArchName) const; +}; + +} +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/Minidump.h b/contrib/libs/llvm12/include/llvm/Object/Minidump.h index 7adc325663d..2b1867e6584 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Minidump.h +++ b/contrib/libs/llvm12/include/llvm/Object/Minidump.h @@ -1,227 +1,227 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Minidump.h - Minidump object file implementation ---------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MINIDUMP_H -#define LLVM_OBJECT_MINIDUMP_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/iterator.h" -#include "llvm/BinaryFormat/Minidump.h" -#include "llvm/Object/Binary.h" -#include "llvm/Support/Error.h" - -namespace llvm { -namespace object { - -/// A class providing access to the contents of a minidump file. -class MinidumpFile : public Binary { -public: - /// Construct a new MinidumpFile object from the given memory buffer. Returns - /// an error if this file cannot be identified as a minidump file, or if its - /// contents are badly corrupted (i.e. we cannot read the stream directory). - static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source); - - static bool classof(const Binary *B) { return B->isMinidump(); } - - /// Returns the contents of the minidump header. - const minidump::Header &header() const { return Header; } - - /// Returns the list of streams (stream directory entries) in this file. - ArrayRef<minidump::Directory> streams() const { return Streams; } - - /// Returns the raw contents of the stream given by the directory entry. - ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const { - return getData().slice(Stream.Location.RVA, Stream.Location.DataSize); - } - - /// Returns the raw contents of the stream of the given type, or None if the - /// file does not contain a stream of this type. - Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const; - - /// Returns the raw contents of an object given by the LocationDescriptor. An - /// error is returned if the descriptor points outside of the minidump file. - Expected<ArrayRef<uint8_t>> - getRawData(minidump::LocationDescriptor Desc) const { - return getDataSlice(getData(), Desc.RVA, Desc.DataSize); - } - - /// Returns the minidump string at the given offset. An error is returned if - /// we fail to parse the string, or the string is invalid UTF16. - Expected<std::string> getString(size_t Offset) const; - - /// Returns the contents of the SystemInfo stream, cast to the appropriate - /// type. An error is returned if the file does not contain this stream, or - /// the stream is smaller than the size of the SystemInfo structure. The - /// internal consistency of the stream is not checked in any way. - Expected<const minidump::SystemInfo &> getSystemInfo() const { - return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo); - } - - /// Returns the module list embedded in the ModuleList stream. An error is - /// returned if the file does not contain this stream, or if the stream is - /// not large enough to contain the number of modules declared in the stream - /// header. The consistency of the Module entries themselves is not checked in - /// any way. - Expected<ArrayRef<minidump::Module>> getModuleList() const { - return getListStream<minidump::Module>(minidump::StreamType::ModuleList); - } - - /// Returns the thread list embedded in the ThreadList stream. An error is - /// returned if the file does not contain this stream, or if the stream is - /// not large enough to contain the number of threads declared in the stream - /// header. The consistency of the Thread entries themselves is not checked in - /// any way. - Expected<ArrayRef<minidump::Thread>> getThreadList() const { - return getListStream<minidump::Thread>(minidump::StreamType::ThreadList); - } - - /// Returns the contents of the Exception stream. An error is returned if the - /// file does not contain this stream, or the stream is smaller than the size - /// of the ExceptionStream structure. The internal consistency of the stream - /// is not checked in any way. - Expected<const minidump::ExceptionStream &> getExceptionStream() const { - return getStream<minidump::ExceptionStream>( - minidump::StreamType::Exception); - } - - /// Returns the list of descriptors embedded in the MemoryList stream. The - /// descriptors provide the content of interesting regions of memory at the - /// time the minidump was taken. An error is returned if the file does not - /// contain this stream, or if the stream is not large enough to contain the - /// number of memory descriptors declared in the stream header. The - /// consistency of the MemoryDescriptor entries themselves is not checked in - /// any way. - Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const { - return getListStream<minidump::MemoryDescriptor>( - minidump::StreamType::MemoryList); - } - - class MemoryInfoIterator - : public iterator_facade_base<MemoryInfoIterator, - std::forward_iterator_tag, - minidump::MemoryInfo> { - public: - MemoryInfoIterator(ArrayRef<uint8_t> Storage, size_t Stride) - : Storage(Storage), Stride(Stride) { - assert(Storage.size() % Stride == 0); - } - - bool operator==(const MemoryInfoIterator &R) const { - return Storage.size() == R.Storage.size(); - } - - const minidump::MemoryInfo &operator*() const { - assert(Storage.size() >= sizeof(minidump::MemoryInfo)); - return *reinterpret_cast<const minidump::MemoryInfo *>(Storage.data()); - } - - MemoryInfoIterator &operator++() { - Storage = Storage.drop_front(Stride); - return *this; - } - - private: - ArrayRef<uint8_t> Storage; - size_t Stride; - }; - - /// Returns the list of descriptors embedded in the MemoryInfoList stream. The - /// descriptors provide properties (e.g. permissions) of interesting regions - /// of memory at the time the minidump was taken. An error is returned if the - /// file does not contain this stream, or if the stream is not large enough to - /// contain the number of memory descriptors declared in the stream header. - /// The consistency of the MemoryInfoList entries themselves is not checked - /// in any way. - Expected<iterator_range<MemoryInfoIterator>> getMemoryInfoList() const; - -private: - static Error createError(StringRef Str) { - return make_error<GenericBinaryError>(Str, object_error::parse_failed); - } - - static Error createEOFError() { - return make_error<GenericBinaryError>("Unexpected EOF", - object_error::unexpected_eof); - } - - /// Return a slice of the given data array, with bounds checking. - static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data, - size_t Offset, size_t Size); - - /// Return the slice of the given data array as an array of objects of the - /// given type. The function checks that the input array is large enough to - /// contain the correct number of objects of the given type. - template <typename T> - static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data, - size_t Offset, size_t Count); - - MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header, - ArrayRef<minidump::Directory> Streams, - DenseMap<minidump::StreamType, std::size_t> StreamMap) - : Binary(ID_Minidump, Source), Header(Header), Streams(Streams), - StreamMap(std::move(StreamMap)) {} - - ArrayRef<uint8_t> getData() const { - return arrayRefFromStringRef(Data.getBuffer()); - } - - /// Return the stream of the given type, cast to the appropriate type. Checks - /// that the stream is large enough to hold an object of this type. - template <typename T> - Expected<const T &> getStream(minidump::StreamType Stream) const; - - /// Return the contents of a stream which contains a list of fixed-size items, - /// prefixed by the list size. - template <typename T> - Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const; - - const minidump::Header &Header; - ArrayRef<minidump::Directory> Streams; - DenseMap<minidump::StreamType, std::size_t> StreamMap; -}; - -template <typename T> -Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const { - if (Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type)) { - if (Stream->size() >= sizeof(T)) - return *reinterpret_cast<const T *>(Stream->data()); - return createEOFError(); - } - return createError("No such stream"); -} - -template <typename T> -Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data, - size_t Offset, - size_t Count) { - // Check for overflow. - if (Count > std::numeric_limits<size_t>::max() / sizeof(T)) - return createEOFError(); - Expected<ArrayRef<uint8_t>> Slice = - getDataSlice(Data, Offset, sizeof(T) * Count); - if (!Slice) - return Slice.takeError(); - return ArrayRef<T>(reinterpret_cast<const T *>(Slice->data()), Count); -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_MINIDUMP_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Minidump.h - Minidump object file implementation ---------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MINIDUMP_H +#define LLVM_OBJECT_MINIDUMP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/iterator.h" +#include "llvm/BinaryFormat/Minidump.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace object { + +/// A class providing access to the contents of a minidump file. +class MinidumpFile : public Binary { +public: + /// Construct a new MinidumpFile object from the given memory buffer. Returns + /// an error if this file cannot be identified as a minidump file, or if its + /// contents are badly corrupted (i.e. we cannot read the stream directory). + static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source); + + static bool classof(const Binary *B) { return B->isMinidump(); } + + /// Returns the contents of the minidump header. + const minidump::Header &header() const { return Header; } + + /// Returns the list of streams (stream directory entries) in this file. + ArrayRef<minidump::Directory> streams() const { return Streams; } + + /// Returns the raw contents of the stream given by the directory entry. + ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const { + return getData().slice(Stream.Location.RVA, Stream.Location.DataSize); + } + + /// Returns the raw contents of the stream of the given type, or None if the + /// file does not contain a stream of this type. + Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const; + + /// Returns the raw contents of an object given by the LocationDescriptor. An + /// error is returned if the descriptor points outside of the minidump file. + Expected<ArrayRef<uint8_t>> + getRawData(minidump::LocationDescriptor Desc) const { + return getDataSlice(getData(), Desc.RVA, Desc.DataSize); + } + + /// Returns the minidump string at the given offset. An error is returned if + /// we fail to parse the string, or the string is invalid UTF16. + Expected<std::string> getString(size_t Offset) const; + + /// Returns the contents of the SystemInfo stream, cast to the appropriate + /// type. An error is returned if the file does not contain this stream, or + /// the stream is smaller than the size of the SystemInfo structure. The + /// internal consistency of the stream is not checked in any way. + Expected<const minidump::SystemInfo &> getSystemInfo() const { + return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo); + } + + /// Returns the module list embedded in the ModuleList stream. An error is + /// returned if the file does not contain this stream, or if the stream is + /// not large enough to contain the number of modules declared in the stream + /// header. The consistency of the Module entries themselves is not checked in + /// any way. + Expected<ArrayRef<minidump::Module>> getModuleList() const { + return getListStream<minidump::Module>(minidump::StreamType::ModuleList); + } + + /// Returns the thread list embedded in the ThreadList stream. An error is + /// returned if the file does not contain this stream, or if the stream is + /// not large enough to contain the number of threads declared in the stream + /// header. The consistency of the Thread entries themselves is not checked in + /// any way. + Expected<ArrayRef<minidump::Thread>> getThreadList() const { + return getListStream<minidump::Thread>(minidump::StreamType::ThreadList); + } + + /// Returns the contents of the Exception stream. An error is returned if the + /// file does not contain this stream, or the stream is smaller than the size + /// of the ExceptionStream structure. The internal consistency of the stream + /// is not checked in any way. + Expected<const minidump::ExceptionStream &> getExceptionStream() const { + return getStream<minidump::ExceptionStream>( + minidump::StreamType::Exception); + } + + /// Returns the list of descriptors embedded in the MemoryList stream. The + /// descriptors provide the content of interesting regions of memory at the + /// time the minidump was taken. An error is returned if the file does not + /// contain this stream, or if the stream is not large enough to contain the + /// number of memory descriptors declared in the stream header. The + /// consistency of the MemoryDescriptor entries themselves is not checked in + /// any way. + Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const { + return getListStream<minidump::MemoryDescriptor>( + minidump::StreamType::MemoryList); + } + + class MemoryInfoIterator + : public iterator_facade_base<MemoryInfoIterator, + std::forward_iterator_tag, + minidump::MemoryInfo> { + public: + MemoryInfoIterator(ArrayRef<uint8_t> Storage, size_t Stride) + : Storage(Storage), Stride(Stride) { + assert(Storage.size() % Stride == 0); + } + + bool operator==(const MemoryInfoIterator &R) const { + return Storage.size() == R.Storage.size(); + } + + const minidump::MemoryInfo &operator*() const { + assert(Storage.size() >= sizeof(minidump::MemoryInfo)); + return *reinterpret_cast<const minidump::MemoryInfo *>(Storage.data()); + } + + MemoryInfoIterator &operator++() { + Storage = Storage.drop_front(Stride); + return *this; + } + + private: + ArrayRef<uint8_t> Storage; + size_t Stride; + }; + + /// Returns the list of descriptors embedded in the MemoryInfoList stream. The + /// descriptors provide properties (e.g. permissions) of interesting regions + /// of memory at the time the minidump was taken. An error is returned if the + /// file does not contain this stream, or if the stream is not large enough to + /// contain the number of memory descriptors declared in the stream header. + /// The consistency of the MemoryInfoList entries themselves is not checked + /// in any way. + Expected<iterator_range<MemoryInfoIterator>> getMemoryInfoList() const; + +private: + static Error createError(StringRef Str) { + return make_error<GenericBinaryError>(Str, object_error::parse_failed); + } + + static Error createEOFError() { + return make_error<GenericBinaryError>("Unexpected EOF", + object_error::unexpected_eof); + } + + /// Return a slice of the given data array, with bounds checking. + static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data, + size_t Offset, size_t Size); + + /// Return the slice of the given data array as an array of objects of the + /// given type. The function checks that the input array is large enough to + /// contain the correct number of objects of the given type. + template <typename T> + static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data, + size_t Offset, size_t Count); + + MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header, + ArrayRef<minidump::Directory> Streams, + DenseMap<minidump::StreamType, std::size_t> StreamMap) + : Binary(ID_Minidump, Source), Header(Header), Streams(Streams), + StreamMap(std::move(StreamMap)) {} + + ArrayRef<uint8_t> getData() const { + return arrayRefFromStringRef(Data.getBuffer()); + } + + /// Return the stream of the given type, cast to the appropriate type. Checks + /// that the stream is large enough to hold an object of this type. + template <typename T> + Expected<const T &> getStream(minidump::StreamType Stream) const; + + /// Return the contents of a stream which contains a list of fixed-size items, + /// prefixed by the list size. + template <typename T> + Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const; + + const minidump::Header &Header; + ArrayRef<minidump::Directory> Streams; + DenseMap<minidump::StreamType, std::size_t> StreamMap; +}; + +template <typename T> +Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const { + if (Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type)) { + if (Stream->size() >= sizeof(T)) + return *reinterpret_cast<const T *>(Stream->data()); + return createEOFError(); + } + return createError("No such stream"); +} + +template <typename T> +Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data, + size_t Offset, + size_t Count) { + // Check for overflow. + if (Count > std::numeric_limits<size_t>::max() / sizeof(T)) + return createEOFError(); + Expected<ArrayRef<uint8_t>> Slice = + getDataSlice(Data, Offset, sizeof(T) * Count); + if (!Slice) + return Slice.takeError(); + return ArrayRef<T>(reinterpret_cast<const T *>(Slice->data()), Count); +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_MINIDUMP_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h b/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h index b661386eebb..0021f4c5cc8 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h +++ b/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h @@ -1,84 +1,84 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ModuleSymbolTable.h - symbol table for in-memory IR ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This class represents a symbol table built from in-memory IR. It provides -// access to GlobalValues and should only be used if such access is required -// (e.g. in the LTO implementation). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MODULESYMBOLTABLE_H -#define LLVM_OBJECT_MODULESYMBOLTABLE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/IR/Mangler.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/Allocator.h" -#include <cstdint> -#include <string> -#include <utility> -#include <vector> - -namespace llvm { - -class GlobalValue; -class Module; - -class ModuleSymbolTable { -public: - using AsmSymbol = std::pair<std::string, uint32_t>; - using Symbol = PointerUnion<GlobalValue *, AsmSymbol *>; - -private: - Module *FirstMod = nullptr; - - SpecificBumpPtrAllocator<AsmSymbol> AsmSymbols; - std::vector<Symbol> SymTab; - Mangler Mang; - -public: - ArrayRef<Symbol> symbols() const { return SymTab; } - void addModule(Module *M); - - void printSymbolName(raw_ostream &OS, Symbol S) const; - uint32_t getSymbolFlags(Symbol S) const; - - /// Parse inline ASM and collect the symbols that are defined or referenced in - /// the current module. - /// - /// For each found symbol, call \p AsmSymbol with the name of the symbol found - /// and the associated flags. - static void CollectAsmSymbols( - const Module &M, - function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol); - - /// Parse inline ASM and collect the symvers directives that are defined in - /// the current module. - /// - /// For each found symbol, call \p AsmSymver with the name of the symbol and - /// its alias. - static void - CollectAsmSymvers(const Module &M, - function_ref<void(StringRef, StringRef)> AsmSymver); -}; - -} // end namespace llvm - -#endif // LLVM_OBJECT_MODULESYMBOLTABLE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ModuleSymbolTable.h - symbol table for in-memory IR ------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This class represents a symbol table built from in-memory IR. It provides +// access to GlobalValues and should only be used if such access is required +// (e.g. in the LTO implementation). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MODULESYMBOLTABLE_H +#define LLVM_OBJECT_MODULESYMBOLTABLE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Allocator.h" +#include <cstdint> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +class GlobalValue; +class Module; + +class ModuleSymbolTable { +public: + using AsmSymbol = std::pair<std::string, uint32_t>; + using Symbol = PointerUnion<GlobalValue *, AsmSymbol *>; + +private: + Module *FirstMod = nullptr; + + SpecificBumpPtrAllocator<AsmSymbol> AsmSymbols; + std::vector<Symbol> SymTab; + Mangler Mang; + +public: + ArrayRef<Symbol> symbols() const { return SymTab; } + void addModule(Module *M); + + void printSymbolName(raw_ostream &OS, Symbol S) const; + uint32_t getSymbolFlags(Symbol S) const; + + /// Parse inline ASM and collect the symbols that are defined or referenced in + /// the current module. + /// + /// For each found symbol, call \p AsmSymbol with the name of the symbol found + /// and the associated flags. + static void CollectAsmSymbols( + const Module &M, + function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol); + + /// Parse inline ASM and collect the symvers directives that are defined in + /// the current module. + /// + /// For each found symbol, call \p AsmSymver with the name of the symbol and + /// its alias. + static void + CollectAsmSymvers(const Module &M, + function_ref<void(StringRef, StringRef)> AsmSymver); +}; + +} // end namespace llvm + +#endif // LLVM_OBJECT_MODULESYMBOLTABLE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h index 7f9ec78c1d4..76e157182d4 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h @@ -1,603 +1,603 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ObjectFile.h - File format independent object file -------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectFile class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_OBJECTFILE_H -#define LLVM_OBJECT_OBJECTFILE_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/Magic.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/Error.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include <cassert> -#include <cstdint> -#include <memory> -#include <system_error> - -namespace llvm { - -class ARMAttributeParser; -class SubtargetFeatures; - -namespace object { - -class COFFObjectFile; -class MachOObjectFile; -class ObjectFile; -class SectionRef; -class SymbolRef; -class symbol_iterator; -class WasmObjectFile; - -using section_iterator = content_iterator<SectionRef>; - -/// This is a value type class that represents a single relocation in the list -/// of relocations in the object file. -class RelocationRef { - DataRefImpl RelocationPimpl; - const ObjectFile *OwningObject = nullptr; - -public: - RelocationRef() = default; - RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); - - bool operator==(const RelocationRef &Other) const; - - void moveNext(); - - uint64_t getOffset() const; - symbol_iterator getSymbol() const; - uint64_t getType() const; - - /// Get a string that represents the type of this relocation. - /// - /// This is for display purposes only. - void getTypeName(SmallVectorImpl<char> &Result) const; - - DataRefImpl getRawDataRefImpl() const; - const ObjectFile *getObject() const; -}; - -using relocation_iterator = content_iterator<RelocationRef>; - -/// This is a value type class that represents a single section in the list of -/// sections in the object file. -class SectionRef { - friend class SymbolRef; - - DataRefImpl SectionPimpl; - const ObjectFile *OwningObject = nullptr; - -public: - SectionRef() = default; - SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); - - bool operator==(const SectionRef &Other) const; - bool operator!=(const SectionRef &Other) const; - bool operator<(const SectionRef &Other) const; - - void moveNext(); - - Expected<StringRef> getName() const; - uint64_t getAddress() const; - uint64_t getIndex() const; - uint64_t getSize() const; - Expected<StringRef> getContents() const; - - /// Get the alignment of this section as the actual value (not log 2). - uint64_t getAlignment() const; - - bool isCompressed() const; - /// Whether this section contains instructions. - bool isText() const; - /// Whether this section contains data, not instructions. - bool isData() const; - /// Whether this section contains BSS uninitialized data. - bool isBSS() const; - bool isVirtual() const; - bool isBitcode() const; - bool isStripped() const; - - /// Whether this section will be placed in the text segment, according to the - /// Berkeley size format. This is true if the section is allocatable, and - /// contains either code or readonly data. - bool isBerkeleyText() const; - /// Whether this section will be placed in the data segment, according to the - /// Berkeley size format. This is true if the section is allocatable and - /// contains data (e.g. PROGBITS), but is not text. - bool isBerkeleyData() const; - - /// Whether this section is a debug section. - bool isDebugSection(StringRef SectionName) const; - - bool containsSymbol(SymbolRef S) const; - - relocation_iterator relocation_begin() const; - relocation_iterator relocation_end() const; - iterator_range<relocation_iterator> relocations() const { - return make_range(relocation_begin(), relocation_end()); - } - Expected<section_iterator> getRelocatedSection() const; - - DataRefImpl getRawDataRefImpl() const; - const ObjectFile *getObject() const; -}; - -struct SectionedAddress { - const static uint64_t UndefSection = UINT64_MAX; - - uint64_t Address = 0; - uint64_t SectionIndex = UndefSection; -}; - -inline bool operator<(const SectionedAddress &LHS, - const SectionedAddress &RHS) { - return std::tie(LHS.SectionIndex, LHS.Address) < - std::tie(RHS.SectionIndex, RHS.Address); -} - -inline bool operator==(const SectionedAddress &LHS, - const SectionedAddress &RHS) { - return std::tie(LHS.SectionIndex, LHS.Address) == - std::tie(RHS.SectionIndex, RHS.Address); -} - -raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr); - -/// This is a value type class that represents a single symbol in the list of -/// symbols in the object file. -class SymbolRef : public BasicSymbolRef { - friend class SectionRef; - -public: - enum Type { - ST_Unknown, // Type not specified - ST_Data, - ST_Debug, - ST_File, - ST_Function, - ST_Other - }; - - SymbolRef() = default; - SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); - SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) { - assert(isa<ObjectFile>(BasicSymbolRef::getObject())); - } - - Expected<StringRef> getName() const; - /// Returns the symbol virtual address (i.e. address at which it will be - /// mapped). - Expected<uint64_t> getAddress() const; - - /// Return the value of the symbol depending on the object this can be an - /// offset or a virtual address. - Expected<uint64_t> getValue() const; - - /// Get the alignment of this symbol as the actual value (not log 2). - uint32_t getAlignment() const; - uint64_t getCommonSize() const; - Expected<SymbolRef::Type> getType() const; - - /// Get section this symbol is defined in reference to. Result is - /// end_sections() if it is undefined or is an absolute symbol. - Expected<section_iterator> getSection() const; - - const ObjectFile *getObject() const; -}; - -class symbol_iterator : public basic_symbol_iterator { -public: - symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} - symbol_iterator(const basic_symbol_iterator &B) - : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), - cast<ObjectFile>(B->getObject()))) {} - - const SymbolRef *operator->() const { - const BasicSymbolRef &P = basic_symbol_iterator::operator *(); - return static_cast<const SymbolRef*>(&P); - } - - const SymbolRef &operator*() const { - const BasicSymbolRef &P = basic_symbol_iterator::operator *(); - return static_cast<const SymbolRef&>(P); - } -}; - -/// This class is the base class for all object file types. Concrete instances -/// of this object are created by createObjectFile, which figures out which type -/// to create. -class ObjectFile : public SymbolicFile { - virtual void anchor(); - -protected: - ObjectFile(unsigned int Type, MemoryBufferRef Source); - - const uint8_t *base() const { - return reinterpret_cast<const uint8_t *>(Data.getBufferStart()); - } - - // These functions are for SymbolRef to call internally. The main goal of - // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol - // entry in the memory mapped object file. SymbolPimpl cannot contain any - // virtual functions because then it could not point into the memory mapped - // file. - // - // Implementations assume that the DataRefImpl is valid and has not been - // modified externally. It's UB otherwise. - friend class SymbolRef; - - virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0; - Error printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const override; - virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; - virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; - virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; - virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0; - virtual Expected<section_iterator> - getSymbolSection(DataRefImpl Symb) const = 0; - - // Same as above for SectionRef. - friend class SectionRef; - - virtual void moveSectionNext(DataRefImpl &Sec) const = 0; - virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; - virtual Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; - virtual bool isSectionCompressed(DataRefImpl Sec) const = 0; - virtual bool isSectionText(DataRefImpl Sec) const = 0; - virtual bool isSectionData(DataRefImpl Sec) const = 0; - virtual bool isSectionBSS(DataRefImpl Sec) const = 0; - // A section is 'virtual' if its contents aren't present in the object image. - virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; - virtual bool isSectionBitcode(DataRefImpl Sec) const; - virtual bool isSectionStripped(DataRefImpl Sec) const; - virtual bool isBerkeleyText(DataRefImpl Sec) const; - virtual bool isBerkeleyData(DataRefImpl Sec) const; - virtual bool isDebugSection(StringRef SectionName) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; - virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const; - - // Same as above for RelocationRef. - friend class RelocationRef; - virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; - virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; - virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; - virtual void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const = 0; - - Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const; - -public: - ObjectFile() = delete; - ObjectFile(const ObjectFile &other) = delete; - - uint64_t getCommonSymbolSize(DataRefImpl Symb) const { - Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb); - if (!SymbolFlagsOrErr) - // TODO: Actually report errors helpfully. - report_fatal_error(SymbolFlagsOrErr.takeError()); - assert(*SymbolFlagsOrErr & SymbolRef::SF_Common); - return getCommonSymbolSizeImpl(Symb); - } - - virtual std::vector<SectionRef> dynamic_relocation_sections() const { - return std::vector<SectionRef>(); - } - - using symbol_iterator_range = iterator_range<symbol_iterator>; - symbol_iterator_range symbols() const { - return symbol_iterator_range(symbol_begin(), symbol_end()); - } - - virtual section_iterator section_begin() const = 0; - virtual section_iterator section_end() const = 0; - - using section_iterator_range = iterator_range<section_iterator>; - section_iterator_range sections() const { - return section_iterator_range(section_begin(), section_end()); - } - - /// The number of bytes used to represent an address in this object - /// file format. - virtual uint8_t getBytesInAddress() const = 0; - - virtual StringRef getFileFormatName() const = 0; - virtual Triple::ArchType getArch() const = 0; - virtual SubtargetFeatures getFeatures() const = 0; +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ObjectFile.h - File format independent object file -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares a file format independent ObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_OBJECTFILE_H +#define LLVM_OBJECT_OBJECTFILE_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <system_error> + +namespace llvm { + +class ARMAttributeParser; +class SubtargetFeatures; + +namespace object { + +class COFFObjectFile; +class MachOObjectFile; +class ObjectFile; +class SectionRef; +class SymbolRef; +class symbol_iterator; +class WasmObjectFile; + +using section_iterator = content_iterator<SectionRef>; + +/// This is a value type class that represents a single relocation in the list +/// of relocations in the object file. +class RelocationRef { + DataRefImpl RelocationPimpl; + const ObjectFile *OwningObject = nullptr; + +public: + RelocationRef() = default; + RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + + bool operator==(const RelocationRef &Other) const; + + void moveNext(); + + uint64_t getOffset() const; + symbol_iterator getSymbol() const; + uint64_t getType() const; + + /// Get a string that represents the type of this relocation. + /// + /// This is for display purposes only. + void getTypeName(SmallVectorImpl<char> &Result) const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; +}; + +using relocation_iterator = content_iterator<RelocationRef>; + +/// This is a value type class that represents a single section in the list of +/// sections in the object file. +class SectionRef { + friend class SymbolRef; + + DataRefImpl SectionPimpl; + const ObjectFile *OwningObject = nullptr; + +public: + SectionRef() = default; + SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); + + bool operator==(const SectionRef &Other) const; + bool operator!=(const SectionRef &Other) const; + bool operator<(const SectionRef &Other) const; + + void moveNext(); + + Expected<StringRef> getName() const; + uint64_t getAddress() const; + uint64_t getIndex() const; + uint64_t getSize() const; + Expected<StringRef> getContents() const; + + /// Get the alignment of this section as the actual value (not log 2). + uint64_t getAlignment() const; + + bool isCompressed() const; + /// Whether this section contains instructions. + bool isText() const; + /// Whether this section contains data, not instructions. + bool isData() const; + /// Whether this section contains BSS uninitialized data. + bool isBSS() const; + bool isVirtual() const; + bool isBitcode() const; + bool isStripped() const; + + /// Whether this section will be placed in the text segment, according to the + /// Berkeley size format. This is true if the section is allocatable, and + /// contains either code or readonly data. + bool isBerkeleyText() const; + /// Whether this section will be placed in the data segment, according to the + /// Berkeley size format. This is true if the section is allocatable and + /// contains data (e.g. PROGBITS), but is not text. + bool isBerkeleyData() const; + + /// Whether this section is a debug section. + bool isDebugSection(StringRef SectionName) const; + + bool containsSymbol(SymbolRef S) const; + + relocation_iterator relocation_begin() const; + relocation_iterator relocation_end() const; + iterator_range<relocation_iterator> relocations() const { + return make_range(relocation_begin(), relocation_end()); + } + Expected<section_iterator> getRelocatedSection() const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; +}; + +struct SectionedAddress { + const static uint64_t UndefSection = UINT64_MAX; + + uint64_t Address = 0; + uint64_t SectionIndex = UndefSection; +}; + +inline bool operator<(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) < + std::tie(RHS.SectionIndex, RHS.Address); +} + +inline bool operator==(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) == + std::tie(RHS.SectionIndex, RHS.Address); +} + +raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr); + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class SymbolRef : public BasicSymbolRef { + friend class SectionRef; + +public: + enum Type { + ST_Unknown, // Type not specified + ST_Data, + ST_Debug, + ST_File, + ST_Function, + ST_Other + }; + + SymbolRef() = default; + SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); + SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) { + assert(isa<ObjectFile>(BasicSymbolRef::getObject())); + } + + Expected<StringRef> getName() const; + /// Returns the symbol virtual address (i.e. address at which it will be + /// mapped). + Expected<uint64_t> getAddress() const; + + /// Return the value of the symbol depending on the object this can be an + /// offset or a virtual address. + Expected<uint64_t> getValue() const; + + /// Get the alignment of this symbol as the actual value (not log 2). + uint32_t getAlignment() const; + uint64_t getCommonSize() const; + Expected<SymbolRef::Type> getType() const; + + /// Get section this symbol is defined in reference to. Result is + /// end_sections() if it is undefined or is an absolute symbol. + Expected<section_iterator> getSection() const; + + const ObjectFile *getObject() const; +}; + +class symbol_iterator : public basic_symbol_iterator { +public: + symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} + symbol_iterator(const basic_symbol_iterator &B) + : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast<ObjectFile>(B->getObject()))) {} + + const SymbolRef *operator->() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef*>(&P); + } + + const SymbolRef &operator*() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef&>(P); + } +}; + +/// This class is the base class for all object file types. Concrete instances +/// of this object are created by createObjectFile, which figures out which type +/// to create. +class ObjectFile : public SymbolicFile { + virtual void anchor(); + +protected: + ObjectFile(unsigned int Type, MemoryBufferRef Source); + + const uint8_t *base() const { + return reinterpret_cast<const uint8_t *>(Data.getBufferStart()); + } + + // These functions are for SymbolRef to call internally. The main goal of + // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol + // entry in the memory mapped object file. SymbolPimpl cannot contain any + // virtual functions because then it could not point into the memory mapped + // file. + // + // Implementations assume that the DataRefImpl is valid and has not been + // modified externally. It's UB otherwise. + friend class SymbolRef; + + virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0; + Error printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; + virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; + virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; + virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0; + virtual Expected<section_iterator> + getSymbolSection(DataRefImpl Symb) const = 0; + + // Same as above for SectionRef. + friend class SectionRef; + + virtual void moveSectionNext(DataRefImpl &Sec) const = 0; + virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; + virtual Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; + virtual bool isSectionCompressed(DataRefImpl Sec) const = 0; + virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual bool isSectionData(DataRefImpl Sec) const = 0; + virtual bool isSectionBSS(DataRefImpl Sec) const = 0; + // A section is 'virtual' if its contents aren't present in the object image. + virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; + virtual bool isSectionBitcode(DataRefImpl Sec) const; + virtual bool isSectionStripped(DataRefImpl Sec) const; + virtual bool isBerkeleyText(DataRefImpl Sec) const; + virtual bool isBerkeleyData(DataRefImpl Sec) const; + virtual bool isDebugSection(StringRef SectionName) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; + virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const; + + // Same as above for RelocationRef. + friend class RelocationRef; + virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; + virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; + virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; + virtual void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const = 0; + + Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const; + +public: + ObjectFile() = delete; + ObjectFile(const ObjectFile &other) = delete; + + uint64_t getCommonSymbolSize(DataRefImpl Symb) const { + Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb); + if (!SymbolFlagsOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(SymbolFlagsOrErr.takeError()); + assert(*SymbolFlagsOrErr & SymbolRef::SF_Common); + return getCommonSymbolSizeImpl(Symb); + } + + virtual std::vector<SectionRef> dynamic_relocation_sections() const { + return std::vector<SectionRef>(); + } + + using symbol_iterator_range = iterator_range<symbol_iterator>; + symbol_iterator_range symbols() const { + return symbol_iterator_range(symbol_begin(), symbol_end()); + } + + virtual section_iterator section_begin() const = 0; + virtual section_iterator section_end() const = 0; + + using section_iterator_range = iterator_range<section_iterator>; + section_iterator_range sections() const { + return section_iterator_range(section_begin(), section_end()); + } + + /// The number of bytes used to represent an address in this object + /// file format. + virtual uint8_t getBytesInAddress() const = 0; + + virtual StringRef getFileFormatName() const = 0; + virtual Triple::ArchType getArch() const = 0; + virtual SubtargetFeatures getFeatures() const = 0; virtual Optional<StringRef> tryGetCPUName() const { return None; }; - virtual void setARMSubArch(Triple &TheTriple) const { } - virtual Expected<uint64_t> getStartAddress() const { - return errorCodeToError(object_error::parse_failed); - }; - - /// Create a triple from the data in this object file. - Triple makeTriple() const; - - /// Maps a debug section name to a standard DWARF section name. - virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; } - - /// True if this is a relocatable object (.o/.obj). - virtual bool isRelocatableObject() const = 0; - - /// @returns Pointer to ObjectFile subclass to handle this type of object. - /// @param ObjectPath The path to the object file. ObjectPath.isObject must - /// return true. - /// Create ObjectFile from path. - static Expected<OwningBinary<ObjectFile>> - createObjectFile(StringRef ObjectPath); - - static Expected<std::unique_ptr<ObjectFile>> + virtual void setARMSubArch(Triple &TheTriple) const { } + virtual Expected<uint64_t> getStartAddress() const { + return errorCodeToError(object_error::parse_failed); + }; + + /// Create a triple from the data in this object file. + Triple makeTriple() const; + + /// Maps a debug section name to a standard DWARF section name. + virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; } + + /// True if this is a relocatable object (.o/.obj). + virtual bool isRelocatableObject() const = 0; + + /// @returns Pointer to ObjectFile subclass to handle this type of object. + /// @param ObjectPath The path to the object file. ObjectPath.isObject must + /// return true. + /// Create ObjectFile from path. + static Expected<OwningBinary<ObjectFile>> + createObjectFile(StringRef ObjectPath); + + static Expected<std::unique_ptr<ObjectFile>> createObjectFile(MemoryBufferRef Object, llvm::file_magic Type, bool InitContent = true); - static Expected<std::unique_ptr<ObjectFile>> - createObjectFile(MemoryBufferRef Object) { - return createObjectFile(Object, llvm::file_magic::unknown); - } - - static bool classof(const Binary *v) { - return v->isObject(); - } - - static Expected<std::unique_ptr<COFFObjectFile>> - createCOFFObjectFile(MemoryBufferRef Object); - - static Expected<std::unique_ptr<ObjectFile>> - createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); - - static Expected<std::unique_ptr<ObjectFile>> + static Expected<std::unique_ptr<ObjectFile>> + createObjectFile(MemoryBufferRef Object) { + return createObjectFile(Object, llvm::file_magic::unknown); + } + + static bool classof(const Binary *v) { + return v->isObject(); + } + + static Expected<std::unique_ptr<COFFObjectFile>> + createCOFFObjectFile(MemoryBufferRef Object); + + static Expected<std::unique_ptr<ObjectFile>> + createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); + + static Expected<std::unique_ptr<ObjectFile>> createELFObjectFile(MemoryBufferRef Object, bool InitContent = true); - - static Expected<std::unique_ptr<MachOObjectFile>> - createMachOObjectFile(MemoryBufferRef Object, - uint32_t UniversalCputype = 0, - uint32_t UniversalIndex = 0); - - static Expected<std::unique_ptr<WasmObjectFile>> - createWasmObjectFile(MemoryBufferRef Object); -}; - -// Inline function definitions. -inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) - : BasicSymbolRef(SymbolP, Owner) {} - -inline Expected<StringRef> SymbolRef::getName() const { - return getObject()->getSymbolName(getRawDataRefImpl()); -} - -inline Expected<uint64_t> SymbolRef::getAddress() const { - return getObject()->getSymbolAddress(getRawDataRefImpl()); -} - -inline Expected<uint64_t> SymbolRef::getValue() const { - return getObject()->getSymbolValue(getRawDataRefImpl()); -} - -inline uint32_t SymbolRef::getAlignment() const { - return getObject()->getSymbolAlignment(getRawDataRefImpl()); -} - -inline uint64_t SymbolRef::getCommonSize() const { - return getObject()->getCommonSymbolSize(getRawDataRefImpl()); -} - -inline Expected<section_iterator> SymbolRef::getSection() const { - return getObject()->getSymbolSection(getRawDataRefImpl()); -} - -inline Expected<SymbolRef::Type> SymbolRef::getType() const { - return getObject()->getSymbolType(getRawDataRefImpl()); -} - -inline const ObjectFile *SymbolRef::getObject() const { - const SymbolicFile *O = BasicSymbolRef::getObject(); - return cast<ObjectFile>(O); -} - -/// SectionRef -inline SectionRef::SectionRef(DataRefImpl SectionP, - const ObjectFile *Owner) - : SectionPimpl(SectionP) - , OwningObject(Owner) {} - -inline bool SectionRef::operator==(const SectionRef &Other) const { - return OwningObject == Other.OwningObject && - SectionPimpl == Other.SectionPimpl; -} - -inline bool SectionRef::operator!=(const SectionRef &Other) const { - return !(*this == Other); -} - -inline bool SectionRef::operator<(const SectionRef &Other) const { - assert(OwningObject == Other.OwningObject); - return SectionPimpl < Other.SectionPimpl; -} - -inline void SectionRef::moveNext() { - return OwningObject->moveSectionNext(SectionPimpl); -} - -inline Expected<StringRef> SectionRef::getName() const { - return OwningObject->getSectionName(SectionPimpl); -} - -inline uint64_t SectionRef::getAddress() const { - return OwningObject->getSectionAddress(SectionPimpl); -} - -inline uint64_t SectionRef::getIndex() const { - return OwningObject->getSectionIndex(SectionPimpl); -} - -inline uint64_t SectionRef::getSize() const { - return OwningObject->getSectionSize(SectionPimpl); -} - -inline Expected<StringRef> SectionRef::getContents() const { - Expected<ArrayRef<uint8_t>> Res = - OwningObject->getSectionContents(SectionPimpl); - if (!Res) - return Res.takeError(); - return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size()); -} - -inline uint64_t SectionRef::getAlignment() const { - return OwningObject->getSectionAlignment(SectionPimpl); -} - -inline bool SectionRef::isCompressed() const { - return OwningObject->isSectionCompressed(SectionPimpl); -} - -inline bool SectionRef::isText() const { - return OwningObject->isSectionText(SectionPimpl); -} - -inline bool SectionRef::isData() const { - return OwningObject->isSectionData(SectionPimpl); -} - -inline bool SectionRef::isBSS() const { - return OwningObject->isSectionBSS(SectionPimpl); -} - -inline bool SectionRef::isVirtual() const { - return OwningObject->isSectionVirtual(SectionPimpl); -} - -inline bool SectionRef::isBitcode() const { - return OwningObject->isSectionBitcode(SectionPimpl); -} - -inline bool SectionRef::isStripped() const { - return OwningObject->isSectionStripped(SectionPimpl); -} - -inline bool SectionRef::isBerkeleyText() const { - return OwningObject->isBerkeleyText(SectionPimpl); -} - -inline bool SectionRef::isBerkeleyData() const { - return OwningObject->isBerkeleyData(SectionPimpl); -} - -inline bool SectionRef::isDebugSection(StringRef SectionName) const { - return OwningObject->isDebugSection(SectionName); -} - -inline relocation_iterator SectionRef::relocation_begin() const { - return OwningObject->section_rel_begin(SectionPimpl); -} - -inline relocation_iterator SectionRef::relocation_end() const { - return OwningObject->section_rel_end(SectionPimpl); -} - -inline Expected<section_iterator> SectionRef::getRelocatedSection() const { - return OwningObject->getRelocatedSection(SectionPimpl); -} - -inline DataRefImpl SectionRef::getRawDataRefImpl() const { - return SectionPimpl; -} - -inline const ObjectFile *SectionRef::getObject() const { - return OwningObject; -} - -/// RelocationRef -inline RelocationRef::RelocationRef(DataRefImpl RelocationP, - const ObjectFile *Owner) - : RelocationPimpl(RelocationP) - , OwningObject(Owner) {} - -inline bool RelocationRef::operator==(const RelocationRef &Other) const { - return RelocationPimpl == Other.RelocationPimpl; -} - -inline void RelocationRef::moveNext() { - return OwningObject->moveRelocationNext(RelocationPimpl); -} - -inline uint64_t RelocationRef::getOffset() const { - return OwningObject->getRelocationOffset(RelocationPimpl); -} - -inline symbol_iterator RelocationRef::getSymbol() const { - return OwningObject->getRelocationSymbol(RelocationPimpl); -} - -inline uint64_t RelocationRef::getType() const { - return OwningObject->getRelocationType(RelocationPimpl); -} - -inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const { - return OwningObject->getRelocationTypeName(RelocationPimpl, Result); -} - -inline DataRefImpl RelocationRef::getRawDataRefImpl() const { - return RelocationPimpl; -} - -inline const ObjectFile *RelocationRef::getObject() const { - return OwningObject; -} - -} // end namespace object - -template <> struct DenseMapInfo<object::SectionRef> { - static bool isEqual(const object::SectionRef &A, - const object::SectionRef &B) { - return A == B; - } - static object::SectionRef getEmptyKey() { - return object::SectionRef({}, nullptr); - } - static object::SectionRef getTombstoneKey() { - object::DataRefImpl TS; - TS.p = (uintptr_t)-1; - return object::SectionRef(TS, nullptr); - } - static unsigned getHashValue(const object::SectionRef &Sec) { - object::DataRefImpl Raw = Sec.getRawDataRefImpl(); - return hash_combine(Raw.p, Raw.d.a, Raw.d.b); - } -}; - -} // end namespace llvm - -#endif // LLVM_OBJECT_OBJECTFILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + + static Expected<std::unique_ptr<MachOObjectFile>> + createMachOObjectFile(MemoryBufferRef Object, + uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); + + static Expected<std::unique_ptr<WasmObjectFile>> + createWasmObjectFile(MemoryBufferRef Object); +}; + +// Inline function definitions. +inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) + : BasicSymbolRef(SymbolP, Owner) {} + +inline Expected<StringRef> SymbolRef::getName() const { + return getObject()->getSymbolName(getRawDataRefImpl()); +} + +inline Expected<uint64_t> SymbolRef::getAddress() const { + return getObject()->getSymbolAddress(getRawDataRefImpl()); +} + +inline Expected<uint64_t> SymbolRef::getValue() const { + return getObject()->getSymbolValue(getRawDataRefImpl()); +} + +inline uint32_t SymbolRef::getAlignment() const { + return getObject()->getSymbolAlignment(getRawDataRefImpl()); +} + +inline uint64_t SymbolRef::getCommonSize() const { + return getObject()->getCommonSymbolSize(getRawDataRefImpl()); +} + +inline Expected<section_iterator> SymbolRef::getSection() const { + return getObject()->getSymbolSection(getRawDataRefImpl()); +} + +inline Expected<SymbolRef::Type> SymbolRef::getType() const { + return getObject()->getSymbolType(getRawDataRefImpl()); +} + +inline const ObjectFile *SymbolRef::getObject() const { + const SymbolicFile *O = BasicSymbolRef::getObject(); + return cast<ObjectFile>(O); +} + +/// SectionRef +inline SectionRef::SectionRef(DataRefImpl SectionP, + const ObjectFile *Owner) + : SectionPimpl(SectionP) + , OwningObject(Owner) {} + +inline bool SectionRef::operator==(const SectionRef &Other) const { + return OwningObject == Other.OwningObject && + SectionPimpl == Other.SectionPimpl; +} + +inline bool SectionRef::operator!=(const SectionRef &Other) const { + return !(*this == Other); +} + +inline bool SectionRef::operator<(const SectionRef &Other) const { + assert(OwningObject == Other.OwningObject); + return SectionPimpl < Other.SectionPimpl; +} + +inline void SectionRef::moveNext() { + return OwningObject->moveSectionNext(SectionPimpl); +} + +inline Expected<StringRef> SectionRef::getName() const { + return OwningObject->getSectionName(SectionPimpl); +} + +inline uint64_t SectionRef::getAddress() const { + return OwningObject->getSectionAddress(SectionPimpl); +} + +inline uint64_t SectionRef::getIndex() const { + return OwningObject->getSectionIndex(SectionPimpl); +} + +inline uint64_t SectionRef::getSize() const { + return OwningObject->getSectionSize(SectionPimpl); +} + +inline Expected<StringRef> SectionRef::getContents() const { + Expected<ArrayRef<uint8_t>> Res = + OwningObject->getSectionContents(SectionPimpl); + if (!Res) + return Res.takeError(); + return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size()); +} + +inline uint64_t SectionRef::getAlignment() const { + return OwningObject->getSectionAlignment(SectionPimpl); +} + +inline bool SectionRef::isCompressed() const { + return OwningObject->isSectionCompressed(SectionPimpl); +} + +inline bool SectionRef::isText() const { + return OwningObject->isSectionText(SectionPimpl); +} + +inline bool SectionRef::isData() const { + return OwningObject->isSectionData(SectionPimpl); +} + +inline bool SectionRef::isBSS() const { + return OwningObject->isSectionBSS(SectionPimpl); +} + +inline bool SectionRef::isVirtual() const { + return OwningObject->isSectionVirtual(SectionPimpl); +} + +inline bool SectionRef::isBitcode() const { + return OwningObject->isSectionBitcode(SectionPimpl); +} + +inline bool SectionRef::isStripped() const { + return OwningObject->isSectionStripped(SectionPimpl); +} + +inline bool SectionRef::isBerkeleyText() const { + return OwningObject->isBerkeleyText(SectionPimpl); +} + +inline bool SectionRef::isBerkeleyData() const { + return OwningObject->isBerkeleyData(SectionPimpl); +} + +inline bool SectionRef::isDebugSection(StringRef SectionName) const { + return OwningObject->isDebugSection(SectionName); +} + +inline relocation_iterator SectionRef::relocation_begin() const { + return OwningObject->section_rel_begin(SectionPimpl); +} + +inline relocation_iterator SectionRef::relocation_end() const { + return OwningObject->section_rel_end(SectionPimpl); +} + +inline Expected<section_iterator> SectionRef::getRelocatedSection() const { + return OwningObject->getRelocatedSection(SectionPimpl); +} + +inline DataRefImpl SectionRef::getRawDataRefImpl() const { + return SectionPimpl; +} + +inline const ObjectFile *SectionRef::getObject() const { + return OwningObject; +} + +/// RelocationRef +inline RelocationRef::RelocationRef(DataRefImpl RelocationP, + const ObjectFile *Owner) + : RelocationPimpl(RelocationP) + , OwningObject(Owner) {} + +inline bool RelocationRef::operator==(const RelocationRef &Other) const { + return RelocationPimpl == Other.RelocationPimpl; +} + +inline void RelocationRef::moveNext() { + return OwningObject->moveRelocationNext(RelocationPimpl); +} + +inline uint64_t RelocationRef::getOffset() const { + return OwningObject->getRelocationOffset(RelocationPimpl); +} + +inline symbol_iterator RelocationRef::getSymbol() const { + return OwningObject->getRelocationSymbol(RelocationPimpl); +} + +inline uint64_t RelocationRef::getType() const { + return OwningObject->getRelocationType(RelocationPimpl); +} + +inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const { + return OwningObject->getRelocationTypeName(RelocationPimpl, Result); +} + +inline DataRefImpl RelocationRef::getRawDataRefImpl() const { + return RelocationPimpl; +} + +inline const ObjectFile *RelocationRef::getObject() const { + return OwningObject; +} + +} // end namespace object + +template <> struct DenseMapInfo<object::SectionRef> { + static bool isEqual(const object::SectionRef &A, + const object::SectionRef &B) { + return A == B; + } + static object::SectionRef getEmptyKey() { + return object::SectionRef({}, nullptr); + } + static object::SectionRef getTombstoneKey() { + object::DataRefImpl TS; + TS.p = (uintptr_t)-1; + return object::SectionRef(TS, nullptr); + } + static unsigned getHashValue(const object::SectionRef &Sec) { + object::DataRefImpl Raw = Sec.getRawDataRefImpl(); + return hash_combine(Raw.p, Raw.d.a, Raw.d.b); + } +}; + +} // end namespace llvm + +#endif // LLVM_OBJECT_OBJECTFILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h b/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h index d53f50e3e5e..520d7ff50b1 100644 --- a/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h +++ b/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h @@ -1,59 +1,59 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file provides a wrapper around all the different types of relocations -// in different file formats, such that a client can handle them in a unified -// manner by only implementing a minimal number of functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_RELOCVISITOR_H -#define LLVM_OBJECT_RELOCVISITOR_H - -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/Wasm.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include <cstdint> -#include <system_error> - -namespace llvm { -namespace object { - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around all the different types of relocations +// in different file formats, such that a client can handle them in a unified +// manner by only implementing a minimal number of functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RELOCVISITOR_H +#define LLVM_OBJECT_RELOCVISITOR_H + +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstdint> +#include <system_error> + +namespace llvm { +namespace object { + using SupportsRelocation = bool (*)(uint64_t); using RelocationResolver = uint64_t (*)(uint64_t Type, uint64_t Offset, uint64_t S, uint64_t LocData, int64_t Addend); - + std::pair<SupportsRelocation, RelocationResolver> -getRelocationResolver(const ObjectFile &Obj); - +getRelocationResolver(const ObjectFile &Obj); + uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, uint64_t S, uint64_t LocData); -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_RELOCVISITOR_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_RELOCVISITOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h b/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h index 4551e80bb23..100ad707245 100644 --- a/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h +++ b/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h @@ -1,333 +1,333 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_STACKMAPPARSER_H -#define LLVM_CODEGEN_STACKMAPPARSER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKMAPPARSER_H +#define LLVM_CODEGEN_STACKMAPPARSER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/ELF.h" -#include "llvm/Support/Endian.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <vector> - -namespace llvm { - -/// A parser for the latest stackmap format. At the moment, latest=V3. -template <support::endianness Endianness> -class StackMapParser { -public: - template <typename AccessorT> - class AccessorIterator { - public: - AccessorIterator(AccessorT A) : A(A) {} - - AccessorIterator& operator++() { A = A.next(); return *this; } - AccessorIterator operator++(int) { - auto tmp = *this; - ++*this; - return tmp; - } - - bool operator==(const AccessorIterator &Other) const { - return A.P == Other.A.P; - } - - bool operator!=(const AccessorIterator &Other) const { - return !(*this == Other); - } - - AccessorT& operator*() { return A; } - AccessorT* operator->() { return &A; } - - private: - AccessorT A; - }; - - /// Accessor for function records. - class FunctionAccessor { - friend class StackMapParser; - - public: - /// Get the function address. - uint64_t getFunctionAddress() const { - return read<uint64_t>(P); - } - - /// Get the function's stack size. - uint64_t getStackSize() const { - return read<uint64_t>(P + sizeof(uint64_t)); - } - - /// Get the number of callsite records. - uint64_t getRecordCount() const { - return read<uint64_t>(P + (2 * sizeof(uint64_t))); - } - - private: - FunctionAccessor(const uint8_t *P) : P(P) {} - - const static int FunctionAccessorSize = 3 * sizeof(uint64_t); - - FunctionAccessor next() const { - return FunctionAccessor(P + FunctionAccessorSize); - } - - const uint8_t *P; - }; - - /// Accessor for constants. - class ConstantAccessor { - friend class StackMapParser; - - public: - /// Return the value of this constant. - uint64_t getValue() const { return read<uint64_t>(P); } - - private: - ConstantAccessor(const uint8_t *P) : P(P) {} - - const static int ConstantAccessorSize = sizeof(uint64_t); - - ConstantAccessor next() const { - return ConstantAccessor(P + ConstantAccessorSize); - } - - const uint8_t *P; - }; - - enum class LocationKind : uint8_t { - Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5 - }; - - /// Accessor for location records. - class LocationAccessor { - friend class StackMapParser; - friend class RecordAccessor; - - public: - /// Get the Kind for this location. - LocationKind getKind() const { - return LocationKind(P[KindOffset]); - } - - /// Get the Size for this location. - unsigned getSizeInBytes() const { - return read<uint16_t>(P + SizeOffset); - - } - - /// Get the Dwarf register number for this location. - uint16_t getDwarfRegNum() const { - return read<uint16_t>(P + DwarfRegNumOffset); - } - - /// Get the small-constant for this location. (Kind must be Constant). - uint32_t getSmallConstant() const { - assert(getKind() == LocationKind::Constant && "Not a small constant."); - return read<uint32_t>(P + SmallConstantOffset); - } - - /// Get the constant-index for this location. (Kind must be ConstantIndex). - uint32_t getConstantIndex() const { - assert(getKind() == LocationKind::ConstantIndex && - "Not a constant-index."); - return read<uint32_t>(P + SmallConstantOffset); - } - - /// Get the offset for this location. (Kind must be Direct or Indirect). - int32_t getOffset() const { - assert((getKind() == LocationKind::Direct || - getKind() == LocationKind::Indirect) && - "Not direct or indirect."); - return read<int32_t>(P + SmallConstantOffset); - } - - private: - LocationAccessor(const uint8_t *P) : P(P) {} - - LocationAccessor next() const { - return LocationAccessor(P + LocationAccessorSize); - } - - static const int KindOffset = 0; - static const int SizeOffset = KindOffset + sizeof(uint16_t); - static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t); - static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t); - static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t); - - const uint8_t *P; - }; - - /// Accessor for stackmap live-out fields. - class LiveOutAccessor { - friend class StackMapParser; - friend class RecordAccessor; - - public: - /// Get the Dwarf register number for this live-out. - uint16_t getDwarfRegNum() const { - return read<uint16_t>(P + DwarfRegNumOffset); - } - - /// Get the size in bytes of live [sub]register. - unsigned getSizeInBytes() const { - return read<uint8_t>(P + SizeOffset); - } - - private: - LiveOutAccessor(const uint8_t *P) : P(P) {} - - LiveOutAccessor next() const { - return LiveOutAccessor(P + LiveOutAccessorSize); - } - - static const int DwarfRegNumOffset = 0; - static const int SizeOffset = - DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t); - static const int LiveOutAccessorSize = sizeof(uint32_t); - - const uint8_t *P; - }; - - /// Accessor for stackmap records. - class RecordAccessor { - friend class StackMapParser; - - public: - using location_iterator = AccessorIterator<LocationAccessor>; - using liveout_iterator = AccessorIterator<LiveOutAccessor>; - - /// Get the patchpoint/stackmap ID for this record. - uint64_t getID() const { - return read<uint64_t>(P + PatchpointIDOffset); - } - - /// Get the instruction offset (from the start of the containing function) - /// for this record. - uint32_t getInstructionOffset() const { - return read<uint32_t>(P + InstructionOffsetOffset); - } - - /// Get the number of locations contained in this record. - uint16_t getNumLocations() const { - return read<uint16_t>(P + NumLocationsOffset); - } - - /// Get the location with the given index. - LocationAccessor getLocation(unsigned LocationIndex) const { - unsigned LocationOffset = - LocationListOffset + LocationIndex * LocationSize; - return LocationAccessor(P + LocationOffset); - } - - /// Begin iterator for locations. - location_iterator location_begin() const { - return location_iterator(getLocation(0)); - } - - /// End iterator for locations. - location_iterator location_end() const { - return location_iterator(getLocation(getNumLocations())); - } - - /// Iterator range for locations. - iterator_range<location_iterator> locations() const { - return make_range(location_begin(), location_end()); - } - - /// Get the number of liveouts contained in this record. - uint16_t getNumLiveOuts() const { - return read<uint16_t>(P + getNumLiveOutsOffset()); - } - - /// Get the live-out with the given index. - LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const { - unsigned LiveOutOffset = - getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize; - return LiveOutAccessor(P + LiveOutOffset); - } - - /// Begin iterator for live-outs. - liveout_iterator liveouts_begin() const { - return liveout_iterator(getLiveOut(0)); - } - - /// End iterator for live-outs. - liveout_iterator liveouts_end() const { - return liveout_iterator(getLiveOut(getNumLiveOuts())); - } - - /// Iterator range for live-outs. - iterator_range<liveout_iterator> liveouts() const { - return make_range(liveouts_begin(), liveouts_end()); - } - - private: - RecordAccessor(const uint8_t *P) : P(P) {} - - unsigned getNumLiveOutsOffset() const { - unsigned LocOffset = - ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7; - return LocOffset + sizeof(uint16_t); - } - - unsigned getSizeInBytes() const { - unsigned RecordSize = - getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize; - return (RecordSize + 7) & ~0x7; - } - - RecordAccessor next() const { - return RecordAccessor(P + getSizeInBytes()); - } - - static const unsigned PatchpointIDOffset = 0; - static const unsigned InstructionOffsetOffset = - PatchpointIDOffset + sizeof(uint64_t); - static const unsigned NumLocationsOffset = - InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); - static const unsigned LocationListOffset = - NumLocationsOffset + sizeof(uint16_t); - static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t); - static const unsigned LiveOutSize = sizeof(uint32_t); - - const uint8_t *P; - }; - - /// Construct a parser for a version-3 stackmap. StackMap data will be read - /// from the given array. - StackMapParser(ArrayRef<uint8_t> StackMapSection) - : StackMapSection(StackMapSection) { - ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; - - assert(StackMapSection[0] == 3 && - "StackMapParser can only parse version 3 stackmaps"); - - unsigned CurrentRecordOffset = - ConstantsListOffset + getNumConstants() * ConstantSize; - - for (unsigned I = 0, E = getNumRecords(); I != E; ++I) { - StackMapRecordOffsets.push_back(CurrentRecordOffset); - CurrentRecordOffset += - RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes(); - } - } - +#include "llvm/Support/Endian.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <vector> + +namespace llvm { + +/// A parser for the latest stackmap format. At the moment, latest=V3. +template <support::endianness Endianness> +class StackMapParser { +public: + template <typename AccessorT> + class AccessorIterator { + public: + AccessorIterator(AccessorT A) : A(A) {} + + AccessorIterator& operator++() { A = A.next(); return *this; } + AccessorIterator operator++(int) { + auto tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const AccessorIterator &Other) const { + return A.P == Other.A.P; + } + + bool operator!=(const AccessorIterator &Other) const { + return !(*this == Other); + } + + AccessorT& operator*() { return A; } + AccessorT* operator->() { return &A; } + + private: + AccessorT A; + }; + + /// Accessor for function records. + class FunctionAccessor { + friend class StackMapParser; + + public: + /// Get the function address. + uint64_t getFunctionAddress() const { + return read<uint64_t>(P); + } + + /// Get the function's stack size. + uint64_t getStackSize() const { + return read<uint64_t>(P + sizeof(uint64_t)); + } + + /// Get the number of callsite records. + uint64_t getRecordCount() const { + return read<uint64_t>(P + (2 * sizeof(uint64_t))); + } + + private: + FunctionAccessor(const uint8_t *P) : P(P) {} + + const static int FunctionAccessorSize = 3 * sizeof(uint64_t); + + FunctionAccessor next() const { + return FunctionAccessor(P + FunctionAccessorSize); + } + + const uint8_t *P; + }; + + /// Accessor for constants. + class ConstantAccessor { + friend class StackMapParser; + + public: + /// Return the value of this constant. + uint64_t getValue() const { return read<uint64_t>(P); } + + private: + ConstantAccessor(const uint8_t *P) : P(P) {} + + const static int ConstantAccessorSize = sizeof(uint64_t); + + ConstantAccessor next() const { + return ConstantAccessor(P + ConstantAccessorSize); + } + + const uint8_t *P; + }; + + enum class LocationKind : uint8_t { + Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5 + }; + + /// Accessor for location records. + class LocationAccessor { + friend class StackMapParser; + friend class RecordAccessor; + + public: + /// Get the Kind for this location. + LocationKind getKind() const { + return LocationKind(P[KindOffset]); + } + + /// Get the Size for this location. + unsigned getSizeInBytes() const { + return read<uint16_t>(P + SizeOffset); + + } + + /// Get the Dwarf register number for this location. + uint16_t getDwarfRegNum() const { + return read<uint16_t>(P + DwarfRegNumOffset); + } + + /// Get the small-constant for this location. (Kind must be Constant). + uint32_t getSmallConstant() const { + assert(getKind() == LocationKind::Constant && "Not a small constant."); + return read<uint32_t>(P + SmallConstantOffset); + } + + /// Get the constant-index for this location. (Kind must be ConstantIndex). + uint32_t getConstantIndex() const { + assert(getKind() == LocationKind::ConstantIndex && + "Not a constant-index."); + return read<uint32_t>(P + SmallConstantOffset); + } + + /// Get the offset for this location. (Kind must be Direct or Indirect). + int32_t getOffset() const { + assert((getKind() == LocationKind::Direct || + getKind() == LocationKind::Indirect) && + "Not direct or indirect."); + return read<int32_t>(P + SmallConstantOffset); + } + + private: + LocationAccessor(const uint8_t *P) : P(P) {} + + LocationAccessor next() const { + return LocationAccessor(P + LocationAccessorSize); + } + + static const int KindOffset = 0; + static const int SizeOffset = KindOffset + sizeof(uint16_t); + static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t); + static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t); + static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t); + + const uint8_t *P; + }; + + /// Accessor for stackmap live-out fields. + class LiveOutAccessor { + friend class StackMapParser; + friend class RecordAccessor; + + public: + /// Get the Dwarf register number for this live-out. + uint16_t getDwarfRegNum() const { + return read<uint16_t>(P + DwarfRegNumOffset); + } + + /// Get the size in bytes of live [sub]register. + unsigned getSizeInBytes() const { + return read<uint8_t>(P + SizeOffset); + } + + private: + LiveOutAccessor(const uint8_t *P) : P(P) {} + + LiveOutAccessor next() const { + return LiveOutAccessor(P + LiveOutAccessorSize); + } + + static const int DwarfRegNumOffset = 0; + static const int SizeOffset = + DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t); + static const int LiveOutAccessorSize = sizeof(uint32_t); + + const uint8_t *P; + }; + + /// Accessor for stackmap records. + class RecordAccessor { + friend class StackMapParser; + + public: + using location_iterator = AccessorIterator<LocationAccessor>; + using liveout_iterator = AccessorIterator<LiveOutAccessor>; + + /// Get the patchpoint/stackmap ID for this record. + uint64_t getID() const { + return read<uint64_t>(P + PatchpointIDOffset); + } + + /// Get the instruction offset (from the start of the containing function) + /// for this record. + uint32_t getInstructionOffset() const { + return read<uint32_t>(P + InstructionOffsetOffset); + } + + /// Get the number of locations contained in this record. + uint16_t getNumLocations() const { + return read<uint16_t>(P + NumLocationsOffset); + } + + /// Get the location with the given index. + LocationAccessor getLocation(unsigned LocationIndex) const { + unsigned LocationOffset = + LocationListOffset + LocationIndex * LocationSize; + return LocationAccessor(P + LocationOffset); + } + + /// Begin iterator for locations. + location_iterator location_begin() const { + return location_iterator(getLocation(0)); + } + + /// End iterator for locations. + location_iterator location_end() const { + return location_iterator(getLocation(getNumLocations())); + } + + /// Iterator range for locations. + iterator_range<location_iterator> locations() const { + return make_range(location_begin(), location_end()); + } + + /// Get the number of liveouts contained in this record. + uint16_t getNumLiveOuts() const { + return read<uint16_t>(P + getNumLiveOutsOffset()); + } + + /// Get the live-out with the given index. + LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const { + unsigned LiveOutOffset = + getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize; + return LiveOutAccessor(P + LiveOutOffset); + } + + /// Begin iterator for live-outs. + liveout_iterator liveouts_begin() const { + return liveout_iterator(getLiveOut(0)); + } + + /// End iterator for live-outs. + liveout_iterator liveouts_end() const { + return liveout_iterator(getLiveOut(getNumLiveOuts())); + } + + /// Iterator range for live-outs. + iterator_range<liveout_iterator> liveouts() const { + return make_range(liveouts_begin(), liveouts_end()); + } + + private: + RecordAccessor(const uint8_t *P) : P(P) {} + + unsigned getNumLiveOutsOffset() const { + unsigned LocOffset = + ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7; + return LocOffset + sizeof(uint16_t); + } + + unsigned getSizeInBytes() const { + unsigned RecordSize = + getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize; + return (RecordSize + 7) & ~0x7; + } + + RecordAccessor next() const { + return RecordAccessor(P + getSizeInBytes()); + } + + static const unsigned PatchpointIDOffset = 0; + static const unsigned InstructionOffsetOffset = + PatchpointIDOffset + sizeof(uint64_t); + static const unsigned NumLocationsOffset = + InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); + static const unsigned LocationListOffset = + NumLocationsOffset + sizeof(uint16_t); + static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t); + static const unsigned LiveOutSize = sizeof(uint32_t); + + const uint8_t *P; + }; + + /// Construct a parser for a version-3 stackmap. StackMap data will be read + /// from the given array. + StackMapParser(ArrayRef<uint8_t> StackMapSection) + : StackMapSection(StackMapSection) { + ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; + + assert(StackMapSection[0] == 3 && + "StackMapParser can only parse version 3 stackmaps"); + + unsigned CurrentRecordOffset = + ConstantsListOffset + getNumConstants() * ConstantSize; + + for (unsigned I = 0, E = getNumRecords(); I != E; ++I) { + StackMapRecordOffsets.push_back(CurrentRecordOffset); + CurrentRecordOffset += + RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes(); + } + } + /// Validates the header of the specified stack map section. static Error validateHeader(ArrayRef<uint8_t> StackMapSection) { // See the comment for StackMaps::emitStackmapHeader(). @@ -345,134 +345,134 @@ public: return Error::success(); } - using function_iterator = AccessorIterator<FunctionAccessor>; - using constant_iterator = AccessorIterator<ConstantAccessor>; - using record_iterator = AccessorIterator<RecordAccessor>; - - /// Get the version number of this stackmap. (Always returns 3). - unsigned getVersion() const { return 3; } - - /// Get the number of functions in the stack map. - uint32_t getNumFunctions() const { - return read<uint32_t>(&StackMapSection[NumFunctionsOffset]); - } - - /// Get the number of large constants in the stack map. - uint32_t getNumConstants() const { - return read<uint32_t>(&StackMapSection[NumConstantsOffset]); - } - - /// Get the number of stackmap records in the stackmap. - uint32_t getNumRecords() const { - return read<uint32_t>(&StackMapSection[NumRecordsOffset]); - } - - /// Return an FunctionAccessor for the given function index. - FunctionAccessor getFunction(unsigned FunctionIndex) const { - return FunctionAccessor(StackMapSection.data() + - getFunctionOffset(FunctionIndex)); - } - - /// Begin iterator for functions. - function_iterator functions_begin() const { - return function_iterator(getFunction(0)); - } - - /// End iterator for functions. - function_iterator functions_end() const { - return function_iterator( - FunctionAccessor(StackMapSection.data() + - getFunctionOffset(getNumFunctions()))); - } - - /// Iterator range for functions. - iterator_range<function_iterator> functions() const { - return make_range(functions_begin(), functions_end()); - } - - /// Return the large constant at the given index. - ConstantAccessor getConstant(unsigned ConstantIndex) const { - return ConstantAccessor(StackMapSection.data() + - getConstantOffset(ConstantIndex)); - } - - /// Begin iterator for constants. - constant_iterator constants_begin() const { - return constant_iterator(getConstant(0)); - } - - /// End iterator for constants. - constant_iterator constants_end() const { - return constant_iterator( - ConstantAccessor(StackMapSection.data() + - getConstantOffset(getNumConstants()))); - } - - /// Iterator range for constants. - iterator_range<constant_iterator> constants() const { - return make_range(constants_begin(), constants_end()); - } - - /// Return a RecordAccessor for the given record index. - RecordAccessor getRecord(unsigned RecordIndex) const { - std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex]; - return RecordAccessor(StackMapSection.data() + RecordOffset); - } - - /// Begin iterator for records. - record_iterator records_begin() const { - if (getNumRecords() == 0) - return record_iterator(RecordAccessor(nullptr)); - return record_iterator(getRecord(0)); - } - - /// End iterator for records. - record_iterator records_end() const { - // Records need to be handled specially, since we cache the start addresses - // for them: We can't just compute the 1-past-the-end address, we have to - // look at the last record and use the 'next' method. - if (getNumRecords() == 0) - return record_iterator(RecordAccessor(nullptr)); - return record_iterator(getRecord(getNumRecords() - 1).next()); - } - - /// Iterator range for records. - iterator_range<record_iterator> records() const { - return make_range(records_begin(), records_end()); - } - -private: - template <typename T> - static T read(const uint8_t *P) { - return support::endian::read<T, Endianness, 1>(P); - } - - static const unsigned HeaderOffset = 0; - static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t); - static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t); - static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); - static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); - - static const unsigned FunctionSize = 3 * sizeof(uint64_t); - static const unsigned ConstantSize = sizeof(uint64_t); - - std::size_t getFunctionOffset(unsigned FunctionIndex) const { - return FunctionListOffset + FunctionIndex * FunctionSize; - } - - std::size_t getConstantOffset(unsigned ConstantIndex) const { - return ConstantsListOffset + ConstantIndex * ConstantSize; - } - - ArrayRef<uint8_t> StackMapSection; - unsigned ConstantsListOffset; - std::vector<unsigned> StackMapRecordOffsets; -}; - -} // end namespace llvm - -#endif // LLVM_CODEGEN_STACKMAPPARSER_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + using function_iterator = AccessorIterator<FunctionAccessor>; + using constant_iterator = AccessorIterator<ConstantAccessor>; + using record_iterator = AccessorIterator<RecordAccessor>; + + /// Get the version number of this stackmap. (Always returns 3). + unsigned getVersion() const { return 3; } + + /// Get the number of functions in the stack map. + uint32_t getNumFunctions() const { + return read<uint32_t>(&StackMapSection[NumFunctionsOffset]); + } + + /// Get the number of large constants in the stack map. + uint32_t getNumConstants() const { + return read<uint32_t>(&StackMapSection[NumConstantsOffset]); + } + + /// Get the number of stackmap records in the stackmap. + uint32_t getNumRecords() const { + return read<uint32_t>(&StackMapSection[NumRecordsOffset]); + } + + /// Return an FunctionAccessor for the given function index. + FunctionAccessor getFunction(unsigned FunctionIndex) const { + return FunctionAccessor(StackMapSection.data() + + getFunctionOffset(FunctionIndex)); + } + + /// Begin iterator for functions. + function_iterator functions_begin() const { + return function_iterator(getFunction(0)); + } + + /// End iterator for functions. + function_iterator functions_end() const { + return function_iterator( + FunctionAccessor(StackMapSection.data() + + getFunctionOffset(getNumFunctions()))); + } + + /// Iterator range for functions. + iterator_range<function_iterator> functions() const { + return make_range(functions_begin(), functions_end()); + } + + /// Return the large constant at the given index. + ConstantAccessor getConstant(unsigned ConstantIndex) const { + return ConstantAccessor(StackMapSection.data() + + getConstantOffset(ConstantIndex)); + } + + /// Begin iterator for constants. + constant_iterator constants_begin() const { + return constant_iterator(getConstant(0)); + } + + /// End iterator for constants. + constant_iterator constants_end() const { + return constant_iterator( + ConstantAccessor(StackMapSection.data() + + getConstantOffset(getNumConstants()))); + } + + /// Iterator range for constants. + iterator_range<constant_iterator> constants() const { + return make_range(constants_begin(), constants_end()); + } + + /// Return a RecordAccessor for the given record index. + RecordAccessor getRecord(unsigned RecordIndex) const { + std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex]; + return RecordAccessor(StackMapSection.data() + RecordOffset); + } + + /// Begin iterator for records. + record_iterator records_begin() const { + if (getNumRecords() == 0) + return record_iterator(RecordAccessor(nullptr)); + return record_iterator(getRecord(0)); + } + + /// End iterator for records. + record_iterator records_end() const { + // Records need to be handled specially, since we cache the start addresses + // for them: We can't just compute the 1-past-the-end address, we have to + // look at the last record and use the 'next' method. + if (getNumRecords() == 0) + return record_iterator(RecordAccessor(nullptr)); + return record_iterator(getRecord(getNumRecords() - 1).next()); + } + + /// Iterator range for records. + iterator_range<record_iterator> records() const { + return make_range(records_begin(), records_end()); + } + +private: + template <typename T> + static T read(const uint8_t *P) { + return support::endian::read<T, Endianness, 1>(P); + } + + static const unsigned HeaderOffset = 0; + static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t); + static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t); + static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); + static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); + + static const unsigned FunctionSize = 3 * sizeof(uint64_t); + static const unsigned ConstantSize = sizeof(uint64_t); + + std::size_t getFunctionOffset(unsigned FunctionIndex) const { + return FunctionListOffset + FunctionIndex * FunctionSize; + } + + std::size_t getConstantOffset(unsigned ConstantIndex) const { + return ConstantsListOffset + ConstantIndex * ConstantSize; + } + + ArrayRef<uint8_t> StackMapSection; + unsigned ConstantsListOffset; + std::vector<unsigned> StackMapRecordOffsets; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_STACKMAPPARSER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h b/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h index ae0fb0b12ff..6d7b7442af2 100644 --- a/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h +++ b/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h @@ -1,44 +1,44 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- SymbolSize.h ---------------------------------------------*- C++ -*-===// -// -// 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 -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_SYMBOLSIZE_H -#define LLVM_OBJECT_SYMBOLSIZE_H - -#include "llvm/Object/ObjectFile.h" - -namespace llvm { -namespace object { - -struct SymEntry { - symbol_iterator I; - uint64_t Address; - unsigned Number; - unsigned SectionID; -}; - -int compareAddress(const SymEntry *A, const SymEntry *B); - -std::vector<std::pair<SymbolRef, uint64_t>> -computeSymbolSizes(const ObjectFile &O); - -} -} // namespace llvm - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- SymbolSize.h ---------------------------------------------*- C++ -*-===// +// +// 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 +// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLSIZE_H +#define LLVM_OBJECT_SYMBOLSIZE_H + +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { + +struct SymEntry { + symbol_iterator I; + uint64_t Address; + unsigned Number; + unsigned SectionID; +}; + +int compareAddress(const SymEntry *A, const SymEntry *B); + +std::vector<std::pair<SymbolRef, uint64_t>> +computeSymbolSizes(const ObjectFile &O); + +} +} // namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h b/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h index 928c0ad8b35..d890fd2aa58 100644 --- a/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h @@ -1,224 +1,224 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the SymbolicFile interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_SYMBOLICFILE_H -#define LLVM_OBJECT_SYMBOLICFILE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/Magic.h" -#include "llvm/Object/Binary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MemoryBuffer.h" -#include <cinttypes> -#include <cstdint> -#include <cstring> -#include <iterator> -#include <memory> -#include <system_error> - -namespace llvm { -namespace object { - -union DataRefImpl { - // This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - struct { - uint32_t a, b; - } d; - uintptr_t p; - - DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } -}; - -template <typename OStream> -OStream& operator<<(OStream &OS, const DataRefImpl &D) { - OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a) - << ", " << format("0x%08x", D.d.b) << "))"; - return OS; -} - -inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; -} - -inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) { - return !operator==(a, b); -} - -inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; -} - -template <class content_type> -class content_iterator - : public std::iterator<std::forward_iterator_tag, content_type> { - content_type Current; - -public: - content_iterator(content_type symb) : Current(std::move(symb)) {} - - const content_type *operator->() const { return &Current; } - - const content_type &operator*() const { return Current; } - - bool operator==(const content_iterator &other) const { - return Current == other.Current; - } - - bool operator!=(const content_iterator &other) const { - return !(*this == other); - } - - content_iterator &operator++() { // preincrement - Current.moveNext(); - return *this; - } -}; - -class SymbolicFile; - -/// This is a value type class that represents a single symbol in the list of -/// symbols in the object file. -class BasicSymbolRef { - DataRefImpl SymbolPimpl; - const SymbolicFile *OwningObject = nullptr; - -public: - enum Flags : unsigned { - SF_None = 0, - SF_Undefined = 1U << 0, // Symbol is defined in another object file - SF_Global = 1U << 1, // Global symbol - SF_Weak = 1U << 2, // Weak symbol - SF_Absolute = 1U << 3, // Absolute symbol - SF_Common = 1U << 4, // Symbol has common linkage - SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_Exported = 1U << 6, // Symbol is visible to other DSOs - SF_FormatSpecific = 1U << 7, // Specific to the object file format - // (e.g. section symbols) - SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary - SF_Hidden = 1U << 9, // Symbol has hidden visibility - SF_Const = 1U << 10, // Symbol value is constant - SF_Executable = 1U << 11, // Symbol points to an executable section - // (IR only) - }; - - BasicSymbolRef() = default; - BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); - - bool operator==(const BasicSymbolRef &Other) const; - bool operator<(const BasicSymbolRef &Other) const; - - void moveNext(); - - Error printName(raw_ostream &OS) const; - - /// Get symbol flags (bitwise OR of SymbolRef::Flags) - Expected<uint32_t> getFlags() const; - - DataRefImpl getRawDataRefImpl() const; - const SymbolicFile *getObject() const; -}; - -using basic_symbol_iterator = content_iterator<BasicSymbolRef>; - -class SymbolicFile : public Binary { -public: - SymbolicFile(unsigned int Type, MemoryBufferRef Source); - ~SymbolicFile() override; - - // virtual interface. - virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; - - virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; - - virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0; - - virtual basic_symbol_iterator symbol_begin() const = 0; - - virtual basic_symbol_iterator symbol_end() const = 0; - - // convenience wrappers. - using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>; - basic_symbol_iterator_range symbols() const { - return basic_symbol_iterator_range(symbol_begin(), symbol_end()); - } - - // construction aux. - static Expected<std::unique_ptr<SymbolicFile>> - createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolicFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLICFILE_H +#define LLVM_OBJECT_SYMBOLICFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cinttypes> +#include <cstdint> +#include <cstring> +#include <iterator> +#include <memory> +#include <system_error> + +namespace llvm { +namespace object { + +union DataRefImpl { + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. + struct { + uint32_t a, b; + } d; + uintptr_t p; + + DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } +}; + +template <typename OStream> +OStream& operator<<(OStream &OS, const DataRefImpl &D) { + OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a) + << ", " << format("0x%08x", D.d.b) << "))"; + return OS; +} + +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) { + return !operator==(a, b); +} + +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; +} + +template <class content_type> +class content_iterator + : public std::iterator<std::forward_iterator_tag, content_type> { + content_type Current; + +public: + content_iterator(content_type symb) : Current(std::move(symb)) {} + + const content_type *operator->() const { return &Current; } + + const content_type &operator*() const { return Current; } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator &operator++() { // preincrement + Current.moveNext(); + return *this; + } +}; + +class SymbolicFile; + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class BasicSymbolRef { + DataRefImpl SymbolPimpl; + const SymbolicFile *OwningObject = nullptr; + +public: + enum Flags : unsigned { + SF_None = 0, + SF_Undefined = 1U << 0, // Symbol is defined in another object file + SF_Global = 1U << 1, // Global symbol + SF_Weak = 1U << 2, // Weak symbol + SF_Absolute = 1U << 3, // Absolute symbol + SF_Common = 1U << 4, // Symbol has common linkage + SF_Indirect = 1U << 5, // Symbol is an alias to another symbol + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format + // (e.g. section symbols) + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary + SF_Hidden = 1U << 9, // Symbol has hidden visibility + SF_Const = 1U << 10, // Symbol value is constant + SF_Executable = 1U << 11, // Symbol points to an executable section + // (IR only) + }; + + BasicSymbolRef() = default; + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + Error printName(raw_ostream &OS) const; + + /// Get symbol flags (bitwise OR of SymbolRef::Flags) + Expected<uint32_t> getFlags() const; + + DataRefImpl getRawDataRefImpl() const; + const SymbolicFile *getObject() const; +}; + +using basic_symbol_iterator = content_iterator<BasicSymbolRef>; + +class SymbolicFile : public Binary { +public: + SymbolicFile(unsigned int Type, MemoryBufferRef Source); + ~SymbolicFile() override; + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; + + virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0; + + virtual basic_symbol_iterator symbol_begin() const = 0; + + virtual basic_symbol_iterator symbol_end() const = 0; + + // convenience wrappers. + using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>; + basic_symbol_iterator_range symbols() const { + return basic_symbol_iterator_range(symbol_begin(), symbol_end()); + } + + // construction aux. + static Expected<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, LLVMContext *Context, bool InitContent = true); - - static Expected<std::unique_ptr<SymbolicFile>> - createSymbolicFile(MemoryBufferRef Object) { - return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr); - } - - static bool classof(const Binary *v) { - return v->isSymbolic(); - } + + static Expected<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object) { + return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr); + } + + static bool classof(const Binary *v) { + return v->isSymbolic(); + } static bool isSymbolicFile(file_magic Type, const LLVMContext *Context); -}; - -inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, - const SymbolicFile *Owner) - : SymbolPimpl(SymbolP), OwningObject(Owner) {} - -inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { - return SymbolPimpl == Other.SymbolPimpl; -} - -inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { - return SymbolPimpl < Other.SymbolPimpl; -} - -inline void BasicSymbolRef::moveNext() { - return OwningObject->moveSymbolNext(SymbolPimpl); -} - -inline Error BasicSymbolRef::printName(raw_ostream &OS) const { - return OwningObject->printSymbolName(OS, SymbolPimpl); -} - -inline Expected<uint32_t> BasicSymbolRef::getFlags() const { - return OwningObject->getSymbolFlags(SymbolPimpl); -} - -inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { - return SymbolPimpl; -} - -inline const SymbolicFile *BasicSymbolRef::getObject() const { - return OwningObject; -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_SYMBOLICFILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +}; + +inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, + const SymbolicFile *Owner) + : SymbolPimpl(SymbolP), OwningObject(Owner) {} + +inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { + return SymbolPimpl < Other.SymbolPimpl; +} + +inline void BasicSymbolRef::moveNext() { + return OwningObject->moveSymbolNext(SymbolPimpl); +} + +inline Error BasicSymbolRef::printName(raw_ostream &OS) const { + return OwningObject->printSymbolName(OS, SymbolPimpl); +} + +inline Expected<uint32_t> BasicSymbolRef::getFlags() const { + return OwningObject->getSymbolFlags(SymbolPimpl); +} + +inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + +inline const SymbolicFile *BasicSymbolRef::getObject() const { + return OwningObject; +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_SYMBOLICFILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/TapiFile.h b/contrib/libs/llvm12/include/llvm/Object/TapiFile.h index 04c07c01cbc..89b2b18e983 100644 --- a/contrib/libs/llvm12/include/llvm/Object/TapiFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/TapiFile.h @@ -1,74 +1,74 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- TapiFile.h - Text-based Dynamic Library Stub -------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the TapiFile interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_TAPI_FILE_H -#define LLVM_OBJECT_TAPI_FILE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/TextAPI/MachO/InterfaceFile.h" - -namespace llvm { -namespace object { - -class TapiFile : public SymbolicFile { -public: - TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface, - MachO::Architecture Arch); - ~TapiFile() override; - - void moveSymbolNext(DataRefImpl &DRI) const override; - - Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override; - - Expected<uint32_t> getSymbolFlags(DataRefImpl DRI) const override; - - basic_symbol_iterator symbol_begin() const override; - - basic_symbol_iterator symbol_end() const override; - - static bool classof(const Binary *v) { return v->isTapiFile(); } - - bool is64Bit() { return MachO::is64Bit(Arch); } - -private: - struct Symbol { - StringRef Prefix; - StringRef Name; - uint32_t Flags; - - constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags) - : Prefix(Prefix), Name(Name), Flags(Flags) {} - }; - - std::vector<Symbol> Symbols; - MachO::Architecture Arch; -}; - -} // end namespace object. -} // end namespace llvm. - -#endif // LLVM_OBJECT_TAPI_FILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- TapiFile.h - Text-based Dynamic Library Stub -------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the TapiFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_TAPI_FILE_H +#define LLVM_OBJECT_TAPI_FILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TextAPI/MachO/InterfaceFile.h" + +namespace llvm { +namespace object { + +class TapiFile : public SymbolicFile { +public: + TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface, + MachO::Architecture Arch); + ~TapiFile() override; + + void moveSymbolNext(DataRefImpl &DRI) const override; + + Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override; + + Expected<uint32_t> getSymbolFlags(DataRefImpl DRI) const override; + + basic_symbol_iterator symbol_begin() const override; + + basic_symbol_iterator symbol_end() const override; + + static bool classof(const Binary *v) { return v->isTapiFile(); } + + bool is64Bit() { return MachO::is64Bit(Arch); } + +private: + struct Symbol { + StringRef Prefix; + StringRef Name; + uint32_t Flags; + + constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags) + : Prefix(Prefix), Name(Name), Flags(Flags) {} + }; + + std::vector<Symbol> Symbols; + MachO::Architecture Arch; +}; + +} // end namespace object. +} // end namespace llvm. + +#endif // LLVM_OBJECT_TAPI_FILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h b/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h index 20eed191dd4..7b7cb43f955 100644 --- a/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h +++ b/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h @@ -1,132 +1,132 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===-- TapiUniversal.h - Text-based Dynamic Library Stub -------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the TapiUniversal interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_TAPI_UNIVERSAL_H -#define LLVM_OBJECT_TAPI_UNIVERSAL_H - -#include "llvm/Object/Binary.h" -#include "llvm/Object/TapiFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/TextAPI/MachO/Architecture.h" -#include "llvm/TextAPI/MachO/InterfaceFile.h" - -namespace llvm { -namespace object { - -class TapiUniversal : public Binary { -public: - class ObjectForArch { - const TapiUniversal *Parent; - int Index; - - public: - ObjectForArch(const TapiUniversal *Parent, int Index) - : Parent(Parent), Index(Index) {} - - ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } - - bool operator==(const ObjectForArch &Other) const { - return (Parent == Other.Parent) && (Index == Other.Index); - } - - uint32_t getCPUType() const { - auto Result = - MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch); - return Result.first; - } - - uint32_t getCPUSubType() const { - auto Result = - MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch); - return Result.second; - } - - StringRef getArchFlagName() const { - return MachO::getArchitectureName(Parent->Libraries[Index].Arch); - } - - std::string getInstallName() const { - return std::string(Parent->Libraries[Index].InstallName); - } - - bool isTopLevelLib() const { - return Parent->ParsedFile->getInstallName() == getInstallName(); - } - - Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const; - }; - - class object_iterator { - ObjectForArch Obj; - - public: - object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} - const ObjectForArch *operator->() const { return &Obj; } - const ObjectForArch &operator*() const { return Obj; } - - bool operator==(const object_iterator &Other) const { - return Obj == Other.Obj; - } - bool operator!=(const object_iterator &Other) const { - return !(*this == Other); - } - - object_iterator &operator++() { // Preincrement - Obj = Obj.getNext(); - return *this; - } - }; - - TapiUniversal(MemoryBufferRef Source, Error &Err); - static Expected<std::unique_ptr<TapiUniversal>> - create(MemoryBufferRef Source); - ~TapiUniversal() override; - - object_iterator begin_objects() const { return ObjectForArch(this, 0); } - object_iterator end_objects() const { - return ObjectForArch(this, Libraries.size()); - } - - iterator_range<object_iterator> objects() const { - return make_range(begin_objects(), end_objects()); - } - - uint32_t getNumberOfObjects() const { return Libraries.size(); } - - static bool classof(const Binary *v) { return v->isTapiUniversal(); } - -private: - struct Library { - StringRef InstallName; - MachO::Architecture Arch; - }; - - std::unique_ptr<MachO::InterfaceFile> ParsedFile; - std::vector<Library> Libraries; -}; - -} // end namespace object. -} // end namespace llvm. - -#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- TapiUniversal.h - Text-based Dynamic Library Stub -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the TapiUniversal interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_TAPI_UNIVERSAL_H +#define LLVM_OBJECT_TAPI_UNIVERSAL_H + +#include "llvm/Object/Binary.h" +#include "llvm/Object/TapiFile.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TextAPI/MachO/Architecture.h" +#include "llvm/TextAPI/MachO/InterfaceFile.h" + +namespace llvm { +namespace object { + +class TapiUniversal : public Binary { +public: + class ObjectForArch { + const TapiUniversal *Parent; + int Index; + + public: + ObjectForArch(const TapiUniversal *Parent, int Index) + : Parent(Parent), Index(Index) {} + + ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } + + bool operator==(const ObjectForArch &Other) const { + return (Parent == Other.Parent) && (Index == Other.Index); + } + + uint32_t getCPUType() const { + auto Result = + MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch); + return Result.first; + } + + uint32_t getCPUSubType() const { + auto Result = + MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch); + return Result.second; + } + + StringRef getArchFlagName() const { + return MachO::getArchitectureName(Parent->Libraries[Index].Arch); + } + + std::string getInstallName() const { + return std::string(Parent->Libraries[Index].InstallName); + } + + bool isTopLevelLib() const { + return Parent->ParsedFile->getInstallName() == getInstallName(); + } + + Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const; + }; + + class object_iterator { + ObjectForArch Obj; + + public: + object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} + const ObjectForArch *operator->() const { return &Obj; } + const ObjectForArch &operator*() const { return Obj; } + + bool operator==(const object_iterator &Other) const { + return Obj == Other.Obj; + } + bool operator!=(const object_iterator &Other) const { + return !(*this == Other); + } + + object_iterator &operator++() { // Preincrement + Obj = Obj.getNext(); + return *this; + } + }; + + TapiUniversal(MemoryBufferRef Source, Error &Err); + static Expected<std::unique_ptr<TapiUniversal>> + create(MemoryBufferRef Source); + ~TapiUniversal() override; + + object_iterator begin_objects() const { return ObjectForArch(this, 0); } + object_iterator end_objects() const { + return ObjectForArch(this, Libraries.size()); + } + + iterator_range<object_iterator> objects() const { + return make_range(begin_objects(), end_objects()); + } + + uint32_t getNumberOfObjects() const { return Libraries.size(); } + + static bool classof(const Binary *v) { return v->isTapiUniversal(); } + +private: + struct Library { + StringRef InstallName; + MachO::Architecture Arch; + }; + + std::unique_ptr<MachO::InterfaceFile> ParsedFile; + std::vector<Library> Libraries; +}; + +} // end namespace object. +} // end namespace llvm. + +#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/Wasm.h b/contrib/libs/llvm12/include/llvm/Object/Wasm.h index 80e3ddd109f..8f12bd09102 100644 --- a/contrib/libs/llvm12/include/llvm/Object/Wasm.h +++ b/contrib/libs/llvm12/include/llvm/Object/Wasm.h @@ -1,381 +1,381 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Wasm.h - Wasm object file implementation -----------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the WasmObjectFile class, which implements the ObjectFile -// interface for Wasm files. -// -// See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_WASM_H -#define LLVM_OBJECT_WASM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/Wasm.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCSymbolWasm.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include <cstddef> -#include <cstdint> -#include <vector> - -namespace llvm { -namespace object { - -class WasmSymbol { -public: - WasmSymbol(const wasm::WasmSymbolInfo &Info, - const wasm::WasmGlobalType *GlobalType, +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Wasm.h - Wasm object file implementation -----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the WasmObjectFile class, which implements the ObjectFile +// interface for Wasm files. +// +// See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_WASM_H +#define LLVM_OBJECT_WASM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Wasm.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cstddef> +#include <cstdint> +#include <vector> + +namespace llvm { +namespace object { + +class WasmSymbol { +public: + WasmSymbol(const wasm::WasmSymbolInfo &Info, + const wasm::WasmGlobalType *GlobalType, const wasm::WasmTableType *TableType, - const wasm::WasmEventType *EventType, - const wasm::WasmSignature *Signature) + const wasm::WasmEventType *EventType, + const wasm::WasmSignature *Signature) : Info(Info), GlobalType(GlobalType), TableType(TableType), EventType(EventType), Signature(Signature) {} - - const wasm::WasmSymbolInfo &Info; - const wasm::WasmGlobalType *GlobalType; + + const wasm::WasmSymbolInfo &Info; + const wasm::WasmGlobalType *GlobalType; const wasm::WasmTableType *TableType; - const wasm::WasmEventType *EventType; - const wasm::WasmSignature *Signature; - - bool isTypeFunction() const { - return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION; - } - + const wasm::WasmEventType *EventType; + const wasm::WasmSignature *Signature; + + bool isTypeFunction() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION; + } + bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; } - bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; } - - bool isTypeGlobal() const { - return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL; - } - - bool isTypeSection() const { - return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION; - } - - bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; } - - bool isDefined() const { return !isUndefined(); } - - bool isUndefined() const { - return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0; - } - - bool isBindingWeak() const { - return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; - } - - bool isBindingGlobal() const { - return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; - } - - bool isBindingLocal() const { - return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; - } - - unsigned getBinding() const { - return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK; - } - - bool isHidden() const { - return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; - } - - unsigned getVisibility() const { - return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; - } - - void print(raw_ostream &Out) const; - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const; -#endif -}; - -struct WasmSection { - WasmSection() = default; - - uint32_t Type = 0; // Section type (See below) - uint32_t Offset = 0; // Offset with in the file - StringRef Name; // Section name (User-defined sections only) + bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; } + + bool isTypeGlobal() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL; + } + + bool isTypeSection() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION; + } + + bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; } + + bool isDefined() const { return !isUndefined(); } + + bool isUndefined() const { + return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0; + } + + bool isBindingWeak() const { + return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; + } + + bool isBindingGlobal() const { + return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; + } + + bool isBindingLocal() const { + return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; + } + + unsigned getBinding() const { + return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK; + } + + bool isHidden() const { + return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; + } + + unsigned getVisibility() const { + return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; + } + + void print(raw_ostream &Out) const; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + LLVM_DUMP_METHOD void dump() const; +#endif +}; + +struct WasmSection { + WasmSection() = default; + + uint32_t Type = 0; // Section type (See below) + uint32_t Offset = 0; // Offset with in the file + StringRef Name; // Section name (User-defined sections only) uint32_t Comdat = UINT32_MAX; // From the "comdat info" section - ArrayRef<uint8_t> Content; // Section content - std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section -}; - -struct WasmSegment { - uint32_t SectionOffset; - wasm::WasmDataSegment Data; -}; - -class WasmObjectFile : public ObjectFile { - -public: - WasmObjectFile(MemoryBufferRef Object, Error &Err); - - const wasm::WasmObjectHeader &getHeader() const; - const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const; - const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const; - const WasmSection &getWasmSection(const SectionRef &Section) const; - const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const; - - static bool classof(const Binary *v) { return v->isWasm(); } - - const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; } - const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; } - ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const { - return TargetFeatures; - } - ArrayRef<wasm::WasmSignature> types() const { return Signatures; } - ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; } - ArrayRef<wasm::WasmImport> imports() const { return Imports; } - ArrayRef<wasm::WasmTable> tables() const { return Tables; } - ArrayRef<wasm::WasmLimits> memories() const { return Memories; } - ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } - ArrayRef<wasm::WasmEvent> events() const { return Events; } - ArrayRef<wasm::WasmExport> exports() const { return Exports; } - ArrayRef<WasmSymbol> syms() const { return Symbols; } - const wasm::WasmLinkingData &linkingData() const { return LinkingData; } - uint32_t getNumberOfSymbols() const { return Symbols.size(); } - ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } - ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } - ArrayRef<wasm::WasmFunction> functions() const { return Functions; } + ArrayRef<uint8_t> Content; // Section content + std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section +}; + +struct WasmSegment { + uint32_t SectionOffset; + wasm::WasmDataSegment Data; +}; + +class WasmObjectFile : public ObjectFile { + +public: + WasmObjectFile(MemoryBufferRef Object, Error &Err); + + const wasm::WasmObjectHeader &getHeader() const; + const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const; + const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const; + const WasmSection &getWasmSection(const SectionRef &Section) const; + const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const; + + static bool classof(const Binary *v) { return v->isWasm(); } + + const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; } + const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; } + ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const { + return TargetFeatures; + } + ArrayRef<wasm::WasmSignature> types() const { return Signatures; } + ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; } + ArrayRef<wasm::WasmImport> imports() const { return Imports; } + ArrayRef<wasm::WasmTable> tables() const { return Tables; } + ArrayRef<wasm::WasmLimits> memories() const { return Memories; } + ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } + ArrayRef<wasm::WasmEvent> events() const { return Events; } + ArrayRef<wasm::WasmExport> exports() const { return Exports; } + ArrayRef<WasmSymbol> syms() const { return Symbols; } + const wasm::WasmLinkingData &linkingData() const { return LinkingData; } + uint32_t getNumberOfSymbols() const { return Symbols.size(); } + ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } + ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } + ArrayRef<wasm::WasmFunction> functions() const { return Functions; } ArrayRef<wasm::WasmDebugName> debugNames() const { return DebugNames; } - uint32_t startFunction() const { return StartFunction; } - uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } + uint32_t startFunction() const { return StartFunction; } + uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } uint32_t getNumImportedTables() const { return NumImportedTables; } - uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } - uint32_t getNumImportedEvents() const { return NumImportedEvents; } - uint32_t getNumSections() const { return Sections.size(); } - void moveSymbolNext(DataRefImpl &Symb) const override; - - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - - basic_symbol_iterator symbol_begin() const override; - - basic_symbol_iterator symbol_end() const override; - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const; - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - uint32_t getSymbolAlignment(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - uint32_t getSymbolSectionId(SymbolRef Sym) const; - - // Overrides from SectionRef. - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionVirtual(DataRefImpl Sec) const override; - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - - // Overrides from RelocationRef. - void moveRelocationNext(DataRefImpl &Rel) const override; - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - - section_iterator section_begin() const override; - section_iterator section_end() const override; - uint8_t getBytesInAddress() const override; - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override; - bool isRelocatableObject() const override; - bool isSharedObject() const; - - struct ReadContext { - const uint8_t *Start; - const uint8_t *Ptr; - const uint8_t *End; - }; - -private: - bool isValidFunctionIndex(uint32_t Index) const; - bool isDefinedFunctionIndex(uint32_t Index) const; - bool isValidGlobalIndex(uint32_t Index) const; + uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } + uint32_t getNumImportedEvents() const { return NumImportedEvents; } + uint32_t getNumSections() const { return Sections.size(); } + void moveSymbolNext(DataRefImpl &Symb) const override; + + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + + basic_symbol_iterator symbol_begin() const override; + + basic_symbol_iterator symbol_end() const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + uint32_t getSymbolSectionId(SymbolRef Sym) const; + + // Overrides from SectionRef. + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + // Overrides from RelocationRef. + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + SubtargetFeatures getFeatures() const override; + bool isRelocatableObject() const override; + bool isSharedObject() const; + + struct ReadContext { + const uint8_t *Start; + const uint8_t *Ptr; + const uint8_t *End; + }; + +private: + bool isValidFunctionIndex(uint32_t Index) const; + bool isDefinedFunctionIndex(uint32_t Index) const; + bool isValidGlobalIndex(uint32_t Index) const; bool isValidTableIndex(uint32_t Index) const; - bool isDefinedGlobalIndex(uint32_t Index) const; + bool isDefinedGlobalIndex(uint32_t Index) const; bool isDefinedTableIndex(uint32_t Index) const; - bool isValidEventIndex(uint32_t Index) const; - bool isDefinedEventIndex(uint32_t Index) const; - bool isValidFunctionSymbol(uint32_t Index) const; + bool isValidEventIndex(uint32_t Index) const; + bool isDefinedEventIndex(uint32_t Index) const; + bool isValidFunctionSymbol(uint32_t Index) const; bool isValidTableSymbol(uint32_t Index) const; - bool isValidGlobalSymbol(uint32_t Index) const; - bool isValidEventSymbol(uint32_t Index) const; - bool isValidDataSymbol(uint32_t Index) const; - bool isValidSectionSymbol(uint32_t Index) const; - wasm::WasmFunction &getDefinedFunction(uint32_t Index); - const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const; - wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); - wasm::WasmEvent &getDefinedEvent(uint32_t Index); - - const WasmSection &getWasmSection(DataRefImpl Ref) const; - const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; - uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const; - - Error parseSection(WasmSection &Sec); - Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx); - - // Standard section types - Error parseTypeSection(ReadContext &Ctx); - Error parseImportSection(ReadContext &Ctx); - Error parseFunctionSection(ReadContext &Ctx); - Error parseTableSection(ReadContext &Ctx); - Error parseMemorySection(ReadContext &Ctx); - Error parseEventSection(ReadContext &Ctx); - Error parseGlobalSection(ReadContext &Ctx); - Error parseExportSection(ReadContext &Ctx); - Error parseStartSection(ReadContext &Ctx); - Error parseElemSection(ReadContext &Ctx); - Error parseCodeSection(ReadContext &Ctx); - Error parseDataSection(ReadContext &Ctx); - Error parseDataCountSection(ReadContext &Ctx); - - // Custom section types - Error parseDylinkSection(ReadContext &Ctx); - Error parseNameSection(ReadContext &Ctx); - Error parseLinkingSection(ReadContext &Ctx); - Error parseLinkingSectionSymtab(ReadContext &Ctx); - Error parseLinkingSectionComdat(ReadContext &Ctx); - Error parseProducersSection(ReadContext &Ctx); - Error parseTargetFeaturesSection(ReadContext &Ctx); - Error parseRelocSection(StringRef Name, ReadContext &Ctx); - - wasm::WasmObjectHeader Header; - std::vector<WasmSection> Sections; - wasm::WasmDylinkInfo DylinkInfo; - wasm::WasmProducerInfo ProducerInfo; - std::vector<wasm::WasmFeatureEntry> TargetFeatures; - std::vector<wasm::WasmSignature> Signatures; - std::vector<uint32_t> FunctionTypes; - std::vector<wasm::WasmTable> Tables; - std::vector<wasm::WasmLimits> Memories; - std::vector<wasm::WasmGlobal> Globals; - std::vector<wasm::WasmEvent> Events; - std::vector<wasm::WasmImport> Imports; - std::vector<wasm::WasmExport> Exports; - std::vector<wasm::WasmElemSegment> ElemSegments; - std::vector<WasmSegment> DataSegments; - llvm::Optional<size_t> DataCount; - std::vector<wasm::WasmFunction> Functions; - std::vector<WasmSymbol> Symbols; + bool isValidGlobalSymbol(uint32_t Index) const; + bool isValidEventSymbol(uint32_t Index) const; + bool isValidDataSymbol(uint32_t Index) const; + bool isValidSectionSymbol(uint32_t Index) const; + wasm::WasmFunction &getDefinedFunction(uint32_t Index); + const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const; + wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); + wasm::WasmEvent &getDefinedEvent(uint32_t Index); + + const WasmSection &getWasmSection(DataRefImpl Ref) const; + const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; + uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const; + + Error parseSection(WasmSection &Sec); + Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx); + + // Standard section types + Error parseTypeSection(ReadContext &Ctx); + Error parseImportSection(ReadContext &Ctx); + Error parseFunctionSection(ReadContext &Ctx); + Error parseTableSection(ReadContext &Ctx); + Error parseMemorySection(ReadContext &Ctx); + Error parseEventSection(ReadContext &Ctx); + Error parseGlobalSection(ReadContext &Ctx); + Error parseExportSection(ReadContext &Ctx); + Error parseStartSection(ReadContext &Ctx); + Error parseElemSection(ReadContext &Ctx); + Error parseCodeSection(ReadContext &Ctx); + Error parseDataSection(ReadContext &Ctx); + Error parseDataCountSection(ReadContext &Ctx); + + // Custom section types + Error parseDylinkSection(ReadContext &Ctx); + Error parseNameSection(ReadContext &Ctx); + Error parseLinkingSection(ReadContext &Ctx); + Error parseLinkingSectionSymtab(ReadContext &Ctx); + Error parseLinkingSectionComdat(ReadContext &Ctx); + Error parseProducersSection(ReadContext &Ctx); + Error parseTargetFeaturesSection(ReadContext &Ctx); + Error parseRelocSection(StringRef Name, ReadContext &Ctx); + + wasm::WasmObjectHeader Header; + std::vector<WasmSection> Sections; + wasm::WasmDylinkInfo DylinkInfo; + wasm::WasmProducerInfo ProducerInfo; + std::vector<wasm::WasmFeatureEntry> TargetFeatures; + std::vector<wasm::WasmSignature> Signatures; + std::vector<uint32_t> FunctionTypes; + std::vector<wasm::WasmTable> Tables; + std::vector<wasm::WasmLimits> Memories; + std::vector<wasm::WasmGlobal> Globals; + std::vector<wasm::WasmEvent> Events; + std::vector<wasm::WasmImport> Imports; + std::vector<wasm::WasmExport> Exports; + std::vector<wasm::WasmElemSegment> ElemSegments; + std::vector<WasmSegment> DataSegments; + llvm::Optional<size_t> DataCount; + std::vector<wasm::WasmFunction> Functions; + std::vector<WasmSymbol> Symbols; std::vector<wasm::WasmDebugName> DebugNames; - uint32_t StartFunction = -1; - bool HasLinkingSection = false; - bool HasDylinkSection = false; - bool SeenCodeSection = false; + uint32_t StartFunction = -1; + bool HasLinkingSection = false; + bool HasDylinkSection = false; + bool SeenCodeSection = false; bool HasMemory64 = false; - wasm::WasmLinkingData LinkingData; - uint32_t NumImportedGlobals = 0; + wasm::WasmLinkingData LinkingData; + uint32_t NumImportedGlobals = 0; uint32_t NumImportedTables = 0; - uint32_t NumImportedFunctions = 0; - uint32_t NumImportedEvents = 0; - uint32_t CodeSection = 0; - uint32_t DataSection = 0; - uint32_t EventSection = 0; - uint32_t GlobalSection = 0; + uint32_t NumImportedFunctions = 0; + uint32_t NumImportedEvents = 0; + uint32_t CodeSection = 0; + uint32_t DataSection = 0; + uint32_t EventSection = 0; + uint32_t GlobalSection = 0; uint32_t TableSection = 0; -}; - -class WasmSectionOrderChecker { -public: - // We define orders for all core wasm sections and known custom sections. - enum : int { - // Sentinel, must be zero - WASM_SEC_ORDER_NONE = 0, - - // Core sections - WASM_SEC_ORDER_TYPE, - WASM_SEC_ORDER_IMPORT, - WASM_SEC_ORDER_FUNCTION, - WASM_SEC_ORDER_TABLE, - WASM_SEC_ORDER_MEMORY, - WASM_SEC_ORDER_EVENT, - WASM_SEC_ORDER_GLOBAL, - WASM_SEC_ORDER_EXPORT, - WASM_SEC_ORDER_START, - WASM_SEC_ORDER_ELEM, - WASM_SEC_ORDER_DATACOUNT, - WASM_SEC_ORDER_CODE, - WASM_SEC_ORDER_DATA, - - // Custom sections - // "dylink" should be the very first section in the module - WASM_SEC_ORDER_DYLINK, - // "linking" section requires DATA section in order to validate data symbols - WASM_SEC_ORDER_LINKING, - // Must come after "linking" section in order to validate reloc indexes. - WASM_SEC_ORDER_RELOC, - // "name" section must appear after DATA. Comes after "linking" to allow - // symbol table to set default function name. - WASM_SEC_ORDER_NAME, - // "producers" section must appear after "name" section. - WASM_SEC_ORDER_PRODUCERS, - // "target_features" section must appear after producers section - WASM_SEC_ORDER_TARGET_FEATURES, - - // Must be last - WASM_NUM_SEC_ORDERS - - }; - - // Sections that may or may not be present, but cannot be predecessors - static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]; - - bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = ""); - -private: - bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already - - // Returns -1 for unknown sections. - int getSectionOrder(unsigned ID, StringRef CustomSectionName = ""); -}; - -} // end namespace object - -inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) { - Sym.print(OS); - return OS; -} - -} // end namespace llvm - -#endif // LLVM_OBJECT_WASM_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +}; + +class WasmSectionOrderChecker { +public: + // We define orders for all core wasm sections and known custom sections. + enum : int { + // Sentinel, must be zero + WASM_SEC_ORDER_NONE = 0, + + // Core sections + WASM_SEC_ORDER_TYPE, + WASM_SEC_ORDER_IMPORT, + WASM_SEC_ORDER_FUNCTION, + WASM_SEC_ORDER_TABLE, + WASM_SEC_ORDER_MEMORY, + WASM_SEC_ORDER_EVENT, + WASM_SEC_ORDER_GLOBAL, + WASM_SEC_ORDER_EXPORT, + WASM_SEC_ORDER_START, + WASM_SEC_ORDER_ELEM, + WASM_SEC_ORDER_DATACOUNT, + WASM_SEC_ORDER_CODE, + WASM_SEC_ORDER_DATA, + + // Custom sections + // "dylink" should be the very first section in the module + WASM_SEC_ORDER_DYLINK, + // "linking" section requires DATA section in order to validate data symbols + WASM_SEC_ORDER_LINKING, + // Must come after "linking" section in order to validate reloc indexes. + WASM_SEC_ORDER_RELOC, + // "name" section must appear after DATA. Comes after "linking" to allow + // symbol table to set default function name. + WASM_SEC_ORDER_NAME, + // "producers" section must appear after "name" section. + WASM_SEC_ORDER_PRODUCERS, + // "target_features" section must appear after producers section + WASM_SEC_ORDER_TARGET_FEATURES, + + // Must be last + WASM_NUM_SEC_ORDERS + + }; + + // Sections that may or may not be present, but cannot be predecessors + static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]; + + bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = ""); + +private: + bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already + + // Returns -1 for unknown sections. + int getSectionOrder(unsigned ID, StringRef CustomSectionName = ""); +}; + +} // end namespace object + +inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) { + Sym.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_OBJECT_WASM_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h b/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h index c6e06c47d09..2de58aa32db 100644 --- a/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h +++ b/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h @@ -1,44 +1,44 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- WindowsMachineFlag.h -------------------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Functions for implementing the /machine: flag. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H -#define LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H - -namespace llvm { - -class StringRef; -namespace COFF { -enum MachineTypes : unsigned; -} - -// Returns a user-readable string for ARMNT, ARM64, AMD64, I386. -// Other MachineTypes values must not be passed in. -StringRef machineToStr(COFF::MachineTypes MT); - -// Maps /machine: arguments to a MachineTypes value. -// Only returns ARMNT, ARM64, AMD64, I386, or IMAGE_FILE_MACHINE_UNKNOWN. -COFF::MachineTypes getMachineType(StringRef S); - -} - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- WindowsMachineFlag.h -------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Functions for implementing the /machine: flag. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H +#define LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H + +namespace llvm { + +class StringRef; +namespace COFF { +enum MachineTypes : unsigned; +} + +// Returns a user-readable string for ARMNT, ARM64, AMD64, I386. +// Other MachineTypes values must not be passed in. +StringRef machineToStr(COFF::MachineTypes MT); + +// Maps /machine: arguments to a MachineTypes value. +// Only returns ARMNT, ARM64, AMD64, I386, or IMAGE_FILE_MACHINE_UNKNOWN. +COFF::MachineTypes getMachineType(StringRef S); + +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h b/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h index 42f6885aef9..8920c528a33 100644 --- a/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h +++ b/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h @@ -1,282 +1,282 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===-- WindowsResource.h ---------------------------------------*- C++-*-===// -// -// 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 -// -//===---------------------------------------------------------------------===// -// -// This file declares the .res file class. .res files are intermediate -// products of the typical resource-compilation process on Windows. This -// process is as follows: -// -// .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file -// -// .rc files are human-readable scripts that list all resources a program uses. -// -// They are compiled into .res files, which are a list of the resources in -// binary form. -// -// Finally the data stored in the .res is compiled into a COFF file, where it -// is organized in a directory tree structure for optimized access by the -// program during runtime. -// -// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx -// -//===---------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H -#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/Error.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" - -#include <map> - -namespace llvm { - -class raw_ostream; -class ScopedPrinter; - -namespace object { - -class WindowsResource; -class ResourceSectionRef; - -const size_t WIN_RES_MAGIC_SIZE = 16; -const size_t WIN_RES_NULL_ENTRY_SIZE = 16; -const uint32_t WIN_RES_HEADER_ALIGNMENT = 4; -const uint32_t WIN_RES_DATA_ALIGNMENT = 4; -const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030; - -struct WinResHeaderPrefix { - support::ulittle32_t DataSize; - support::ulittle32_t HeaderSize; -}; - -// Type and Name may each either be an integer ID or a string. This struct is -// only used in the case where they are both IDs. -struct WinResIDs { - uint16_t TypeFlag; - support::ulittle16_t TypeID; - uint16_t NameFlag; - support::ulittle16_t NameID; - - void setType(uint16_t ID) { - TypeFlag = 0xffff; - TypeID = ID; - } - - void setName(uint16_t ID) { - NameFlag = 0xffff; - NameID = ID; - } -}; - -struct WinResHeaderSuffix { - support::ulittle32_t DataVersion; - support::ulittle16_t MemoryFlags; - support::ulittle16_t Language; - support::ulittle32_t Version; - support::ulittle32_t Characteristics; -}; - -class EmptyResError : public GenericBinaryError { -public: - EmptyResError(Twine Msg, object_error ECOverride) - : GenericBinaryError(Msg, ECOverride) {} -}; - -class ResourceEntryRef { -public: - Error moveNext(bool &End); - bool checkTypeString() const { return IsStringType; } - ArrayRef<UTF16> getTypeString() const { return Type; } - uint16_t getTypeID() const { return TypeID; } - bool checkNameString() const { return IsStringName; } - ArrayRef<UTF16> getNameString() const { return Name; } - uint16_t getNameID() const { return NameID; } - uint16_t getDataVersion() const { return Suffix->DataVersion; } - uint16_t getLanguage() const { return Suffix->Language; } - uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; } - uint16_t getMajorVersion() const { return Suffix->Version >> 16; } - uint16_t getMinorVersion() const { return Suffix->Version; } - uint32_t getCharacteristics() const { return Suffix->Characteristics; } - ArrayRef<uint8_t> getData() const { return Data; } - -private: - friend class WindowsResource; - - ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner); - Error loadNext(); - - static Expected<ResourceEntryRef> create(BinaryStreamRef Ref, - const WindowsResource *Owner); - - BinaryStreamReader Reader; - const WindowsResource *Owner; - bool IsStringType; - ArrayRef<UTF16> Type; - uint16_t TypeID; - bool IsStringName; - ArrayRef<UTF16> Name; - uint16_t NameID; - const WinResHeaderSuffix *Suffix = nullptr; - ArrayRef<uint8_t> Data; -}; - -class WindowsResource : public Binary { -public: - Expected<ResourceEntryRef> getHeadEntry(); - - static bool classof(const Binary *V) { return V->isWinRes(); } - - static Expected<std::unique_ptr<WindowsResource>> - createWindowsResource(MemoryBufferRef Source); - -private: - friend class ResourceEntryRef; - - WindowsResource(MemoryBufferRef Source); - - BinaryByteStream BBS; -}; - -class WindowsResourceParser { -public: - class TreeNode; - WindowsResourceParser(bool MinGW = false); - Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates); - Error parse(ResourceSectionRef &RSR, StringRef Filename, - std::vector<std::string> &Duplicates); - void cleanUpManifests(std::vector<std::string> &Duplicates); - void printTree(raw_ostream &OS) const; - const TreeNode &getTree() const { return Root; } - const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } - const ArrayRef<std::vector<UTF16>> getStringTable() const { - return StringTable; - } - - class TreeNode { - public: - template <typename T> - using Children = std::map<T, std::unique_ptr<TreeNode>>; - - void print(ScopedPrinter &Writer, StringRef Name) const; - uint32_t getTreeSize() const; - uint32_t getStringIndex() const { return StringIndex; } - uint32_t getDataIndex() const { return DataIndex; } - uint16_t getMajorVersion() const { return MajorVersion; } - uint16_t getMinorVersion() const { return MinorVersion; } - uint32_t getCharacteristics() const { return Characteristics; } - bool checkIsDataNode() const { return IsDataNode; } - const Children<uint32_t> &getIDChildren() const { return IDChildren; } - const Children<std::string> &getStringChildren() const { - return StringChildren; - } - - private: - friend class WindowsResourceParser; - - // Index is the StringTable vector index for this node's name. - static std::unique_ptr<TreeNode> createStringNode(uint32_t Index); - static std::unique_ptr<TreeNode> createIDNode(); - // DataIndex is the Data vector index that the data node points at. - static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, - uint16_t MinorVersion, - uint32_t Characteristics, - uint32_t Origin, - uint32_t DataIndex); - - explicit TreeNode(uint32_t StringIndex); - TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, - uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex); - - bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin, - std::vector<std::vector<uint8_t>> &Data, - std::vector<std::vector<UTF16>> &StringTable, - TreeNode *&Result); - TreeNode &addTypeNode(const ResourceEntryRef &Entry, - std::vector<std::vector<UTF16>> &StringTable); - TreeNode &addNameNode(const ResourceEntryRef &Entry, - std::vector<std::vector<UTF16>> &StringTable); - bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin, - std::vector<std::vector<uint8_t>> &Data, - TreeNode *&Result); - bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion, - uint32_t Characteristics, uint32_t Origin, - uint32_t DataIndex, TreeNode *&Result); - TreeNode &addIDChild(uint32_t ID); - TreeNode &addNameChild(ArrayRef<UTF16> NameRef, - std::vector<std::vector<UTF16>> &StringTable); - void shiftDataIndexDown(uint32_t Index); - - bool IsDataNode = false; - uint32_t StringIndex; - uint32_t DataIndex; - Children<uint32_t> IDChildren; - Children<std::string> StringChildren; - uint16_t MajorVersion = 0; - uint16_t MinorVersion = 0; - uint32_t Characteristics = 0; - - // The .res file that defined this TreeNode, for diagnostics. - // Index into InputFilenames. - uint32_t Origin; - }; - - struct StringOrID { - bool IsString; - ArrayRef<UTF16> String; - uint32_t ID; - - StringOrID(uint32_t ID) : IsString(false), ID(ID) {} - StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {} - }; - -private: - Error addChildren(TreeNode &Node, ResourceSectionRef &RSR, - const coff_resource_dir_table &Table, uint32_t Origin, - std::vector<StringOrID> &Context, - std::vector<std::string> &Duplicates); - bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const; - bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const; - - TreeNode Root; - std::vector<std::vector<uint8_t>> Data; - std::vector<std::vector<UTF16>> StringTable; - - std::vector<std::string> InputFilenames; - - bool MinGW; -}; - -Expected<std::unique_ptr<MemoryBuffer>> -writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, - const WindowsResourceParser &Parser, - uint32_t TimeDateStamp); - -void printResourceTypeName(uint16_t TypeID, raw_ostream &OS); -} // namespace object -} // namespace llvm - -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- WindowsResource.h ---------------------------------------*- C++-*-===// +// +// 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 +// +//===---------------------------------------------------------------------===// +// +// This file declares the .res file class. .res files are intermediate +// products of the typical resource-compilation process on Windows. This +// process is as follows: +// +// .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file +// +// .rc files are human-readable scripts that list all resources a program uses. +// +// They are compiled into .res files, which are a list of the resources in +// binary form. +// +// Finally the data stored in the .res is compiled into a COFF file, where it +// is organized in a directory tree structure for optimized access by the +// program during runtime. +// +// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx +// +//===---------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H +#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +#include <map> + +namespace llvm { + +class raw_ostream; +class ScopedPrinter; + +namespace object { + +class WindowsResource; +class ResourceSectionRef; + +const size_t WIN_RES_MAGIC_SIZE = 16; +const size_t WIN_RES_NULL_ENTRY_SIZE = 16; +const uint32_t WIN_RES_HEADER_ALIGNMENT = 4; +const uint32_t WIN_RES_DATA_ALIGNMENT = 4; +const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030; + +struct WinResHeaderPrefix { + support::ulittle32_t DataSize; + support::ulittle32_t HeaderSize; +}; + +// Type and Name may each either be an integer ID or a string. This struct is +// only used in the case where they are both IDs. +struct WinResIDs { + uint16_t TypeFlag; + support::ulittle16_t TypeID; + uint16_t NameFlag; + support::ulittle16_t NameID; + + void setType(uint16_t ID) { + TypeFlag = 0xffff; + TypeID = ID; + } + + void setName(uint16_t ID) { + NameFlag = 0xffff; + NameID = ID; + } +}; + +struct WinResHeaderSuffix { + support::ulittle32_t DataVersion; + support::ulittle16_t MemoryFlags; + support::ulittle16_t Language; + support::ulittle32_t Version; + support::ulittle32_t Characteristics; +}; + +class EmptyResError : public GenericBinaryError { +public: + EmptyResError(Twine Msg, object_error ECOverride) + : GenericBinaryError(Msg, ECOverride) {} +}; + +class ResourceEntryRef { +public: + Error moveNext(bool &End); + bool checkTypeString() const { return IsStringType; } + ArrayRef<UTF16> getTypeString() const { return Type; } + uint16_t getTypeID() const { return TypeID; } + bool checkNameString() const { return IsStringName; } + ArrayRef<UTF16> getNameString() const { return Name; } + uint16_t getNameID() const { return NameID; } + uint16_t getDataVersion() const { return Suffix->DataVersion; } + uint16_t getLanguage() const { return Suffix->Language; } + uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; } + uint16_t getMajorVersion() const { return Suffix->Version >> 16; } + uint16_t getMinorVersion() const { return Suffix->Version; } + uint32_t getCharacteristics() const { return Suffix->Characteristics; } + ArrayRef<uint8_t> getData() const { return Data; } + +private: + friend class WindowsResource; + + ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner); + Error loadNext(); + + static Expected<ResourceEntryRef> create(BinaryStreamRef Ref, + const WindowsResource *Owner); + + BinaryStreamReader Reader; + const WindowsResource *Owner; + bool IsStringType; + ArrayRef<UTF16> Type; + uint16_t TypeID; + bool IsStringName; + ArrayRef<UTF16> Name; + uint16_t NameID; + const WinResHeaderSuffix *Suffix = nullptr; + ArrayRef<uint8_t> Data; +}; + +class WindowsResource : public Binary { +public: + Expected<ResourceEntryRef> getHeadEntry(); + + static bool classof(const Binary *V) { return V->isWinRes(); } + + static Expected<std::unique_ptr<WindowsResource>> + createWindowsResource(MemoryBufferRef Source); + +private: + friend class ResourceEntryRef; + + WindowsResource(MemoryBufferRef Source); + + BinaryByteStream BBS; +}; + +class WindowsResourceParser { +public: + class TreeNode; + WindowsResourceParser(bool MinGW = false); + Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates); + Error parse(ResourceSectionRef &RSR, StringRef Filename, + std::vector<std::string> &Duplicates); + void cleanUpManifests(std::vector<std::string> &Duplicates); + void printTree(raw_ostream &OS) const; + const TreeNode &getTree() const { return Root; } + const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } + const ArrayRef<std::vector<UTF16>> getStringTable() const { + return StringTable; + } + + class TreeNode { + public: + template <typename T> + using Children = std::map<T, std::unique_ptr<TreeNode>>; + + void print(ScopedPrinter &Writer, StringRef Name) const; + uint32_t getTreeSize() const; + uint32_t getStringIndex() const { return StringIndex; } + uint32_t getDataIndex() const { return DataIndex; } + uint16_t getMajorVersion() const { return MajorVersion; } + uint16_t getMinorVersion() const { return MinorVersion; } + uint32_t getCharacteristics() const { return Characteristics; } + bool checkIsDataNode() const { return IsDataNode; } + const Children<uint32_t> &getIDChildren() const { return IDChildren; } + const Children<std::string> &getStringChildren() const { + return StringChildren; + } + + private: + friend class WindowsResourceParser; + + // Index is the StringTable vector index for this node's name. + static std::unique_ptr<TreeNode> createStringNode(uint32_t Index); + static std::unique_ptr<TreeNode> createIDNode(); + // DataIndex is the Data vector index that the data node points at. + static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, + uint16_t MinorVersion, + uint32_t Characteristics, + uint32_t Origin, + uint32_t DataIndex); + + explicit TreeNode(uint32_t StringIndex); + TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, + uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex); + + bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin, + std::vector<std::vector<uint8_t>> &Data, + std::vector<std::vector<UTF16>> &StringTable, + TreeNode *&Result); + TreeNode &addTypeNode(const ResourceEntryRef &Entry, + std::vector<std::vector<UTF16>> &StringTable); + TreeNode &addNameNode(const ResourceEntryRef &Entry, + std::vector<std::vector<UTF16>> &StringTable); + bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin, + std::vector<std::vector<uint8_t>> &Data, + TreeNode *&Result); + bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion, + uint32_t Characteristics, uint32_t Origin, + uint32_t DataIndex, TreeNode *&Result); + TreeNode &addIDChild(uint32_t ID); + TreeNode &addNameChild(ArrayRef<UTF16> NameRef, + std::vector<std::vector<UTF16>> &StringTable); + void shiftDataIndexDown(uint32_t Index); + + bool IsDataNode = false; + uint32_t StringIndex; + uint32_t DataIndex; + Children<uint32_t> IDChildren; + Children<std::string> StringChildren; + uint16_t MajorVersion = 0; + uint16_t MinorVersion = 0; + uint32_t Characteristics = 0; + + // The .res file that defined this TreeNode, for diagnostics. + // Index into InputFilenames. + uint32_t Origin; + }; + + struct StringOrID { + bool IsString; + ArrayRef<UTF16> String; + uint32_t ID; + + StringOrID(uint32_t ID) : IsString(false), ID(ID) {} + StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {} + }; + +private: + Error addChildren(TreeNode &Node, ResourceSectionRef &RSR, + const coff_resource_dir_table &Table, uint32_t Origin, + std::vector<StringOrID> &Context, + std::vector<std::string> &Duplicates); + bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const; + bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const; + + TreeNode Root; + std::vector<std::vector<uint8_t>> Data; + std::vector<std::vector<UTF16>> StringTable; + + std::vector<std::string> InputFilenames; + + bool MinGW; +}; + +Expected<std::unique_ptr<MemoryBuffer>> +writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, + const WindowsResourceParser &Parser, + uint32_t TimeDateStamp); + +void printResourceTypeName(uint16_t TypeID, raw_ostream &OS); +} // namespace object +} // namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h index ba11d43c43d..87f5ef02429 100644 --- a/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h @@ -1,407 +1,407 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares the XCOFFObjectFile class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H -#define LLVM_OBJECT_XCOFFOBJECTFILE_H - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the XCOFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H +#define LLVM_OBJECT_XCOFFOBJECTFILE_H + #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/BinaryFormat/XCOFF.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Endian.h" -#include <limits> - -namespace llvm { -namespace object { - -struct XCOFFFileHeader32 { - support::ubig16_t Magic; - support::ubig16_t NumberOfSections; - - // Unix time value, value of 0 indicates no timestamp. - // Negative values are reserved. - support::big32_t TimeStamp; - - support::ubig32_t SymbolTableOffset; // File offset to symbol table. - support::big32_t NumberOfSymTableEntries; - support::ubig16_t AuxHeaderSize; - support::ubig16_t Flags; -}; - -struct XCOFFFileHeader64 { - support::ubig16_t Magic; - support::ubig16_t NumberOfSections; - - // Unix time value, value of 0 indicates no timestamp. - // Negative values are reserved. - support::big32_t TimeStamp; - - support::ubig64_t SymbolTableOffset; // File offset to symbol table. - support::ubig16_t AuxHeaderSize; - support::ubig16_t Flags; - support::ubig32_t NumberOfSymTableEntries; -}; - -template <typename T> struct XCOFFSectionHeader { - // Least significant 3 bits are reserved. - static constexpr unsigned SectionFlagsReservedMask = 0x7; - - // The low order 16 bits of section flags denotes the section type. - static constexpr unsigned SectionFlagsTypeMask = 0xffffu; - -public: - StringRef getName() const; - uint16_t getSectionType() const; - bool isReservedSectionType() const; -}; - -// Explicit extern template declarations. -struct XCOFFSectionHeader32; -struct XCOFFSectionHeader64; -extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>; -extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>; - -struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> { - char Name[XCOFF::NameSize]; - support::ubig32_t PhysicalAddress; - support::ubig32_t VirtualAddress; - support::ubig32_t SectionSize; - support::ubig32_t FileOffsetToRawData; - support::ubig32_t FileOffsetToRelocationInfo; - support::ubig32_t FileOffsetToLineNumberInfo; - support::ubig16_t NumberOfRelocations; - support::ubig16_t NumberOfLineNumbers; - support::big32_t Flags; -}; - -struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> { - char Name[XCOFF::NameSize]; - support::ubig64_t PhysicalAddress; - support::ubig64_t VirtualAddress; - support::ubig64_t SectionSize; - support::big64_t FileOffsetToRawData; - support::big64_t FileOffsetToRelocationInfo; - support::big64_t FileOffsetToLineNumberInfo; - support::ubig32_t NumberOfRelocations; - support::ubig32_t NumberOfLineNumbers; - support::big32_t Flags; - char Padding[4]; -}; - -struct XCOFFSymbolEntry { - enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; - typedef struct { - support::big32_t Magic; // Zero indicates name in string table. - support::ubig32_t Offset; - } NameInStrTblType; - - typedef struct { - uint8_t LanguageId; - uint8_t CpuTypeId; - } CFileLanguageIdAndTypeIdType; - - union { - char SymbolName[XCOFF::NameSize]; - NameInStrTblType NameInStrTbl; - }; - - support::ubig32_t Value; // Symbol value; storage class-dependent. - support::big16_t SectionNumber; - - union { - support::ubig16_t SymbolType; - CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; - }; - - XCOFF::StorageClass StorageClass; - uint8_t NumberOfAuxEntries; -}; - -struct XCOFFStringTable { - uint32_t Size; - const char *Data; -}; - -struct XCOFFCsectAuxEnt32 { - static constexpr uint8_t SymbolTypeMask = 0x07; - static constexpr uint8_t SymbolAlignmentMask = 0xF8; - static constexpr size_t SymbolAlignmentBitOffset = 3; - - support::ubig32_t - SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect - // length. - // If the symbol type is XTY_LD, the symbol table - // index of the containing csect. - // If the symbol type is XTY_ER, 0. - support::ubig32_t ParameterHashIndex; - support::ubig16_t TypeChkSectNum; - uint8_t SymbolAlignmentAndType; - XCOFF::StorageMappingClass StorageMappingClass; - support::ubig32_t StabInfoIndex; - support::ubig16_t StabSectNum; - - uint16_t getAlignmentLog2() const { - return (SymbolAlignmentAndType & SymbolAlignmentMask) >> - SymbolAlignmentBitOffset; - } - - uint8_t getSymbolType() const { - return SymbolAlignmentAndType & SymbolTypeMask; - } - - bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } -}; - -struct XCOFFFileAuxEnt { - typedef struct { - support::big32_t Magic; // Zero indicates name in string table. - support::ubig32_t Offset; - char NamePad[XCOFF::FileNamePadSize]; - } NameInStrTblType; - union { - char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; - NameInStrTblType NameInStrTbl; - }; - XCOFF::CFileStringType Type; - uint8_t ReservedZeros[2]; - uint8_t AuxType; // 64-bit XCOFF file only. -}; - -struct XCOFFSectAuxEntForStat { - support::ubig32_t SectionLength; - support::ubig16_t NumberOfRelocEnt; - support::ubig16_t NumberOfLineNum; - uint8_t Pad[10]; -}; - -struct XCOFFRelocation32 { - // Masks for packing/unpacking the r_rsize field of relocations. - - // The msb is used to indicate if the bits being relocated are signed or - // unsigned. - static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80; - - // The 2nd msb is used to indicate that the binder has replaced/modified the - // original instruction. - static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40; - - // The remaining bits specify the bit length of the relocatable reference - // minus one. - static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f; - -public: - support::ubig32_t VirtualAddress; - support::ubig32_t SymbolIndex; - - // Packed field, see XR_* masks for details of packing. - uint8_t Info; - - XCOFF::RelocationType Type; - -public: - bool isRelocationSigned() const; - bool isFixupIndicated() const; - - // Returns the number of bits being relocated. - uint8_t getRelocatedLength() const; -}; - -class XCOFFObjectFile : public ObjectFile { -private: - const void *FileHeader = nullptr; - const void *SectionHeaderTable = nullptr; - - const XCOFFSymbolEntry *SymbolTblPtr = nullptr; - XCOFFStringTable StringTable = {0, nullptr}; - - const XCOFFFileHeader32 *fileHeader32() const; - const XCOFFFileHeader64 *fileHeader64() const; - - const XCOFFSectionHeader32 *sectionHeaderTable32() const; - const XCOFFSectionHeader64 *sectionHeaderTable64() const; - - size_t getFileHeaderSize() const; - size_t getSectionHeaderSize() const; - - const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; - const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; - uintptr_t getSectionHeaderTableAddress() const; - uintptr_t getEndOfSymbolTableAddress() const; - - // This returns a pointer to the start of the storage for the name field of - // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily - // null-terminated. - const char *getSectionNameInternal(DataRefImpl Sec) const; - - // This function returns string table entry. - Expected<StringRef> getStringTableEntry(uint32_t Offset) const; - - static bool isReservedSectionNumber(int16_t SectionNumber); - - // Constructor and "create" factory function. The constructor is only a thin - // wrapper around the base constructor. The "create" function fills out the - // XCOFF-specific information and performs the error checking along the way. - XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); - static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, - MemoryBufferRef MBR); - - // Helper for parsing the StringTable. Returns an 'Error' if parsing failed - // and an XCOFFStringTable if parsing succeeded. - static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, - uint64_t Offset); - - // Make a friend so it can call the private 'create' function. - friend Expected<std::unique_ptr<ObjectFile>> - ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); - - void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; - -public: - static constexpr uint64_t InvalidRelocOffset = - std::numeric_limits<uint64_t>::max(); - - // Interface inherited from base classes. - void moveSymbolNext(DataRefImpl &Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - - bool isSectionVirtual(DataRefImpl Sec) const override; - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - - void moveRelocationNext(DataRefImpl &Rel) const override; - - /// \returns the relocation offset with the base address of the containing - /// section as zero, or InvalidRelocOffset on errors (such as a relocation - /// that does not refer to an address in any section). - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - - section_iterator section_begin() const override; - section_iterator section_end() const override; - uint8_t getBytesInAddress() const override; - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override; - Expected<uint64_t> getStartAddress() const override; - bool isRelocatableObject() const override; - - // Below here is the non-inherited interface. - bool is64Bit() const; - - const XCOFFSymbolEntry *getPointerToSymbolTable() const { - assert(!is64Bit() && "Symbol table handling not supported yet."); - return SymbolTblPtr; - } - - Expected<StringRef> - getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const; - - const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const; - - // File header related interfaces. - uint16_t getMagic() const; - uint16_t getNumberOfSections() const; - int32_t getTimeStamp() const; - - // Symbol table offset and entry count are handled differently between - // XCOFF32 and XCOFF64. - uint32_t getSymbolTableOffset32() const; - uint64_t getSymbolTableOffset64() const; - - // Note that this value is signed and might return a negative value. Negative - // values are reserved for future use. - int32_t getRawNumberOfSymbolTableEntries32() const; - - // The sanitized value appropriate to use as an index into the symbol table. - uint32_t getLogicalNumberOfSymbolTableEntries32() const; - - uint32_t getNumberOfSymbolTableEntries64() const; - uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; - Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const; - - Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; - uint16_t getOptionalHeaderSize() const; - uint16_t getFlags() const; - - // Section header table related interfaces. - ArrayRef<XCOFFSectionHeader32> sections32() const; - ArrayRef<XCOFFSectionHeader64> sections64() const; - - int32_t getSectionFlags(DataRefImpl Sec) const; - Expected<DataRefImpl> getSectionByNum(int16_t Num) const; - - void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; - - // Relocation-related interfaces. - Expected<uint32_t> - getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const; - - Expected<ArrayRef<XCOFFRelocation32>> - relocations(const XCOFFSectionHeader32 &) const; +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Endian.h" +#include <limits> + +namespace llvm { +namespace object { + +struct XCOFFFileHeader32 { + support::ubig16_t Magic; + support::ubig16_t NumberOfSections; + + // Unix time value, value of 0 indicates no timestamp. + // Negative values are reserved. + support::big32_t TimeStamp; + + support::ubig32_t SymbolTableOffset; // File offset to symbol table. + support::big32_t NumberOfSymTableEntries; + support::ubig16_t AuxHeaderSize; + support::ubig16_t Flags; +}; + +struct XCOFFFileHeader64 { + support::ubig16_t Magic; + support::ubig16_t NumberOfSections; + + // Unix time value, value of 0 indicates no timestamp. + // Negative values are reserved. + support::big32_t TimeStamp; + + support::ubig64_t SymbolTableOffset; // File offset to symbol table. + support::ubig16_t AuxHeaderSize; + support::ubig16_t Flags; + support::ubig32_t NumberOfSymTableEntries; +}; + +template <typename T> struct XCOFFSectionHeader { + // Least significant 3 bits are reserved. + static constexpr unsigned SectionFlagsReservedMask = 0x7; + + // The low order 16 bits of section flags denotes the section type. + static constexpr unsigned SectionFlagsTypeMask = 0xffffu; + +public: + StringRef getName() const; + uint16_t getSectionType() const; + bool isReservedSectionType() const; +}; + +// Explicit extern template declarations. +struct XCOFFSectionHeader32; +struct XCOFFSectionHeader64; +extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>; +extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>; + +struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> { + char Name[XCOFF::NameSize]; + support::ubig32_t PhysicalAddress; + support::ubig32_t VirtualAddress; + support::ubig32_t SectionSize; + support::ubig32_t FileOffsetToRawData; + support::ubig32_t FileOffsetToRelocationInfo; + support::ubig32_t FileOffsetToLineNumberInfo; + support::ubig16_t NumberOfRelocations; + support::ubig16_t NumberOfLineNumbers; + support::big32_t Flags; +}; + +struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> { + char Name[XCOFF::NameSize]; + support::ubig64_t PhysicalAddress; + support::ubig64_t VirtualAddress; + support::ubig64_t SectionSize; + support::big64_t FileOffsetToRawData; + support::big64_t FileOffsetToRelocationInfo; + support::big64_t FileOffsetToLineNumberInfo; + support::ubig32_t NumberOfRelocations; + support::ubig32_t NumberOfLineNumbers; + support::big32_t Flags; + char Padding[4]; +}; + +struct XCOFFSymbolEntry { + enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; + typedef struct { + support::big32_t Magic; // Zero indicates name in string table. + support::ubig32_t Offset; + } NameInStrTblType; + + typedef struct { + uint8_t LanguageId; + uint8_t CpuTypeId; + } CFileLanguageIdAndTypeIdType; + + union { + char SymbolName[XCOFF::NameSize]; + NameInStrTblType NameInStrTbl; + }; + + support::ubig32_t Value; // Symbol value; storage class-dependent. + support::big16_t SectionNumber; + + union { + support::ubig16_t SymbolType; + CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; + }; + + XCOFF::StorageClass StorageClass; + uint8_t NumberOfAuxEntries; +}; + +struct XCOFFStringTable { + uint32_t Size; + const char *Data; +}; + +struct XCOFFCsectAuxEnt32 { + static constexpr uint8_t SymbolTypeMask = 0x07; + static constexpr uint8_t SymbolAlignmentMask = 0xF8; + static constexpr size_t SymbolAlignmentBitOffset = 3; + + support::ubig32_t + SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect + // length. + // If the symbol type is XTY_LD, the symbol table + // index of the containing csect. + // If the symbol type is XTY_ER, 0. + support::ubig32_t ParameterHashIndex; + support::ubig16_t TypeChkSectNum; + uint8_t SymbolAlignmentAndType; + XCOFF::StorageMappingClass StorageMappingClass; + support::ubig32_t StabInfoIndex; + support::ubig16_t StabSectNum; + + uint16_t getAlignmentLog2() const { + return (SymbolAlignmentAndType & SymbolAlignmentMask) >> + SymbolAlignmentBitOffset; + } + + uint8_t getSymbolType() const { + return SymbolAlignmentAndType & SymbolTypeMask; + } + + bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } +}; + +struct XCOFFFileAuxEnt { + typedef struct { + support::big32_t Magic; // Zero indicates name in string table. + support::ubig32_t Offset; + char NamePad[XCOFF::FileNamePadSize]; + } NameInStrTblType; + union { + char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; + NameInStrTblType NameInStrTbl; + }; + XCOFF::CFileStringType Type; + uint8_t ReservedZeros[2]; + uint8_t AuxType; // 64-bit XCOFF file only. +}; + +struct XCOFFSectAuxEntForStat { + support::ubig32_t SectionLength; + support::ubig16_t NumberOfRelocEnt; + support::ubig16_t NumberOfLineNum; + uint8_t Pad[10]; +}; + +struct XCOFFRelocation32 { + // Masks for packing/unpacking the r_rsize field of relocations. + + // The msb is used to indicate if the bits being relocated are signed or + // unsigned. + static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80; + + // The 2nd msb is used to indicate that the binder has replaced/modified the + // original instruction. + static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40; + + // The remaining bits specify the bit length of the relocatable reference + // minus one. + static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f; + +public: + support::ubig32_t VirtualAddress; + support::ubig32_t SymbolIndex; + + // Packed field, see XR_* masks for details of packing. + uint8_t Info; + + XCOFF::RelocationType Type; + +public: + bool isRelocationSigned() const; + bool isFixupIndicated() const; + + // Returns the number of bits being relocated. + uint8_t getRelocatedLength() const; +}; + +class XCOFFObjectFile : public ObjectFile { +private: + const void *FileHeader = nullptr; + const void *SectionHeaderTable = nullptr; + + const XCOFFSymbolEntry *SymbolTblPtr = nullptr; + XCOFFStringTable StringTable = {0, nullptr}; + + const XCOFFFileHeader32 *fileHeader32() const; + const XCOFFFileHeader64 *fileHeader64() const; + + const XCOFFSectionHeader32 *sectionHeaderTable32() const; + const XCOFFSectionHeader64 *sectionHeaderTable64() const; + + size_t getFileHeaderSize() const; + size_t getSectionHeaderSize() const; + + const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; + const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; + uintptr_t getSectionHeaderTableAddress() const; + uintptr_t getEndOfSymbolTableAddress() const; + + // This returns a pointer to the start of the storage for the name field of + // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily + // null-terminated. + const char *getSectionNameInternal(DataRefImpl Sec) const; + + // This function returns string table entry. + Expected<StringRef> getStringTableEntry(uint32_t Offset) const; + + static bool isReservedSectionNumber(int16_t SectionNumber); + + // Constructor and "create" factory function. The constructor is only a thin + // wrapper around the base constructor. The "create" function fills out the + // XCOFF-specific information and performs the error checking along the way. + XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); + static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, + MemoryBufferRef MBR); + + // Helper for parsing the StringTable. Returns an 'Error' if parsing failed + // and an XCOFFStringTable if parsing succeeded. + static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, + uint64_t Offset); + + // Make a friend so it can call the private 'create' function. + friend Expected<std::unique_ptr<ObjectFile>> + ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); + + void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; + +public: + static constexpr uint64_t InvalidRelocOffset = + std::numeric_limits<uint64_t>::max(); + + // Interface inherited from base classes. + void moveSymbolNext(DataRefImpl &Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + + bool isSectionVirtual(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + + /// \returns the relocation offset with the base address of the containing + /// section as zero, or InvalidRelocOffset on errors (such as a relocation + /// that does not refer to an address in any section). + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + SubtargetFeatures getFeatures() const override; + Expected<uint64_t> getStartAddress() const override; + bool isRelocatableObject() const override; + + // Below here is the non-inherited interface. + bool is64Bit() const; + + const XCOFFSymbolEntry *getPointerToSymbolTable() const { + assert(!is64Bit() && "Symbol table handling not supported yet."); + return SymbolTblPtr; + } + + Expected<StringRef> + getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const; + + const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const; + + // File header related interfaces. + uint16_t getMagic() const; + uint16_t getNumberOfSections() const; + int32_t getTimeStamp() const; + + // Symbol table offset and entry count are handled differently between + // XCOFF32 and XCOFF64. + uint32_t getSymbolTableOffset32() const; + uint64_t getSymbolTableOffset64() const; + + // Note that this value is signed and might return a negative value. Negative + // values are reserved for future use. + int32_t getRawNumberOfSymbolTableEntries32() const; + + // The sanitized value appropriate to use as an index into the symbol table. + uint32_t getLogicalNumberOfSymbolTableEntries32() const; + + uint32_t getNumberOfSymbolTableEntries64() const; + uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; + Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const; + + Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; + uint16_t getOptionalHeaderSize() const; + uint16_t getFlags() const; + + // Section header table related interfaces. + ArrayRef<XCOFFSectionHeader32> sections32() const; + ArrayRef<XCOFFSectionHeader64> sections64() const; + + int32_t getSectionFlags(DataRefImpl Sec) const; + Expected<DataRefImpl> getSectionByNum(int16_t Num) const; + + void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; + + // Relocation-related interfaces. + Expected<uint32_t> + getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const; + + Expected<ArrayRef<XCOFFRelocation32>> + relocations(const XCOFFSectionHeader32 &) const; static bool classof(const Binary *B) { return B->isXCOFF(); } -}; // XCOFFObjectFile - -class XCOFFSymbolRef { - const DataRefImpl SymEntDataRef; - const XCOFFObjectFile *const OwningObjectPtr; - -public: - XCOFFSymbolRef(DataRefImpl SymEntDataRef, - const XCOFFObjectFile *OwningObjectPtr) - : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){}; - - XCOFF::StorageClass getStorageClass() const; - uint8_t getNumberOfAuxEntries() const; - const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const; - uint16_t getType() const; - int16_t getSectionNumber() const; - - bool hasCsectAuxEnt() const; - bool isFunction() const; -}; - +}; // XCOFFObjectFile + +class XCOFFSymbolRef { + const DataRefImpl SymEntDataRef; + const XCOFFObjectFile *const OwningObjectPtr; + +public: + XCOFFSymbolRef(DataRefImpl SymEntDataRef, + const XCOFFObjectFile *OwningObjectPtr) + : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){}; + + XCOFF::StorageClass getStorageClass() const; + uint8_t getNumberOfAuxEntries() const; + const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const; + uint16_t getType() const; + int16_t getSectionNumber() const; + + bool hasCsectAuxEnt() const; + bool isFunction() const; +}; + class TBVectorExt { friend class XCOFFTracebackTable; @@ -499,11 +499,11 @@ public: }; bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes); -} // namespace object -} // namespace llvm - -#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |
