1 | //===- Binary.cpp - A generic binary file ---------------------------------===// |
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 defines the Binary class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Object/Binary.h" |
14 | #include "llvm/ADT/StringRef.h" |
15 | #include "llvm/BinaryFormat/Magic.h" |
16 | #include "llvm/Object/Archive.h" |
17 | #include "llvm/Object/Error.h" |
18 | #include "llvm/Object/MachOUniversal.h" |
19 | #include "llvm/Object/Minidump.h" |
20 | #include "llvm/Object/ObjectFile.h" |
21 | #include "llvm/Object/OffloadBinary.h" |
22 | #include "llvm/Object/TapiUniversal.h" |
23 | #include "llvm/Object/WindowsResource.h" |
24 | #include "llvm/Support/Error.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/ErrorOr.h" |
27 | #include "llvm/Support/MemoryBuffer.h" |
28 | #include <memory> |
29 | #include <system_error> |
30 | |
31 | using namespace llvm; |
32 | using namespace object; |
33 | |
34 | Binary::~Binary() = default; |
35 | |
36 | Binary::Binary(unsigned int Type, MemoryBufferRef Source) |
37 | : TypeID(Type), Data(Source) {} |
38 | |
39 | StringRef Binary::getData() const { return Data.getBuffer(); } |
40 | |
41 | StringRef Binary::getFileName() const { return Data.getBufferIdentifier(); } |
42 | |
43 | MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; } |
44 | |
45 | Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, |
46 | LLVMContext *Context, |
47 | bool InitContent) { |
48 | file_magic Type = identify_magic(magic: Buffer.getBuffer()); |
49 | |
50 | switch (Type) { |
51 | case file_magic::archive: |
52 | return Archive::create(Source: Buffer); |
53 | case file_magic::elf: |
54 | case file_magic::elf_relocatable: |
55 | case file_magic::elf_executable: |
56 | case file_magic::elf_shared_object: |
57 | case file_magic::elf_core: |
58 | case file_magic::goff_object: |
59 | case file_magic::macho_object: |
60 | case file_magic::macho_executable: |
61 | case file_magic::macho_fixed_virtual_memory_shared_lib: |
62 | case file_magic::macho_core: |
63 | case file_magic::macho_preload_executable: |
64 | case file_magic::macho_dynamically_linked_shared_lib: |
65 | case file_magic::macho_dynamic_linker: |
66 | case file_magic::macho_bundle: |
67 | case file_magic::macho_dynamically_linked_shared_lib_stub: |
68 | case file_magic::macho_dsym_companion: |
69 | case file_magic::macho_kext_bundle: |
70 | case file_magic::macho_file_set: |
71 | case file_magic::coff_object: |
72 | case file_magic::coff_import_library: |
73 | case file_magic::pecoff_executable: |
74 | case file_magic::bitcode: |
75 | case file_magic::xcoff_object_32: |
76 | case file_magic::xcoff_object_64: |
77 | case file_magic::wasm_object: |
78 | return ObjectFile::createSymbolicFile(Object: Buffer, Type, Context, InitContent); |
79 | case file_magic::macho_universal_binary: |
80 | return MachOUniversalBinary::create(Source: Buffer); |
81 | case file_magic::windows_resource: |
82 | return WindowsResource::createWindowsResource(Source: Buffer); |
83 | case file_magic::pdb: |
84 | // PDB does not support the Binary interface. |
85 | return errorCodeToError(EC: object_error::invalid_file_type); |
86 | case file_magic::unknown: |
87 | case file_magic::clang_ast: |
88 | case file_magic::cuda_fatbinary: |
89 | case file_magic::coff_cl_gl_object: |
90 | case file_magic::dxcontainer_object: |
91 | case file_magic::offload_bundle: |
92 | case file_magic::offload_bundle_compressed: |
93 | case file_magic::spirv_object: |
94 | // Unrecognized object file format. |
95 | return errorCodeToError(EC: object_error::invalid_file_type); |
96 | case file_magic::offload_binary: |
97 | return OffloadBinary::create(Buffer); |
98 | case file_magic::minidump: |
99 | return MinidumpFile::create(Source: Buffer); |
100 | case file_magic::tapi_file: |
101 | return TapiUniversal::create(Source: Buffer); |
102 | } |
103 | llvm_unreachable("Unexpected Binary File Type" ); |
104 | } |
105 | |
106 | Expected<OwningBinary<Binary>> |
107 | object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) { |
108 | ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = |
109 | MemoryBuffer::getFileOrSTDIN(Filename: Path, /*IsText=*/false, |
110 | /*RequiresNullTerminator=*/false); |
111 | if (std::error_code EC = FileOrErr.getError()) |
112 | return errorCodeToError(EC); |
113 | std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); |
114 | |
115 | Expected<std::unique_ptr<Binary>> BinOrErr = |
116 | createBinary(Buffer: Buffer->getMemBufferRef(), Context, InitContent); |
117 | if (!BinOrErr) |
118 | return BinOrErr.takeError(); |
119 | std::unique_ptr<Binary> &Bin = BinOrErr.get(); |
120 | |
121 | return OwningBinary<Binary>(std::move(Bin), std::move(Buffer)); |
122 | } |
123 | |