Home | History | Annotate | Download | only in Object
      1 //===- Binary.h - A generic binary file -------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file declares the Binary class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_OBJECT_BINARY_H
     15 #define LLVM_OBJECT_BINARY_H
     16 
     17 #include "llvm/ADT/Triple.h"
     18 #include "llvm/Object/Error.h"
     19 #include "llvm/Support/Error.h"
     20 #include "llvm/Support/MemoryBuffer.h"
     21 #include <algorithm>
     22 #include <memory>
     23 #include <utility>
     24 
     25 namespace llvm {
     26 
     27 class LLVMContext;
     28 class StringRef;
     29 
     30 namespace object {
     31 
     32 class Binary {
     33 private:
     34   unsigned int TypeID;
     35 
     36 protected:
     37   MemoryBufferRef Data;
     38 
     39   Binary(unsigned int Type, MemoryBufferRef Source);
     40 
     41   enum {
     42     ID_Archive,
     43     ID_MachOUniversalBinary,
     44     ID_COFFImportFile,
     45     ID_IR,                 // LLVM IR
     46 
     47     ID_WinRes, // Windows resource (.res) file.
     48 
     49     // Object and children.
     50     ID_StartObjects,
     51     ID_COFF,
     52 
     53     ID_ELF32L, // ELF 32-bit, little endian
     54     ID_ELF32B, // ELF 32-bit, big endian
     55     ID_ELF64L, // ELF 64-bit, little endian
     56     ID_ELF64B, // ELF 64-bit, big endian
     57 
     58     ID_MachO32L, // MachO 32-bit, little endian
     59     ID_MachO32B, // MachO 32-bit, big endian
     60     ID_MachO64L, // MachO 64-bit, little endian
     61     ID_MachO64B, // MachO 64-bit, big endian
     62 
     63     ID_Wasm,
     64 
     65     ID_EndObjects
     66   };
     67 
     68   static inline unsigned int getELFType(bool isLE, bool is64Bits) {
     69     if (isLE)
     70       return is64Bits ? ID_ELF64L : ID_ELF32L;
     71     else
     72       return is64Bits ? ID_ELF64B : ID_ELF32B;
     73   }
     74 
     75   static unsigned int getMachOType(bool isLE, bool is64Bits) {
     76     if (isLE)
     77       return is64Bits ? ID_MachO64L : ID_MachO32L;
     78     else
     79       return is64Bits ? ID_MachO64B : ID_MachO32B;
     80   }
     81 
     82 public:
     83   Binary() = delete;
     84   Binary(const Binary &other) = delete;
     85   virtual ~Binary();
     86 
     87   StringRef getData() const;
     88   StringRef getFileName() const;
     89   MemoryBufferRef getMemoryBufferRef() const;
     90 
     91   // Cast methods.
     92   unsigned int getType() const { return TypeID; }
     93 
     94   // Convenience methods
     95   bool isObject() const {
     96     return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
     97   }
     98 
     99   bool isSymbolic() const { return isIR() || isObject() || isCOFFImportFile(); }
    100 
    101   bool isArchive() const {
    102     return TypeID == ID_Archive;
    103   }
    104 
    105   bool isMachOUniversalBinary() const {
    106     return TypeID == ID_MachOUniversalBinary;
    107   }
    108 
    109   bool isELF() const {
    110     return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
    111   }
    112 
    113   bool isMachO() const {
    114     return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B;
    115   }
    116 
    117   bool isCOFF() const {
    118     return TypeID == ID_COFF;
    119   }
    120 
    121   bool isWasm() const { return TypeID == ID_Wasm; }
    122 
    123   bool isCOFFImportFile() const {
    124     return TypeID == ID_COFFImportFile;
    125   }
    126 
    127   bool isIR() const {
    128     return TypeID == ID_IR;
    129   }
    130 
    131   bool isLittleEndian() const {
    132     return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
    133              TypeID == ID_MachO32B || TypeID == ID_MachO64B);
    134   }
    135 
    136   bool isWinRes() const { return TypeID == ID_WinRes; }
    137 
    138   Triple::ObjectFormatType getTripleObjectFormat() const {
    139     if (isCOFF())
    140       return Triple::COFF;
    141     if (isMachO())
    142       return Triple::MachO;
    143     if (isELF())
    144       return Triple::ELF;
    145     return Triple::UnknownObjectFormat;
    146   }
    147 
    148   static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
    149                                      const uint64_t Size) {
    150     if (Addr + Size < Addr || Addr + Size < Size ||
    151         Addr + Size > uintptr_t(M.getBufferEnd()) ||
    152         Addr < uintptr_t(M.getBufferStart())) {
    153       return object_error::unexpected_eof;
    154     }
    155     return std::error_code();
    156   }
    157 };
    158 
    159 /// @brief Create a Binary from Source, autodetecting the file type.
    160 ///
    161 /// @param Source The data to create the Binary from.
    162 Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
    163                                                LLVMContext *Context = nullptr);
    164 
    165 template <typename T> class OwningBinary {
    166   std::unique_ptr<T> Bin;
    167   std::unique_ptr<MemoryBuffer> Buf;
    168 
    169 public:
    170   OwningBinary();
    171   OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf);
    172   OwningBinary(OwningBinary<T>&& Other);
    173   OwningBinary<T> &operator=(OwningBinary<T> &&Other);
    174 
    175   std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary();
    176 
    177   T* getBinary();
    178   const T* getBinary() const;
    179 };
    180 
    181 template <typename T>
    182 OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
    183                               std::unique_ptr<MemoryBuffer> Buf)
    184     : Bin(std::move(Bin)), Buf(std::move(Buf)) {}
    185 
    186 template <typename T> OwningBinary<T>::OwningBinary() = default;
    187 
    188 template <typename T>
    189 OwningBinary<T>::OwningBinary(OwningBinary &&Other)
    190     : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {}
    191 
    192 template <typename T>
    193 OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) {
    194   Bin = std::move(Other.Bin);
    195   Buf = std::move(Other.Buf);
    196   return *this;
    197 }
    198 
    199 template <typename T>
    200 std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>>
    201 OwningBinary<T>::takeBinary() {
    202   return std::make_pair(std::move(Bin), std::move(Buf));
    203 }
    204 
    205 template <typename T> T* OwningBinary<T>::getBinary() {
    206   return Bin.get();
    207 }
    208 
    209 template <typename T> const T* OwningBinary<T>::getBinary() const {
    210   return Bin.get();
    211 }
    212 
    213 Expected<OwningBinary<Binary>> createBinary(StringRef Path);
    214 
    215 } // end namespace object
    216 
    217 } // end namespace llvm
    218 
    219 #endif // LLVM_OBJECT_BINARY_H
    220