LLVM: lib/ExecutionEngine/Orc/MachO.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

19

20#define DEBUG_TYPE "orc"

21

22namespace llvm {

23namespace orc {

24

26 bool ObjIsSlice) {

27 std::string Desc;

28 if (ObjIsSlice)

29 Desc += (TT.getArchName() + " slice of universal binary").str();

30 Desc += Obj.getBufferIdentifier();

32}

33

34template

36 bool SwapEndianness, const Triple &TT,

37 bool ObjIsSlice) {

39

40 HeaderType Hdr;

41 memcpy(&Hdr, Data.data(), sizeof(HeaderType));

42

43 if (SwapEndianness)

44 swapStruct(Hdr);

45

48 " is not a MachO relocatable object",

50

52 if (ObjArch != TT.getArch())

55 ", cannot be loaded into " + TT.str() + " process",

57

59}

60

62 bool ObjIsSlice) {

64

65 if (Data.size() < 4)

67 objDesc(Obj, TT, ObjIsSlice) +

68 " is not a valid MachO relocatable object file (truncated header)",

70

72 memcpy(&Magic, Data.data(), sizeof(uint32_t));

73

74 switch (Magic) {

78 std::move(Obj), Magic == MachO::MH_CIGAM, TT, ObjIsSlice);

83 default:

85 objDesc(Obj, TT, ObjIsSlice) +

86 " is not a valid MachO relocatable object (bad magic value)",

88 }

89}

90

93 bool ObjIsSlice) {

94 if (auto Err =

96 return std::move(Err);

97 return std::move(Obj);

98}

99

102 std::optional IdentifierOverride) {

105 "TT must specify MachO or Unknown object format");

106

107 if (!IdentifierOverride)

108 IdentifierOverride = Path;

109

112 if (!FDOrErr)

116

117 auto Buf =

119 if (!Buf)

121 StringRef("Could not load MachO object at path ") + Path,

122 Buf.getError());

123

127 if (!CheckedObj)

128 return CheckedObj.takeError();

129 return std::make_pair(std::move(*CheckedObj),

131 }

135 *IdentifierOverride);

136 default:

138 Path + " does not contain a relocatable object file compatible with " +

139 TT.str(),

141 }

142}

143

146 std::unique_ptr UBBuf,

150

151 auto UniversalBin =

153 if (!UniversalBin)

154 return UniversalBin.takeError();

155

157 if (!SliceRange)

158 return SliceRange.takeError();

159

161 SliceRange->first);

162 if (!Buf)

164 "Could not load " + TT.getArchName() +

165 " slice of MachO universal binary at path " + UBPath,

166 Buf.getError());

167

172 break;

176 if (!CheckedObj)

177 return CheckedObj.takeError();

178 return std::make_pair(std::move(*CheckedObj),

180 }

181 break;

182 }

183 default:

184 break;

185 }

186

187 auto FT = [&] {

188 switch (LA) {

190 return "a mach-o relocatable object file";

192 return "a mach-o relocatable object file or archive";

194 return "an archive";

195 }

197 };

198

200 " does not contain " + FT(),

202}

203

207

208 for (const auto &Obj : UB.objects()) {

209 auto ObjTT = Obj.getTriple();

210 if (ObjTT.getArch() == TT.getArch() &&

211 ObjTT.getSubArch() == TT.getSubArch() &&

213 ObjTT.getVendor() == TT.getVendor())) {

214

215 return std::make_pair(Obj.getOffset(), Obj.getSize());

216 }

217 }

218

220 " does not contain a slice for " +

221 TT.str(),

223}

224

227

229 if (!UB)

230 return UB.takeError();

231

233}

234

237

238 auto LoadMember = [&]() {

240 Index);

241 };

242

243 if (!ObjCOnly) {

244

245

246 if (auto Err = L.add(JD, LoadMember()))

247 return Err;

248 return false;

249 }

250

251

252

254 if (!Obj) {

255

257 return false;

258 }

259

261

262 for (auto Sec : MachOObj->sections()) {

263 auto SegName =

264 MachOObj->getSectionFinalSegmentName(Sec.getRawDataRefImpl());

265 if (auto SecName = Sec.getName()) {

266 if (*SecName == "__objc_classlist" || *SecName == "__objc_protolist" ||

267 *SecName == "__objc_clsrolist" || *SecName == "__objc_catlist" ||

268 *SecName == "__objc_catlist2" || *SecName == "__objc_nlcatlist" ||

269 (SegName == "__TEXT" && (*SecName).starts_with("__swift") &&

270 *SecName != "__swift_modhash")) {

271 if (auto Err = L.add(JD, LoadMember()))

272 return Err;

273 return false;

274 }

275 } else

276 return SecName.takeError();

277 }

278 }

279

280

281

282 return true;

283}

284

288 Result.push_back({CPUType, CPUSubType});

290}

291

295

296

297 Archs.push_back({CPUType, CPUSubType});

298

299 switch (CPUType) {

301

302 switch (CPUSubType) {

305 break;

306 default:

307 break;

308 }

309 break;

310 default:

311 break;

312 }

313

314 return Archs;

315}

316

321 if (!InitCPUType)

322 return InitCPUType.takeError();

323

325 if (!InitCPUSubType)

326 return InitCPUSubType.takeError();

327

329 if (!Buf)

331

333 if (!BinFile)

334 return BinFile.takeError();

335

336 std::unique_ptrobject::MachOObjectFile MachOFile;

339

340

341 } else if (auto *MachOUni =

344 if (GetFallbackArchs)

345 ArchsToTry = GetFallbackArchs(*InitCPUType, *InitCPUSubType);

346 else

347 ArchsToTry.push_back({*InitCPUType, *InitCPUSubType});

348

349 for (auto &[CPUType, CPUSubType] : ArchsToTry) {

350 for (auto &O : MachOUni->objects()) {

351 if (O.getCPUType() == CPUType &&

353 if (auto Obj = O.getAsObjectFile())

354 MachOFile = std::move(*Obj);

355 else

356 return Obj.takeError();

357 break;

358 }

359 }

360 if (MachOFile)

361 break;

362 }

363 if (!MachOFile)

365 "MachO universal binary at " + Path +

366 " does not contain a compatible slice for " +

369 } else

372

376

378 for (auto &Sym : MachOFile->symbols()) {

379 if (auto Name = Sym.getName())

380 Symbols.insert(ES.intern(*Name));

381 else

382 return Name.takeError();

383 }

384

385 return std::move(Symbols);

386}

387

392

394 if (!TapiFileBuffer)

396

397 auto Tapi =

399 if (!Tapi)

400 return Tapi.takeError();

401

403 if (!InitCPUType)

404 return InitCPUType.takeError();

405

407 if (!InitCPUSubType)

408 return InitCPUSubType.takeError();

409

411 if (GetFallbackArchs)

412 ArchsToTry = GetFallbackArchs(*InitCPUType, *InitCPUSubType);

413 else

414 ArchsToTry.push_back({*InitCPUType, *InitCPUSubType});

415

416 auto &IF = (*Tapi)->getInterfaceFile();

417

418 auto ArchSet = IF.getArchitectures();

419 for (auto [CPUType, CPUSubType] : ArchsToTry) {

421 if (ArchSet.has(A)) {

422 if (auto Interface = IF.extract(A)) {

423 for (auto *Sym : (*Interface)->exports())

424 Symbols.insert(ES.intern(Sym->getName()));

425 return Symbols;

426 } else

427 return Interface.takeError();

428 }

429 }

430

432 "MachO interface file at " + Path +

433 " does not contain a compatible slice for " +

436}

437

443

444 switch (Magic) {

450 default:

452 " unrecognized file type",

454 }

455}

456

457}

458}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Given an already-open file descriptor, read the file and return a MemoryBuffer.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Given an already-open file descriptor, map some slice of it into 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,...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

Triple - Helper class for working with autoconf configuration names.

const std::string & str() const

static LLVM_ABI StringRef getArchTypeName(ArchType Kind)

Get the canonical name for the Kind architecture.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

StringRef getFileName() const

Triple::ArchType getArch() const override

static Expected< std::unique_ptr< MachOUniversalBinary > > create(MemoryBufferRef Source)

iterator_range< object_iterator > objects() const

static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)

static Expected< std::unique_ptr< TapiUniversal > > create(MemoryBufferRef Source)

An ExecutionSession represents a running JIT program.

const Triple & getTargetTriple() const

Return the triple for the executor.

SymbolStringPtr intern(StringRef SymName)

