LLVM 20.0.0git
MachO.cpp
Go to the documentation of this file.
1//===----------------- MachO.cpp - MachO format utilities -----------------===//
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
10
13
14#define DEBUG_TYPE "orc"
15
16namespace llvm {
17namespace orc {
18
19static std::string objDesc(MemoryBuffer &Obj, const Triple &TT,
20 bool ObjIsSlice) {
21 std::string Desc;
22 if (ObjIsSlice)
23 Desc += (TT.getArchName() + " slice of universal binary").str();
25 return Desc;
26}
27
28template <typename HeaderType>
30checkMachORelocatableObject(std::unique_ptr<MemoryBuffer> Obj,
31 bool SwapEndianness, const Triple &TT,
32 bool ObjIsSlice) {
33 StringRef Data = Obj->getBuffer();
34
35 HeaderType Hdr;
36 memcpy(&Hdr, Data.data(), sizeof(HeaderType));
37
38 if (SwapEndianness)
39 swapStruct(Hdr);
40
41 if (Hdr.filetype != MachO::MH_OBJECT)
42 return make_error<StringError>(objDesc(*Obj, TT, ObjIsSlice) +
43 " is not a MachO relocatable object",
45
46 auto ObjArch = object::MachOObjectFile::getArch(Hdr.cputype, Hdr.cpusubtype);
47 if (ObjArch != TT.getArch())
48 return make_error<StringError>(
49 objDesc(*Obj, TT, ObjIsSlice) + Triple::getArchTypeName(ObjArch) +
50 ", cannot be loaded into " + TT.str() + " process",
52
53 return std::move(Obj);
54}
55
57checkMachORelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT,
58 bool ObjIsSlice) {
59 StringRef Data = Obj->getBuffer();
60
61 if (Data.size() < 4)
62 return make_error<StringError>(
63 objDesc(*Obj, TT, ObjIsSlice) +
64 " is not a valid MachO relocatable object file (truncated header)",
66
67 uint32_t Magic;
68 memcpy(&Magic, Data.data(), sizeof(uint32_t));
69
70 switch (Magic) {
71 case MachO::MH_MAGIC:
72 case MachO::MH_CIGAM:
73 return checkMachORelocatableObject<MachO::mach_header>(
74 std::move(Obj), Magic == MachO::MH_CIGAM, TT, ObjIsSlice);
77 return checkMachORelocatableObject<MachO::mach_header_64>(
78 std::move(Obj), Magic == MachO::MH_CIGAM_64, TT, ObjIsSlice);
79 default:
80 return make_error<StringError>(
81 objDesc(*Obj, TT, ObjIsSlice) +
82 " is not a valid MachO relocatable object (bad magic value)",
84 }
85}
86
89 assert((TT.getObjectFormat() == Triple::UnknownObjectFormat ||
90 TT.getObjectFormat() == Triple::MachO) &&
91 "TT must specify MachO or Unknown object format");
92
93 auto Buf = MemoryBuffer::getFile(Path);
94 if (!Buf)
95 return createFileError(Path, Buf.getError());
96
97 switch (identify_magic((*Buf)->getBuffer())) {
99 return checkMachORelocatableObject(std::move(*Buf), TT, false);
101 return loadMachORelocatableObjectFromUniversalBinary(Path, std::move(*Buf),
102 TT);
103 default:
104 return make_error<StringError>(
105 Path + " does not contain a relocatable object file compatible with " +
106 TT.str(),
108 }
109}
110
113 StringRef UBPath, std::unique_ptr<MemoryBuffer> UBBuf, const Triple &TT) {
114
115 auto UniversalBin =
116 object::MachOUniversalBinary::create(UBBuf->getMemBufferRef());
117 if (!UniversalBin)
118 return UniversalBin.takeError();
119
120 auto SliceRange = getMachOSliceRangeForTriple(**UniversalBin, TT);
121 if (!SliceRange)
122 return SliceRange.takeError();
123
125 UBPath, SliceRange->second, SliceRange->first, false));
126 if (!ObjBuf)
127 return createFileError(UBPath, ObjBuf.takeError());
128
129 return checkMachORelocatableObject(std::move(*ObjBuf), TT, true);
130}
131
134 const Triple &TT) {
135
136 for (const auto &Obj : UB.objects()) {
137 auto ObjTT = Obj.getTriple();
138 if (ObjTT.getArch() == TT.getArch() &&
139 ObjTT.getSubArch() == TT.getSubArch() &&
140 (TT.getVendor() == Triple::UnknownVendor ||
141 ObjTT.getVendor() == TT.getVendor())) {
142 // We found a match. Return the range for the slice.
143 return std::make_pair(Obj.getOffset(), Obj.getSize());
144 }
145 }
146
147 return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() +
148 " does not contain a slice for " +
149 TT.str(),
151}
152
155
157 if (!UB)
158 return UB.takeError();
159
160 return getMachOSliceRangeForTriple(**UB, TT);
161}
162
163} // End namespace orc.
164} // End namespace llvm.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Tagged union holding either a T or a Error.
Definition: Error.h:481
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Definition: MemoryBuffer.h:76
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Map a subrange of the specified file as a MemoryBuffer.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
static StringRef getArchTypeName(ArchType Kind)
Get the canonical name for the Kind architecture.
Definition: Triple.cpp:24
@ UnknownObjectFormat
Definition: Triple.h:298
@ UnknownVendor
Definition: Triple.h:180
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
StringRef getFileName() const
Definition: Binary.cpp:41
Triple::ArchType getArch() const override
static Expected< std::unique_ptr< MachOUniversalBinary > > create(MemoryBufferRef Source)
iterator_range< object_iterator > objects() const
@ MH_OBJECT
Definition: MachO.h:43
@ MH_MAGIC
Definition: MachO.h:30
@ MH_CIGAM_64
Definition: MachO.h:33
@ MH_CIGAM
Definition: MachO.h:31
@ MH_MAGIC_64
Definition: MachO.h:32
Expected< std::unique_ptr< MemoryBuffer > > checkMachORelocatableObject(std::unique_ptr< MemoryBuffer > Obj, const Triple &TT, bool ObjIsSlice)
Check that the given buffer contains a MachO object file compatible with the given triple.
Definition: MachO.cpp:57
static std::string objDesc(MemoryBuffer &Obj, const Triple &TT, bool ObjIsSlice)
Definition: MachO.cpp:19
Expected< std::pair< size_t, size_t > > getMachOSliceRangeForTriple(object::MachOUniversalBinary &UB, const Triple &TT)
Utility for identifying the file-slice compatible with TT in a universal binary.
Definition: MachO.cpp:133
Expected< std::unique_ptr< MemoryBuffer > > loadMachORelocatableObjectFromUniversalBinary(StringRef UBPath, std::unique_ptr< MemoryBuffer > UBBuf, const Triple &TT)
Load a compatible relocatable object (if available) from a MachO universal binary.
Definition: MachO.cpp:112
Expected< std::unique_ptr< MemoryBuffer > > loadMachORelocatableObject(StringRef Path, const Triple &TT)
Load a relocatable object compatible with TT from Path.
Definition: MachO.cpp:88
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:33
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1380
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
Op::Description Desc
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition: Error.h:1226
Description of the encoding of one expression Op.
@ macho_universal_binary
Mach-O universal binary.
Definition: Magic.h:43
@ macho_object
Mach-O Object file.
Definition: Magic.h:32