|
10 | 10 |
|
11 | 11 | #include "llvm/ADT/ScopeExit.h" |
12 | 12 | #include "llvm/BinaryFormat/MachO.h" |
| 13 | +#include "llvm/BinaryFormat/Magic.h" |
13 | 14 | #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" |
14 | 15 | #include "llvm/ExecutionEngine/Orc/Layer.h" |
15 | 16 | #include "llvm/Object/MachOUniversal.h" |
| 17 | +#include "llvm/Object/TapiUniversal.h" |
16 | 18 | #include "llvm/Support/FileSystem.h" |
17 | 19 |
|
18 | 20 | #define DEBUG_TYPE "orc" |
@@ -280,5 +282,113 @@ Expected<bool> ForceLoadMachOArchiveMembers::operator()( |
280 | 282 | return true; |
281 | 283 | } |
282 | 284 |
|
| 285 | +Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES, |
| 286 | + Twine Path) { |
| 287 | + auto CPUType = MachO::getCPUType(ES.getTargetTriple()); |
| 288 | + if (!CPUType) |
| 289 | + return CPUType.takeError(); |
| 290 | + |
| 291 | + auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple()); |
| 292 | + if (!CPUSubType) |
| 293 | + return CPUSubType.takeError(); |
| 294 | + |
| 295 | + auto Buf = MemoryBuffer::getFile(Path); |
| 296 | + if (!Buf) |
| 297 | + return createFileError(Path, Buf.getError()); |
| 298 | + |
| 299 | + auto BinFile = object::createBinary((*Buf)->getMemBufferRef()); |
| 300 | + if (!BinFile) |
| 301 | + return BinFile.takeError(); |
| 302 | + |
| 303 | + std::unique_ptr<object::MachOObjectFile> MachOFile; |
| 304 | + if (isa<object::MachOObjectFile>(**BinFile)) |
| 305 | + MachOFile.reset(dyn_cast<object::MachOObjectFile>(BinFile->release())); |
| 306 | + else if (auto *MachOUni = |
| 307 | + dyn_cast<object::MachOUniversalBinary>(BinFile->get())) { |
| 308 | + for (auto &O : MachOUni->objects()) { |
| 309 | + if (O.getCPUType() == *CPUType && |
| 310 | + (O.getCPUSubType() & ~MachO::CPU_SUBTYPE_MASK) == *CPUSubType) { |
| 311 | + if (auto Obj = O.getAsObjectFile()) |
| 312 | + MachOFile = std::move(*Obj); |
| 313 | + else |
| 314 | + return Obj.takeError(); |
| 315 | + break; |
| 316 | + } |
| 317 | + } |
| 318 | + if (!MachOFile) |
| 319 | + return make_error<StringError>("MachO universal binary at " + Path + |
| 320 | + " does not contain a slice for " + |
| 321 | + ES.getTargetTriple().str(), |
| 322 | + inconvertibleErrorCode()); |
| 323 | + } else |
| 324 | + return make_error<StringError>("File at " + Path + " is not a MachO", |
| 325 | + inconvertibleErrorCode()); |
| 326 | + |
| 327 | + if (MachOFile->getHeader().filetype != MachO::MH_DYLIB) |
| 328 | + return make_error<StringError>("MachO at " + Path + " is not a dylib", |
| 329 | + inconvertibleErrorCode()); |
| 330 | + |
| 331 | + SymbolNameSet Symbols; |
| 332 | + for (auto &Sym : MachOFile->symbols()) { |
| 333 | + if (auto Name = Sym.getName()) |
| 334 | + Symbols.insert(ES.intern(*Name)); |
| 335 | + else |
| 336 | + return Name.takeError(); |
| 337 | + } |
| 338 | + |
| 339 | + return std::move(Symbols); |
| 340 | +} |
| 341 | + |
| 342 | +Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES, |
| 343 | + Twine Path) { |
| 344 | + SymbolNameSet Symbols; |
| 345 | + |
| 346 | + auto TapiFileBuffer = MemoryBuffer::getFile(Path); |
| 347 | + if (!TapiFileBuffer) |
| 348 | + return createFileError(Path, TapiFileBuffer.getError()); |
| 349 | + |
| 350 | + auto Tapi = |
| 351 | + object::TapiUniversal::create((*TapiFileBuffer)->getMemBufferRef()); |
| 352 | + if (!Tapi) |
| 353 | + return Tapi.takeError(); |
| 354 | + |
| 355 | + auto CPUType = MachO::getCPUType(ES.getTargetTriple()); |
| 356 | + if (!CPUType) |
| 357 | + return CPUType.takeError(); |
| 358 | + |
| 359 | + auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple()); |
| 360 | + if (!CPUSubType) |
| 361 | + return CPUSubType.takeError(); |
| 362 | + |
| 363 | + auto &IF = (*Tapi)->getInterfaceFile(); |
| 364 | + auto Interface = |
| 365 | + IF.extract(MachO::getArchitectureFromCpuType(*CPUType, *CPUSubType)); |
| 366 | + if (!Interface) |
| 367 | + return Interface.takeError(); |
| 368 | + |
| 369 | + for (auto *Sym : (*Interface)->exports()) |
| 370 | + Symbols.insert(ES.intern(Sym->getName())); |
| 371 | + |
| 372 | + return Symbols; |
| 373 | +} |
| 374 | + |
| 375 | +Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path) { |
| 376 | + file_magic Magic; |
| 377 | + if (auto EC = identify_magic(Path, Magic)) |
| 378 | + return createFileError(Path, EC); |
| 379 | + |
| 380 | + switch (Magic) { |
| 381 | + case file_magic::macho_universal_binary: |
| 382 | + case file_magic::macho_dynamically_linked_shared_lib: |
| 383 | + return getDylibInterfaceFromDylib(ES, Path); |
| 384 | + case file_magic::tapi_file: |
| 385 | + return getDylibInterfaceFromTapiFile(ES, Path); |
| 386 | + default: |
| 387 | + return make_error<StringError>("Cannot get interface for " + Path + |
| 388 | + " unrecognized file type", |
| 389 | + inconvertibleErrorCode()); |
| 390 | + } |
| 391 | +} |
| 392 | + |
283 | 393 | } // End namespace orc. |
284 | 394 | } // End namespace llvm. |
0 commit comments