Add a symbol name to the SymbolStringPool and return a pointer to it.

LLVM_ABI Expected< bool > operator()(object::Archive &A, MemoryBufferRef MemberBuf, size_t Index)

Definition MachO.cpp:235

static std::unique_ptr< MemoryBuffer > createMemberBuffer(object::Archive &A, MemoryBufferRef BufRef, size_t Index)

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

LLVM_ABI Expected< uint32_t > getCPUSubType(const Triple &T)

LLVM_ABI Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType)

Convert a CPU Type and Subtype pair to an architecture slice.

LLVM_ABI Expected< uint32_t > getCPUType(const Triple &T)

LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)

Create a Binary from Source, autodetecting the file type.

LLVM_ABI SmallVector< std::pair< uint32_t, uint32_t > > noFallbackArchs(uint32_t CPUType, uint32_t CPUSubType)

Match the exact CPU type/subtype only.

Definition MachO.cpp:286

LLVM_ABI Expected< SymbolNameSet > getDylibInterfaceFromTapiFile(ExecutionSession &ES, Twine Path, GetFallbackArchsFn GetFallbackArchs=standardMachOFallbackArchs)

Returns a SymbolNameSet containing the exported symbols defined in the relevant slice of the TapiUniv...

Definition MachO.cpp:389

LLVM_ABI Expected< std::pair< std::unique_ptr< MemoryBuffer >, LinkableFileKind > > loadLinkableSliceFromMachOUniversalBinary(sys::fs::file_t FD, std::unique_ptr< MemoryBuffer > UBBuf, const Triple &TT, LoadArchives LA, StringRef UBPath, StringRef Identifier)

Load a compatible relocatable object (if available) from a MachO universal binary.

Definition MachO.cpp:145

unique_function< SmallVector< std::pair< uint32_t, uint32_t > >( uint32_t CPUType, uint32_t CPUSubType)> GetFallbackArchsFn

LLVM_ABI SmallVector< std::pair< uint32_t, uint32_t > > standardMachOFallbackArchs(uint32_t CPUType, uint32_t CPUSubType)

Match standard dynamic loader fallback rules.

Definition MachO.cpp:293

LLVM_ABI Expected< SymbolNameSet > getDylibInterface(ExecutionSession &ES, Twine Path, GetFallbackArchsFn GetFallbackArchs=standardMachOFallbackArchs)

Returns a SymbolNameSet containing the exported symbols defined in the relevant slice of the given fi...

Definition MachO.cpp:438

LLVM_ABI Error checkMachORelocatableObject(MemoryBufferRef Obj, const Triple &TT, bool ObjIsSlice)

Check that the given buffer contains a MachO object file compatible with the given triple.

Definition MachO.cpp:61

LLVM_ABI 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:205

LLVM_ABI Expected< SymbolNameSet > getDylibInterfaceFromDylib(ExecutionSession &ES, Twine Path, GetFallbackArchsFn GetFallbackArchs=standardMachOFallbackArchs)

Returns a SymbolNameSet containing the exported symbols defined in the given dylib.

Definition MachO.cpp:318

DenseSet< SymbolStringPtr > SymbolNameSet

A set of symbol names (represented by SymbolStringPtrs for.

static std::string objDesc(const MemoryBufferRef &Obj, const Triple &TT, bool ObjIsSlice)

Definition MachO.cpp:25

Expected< std::pair< std::unique_ptr< MemoryBuffer >, LinkableFileKind > > loadMachORelocatableObject(StringRef Path, const Triple &TT, LoadArchives LA, std::optional< StringRef > IdentifierOverride)

Definition MachO.cpp:101

LLVM_ABI std::error_code closeFile(file_t &F)

Close the file object.

LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)

Opens the file with the given name in a read-only mode, returning its open file descriptor.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI file_magic identify_magic(StringRef magic)

Identify the type of a binary file based on how magical it is.

Error createFileError(const Twine &F, Error E)

Concatenate a source file path and/or name with an Error.

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

void consumeError(Error Err)

Consume a Error without doing anything.

file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...

@ archive

ar style archive file

@ macho_dynamically_linked_shared_lib

Mach-O dynlinked shared lib.

@ macho_universal_binary

Mach-O universal binary.

@ macho_object

Mach-O Object file.

@ tapi_file

Text-based Dynamic Library Stub file.