1//===----------------------------------------------------------------------===//
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// These factories reference every object file format. They live apart from
10// the Binary, SymbolicFile and ObjectFile base classes so that a tool which
11// only uses one format does not link all of them.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Object/Archive.h"
16#include "llvm/Object/COFFImportFile.h"
17#include "llvm/Object/DXContainer.h"
18#include "llvm/Object/IRObjectFile.h"
19#include "llvm/Object/MachOUniversal.h"
20#include "llvm/Object/Minidump.h"
21#include "llvm/Object/OffloadBinary.h"
22#include "llvm/Object/TapiUniversal.h"
23#include "llvm/Object/Wasm.h"
24#include "llvm/Object/WindowsResource.h"
25
26using namespace llvm;
27using namespace llvm::object;
28
29Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
30 LLVMContext *Context,
31 bool InitContent) {
32 file_magic Type = identify_magic(magic: Buffer.getBuffer());
33
34 switch (Type) {
35 case file_magic::archive:
36 return Archive::create(Source: Buffer);
37 case file_magic::elf:
38 case file_magic::elf_relocatable:
39 case file_magic::elf_executable:
40 case file_magic::elf_shared_object:
41 case file_magic::elf_core:
42 case file_magic::goff_object:
43 case file_magic::macho_object:
44 case file_magic::macho_executable:
45 case file_magic::macho_fixed_virtual_memory_shared_lib:
46 case file_magic::macho_core:
47 case file_magic::macho_preload_executable:
48 case file_magic::macho_dynamically_linked_shared_lib:
49 case file_magic::macho_dynamic_linker:
50 case file_magic::macho_bundle:
51 case file_magic::macho_dynamically_linked_shared_lib_stub:
52 case file_magic::macho_dsym_companion:
53 case file_magic::macho_kext_bundle:
54 case file_magic::macho_file_set:
55 case file_magic::coff_object:
56 case file_magic::coff_import_library:
57 case file_magic::pecoff_executable:
58 case file_magic::bitcode:
59 case file_magic::xcoff_object_32:
60 case file_magic::xcoff_object_64:
61 case file_magic::wasm_object:
62 case file_magic::dxcontainer_object:
63 return ObjectFile::createSymbolicFile(Object: Buffer, Type, Context, InitContent);
64 case file_magic::macho_universal_binary:
65 return MachOUniversalBinary::create(Source: Buffer);
66 case file_magic::windows_resource:
67 return WindowsResource::createWindowsResource(Source: Buffer);
68 case file_magic::pdb:
69 // PDB does not support the Binary interface.
70 return errorCodeToError(EC: object_error::invalid_file_type);
71 case file_magic::unknown:
72 case file_magic::clang_ast:
73 case file_magic::cuda_fatbinary:
74 case file_magic::coff_cl_gl_object:
75 case file_magic::offload_bundle:
76 case file_magic::offload_bundle_compressed:
77 case file_magic::spirv_object:
78 // Unrecognized object file format.
79 return errorCodeToError(EC: object_error::invalid_file_type);
80 case file_magic::offload_binary: {
81 auto OffloadBinaryOrErr = OffloadBinary::create(Buf: Buffer);
82 if (!OffloadBinaryOrErr)
83 return OffloadBinaryOrErr.takeError();
84 return std::move((*OffloadBinaryOrErr)[0]);
85 }
86 case file_magic::minidump:
87 return MinidumpFile::create(Source: Buffer);
88 case file_magic::tapi_file:
89 return TapiUniversal::create(Source: Buffer);
90 }
91 llvm_unreachable("Unexpected Binary File Type");
92}
93
94Expected<OwningBinary<Binary>>
95object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) {
96 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
97 MemoryBuffer::getFileOrSTDIN(Filename: Path, /*IsText=*/false,
98 /*RequiresNullTerminator=*/false);
99 if (std::error_code EC = FileOrErr.getError())
100 return errorCodeToError(EC);
101 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
102
103 Expected<std::unique_ptr<Binary>> BinOrErr =
104 createBinary(Buffer: Buffer->getMemBufferRef(), Context, InitContent);
105 if (!BinOrErr)
106 return BinOrErr.takeError();
107 std::unique_ptr<Binary> &Bin = BinOrErr.get();
108
109 return OwningBinary<Binary>(std::move(Bin), std::move(Buffer));
110}
111
112Expected<std::unique_ptr<ObjectFile>>
113ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
114 bool InitContent) {
115 StringRef Data = Object.getBuffer();
116 if (Type == file_magic::unknown)
117 Type = identify_magic(magic: Data);
118
119 switch (Type) {
120 case file_magic::unknown:
121 case file_magic::bitcode:
122 case file_magic::clang_ast:
123 case file_magic::coff_cl_gl_object:
124 case file_magic::archive:
125 case file_magic::macho_universal_binary:
126 case file_magic::windows_resource:
127 case file_magic::pdb:
128 case file_magic::minidump:
129 case file_magic::cuda_fatbinary:
130 case file_magic::offload_binary:
131 case file_magic::offload_bundle:
132 case file_magic::offload_bundle_compressed:
133 case file_magic::spirv_object:
134 return errorCodeToError(EC: object_error::invalid_file_type);
135 case file_magic::tapi_file:
136 return errorCodeToError(EC: object_error::invalid_file_type);
137 case file_magic::elf:
138 case file_magic::elf_relocatable:
139 case file_magic::elf_executable:
140 case file_magic::elf_shared_object:
141 case file_magic::elf_core:
142 return createELFObjectFile(Object, InitContent);
143 case file_magic::macho_object:
144 case file_magic::macho_executable:
145 case file_magic::macho_fixed_virtual_memory_shared_lib:
146 case file_magic::macho_core:
147 case file_magic::macho_preload_executable:
148 case file_magic::macho_dynamically_linked_shared_lib:
149 case file_magic::macho_dynamic_linker:
150 case file_magic::macho_bundle:
151 case file_magic::macho_dynamically_linked_shared_lib_stub:
152 case file_magic::macho_dsym_companion:
153 case file_magic::macho_kext_bundle:
154 case file_magic::macho_file_set:
155 return createMachOObjectFile(Object);
156 case file_magic::coff_object:
157 case file_magic::coff_import_library:
158 case file_magic::pecoff_executable:
159 return createCOFFObjectFile(Object);
160 case file_magic::xcoff_object_32:
161 return createXCOFFObjectFile(Object, FileType: Binary::ID_XCOFF32);
162 case file_magic::xcoff_object_64:
163 return createXCOFFObjectFile(Object, FileType: Binary::ID_XCOFF64);
164 case file_magic::wasm_object:
165 return createWasmObjectFile(Object);
166 case file_magic::dxcontainer_object:
167 return createDXContainerObjectFile(Object);
168 case file_magic::goff_object:
169 return createGOFFObjectFile(Object);
170 }
171 llvm_unreachable("Unexpected Object File Type");
172}
173
174Expected<OwningBinary<ObjectFile>>
175ObjectFile::createObjectFile(StringRef ObjectPath) {
176 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
177 MemoryBuffer::getFile(Filename: ObjectPath);
178 if (std::error_code EC = FileOrErr.getError())
179 return errorCodeToError(EC);
180 std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
181
182 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
183 createObjectFile(Object: Buffer->getMemBufferRef());
184 if (Error Err = ObjOrErr.takeError())
185 return std::move(Err);
186 std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
187
188 return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
189}
190
191Expected<std::unique_ptr<SymbolicFile>>
192SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type,
193 LLVMContext *Context, bool InitContent) {
194 StringRef Data = Object.getBuffer();
195 if (Type == file_magic::unknown)
196 Type = identify_magic(magic: Data);
197
198 if (!isSymbolicFile(Type, Context))
199 return errorCodeToError(EC: object_error::invalid_file_type);
200
201 switch (Type) {
202 case file_magic::bitcode:
203 // Context is guaranteed to be non-null here, because bitcode magic only
204 // indicates a symbolic file when Context is non-null.
205 return IRObjectFile::create(Object, Context&: *Context);
206 case file_magic::elf:
207 case file_magic::elf_executable:
208 case file_magic::elf_shared_object:
209 case file_magic::elf_core:
210 case file_magic::goff_object:
211 case file_magic::macho_executable:
212 case file_magic::macho_fixed_virtual_memory_shared_lib:
213 case file_magic::macho_core:
214 case file_magic::macho_preload_executable:
215 case file_magic::macho_dynamically_linked_shared_lib:
216 case file_magic::macho_dynamic_linker:
217 case file_magic::macho_bundle:
218 case file_magic::macho_dynamically_linked_shared_lib_stub:
219 case file_magic::macho_dsym_companion:
220 case file_magic::macho_kext_bundle:
221 case file_magic::macho_file_set:
222 case file_magic::pecoff_executable:
223 case file_magic::xcoff_object_32:
224 case file_magic::xcoff_object_64:
225 case file_magic::wasm_object:
226 case file_magic::dxcontainer_object:
227 return ObjectFile::createObjectFile(Object, Type, InitContent);
228 case file_magic::coff_import_library:
229 return std::unique_ptr<SymbolicFile>(new COFFImportFile(Object));
230 case file_magic::elf_relocatable:
231 case file_magic::macho_object:
232 case file_magic::coff_object: {
233 Expected<std::unique_ptr<ObjectFile>> Obj =
234 ObjectFile::createObjectFile(Object, Type, InitContent);
235 if (!Obj || !Context)
236 return std::move(Obj);
237
238 Expected<MemoryBufferRef> BCData =
239 IRObjectFile::findBitcodeInObject(Obj: *Obj->get());
240 if (!BCData) {
241 consumeError(Err: BCData.takeError());
242 return std::move(Obj);
243 }
244
245 return IRObjectFile::create(
246 Object: MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()),
247 Context&: *Context);
248 }
249 default:
250 llvm_unreachable("Unexpected Binary File Type");
251 }
252}
253