xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Object/Binary.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- Binary.h - A generic binary file -------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the Binary class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_OBJECT_BINARY_H
14 #define LLVM_OBJECT_BINARY_H
15 
16 #include "llvm-c/Types.h"
17 #include "llvm/Object/Error.h"
18 #include "llvm/Support/CBindingWrapping.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/TargetParser/Triple.h"
23 #include <memory>
24 #include <utility>
25 
26 namespace llvm {
27 
28 class LLVMContext;
29 class StringRef;
30 
31 namespace object {
32 
33 class LLVM_ABI Binary {
34 private:
35   unsigned int TypeID;
36 
37 protected:
38   MemoryBufferRef Data;
39 
40   Binary(unsigned int Type, MemoryBufferRef Source);
41 
42   enum {
43     ID_Archive,
44     ID_MachOUniversalBinary,
45     ID_COFFImportFile,
46     ID_IR,            // LLVM IR
47     ID_TapiUniversal, // Text-based Dynamic Library Stub file.
48     ID_TapiFile,      // Text-based Dynamic Library Stub file.
49 
50     ID_Minidump,
51 
52     ID_WinRes, // Windows resource (.res) file.
53 
54     ID_Offload, // Offloading binary file.
55 
56     // Object and children.
57     ID_StartObjects,
58     ID_COFF,
59 
60     ID_XCOFF32, // AIX XCOFF 32-bit
61     ID_XCOFF64, // AIX XCOFF 64-bit
62 
63     ID_ELF32L, // ELF 32-bit, little endian
64     ID_ELF32B, // ELF 32-bit, big endian
65     ID_ELF64L, // ELF 64-bit, little endian
66     ID_ELF64B, // ELF 64-bit, big endian
67 
68     ID_MachO32L, // MachO 32-bit, little endian
69     ID_MachO32B, // MachO 32-bit, big endian
70     ID_MachO64L, // MachO 64-bit, little endian
71     ID_MachO64B, // MachO 64-bit, big endian
72 
73     ID_GOFF,
74     ID_Wasm,
75 
76     ID_EndObjects
77   };
78 
getELFType(bool isLE,bool is64Bits)79   static inline unsigned int getELFType(bool isLE, bool is64Bits) {
80     if (isLE)
81       return is64Bits ? ID_ELF64L : ID_ELF32L;
82     else
83       return is64Bits ? ID_ELF64B : ID_ELF32B;
84   }
85 
getMachOType(bool isLE,bool is64Bits)86   static unsigned int getMachOType(bool isLE, bool is64Bits) {
87     if (isLE)
88       return is64Bits ? ID_MachO64L : ID_MachO32L;
89     else
90       return is64Bits ? ID_MachO64B : ID_MachO32B;
91   }
92 
93 public:
94   Binary() = delete;
95   Binary(const Binary &other) = delete;
96   virtual ~Binary();
97 
initContent()98   virtual Error initContent() { return Error::success(); };
99 
100   StringRef getData() const;
101   StringRef getFileName() const;
102   MemoryBufferRef getMemoryBufferRef() const;
103 
104   // Cast methods.
getType()105   unsigned int getType() const { return TypeID; }
106 
107   // Convenience methods
isObject()108   bool isObject() const {
109     return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
110   }
111 
isSymbolic()112   bool isSymbolic() const {
113     return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
114   }
115 
isArchive()116   bool isArchive() const { return TypeID == ID_Archive; }
117 
isMachOUniversalBinary()118   bool isMachOUniversalBinary() const {
119     return TypeID == ID_MachOUniversalBinary;
120   }
121 
isTapiUniversal()122   bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
123 
isELF()124   bool isELF() const {
125     return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
126   }
127 
isMachO()128   bool isMachO() const {
129     return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B;
130   }
131 
isCOFF()132   bool isCOFF() const {
133     return TypeID == ID_COFF;
134   }
135 
isXCOFF()136   bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
137 
isWasm()138   bool isWasm() const { return TypeID == ID_Wasm; }
139 
isOffloadFile()140   bool isOffloadFile() const { return TypeID == ID_Offload; }
141 
isCOFFImportFile()142   bool isCOFFImportFile() const {
143     return TypeID == ID_COFFImportFile;
144   }
145 
isIR()146   bool isIR() const {
147     return TypeID == ID_IR;
148   }
149 
isGOFF()150   bool isGOFF() const { return TypeID == ID_GOFF; }
151 
isMinidump()152   bool isMinidump() const { return TypeID == ID_Minidump; }
153 
isTapiFile()154   bool isTapiFile() const { return TypeID == ID_TapiFile; }
155 
isLittleEndian()156   bool isLittleEndian() const {
157     return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
158              TypeID == ID_MachO32B || TypeID == ID_MachO64B ||
159              TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64);
160   }
161 
isWinRes()162   bool isWinRes() const { return TypeID == ID_WinRes; }
163 
getTripleObjectFormat()164   Triple::ObjectFormatType getTripleObjectFormat() const {
165     if (isCOFF())
166       return Triple::COFF;
167     if (isMachO())
168       return Triple::MachO;
169     if (isELF())
170       return Triple::ELF;
171     if (isGOFF())
172       return Triple::GOFF;
173     return Triple::UnknownObjectFormat;
174   }
175 
checkOffset(MemoryBufferRef M,uintptr_t Addr,const uint64_t Size)176   static Error checkOffset(MemoryBufferRef M, uintptr_t Addr,
177                            const uint64_t Size) {
178     if (Addr + Size < Addr || Addr + Size < Size ||
179         Addr + Size > reinterpret_cast<uintptr_t>(M.getBufferEnd()) ||
180         Addr < reinterpret_cast<uintptr_t>(M.getBufferStart())) {
181       return errorCodeToError(object_error::unexpected_eof);
182     }
183     return Error::success();
184   }
185 };
186 
187 // Create wrappers for C Binding types (see CBindingWrapping.h).
188 DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef)
189 
190 /// Create a Binary from Source, autodetecting the file type.
191 ///
192 /// @param Source The data to create the Binary from.
193 LLVM_ABI Expected<std::unique_ptr<Binary>>
194 createBinary(MemoryBufferRef Source, LLVMContext *Context = nullptr,
195              bool InitContent = true);
196 
197 template <typename T> class OwningBinary {
198   std::unique_ptr<T> Bin;
199   std::unique_ptr<MemoryBuffer> Buf;
200 
201 public:
202   OwningBinary();
203   OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf);
204   OwningBinary(OwningBinary<T>&& Other);
205   OwningBinary<T> &operator=(OwningBinary<T> &&Other);
206 
207   std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary();
208 
209   T* getBinary();
210   const T* getBinary() const;
211 };
212 
213 template <typename T>
OwningBinary(std::unique_ptr<T> Bin,std::unique_ptr<MemoryBuffer> Buf)214 OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
215                               std::unique_ptr<MemoryBuffer> Buf)
216     : Bin(std::move(Bin)), Buf(std::move(Buf)) {}
217 
218 template <typename T> OwningBinary<T>::OwningBinary() = default;
219 
220 template <typename T>
OwningBinary(OwningBinary && Other)221 OwningBinary<T>::OwningBinary(OwningBinary &&Other)
222     : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {}
223 
224 template <typename T>
225 OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) {
226   Bin = std::move(Other.Bin);
227   Buf = std::move(Other.Buf);
228   return *this;
229 }
230 
231 template <typename T>
232 std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>>
takeBinary()233 OwningBinary<T>::takeBinary() {
234   return std::make_pair(std::move(Bin), std::move(Buf));
235 }
236 
getBinary()237 template <typename T> T* OwningBinary<T>::getBinary() {
238   return Bin.get();
239 }
240 
getBinary()241 template <typename T> const T* OwningBinary<T>::getBinary() const {
242   return Bin.get();
243 }
244 
245 LLVM_ABI Expected<OwningBinary<Binary>>
246 createBinary(StringRef Path, LLVMContext *Context = nullptr,
247              bool InitContent = true);
248 
249 } // end namespace object
250 
251 } // end namespace llvm
252 
253 #endif // LLVM_OBJECT_BINARY_H
254