summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/include/llvm/Object
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/llvm12/include/llvm/Object
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/Object')
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Archive.h297
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h61
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Binary.h253
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/COFF.h1291
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h124
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h63
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h65
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Decompressor.h77
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ELF.h1211
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h1316
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ELFTypes.h805
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Error.h105
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h102
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/IRSymtab.h385
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/MachO.h750
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h183
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/MachOUniversalWriter.h113
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Minidump.h227
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h84
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/ObjectFile.h603
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h59
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/StackMapParser.h478
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/SymbolSize.h44
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h224
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/TapiFile.h74
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h132
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/Wasm.h381
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h44
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/WindowsResource.h282
-rw-r--r--contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h509
30 files changed, 10342 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/include/llvm/Object/Archive.h b/contrib/libs/llvm12/include/llvm/Object/Archive.h
new file mode 100644
index 00000000000..b6b1a126ac3
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Archive.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h b/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h
new file mode 100644
index 00000000000..a2c582c4804
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ArchiveWriter.h
@@ -0,0 +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);
+
+// 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/Binary.h b/contrib/libs/llvm12/include/llvm/Object/Binary.h
new file mode 100644
index 00000000000..0b1ee8456bb
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Binary.h
@@ -0,0 +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();
+
+ 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 ||
+ 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,
+ 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();
+}
+
+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
diff --git a/contrib/libs/llvm12/include/llvm/Object/COFF.h b/contrib/libs/llvm12/include/llvm/Object/COFF.h
new file mode 100644
index 00000000000..816a078cfcd
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/COFF.h
@@ -0,0 +1,1291 @@
+#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;
+ }
+
+ void setAlignment(uint32_t Align) {
+ uint32_t AlignBits = 0;
+ if (Align) {
+ assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2");
+ assert(llvm::Log2_32(Align) <= 13 && "alignment requested is too large");
+ AlignBits = (llvm::Log2_32(Align) + 1) << 20;
+ }
+ 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;
+ 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();
+ 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());
+ }
+
+ const coff_tls_directory32 *getTLSDirectory32() const {
+ return TLSDirectory32;
+ }
+ const coff_tls_directory64 *getTLSDirectory64() const {
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h b/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h
new file mode 100644
index 00000000000..d5d5a369dff
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/COFFImportFile.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h b/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h
new file mode 100644
index 00000000000..3661c193331
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/COFFModuleDefinition.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h b/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h
new file mode 100644
index 00000000000..17685635bfd
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/CVDebugRecord.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/Decompressor.h b/contrib/libs/llvm12/include/llvm/Object/Decompressor.h
new file mode 100644
index 00000000000..92409641e48
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Decompressor.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ELF.h b/contrib/libs/llvm12/include/llvm/Object/ELF.h
new file mode 100644
index 00000000000..20e25a9ee28
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ELF.h
@@ -0,0 +1,1211 @@
+#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;
+};
+
+struct VerDef {
+ unsigned Offset;
+ unsigned Version;
+ unsigned Flags;
+ unsigned Ndx;
+ unsigned Cnt;
+ unsigned Hash;
+ std::string Name;
+ std::vector<VerdAux> AuxV;
+};
+
+struct VernAux {
+ unsigned Hash;
+ unsigned Flags;
+ unsigned Other;
+ unsigned Offset;
+ std::string Name;
+};
+
+struct VerNeed {
+ unsigned Version;
+ unsigned Cnt;
+ unsigned Offset;
+ std::string File;
+ std::vector<VernAux> AuxV;
+};
+
+struct VersionEntry {
+ std::string Name;
+ 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);
+}
+
+enum PPCInstrMasks : uint64_t {
+ PADDI_R12_NO_DISP = 0x0610000039800000,
+ PLD_R12_NO_DISP = 0x04100000E5800000,
+ MTCTR_R12 = 0x7D8903A6,
+ BCTR = 0x4E800420,
+};
+
+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.
+ DataRegion(ArrayRef<T> Arr) : First(Arr.data()), Size(Arr.size()) {}
+
+ // Sometimes we only know the start of a data region. We still don't want to
+ // read past the end of the file, so we provide the end of a buffer.
+ DataRegion(const T *Data, const uint8_t *BufferEnd)
+ : First(Data), BufEnd(BufferEnd) {}
+
+ Expected<T> operator[](uint64_t N) {
+ assert(Size || BufEnd);
+ if (Size) {
+ if (N >= *Size)
+ return createError(
+ "the index is greater than or equal to the number of entries (" +
+ Twine(*Size) + ")");
+ } else {
+ const uint8_t *EntryStart = (const uint8_t *)First + N * sizeof(T);
+ if (EntryStart + sizeof(T) > BufEnd)
+ return createError("can't read past the end of the file");
+ }
+ return *(First + N);
+ }
+
+ const T *First;
+ Optional<uint64_t> Size = None;
+ const uint8_t *BufEnd = nullptr;
+};
+
+template <class ELFT>
+std::string getSecIndexForError(const ELFFile<ELFT> &Obj,
+ const typename ELFT::Shdr &Sec) {
+ auto TableOrErr = Obj.sections();
+ 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>
+static std::string describe(const ELFFile<ELFT> &Obj,
+ const typename ELFT::Shdr &Sec) {
+ unsigned SecNdx = &Sec - &cantFail(Obj.sections()).front();
+ return (object::getELFSectionTypeName(Obj.getHeader().e_machine,
+ Sec.sh_type) +
+ " section with index " + Twine(SecNdx))
+ .str();
+}
+
+template <class ELFT>
+std::string getPhdrIndexForError(const ELFFile<ELFT> &Obj,
+ const typename ELFT::Phdr &Phdr) {
+ auto Headers = Obj.program_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(); }
+ const uint8_t *end() const { return base() + getBufSize(); }
+
+ 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>
+ 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>
+ 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;
+ 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<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.
+ Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel &Rel,
+ 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 {
+ return getHeader().getDataEncoding() == ELF::ELFDATA2LSB;
+ }
+
+ 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;
+
+ 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);
+ return getSectionContentsAsArray<Elf_Sym>(*Sec);
+ }
+
+ Expected<Elf_Rela_Range> relas(const Elf_Shdr &Sec) const {
+ return getSectionContentsAsArray<Elf_Rela>(Sec);
+ }
+
+ Expected<Elf_Rel_Range> rels(const Elf_Shdr &Sec) const {
+ return getSectionContentsAsArray<Elf_Rel>(Sec);
+ }
+
+ Expected<Elf_Relr_Range> relrs(const Elf_Shdr &Sec) const {
+ 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 {
+ if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr))
+ return createError("invalid e_phentsize: " +
+ Twine(getHeader().e_phentsize));
+
+ 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" +
+ 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);
+ 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()) {
+ 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()) {
+ 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;
+ 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,
+ DataRegion<Elf_Word> ShndxTable) const;
+ Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym,
+ 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>
+ getSectionName(const Elf_Shdr &Section,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
+ Expected<StringRef> getSectionName(const Elf_Shdr &Section,
+ 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>
+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(
+ "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>
+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) {
+ 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 *>
+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 *>
+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 " +
+ getSecIndexForError(*this, *Sec) +
+ ": 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))
+ return createError("section " + getSecIndexForError(*this, Sec) +
+ " 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)
+ 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())
+ 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>>
+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)
+ 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())
+ 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>>
+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 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 {
+ return getELFRelativeRelocationType(getHeader().e_machine);
+}
+
+template <class ELFT>
+Expected<SmallVector<Optional<VersionEntry>, 0>>
+ELFFile<ELFT>::loadVersionMap(const Elf_Shdr *VerNeedSec,
+ const Elf_Shdr *VerDefSec) const {
+ SmallVector<Optional<VersionEntry>, 0> VersionMap;
+
+ // The first two version indexes are reserved.
+ // Index 0 is VER_NDX_LOCAL, index 1 is VER_NDX_GLOBAL.
+ VersionMap.push_back(VersionEntry());
+ VersionMap.push_back(VersionEntry());
+
+ auto InsertEntry = [&](unsigned N, StringRef Version, bool IsVerdef) {
+ if (N >= VersionMap.size())
+ VersionMap.resize(N + 1);
+ VersionMap[N] = {std::string(Version), IsVerdef};
+ };
+
+ if (VerDefSec) {
+ Expected<std::vector<VerDef>> Defs = getVersionDefinitions(*VerDefSec);
+ if (!Defs)
+ return Defs.takeError();
+ for (const VerDef &Def : *Defs)
+ InsertEntry(Def.Ndx & ELF::VERSYM_VERSION, Def.Name, true);
+ }
+
+ if (VerNeedSec) {
+ Expected<std::vector<VerNeed>> Deps = getVersionDependencies(*VerNeedSec);
+ if (!Deps)
+ return Deps.takeError();
+ for (const VerNeed &Dep : *Deps)
+ for (const VernAux &Aux : Dep.AuxV)
+ InsertEntry(Aux.Other & ELF::VERSYM_VERSION, Aux.Name, false);
+ }
+
+ return VersionMap;
+}
+
+template <class ELFT>
+Expected<const typename ELFT::Sym *>
+ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel &Rel,
+ const Elf_Shdr *SymTab) const {
+ uint32_t Index = Rel.getSymbol(isMips64EL());
+ 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 {
+ 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");
+ 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.
+template <class ELFT>
+static Expected<uint64_t>
+getDynSymtabSizeFromGnuHash(const typename ELFT::GnuHash &Table,
+ const void *BufEnd) {
+ using Elf_Word = typename ELFT::Word;
+ if (Table.nbuckets == 0)
+ return Table.symndx + 1;
+ uint64_t LastSymIdx = 0;
+ // Find the index of the first symbol in the last chain.
+ for (Elf_Word Val : Table.buckets())
+ LastSymIdx = std::max(LastSymIdx, (uint64_t)Val);
+ const Elf_Word *It =
+ reinterpret_cast<const Elf_Word *>(Table.values(LastSymIdx).end());
+ // Locate the end of the chain to find the last symbol index.
+ while (It < BufEnd && (*It & 1) == 0) {
+ ++LastSymIdx;
+ ++It;
+ }
+ if (It >= BufEnd) {
+ return createStringError(
+ object_error::parse_failed,
+ "no terminator found for GNU hash section before buffer end");
+ }
+ return LastSymIdx + 1;
+}
+
+/// This function determines the number of dynamic symbols. It reads section
+/// headers first. If section headers are not available, the number of
+/// symbols will be inferred by parsing dynamic hash tables.
+template <class ELFT>
+Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
+ // Read .dynsym section header first if available.
+ Expected<Elf_Shdr_Range> SectionsOrError = sections();
+ if (!SectionsOrError)
+ return SectionsOrError.takeError();
+ for (const Elf_Shdr &Sec : *SectionsOrError) {
+ if (Sec.sh_type == ELF::SHT_DYNSYM) {
+ if (Sec.sh_size % Sec.sh_entsize != 0) {
+ return createStringError(object_error::parse_failed,
+ "SHT_DYNSYM section has sh_size (" +
+ Twine(Sec.sh_size) + ") % sh_entsize (" +
+ Twine(Sec.sh_entsize) + ") that is not 0");
+ }
+ return Sec.sh_size / Sec.sh_entsize;
+ }
+ }
+
+ if (!SectionsOrError->empty()) {
+ // Section headers are available but .dynsym header is not found.
+ // Return 0 as .dynsym does not exist.
+ return 0;
+ }
+
+ // Section headers do not exist. Falling back to infer
+ // upper bound of .dynsym from .gnu.hash and .hash.
+ Expected<Elf_Dyn_Range> DynTable = dynamicEntries();
+ if (!DynTable)
+ return DynTable.takeError();
+ llvm::Optional<uint64_t> ElfHash;
+ llvm::Optional<uint64_t> ElfGnuHash;
+ for (const Elf_Dyn &Entry : *DynTable) {
+ switch (Entry.d_tag) {
+ case ELF::DT_HASH:
+ ElfHash = Entry.d_un.d_ptr;
+ break;
+ case ELF::DT_GNU_HASH:
+ ElfGnuHash = Entry.d_un.d_ptr;
+ break;
+ }
+ }
+ if (ElfGnuHash) {
+ Expected<const uint8_t *> TablePtr = toMappedAddr(*ElfGnuHash);
+ if (!TablePtr)
+ return TablePtr.takeError();
+ const Elf_GnuHash *Table =
+ reinterpret_cast<const Elf_GnuHash *>(TablePtr.get());
+ return getDynSymtabSizeFromGnuHash<ELFT>(*Table, this->Buf.bytes_end());
+ }
+
+ // Search SYSV hash table to try to find the upper bound of dynsym.
+ if (ElfHash) {
+ Expected<const uint8_t *> TablePtr = toMappedAddr(*ElfHash);
+ if (!TablePtr)
+ return TablePtr.takeError();
+ const Elf_Hash *Table = reinterpret_cast<const Elf_Hash *>(TablePtr.get());
+ return Table->nchain;
+ }
+ 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 {
+ const uintX_t SectionTableOffset = getHeader().e_shoff;
+ if (SectionTableOffset == 0)
+ return ArrayRef<Elf_Shdr>();
+
+ if (getHeader().e_shentsize != sizeof(Elf_Shdr))
+ 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);
+
+ 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();
+ return getEntry<T>(**SecOrErr, Entry);
+}
+
+template <class ELFT>
+template <typename T>
+Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr &Section,
+ uint32_t Entry) const {
+ Expected<ArrayRef<T>> EntriesOrErr = getSectionContentsAsArray<T>(Section);
+ if (!EntriesOrErr)
+ return EntriesOrErr.takeError();
+
+ ArrayRef<T> Arr = *EntriesOrErr;
+ if (Entry >= Arr.size())
+ return createError(
+ "can't read an entry at 0x" +
+ Twine::utohexstr(Entry * static_cast<uint64_t>(sizeof(T))) +
+ ": 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,
+ SmallVector<Optional<VersionEntry>, 0> &VersionMap,
+ Optional<bool> IsSymHidden) const {
+ size_t VersionIndex = SymbolVersionIndex & llvm::ELF::VERSYM_VERSION;
+
+ // Special markers for unversioned symbols.
+ if (VersionIndex == llvm::ELF::VER_NDX_LOCAL ||
+ VersionIndex == llvm::ELF::VER_NDX_GLOBAL) {
+ IsDefault = false;
+ return "";
+ }
+
+ // Lookup this symbol in the version table.
+ if (VersionIndex >= VersionMap.size() || !VersionMap[VersionIndex])
+ return createError("SHT_GNU_versym section refers to a version index " +
+ Twine(VersionIndex) + " which is missing");
+
+ const VersionEntry &Entry = *VersionMap[VersionIndex];
+ // A default version (@@) is only available for defined symbols.
+ if (!Entry.IsVerDef || IsSymHidden.getValueOr(false))
+ IsDefault = false;
+ else
+ IsDefault = !(SymbolVersionIndex & llvm::ELF::VERSYM_HIDDEN);
+ return Entry.Name.c_str();
+}
+
+template <class ELFT>
+Expected<std::vector<VerDef>>
+ELFFile<ELFT>::getVersionDefinitions(const Elf_Shdr &Sec) const {
+ Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Sec);
+ if (!StrTabOrErr)
+ return StrTabOrErr.takeError();
+
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return createError("cannot read content of " + describe(*this, Sec) + ": " +
+ toString(ContentsOrErr.takeError()));
+
+ const uint8_t *Start = ContentsOrErr->data();
+ const uint8_t *End = Start + ContentsOrErr->size();
+
+ auto ExtractNextAux = [&](const uint8_t *&VerdauxBuf,
+ unsigned VerDefNdx) -> Expected<VerdAux> {
+ if (VerdauxBuf + sizeof(Elf_Verdaux) > End)
+ return createError("invalid " + describe(*this, Sec) +
+ ": version definition " + Twine(VerDefNdx) +
+ " refers to an auxiliary entry that goes past the end "
+ "of the section");
+
+ auto *Verdaux = reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf);
+ VerdauxBuf += Verdaux->vda_next;
+
+ VerdAux Aux;
+ Aux.Offset = VerdauxBuf - Start;
+ if (Verdaux->vda_name <= StrTabOrErr->size())
+ Aux.Name = std::string(StrTabOrErr->drop_front(Verdaux->vda_name));
+ else
+ Aux.Name = ("<invalid vda_name: " + Twine(Verdaux->vda_name) + ">").str();
+ return Aux;
+ };
+
+ std::vector<VerDef> Ret;
+ const uint8_t *VerdefBuf = Start;
+ for (unsigned I = 1; I <= /*VerDefsNum=*/Sec.sh_info; ++I) {
+ if (VerdefBuf + sizeof(Elf_Verdef) > End)
+ return createError("invalid " + describe(*this, Sec) +
+ ": version definition " + Twine(I) +
+ " goes past the end of the section");
+
+ if (reinterpret_cast<uintptr_t>(VerdefBuf) % sizeof(uint32_t) != 0)
+ return createError(
+ "invalid " + describe(*this, Sec) +
+ ": found a misaligned version definition entry at offset 0x" +
+ Twine::utohexstr(VerdefBuf - Start));
+
+ unsigned Version = *reinterpret_cast<const Elf_Half *>(VerdefBuf);
+ if (Version != 1)
+ return createError("unable to dump " + describe(*this, Sec) +
+ ": version " + Twine(Version) +
+ " is not yet supported");
+
+ const Elf_Verdef *D = reinterpret_cast<const Elf_Verdef *>(VerdefBuf);
+ VerDef &VD = *Ret.emplace(Ret.end());
+ VD.Offset = VerdefBuf - Start;
+ VD.Version = D->vd_version;
+ VD.Flags = D->vd_flags;
+ VD.Ndx = D->vd_ndx;
+ VD.Cnt = D->vd_cnt;
+ VD.Hash = D->vd_hash;
+
+ const uint8_t *VerdauxBuf = VerdefBuf + D->vd_aux;
+ for (unsigned J = 0; J < D->vd_cnt; ++J) {
+ if (reinterpret_cast<uintptr_t>(VerdauxBuf) % sizeof(uint32_t) != 0)
+ return createError("invalid " + describe(*this, Sec) +
+ ": found a misaligned auxiliary entry at offset 0x" +
+ Twine::utohexstr(VerdauxBuf - Start));
+
+ Expected<VerdAux> AuxOrErr = ExtractNextAux(VerdauxBuf, I);
+ if (!AuxOrErr)
+ return AuxOrErr.takeError();
+
+ if (J == 0)
+ VD.Name = AuxOrErr->Name;
+ else
+ VD.AuxV.push_back(*AuxOrErr);
+ }
+
+ VerdefBuf += D->vd_next;
+ }
+
+ return Ret;
+}
+
+template <class ELFT>
+Expected<std::vector<VerNeed>>
+ELFFile<ELFT>::getVersionDependencies(const Elf_Shdr &Sec,
+ WarningHandler WarnHandler) const {
+ StringRef StrTab;
+ Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Sec);
+ if (!StrTabOrErr) {
+ if (Error E = WarnHandler(toString(StrTabOrErr.takeError())))
+ return std::move(E);
+ } else {
+ StrTab = *StrTabOrErr;
+ }
+
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return createError("cannot read content of " + describe(*this, Sec) + ": " +
+ toString(ContentsOrErr.takeError()));
+
+ const uint8_t *Start = ContentsOrErr->data();
+ const uint8_t *End = Start + ContentsOrErr->size();
+ const uint8_t *VerneedBuf = Start;
+
+ std::vector<VerNeed> Ret;
+ for (unsigned I = 1; I <= /*VerneedNum=*/Sec.sh_info; ++I) {
+ if (VerneedBuf + sizeof(Elf_Verdef) > End)
+ return createError("invalid " + describe(*this, Sec) +
+ ": version dependency " + Twine(I) +
+ " goes past the end of the section");
+
+ if (reinterpret_cast<uintptr_t>(VerneedBuf) % sizeof(uint32_t) != 0)
+ return createError(
+ "invalid " + describe(*this, Sec) +
+ ": found a misaligned version dependency entry at offset 0x" +
+ Twine::utohexstr(VerneedBuf - Start));
+
+ unsigned Version = *reinterpret_cast<const Elf_Half *>(VerneedBuf);
+ if (Version != 1)
+ return createError("unable to dump " + describe(*this, Sec) +
+ ": version " + Twine(Version) +
+ " is not yet supported");
+
+ const Elf_Verneed *Verneed =
+ reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
+
+ VerNeed &VN = *Ret.emplace(Ret.end());
+ VN.Version = Verneed->vn_version;
+ VN.Cnt = Verneed->vn_cnt;
+ VN.Offset = VerneedBuf - Start;
+
+ if (Verneed->vn_file < StrTab.size())
+ VN.File = std::string(StrTab.drop_front(Verneed->vn_file));
+ else
+ VN.File = ("<corrupt vn_file: " + Twine(Verneed->vn_file) + ">").str();
+
+ const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
+ for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
+ if (reinterpret_cast<uintptr_t>(VernauxBuf) % sizeof(uint32_t) != 0)
+ return createError("invalid " + describe(*this, Sec) +
+ ": found a misaligned auxiliary entry at offset 0x" +
+ Twine::utohexstr(VernauxBuf - Start));
+
+ if (VernauxBuf + sizeof(Elf_Vernaux) > End)
+ return createError(
+ "invalid " + describe(*this, Sec) + ": version dependency " +
+ Twine(I) +
+ " refers to an auxiliary entry that goes past the end "
+ "of the section");
+
+ const Elf_Vernaux *Vernaux =
+ reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
+
+ VernAux &Aux = *VN.AuxV.emplace(VN.AuxV.end());
+ Aux.Hash = Vernaux->vna_hash;
+ Aux.Flags = Vernaux->vna_flags;
+ Aux.Other = Vernaux->vna_other;
+ Aux.Offset = VernauxBuf - Start;
+ if (StrTab.size() <= Vernaux->vna_name)
+ Aux.Name = "<corrupt>";
+ else
+ Aux.Name = std::string(StrTab.drop_front(Vernaux->vna_name));
+
+ VernauxBuf += Vernaux->vna_next;
+ }
+ VerneedBuf += Verneed->vn_next;
+ }
+ return Ret;
+}
+
+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>
+ELFFile<ELFT>::getStringTable(const Elf_Shdr &Section,
+ WarningHandler WarnHandler) const {
+ if (Section.sh_type != ELF::SHT_STRTAB)
+ if (Error E = WarnHandler("invalid sh_type for string table section " +
+ getSecIndexForError(*this, Section) +
+ ": 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 " +
+ getSecIndexForError(*this, Section) + " is empty");
+ 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);
+ 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)
+ 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");
+ Expected<const Elf_Shdr *> SectionOrErr =
+ object::getSection<ELFT>(Sections, Sec.sh_link);
+ if (!SectionOrErr)
+ return SectionOrErr.takeError();
+ return getStringTable(**SectionOrErr);
+}
+
+template <class ELFT>
+Expected<StringRef>
+ELFFile<ELFT>::getLinkAsStrtab(const typename ELFT::Shdr &Sec) const {
+ Expected<const typename ELFT::Shdr *> StrTabSecOrErr =
+ getSection(Sec.sh_link);
+ if (!StrTabSecOrErr)
+ return createError("invalid section linked to " + describe(*this, Sec) +
+ ": " + toString(StrTabSecOrErr.takeError()));
+
+ Expected<StringRef> StrTabOrErr = getStringTable(**StrTabSecOrErr);
+ if (!StrTabOrErr)
+ return createError("invalid string table linked to " +
+ describe(*this, Sec) + ": " +
+ toString(StrTabOrErr.takeError()));
+ return *StrTabOrErr;
+}
+
+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>
+Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section,
+ StringRef DotShstrtab) const {
+ uint32_t Offset = Section.sh_name;
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h
new file mode 100644
index 00000000000..28c6ec9bfc8
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h
@@ -0,0 +1,1316 @@
+#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;
+
+ Optional<StringRef> tryGetCPUName() const override;
+
+ 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);
+ }
+
+ 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,
+ 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.
+ 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) {
+ 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);
+ static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object,
+ bool InitContent = true);
+
+ 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);
+ if (!RelSecOrErr)
+ report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message());
+ 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;
+
+ 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;
+}
+
+template <class ELFT> Error ELFObjectFile<ELFT>::initContent() {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return SectionsOrErr.takeError();
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_DYNSYM: {
+ if (!DotDynSymSec)
+ DotDynSymSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB: {
+ if (!DotSymtabSec)
+ DotSymtabSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB_SHNDX: {
+ if (!DotSymtabShndxSec)
+ DotSymtabShndxSec = &Sec;
+ break;
+ }
+ }
+ }
+
+ ContentValid = true;
+ return Error::success();
+}
+
+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 SymStrTabOrErr = EF.getStringTable(*StringTableSec);
+ 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 ((*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 {
+ 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;
+
+ const Elf_Ehdr &Header = EF.getHeader();
+ // 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;
+ 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();
+
+ if (EF.getHeader().e_type == ELF::ET_REL) {
+ ArrayRef<Elf_Word> ShndxTable;
+ if (DotSymtabShndxSec) {
+ // TODO: Test this error.
+ if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
+ EF.getSHNDXTable(*DotSymtabShndxSec))
+ ShndxTable = *ShndxTableOrErr;
+ else
+ return ShndxTableOrErr.takeError();
+ }
+
+ 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 {
+ 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 EF.getHeader().e_machine;
+}
+
+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 {
+ 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 {
+ return getSymbolSize(Symb);
+}
+
+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 {
+ 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 {
+ 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 {
+ 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 {
+ 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();
+
+ 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 {
+ ArrayRef<Elf_Word> ShndxTable;
+ if (DotSymtabShndxSec) {
+ // TODO: Test this error.
+ Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
+ EF.getSHNDXTable(*DotSymtabShndxSec);
+ if (!ShndxTableOrErr)
+ return ShndxTableOrErr.takeError();
+ ShndxTable = *ShndxTableOrErr;
+ }
+
+ 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 {
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ return SymOrErr.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 {
+ 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());
+ 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 {
+ 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 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>>
+ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
+ 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,
+ const Elf_Shdr *DotSymtabShndx)
+ : 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,
+ 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;
+ switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
+ 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:
+ return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc");
+ 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:
+ 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;
+ 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:
+ 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:
+ return IsLittleEndian ? Triple::ppcle : Triple::ppc;
+ 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;
+
+ 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;
+ case ELF::EM_CSKY:
+ return Triple::csky;
+ 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 {
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h b/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h
new file mode 100644
index 00000000000..320dfaa573e
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ELFTypes.h
@@ -0,0 +1,805 @@
+#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; \
+ using Elf_Shdr = typename ELFT::Shdr; \
+ using Elf_Sym = typename ELFT::Sym; \
+ using Elf_Dyn = typename ELFT::Dyn; \
+ using Elf_Phdr = typename ELFT::Phdr; \
+ using Elf_Rel = typename ELFT::Rel; \
+ using Elf_Rela = typename ELFT::Rela; \
+ using Elf_Relr = typename ELFT::Relr; \
+ using Elf_Verdef = typename ELFT::Verdef; \
+ using Elf_Verdaux = typename ELFT::Verdaux; \
+ using Elf_Verneed = typename ELFT::Verneed; \
+ using Elf_Vernaux = typename ELFT::Vernaux; \
+ using Elf_Versym = typename ELFT::Versym; \
+ using Elf_Hash = typename ELFT::Hash; \
+ using Elf_GnuHash = typename ELFT::GnuHash; \
+ using Elf_Nhdr = typename ELFT::Nhdr; \
+ using Elf_Note = typename ELFT::Note; \
+ using Elf_Note_Iterator = typename ELFT::NoteIterator; \
+ using Elf_CGProfile = typename ELFT::CGProfile; \
+ using Elf_Dyn_Range = typename ELFT::DynRange; \
+ using Elf_Shdr_Range = typename ELFT::ShdrRange; \
+ using Elf_Sym_Range = typename ELFT::SymRange; \
+ using Elf_Rel_Range = typename ELFT::RelRange; \
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/Error.h b/contrib/libs/llvm12/include/llvm/Object/Error.h
new file mode 100644
index 00000000000..8cfaa1a87cb
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Error.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h
new file mode 100644
index 00000000000..da4a9d74aaa
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/IRObjectFile.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h b/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h
new file mode 100644
index 00000000000..59a6817bd5d
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/IRSymtab.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/MachO.h b/contrib/libs/llvm12/include/llvm/Object/MachO.h
new file mode 100644
index 00000000000..bbc0a233ee1
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/MachO.h
@@ -0,0 +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";
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h b/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h
new file mode 100644
index 00000000000..2f34b6a71ba
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/MachOUniversal.h
@@ -0,0 +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;
+class Module;
+class LLVMContext;
+
+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;
+ 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<IRObjectFile>>
+ getIRObjectForArch(StringRef ArchName, LLVMContext &Ctx) const;
+
+ 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/MachOUniversalWriter.h b/contrib/libs/llvm12/include/llvm/Object/MachOUniversalWriter.h
new file mode 100644
index 00000000000..0ff4beabc79
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/MachOUniversalWriter.h
@@ -0,0 +1,113 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- MachOUniversalWriter.h - MachO universal binary 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 Slice class and writeUniversalBinary function for writing a
+// MachO universal binary file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_MACHOUNIVERSALWRITER_H
+#define LLVM_OBJECT_MACHOUNIVERSALWRITER_H
+
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/MachO.h"
+
+namespace llvm {
+class LLVMContext;
+
+namespace object {
+class IRObjectFile;
+
+class Slice {
+ const Binary *B;
+ uint32_t CPUType;
+ uint32_t CPUSubType;
+ std::string ArchName;
+
+ // P2Alignment field stores slice alignment values from universal
+ // binaries. This is also needed to order the slices so the total
+ // file size can be calculated before creating the output buffer.
+ uint32_t P2Alignment;
+
+ Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,
+ std::string ArchName, uint32_t Align);
+
+public:
+ explicit Slice(const MachOObjectFile &O);
+
+ Slice(const MachOObjectFile &O, uint32_t Align);
+
+ /// This constructor takes pre-specified \param CPUType , \param CPUSubType ,
+ /// \param ArchName , \param Align instead of inferring them from the archive
+ /// members.
+ Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType,
+ std::string ArchName, uint32_t Align);
+
+ static Expected<Slice> create(const Archive &A,
+ LLVMContext *LLVMCtx = nullptr);
+
+ static Expected<Slice> create(const IRObjectFile &IRO, uint32_t Align);
+
+ void setP2Alignment(uint32_t Align) { P2Alignment = Align; }
+
+ const Binary *getBinary() const { return B; }
+
+ uint32_t getCPUType() const { return CPUType; }
+
+ uint32_t getCPUSubType() const { return CPUSubType; }
+
+ uint32_t getP2Alignment() const { return P2Alignment; }
+
+ uint64_t getCPUID() const {
+ return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
+ }
+
+ std::string getArchString() const {
+ if (!ArchName.empty())
+ return ArchName;
+ return ("unknown(" + Twine(CPUType) + "," +
+ Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
+ .str();
+ }
+
+ friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
+ if (Lhs.CPUType == Rhs.CPUType)
+ return Lhs.CPUSubType < Rhs.CPUSubType;
+ // force arm64-family to follow after all other slices for
+ // compatibility with cctools lipo
+ if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
+ return false;
+ if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
+ return true;
+ // Sort by alignment to minimize file size
+ return Lhs.P2Alignment < Rhs.P2Alignment;
+ }
+};
+
+Error writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName);
+
+Expected<std::unique_ptr<MemoryBuffer>>
+writeUniversalBinaryToBuffer(ArrayRef<Slice> Slices);
+
+} // end namespace object
+
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H
+
+#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
new file mode 100644
index 00000000000..7adc325663d
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Minidump.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h b/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h
new file mode 100644
index 00000000000..b661386eebb
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ModuleSymbolTable.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h
new file mode 100644
index 00000000000..7f9ec78c1d4
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/ObjectFile.h
@@ -0,0 +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;
+ 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>>
+ 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>>
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h b/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h
new file mode 100644
index 00000000000..d53f50e3e5e
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/RelocationResolver.h
@@ -0,0 +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 {
+
+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);
+
+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
diff --git a/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h b/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h
new file mode 100644
index 00000000000..4551e80bb23
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/StackMapParser.h
@@ -0,0 +1,478 @@
+#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();
+ }
+ }
+
+ /// Validates the header of the specified stack map section.
+ static Error validateHeader(ArrayRef<uint8_t> StackMapSection) {
+ // See the comment for StackMaps::emitStackmapHeader().
+ if (StackMapSection.size() < 16)
+ return object::createError(
+ "the stack map section size (" + Twine(StackMapSection.size()) +
+ ") is less than the minimum possible size of its header (16)");
+
+ unsigned Version = StackMapSection[0];
+ if (Version != 3)
+ return object::createError(
+ "the version (" + Twine(Version) +
+ ") of the stack map section is unsupported, the "
+ "supported version is 3");
+ 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h b/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h
new file mode 100644
index 00000000000..ae0fb0b12ff
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/SymbolSize.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h b/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h
new file mode 100644
index 00000000000..928c0ad8b35
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/SymbolicFile.h
@@ -0,0 +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,
+ 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 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/TapiFile.h b/contrib/libs/llvm12/include/llvm/Object/TapiFile.h
new file mode 100644
index 00000000000..04c07c01cbc
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/TapiFile.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h b/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h
new file mode 100644
index 00000000000..20eed191dd4
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/TapiUniversal.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/Wasm.h b/contrib/libs/llvm12/include/llvm/Object/Wasm.h
new file mode 100644
index 00000000000..80e3ddd109f
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/Wasm.h
@@ -0,0 +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,
+ const wasm::WasmTableType *TableType,
+ 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::WasmTableType *TableType;
+ 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)
+ 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<wasm::WasmDebugName> debugNames() const { return DebugNames; }
+ 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;
+ bool isValidTableIndex(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 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;
+ std::vector<wasm::WasmDebugName> DebugNames;
+ uint32_t StartFunction = -1;
+ bool HasLinkingSection = false;
+ bool HasDylinkSection = false;
+ bool SeenCodeSection = false;
+ bool HasMemory64 = false;
+ 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 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
diff --git a/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h b/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h
new file mode 100644
index 00000000000..c6e06c47d09
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/WindowsMachineFlag.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h b/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h
new file mode 100644
index 00000000000..42f6885aef9
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/WindowsResource.h
@@ -0,0 +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
diff --git a/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h
new file mode 100644
index 00000000000..ba11d43c43d
--- /dev/null
+++ b/contrib/libs/llvm12/include/llvm/Object/XCOFFObjectFile.h
@@ -0,0 +1,509 @@
+#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;
+
+ 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;
+};
+
+class TBVectorExt {
+ friend class XCOFFTracebackTable;
+
+ uint16_t Data;
+ uint32_t VecParmsInfo;
+
+ TBVectorExt(StringRef TBvectorStrRef);
+
+public:
+ uint8_t getNumberOfVRSaved() const;
+ bool isVRSavedOnStack() const;
+ bool hasVarArgs() const;
+ uint8_t getNumberOfVectorParms() const;
+ bool hasVMXInstruction() const;
+ SmallString<32> getVectorParmsInfoString() const;
+};
+
+/// This class provides methods to extract traceback table data from a buffer.
+/// The various accessors may reference the buffer provided via the constructor.
+
+class XCOFFTracebackTable {
+ const uint8_t *const TBPtr;
+ Optional<SmallString<32>> ParmsType;
+ Optional<uint32_t> TraceBackTableOffset;
+ Optional<uint32_t> HandlerMask;
+ Optional<uint32_t> NumOfCtlAnchors;
+ Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
+ Optional<StringRef> FunctionName;
+ Optional<uint8_t> AllocaRegister;
+ Optional<TBVectorExt> VecExt;
+ Optional<uint8_t> ExtensionTable;
+
+ XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
+public:
+ /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
+ /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
+ /// Error is returned.
+ ///
+ /// \param[in] Ptr
+ /// A pointer that points just past the initial 4 bytes of zeros at the
+ /// beginning of an XCOFF Traceback Table.
+ ///
+ /// \param[in, out] Size
+ /// A pointer that points to the length of the XCOFF Traceback Table.
+ /// If the XCOFF Traceback Table is not parsed successfully or there are
+ /// extra bytes that are not recognized, \a Size will be updated to be the
+ /// size up to the end of the last successfully parsed field of the table.
+ static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
+ uint64_t &Size);
+ uint8_t getVersion() const;
+ uint8_t getLanguageID() const;
+
+ bool isGlobalLinkage() const;
+ bool isOutOfLineEpilogOrPrologue() const;
+ bool hasTraceBackTableOffset() const;
+ bool isInternalProcedure() const;
+ bool hasControlledStorage() const;
+ bool isTOCless() const;
+ bool isFloatingPointPresent() const;
+ bool isFloatingPointOperationLogOrAbortEnabled() const;
+
+ bool isInterruptHandler() const;
+ bool isFuncNamePresent() const;
+ bool isAllocaUsed() const;
+ uint8_t getOnConditionDirective() const;
+ bool isCRSaved() const;
+ bool isLRSaved() const;
+
+ bool isBackChainStored() const;
+ bool isFixup() const;
+ uint8_t getNumOfFPRsSaved() const;
+
+ bool hasVectorInfo() const;
+ bool hasExtensionTable() const;
+ uint8_t getNumOfGPRsSaved() const;
+
+ uint8_t getNumberOfFixedParms() const;
+
+ uint8_t getNumberOfFPParms() const;
+ bool hasParmsOnStack() const;
+
+ const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
+ const Optional<uint32_t> &getTraceBackTableOffset() const {
+ return TraceBackTableOffset;
+ }
+ const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
+ const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
+ const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
+ return ControlledStorageInfoDisp;
+ }
+ const Optional<StringRef> &getFunctionName() const { return FunctionName; }
+ const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
+ const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
+ const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
+};
+
+bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
+} // namespace object
+} // namespace llvm
+
+#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif