1*cb14a3feSDimitry Andric //===- DylibReader.cpp -------------- TAPI MachO Dylib Reader --*- C++ -*-===// 2*cb14a3feSDimitry Andric // 3*cb14a3feSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*cb14a3feSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*cb14a3feSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*cb14a3feSDimitry Andric // 7*cb14a3feSDimitry Andric //===----------------------------------------------------------------------===// 8*cb14a3feSDimitry Andric /// 9*cb14a3feSDimitry Andric /// Implements the TAPI Reader for Mach-O dynamic libraries. 10*cb14a3feSDimitry Andric /// 11*cb14a3feSDimitry Andric //===----------------------------------------------------------------------===// 12*cb14a3feSDimitry Andric 13*cb14a3feSDimitry Andric #include "llvm/TextAPI/DylibReader.h" 14*cb14a3feSDimitry Andric #include "llvm/ADT/STLExtras.h" 15*cb14a3feSDimitry Andric #include "llvm/ADT/StringMap.h" 16*cb14a3feSDimitry Andric #include "llvm/Object/Binary.h" 17*cb14a3feSDimitry Andric #include "llvm/Object/MachOUniversal.h" 18*cb14a3feSDimitry Andric #include "llvm/Support/Endian.h" 19*cb14a3feSDimitry Andric #include "llvm/TargetParser/Triple.h" 20*cb14a3feSDimitry Andric #include "llvm/TextAPI/RecordsSlice.h" 21*cb14a3feSDimitry Andric #include "llvm/TextAPI/TextAPIError.h" 22*cb14a3feSDimitry Andric #include <iomanip> 23*cb14a3feSDimitry Andric #include <set> 24*cb14a3feSDimitry Andric #include <sstream> 25*cb14a3feSDimitry Andric #include <string> 26*cb14a3feSDimitry Andric #include <tuple> 27*cb14a3feSDimitry Andric 28*cb14a3feSDimitry Andric using namespace llvm; 29*cb14a3feSDimitry Andric using namespace llvm::object; 30*cb14a3feSDimitry Andric using namespace llvm::MachO; 31*cb14a3feSDimitry Andric using namespace llvm::MachO::DylibReader; 32*cb14a3feSDimitry Andric 33*cb14a3feSDimitry Andric using TripleVec = std::vector<Triple>; 34*cb14a3feSDimitry Andric static typename TripleVec::iterator emplace(TripleVec &Container, Triple &&T) { 35*cb14a3feSDimitry Andric auto I = partition_point(Container, [=](const Triple &CT) { 36*cb14a3feSDimitry Andric return std::forward_as_tuple(CT.getArch(), CT.getOS(), 37*cb14a3feSDimitry Andric CT.getEnvironment()) < 38*cb14a3feSDimitry Andric std::forward_as_tuple(T.getArch(), T.getOS(), T.getEnvironment()); 39*cb14a3feSDimitry Andric }); 40*cb14a3feSDimitry Andric 41*cb14a3feSDimitry Andric if (I != Container.end() && *I == T) 42*cb14a3feSDimitry Andric return I; 43*cb14a3feSDimitry Andric return Container.emplace(I, T); 44*cb14a3feSDimitry Andric } 45*cb14a3feSDimitry Andric 46*cb14a3feSDimitry Andric static TripleVec constructTriples(MachOObjectFile *Obj, 47*cb14a3feSDimitry Andric const Architecture ArchT) { 48*cb14a3feSDimitry Andric auto getOSVersionStr = [](uint32_t V) { 49*cb14a3feSDimitry Andric PackedVersion OSVersion(V); 50*cb14a3feSDimitry Andric std::string Vers; 51*cb14a3feSDimitry Andric raw_string_ostream VStream(Vers); 52*cb14a3feSDimitry Andric VStream << OSVersion; 53*cb14a3feSDimitry Andric return VStream.str(); 54*cb14a3feSDimitry Andric }; 55*cb14a3feSDimitry Andric auto getOSVersion = [&](const MachOObjectFile::LoadCommandInfo &cmd) { 56*cb14a3feSDimitry Andric auto Vers = Obj->getVersionMinLoadCommand(cmd); 57*cb14a3feSDimitry Andric return getOSVersionStr(Vers.version); 58*cb14a3feSDimitry Andric }; 59*cb14a3feSDimitry Andric 60*cb14a3feSDimitry Andric TripleVec Triples; 61*cb14a3feSDimitry Andric bool IsIntel = ArchitectureSet(ArchT).hasX86(); 62*cb14a3feSDimitry Andric auto Arch = getArchitectureName(ArchT); 63*cb14a3feSDimitry Andric 64*cb14a3feSDimitry Andric for (const auto &cmd : Obj->load_commands()) { 65*cb14a3feSDimitry Andric std::string OSVersion; 66*cb14a3feSDimitry Andric switch (cmd.C.cmd) { 67*cb14a3feSDimitry Andric case MachO::LC_VERSION_MIN_MACOSX: 68*cb14a3feSDimitry Andric OSVersion = getOSVersion(cmd); 69*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "macos" + OSVersion}); 70*cb14a3feSDimitry Andric break; 71*cb14a3feSDimitry Andric case MachO::LC_VERSION_MIN_IPHONEOS: 72*cb14a3feSDimitry Andric OSVersion = getOSVersion(cmd); 73*cb14a3feSDimitry Andric if (IsIntel) 74*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "ios" + OSVersion, "simulator"}); 75*cb14a3feSDimitry Andric else 76*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "ios" + OSVersion}); 77*cb14a3feSDimitry Andric break; 78*cb14a3feSDimitry Andric case MachO::LC_VERSION_MIN_TVOS: 79*cb14a3feSDimitry Andric OSVersion = getOSVersion(cmd); 80*cb14a3feSDimitry Andric if (IsIntel) 81*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "tvos" + OSVersion, "simulator"}); 82*cb14a3feSDimitry Andric else 83*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "tvos" + OSVersion}); 84*cb14a3feSDimitry Andric break; 85*cb14a3feSDimitry Andric case MachO::LC_VERSION_MIN_WATCHOS: 86*cb14a3feSDimitry Andric OSVersion = getOSVersion(cmd); 87*cb14a3feSDimitry Andric if (IsIntel) 88*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "watchos" + OSVersion, "simulator"}); 89*cb14a3feSDimitry Andric else 90*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "watchos" + OSVersion}); 91*cb14a3feSDimitry Andric break; 92*cb14a3feSDimitry Andric case MachO::LC_BUILD_VERSION: { 93*cb14a3feSDimitry Andric OSVersion = getOSVersionStr(Obj->getBuildVersionLoadCommand(cmd).minos); 94*cb14a3feSDimitry Andric switch (Obj->getBuildVersionLoadCommand(cmd).platform) { 95*cb14a3feSDimitry Andric case MachO::PLATFORM_MACOS: 96*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "macos" + OSVersion}); 97*cb14a3feSDimitry Andric break; 98*cb14a3feSDimitry Andric case MachO::PLATFORM_IOS: 99*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "ios" + OSVersion}); 100*cb14a3feSDimitry Andric break; 101*cb14a3feSDimitry Andric case MachO::PLATFORM_TVOS: 102*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "tvos" + OSVersion}); 103*cb14a3feSDimitry Andric break; 104*cb14a3feSDimitry Andric case MachO::PLATFORM_WATCHOS: 105*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "watchos" + OSVersion}); 106*cb14a3feSDimitry Andric break; 107*cb14a3feSDimitry Andric case MachO::PLATFORM_BRIDGEOS: 108*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "bridgeos" + OSVersion}); 109*cb14a3feSDimitry Andric break; 110*cb14a3feSDimitry Andric case MachO::PLATFORM_MACCATALYST: 111*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "ios" + OSVersion, "macabi"}); 112*cb14a3feSDimitry Andric break; 113*cb14a3feSDimitry Andric case MachO::PLATFORM_IOSSIMULATOR: 114*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "ios" + OSVersion, "simulator"}); 115*cb14a3feSDimitry Andric break; 116*cb14a3feSDimitry Andric case MachO::PLATFORM_TVOSSIMULATOR: 117*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "tvos" + OSVersion, "simulator"}); 118*cb14a3feSDimitry Andric break; 119*cb14a3feSDimitry Andric case MachO::PLATFORM_WATCHOSSIMULATOR: 120*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "watchos" + OSVersion, "simulator"}); 121*cb14a3feSDimitry Andric break; 122*cb14a3feSDimitry Andric case MachO::PLATFORM_DRIVERKIT: 123*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "driverkit" + OSVersion}); 124*cb14a3feSDimitry Andric break; 125*cb14a3feSDimitry Andric default: 126*cb14a3feSDimitry Andric break; // Skip any others. 127*cb14a3feSDimitry Andric } 128*cb14a3feSDimitry Andric break; 129*cb14a3feSDimitry Andric } 130*cb14a3feSDimitry Andric default: 131*cb14a3feSDimitry Andric break; 132*cb14a3feSDimitry Andric } 133*cb14a3feSDimitry Andric } 134*cb14a3feSDimitry Andric 135*cb14a3feSDimitry Andric // Record unknown platform for older binaries that don't enforce platform 136*cb14a3feSDimitry Andric // load commands. 137*cb14a3feSDimitry Andric if (Triples.empty()) 138*cb14a3feSDimitry Andric emplace(Triples, {Arch, "apple", "unknown"}); 139*cb14a3feSDimitry Andric 140*cb14a3feSDimitry Andric return Triples; 141*cb14a3feSDimitry Andric } 142*cb14a3feSDimitry Andric 143*cb14a3feSDimitry Andric static Error readMachOHeader(MachOObjectFile *Obj, RecordsSlice &Slice) { 144*cb14a3feSDimitry Andric auto H = Obj->getHeader(); 145*cb14a3feSDimitry Andric auto &BA = Slice.getBinaryAttrs(); 146*cb14a3feSDimitry Andric 147*cb14a3feSDimitry Andric switch (H.filetype) { 148*cb14a3feSDimitry Andric default: 149*cb14a3feSDimitry Andric llvm_unreachable("unsupported binary type"); 150*cb14a3feSDimitry Andric case MachO::MH_DYLIB: 151*cb14a3feSDimitry Andric BA.File = FileType::MachO_DynamicLibrary; 152*cb14a3feSDimitry Andric break; 153*cb14a3feSDimitry Andric case MachO::MH_DYLIB_STUB: 154*cb14a3feSDimitry Andric BA.File = FileType::MachO_DynamicLibrary_Stub; 155*cb14a3feSDimitry Andric break; 156*cb14a3feSDimitry Andric case MachO::MH_BUNDLE: 157*cb14a3feSDimitry Andric BA.File = FileType::MachO_Bundle; 158*cb14a3feSDimitry Andric break; 159*cb14a3feSDimitry Andric } 160*cb14a3feSDimitry Andric 161*cb14a3feSDimitry Andric if (H.flags & MachO::MH_TWOLEVEL) 162*cb14a3feSDimitry Andric BA.TwoLevelNamespace = true; 163*cb14a3feSDimitry Andric if (H.flags & MachO::MH_APP_EXTENSION_SAFE) 164*cb14a3feSDimitry Andric BA.AppExtensionSafe = true; 165*cb14a3feSDimitry Andric 166*cb14a3feSDimitry Andric for (const auto &LCI : Obj->load_commands()) { 167*cb14a3feSDimitry Andric switch (LCI.C.cmd) { 168*cb14a3feSDimitry Andric case MachO::LC_ID_DYLIB: { 169*cb14a3feSDimitry Andric auto DLLC = Obj->getDylibIDLoadCommand(LCI); 170*cb14a3feSDimitry Andric BA.InstallName = Slice.copyString(LCI.Ptr + DLLC.dylib.name); 171*cb14a3feSDimitry Andric BA.CurrentVersion = DLLC.dylib.current_version; 172*cb14a3feSDimitry Andric BA.CompatVersion = DLLC.dylib.compatibility_version; 173*cb14a3feSDimitry Andric break; 174*cb14a3feSDimitry Andric } 175*cb14a3feSDimitry Andric case MachO::LC_REEXPORT_DYLIB: { 176*cb14a3feSDimitry Andric auto DLLC = Obj->getDylibIDLoadCommand(LCI); 177*cb14a3feSDimitry Andric BA.RexportedLibraries.emplace_back( 178*cb14a3feSDimitry Andric Slice.copyString(LCI.Ptr + DLLC.dylib.name)); 179*cb14a3feSDimitry Andric break; 180*cb14a3feSDimitry Andric } 181*cb14a3feSDimitry Andric case MachO::LC_SUB_FRAMEWORK: { 182*cb14a3feSDimitry Andric auto SFC = Obj->getSubFrameworkCommand(LCI); 183*cb14a3feSDimitry Andric BA.ParentUmbrella = Slice.copyString(LCI.Ptr + SFC.umbrella); 184*cb14a3feSDimitry Andric break; 185*cb14a3feSDimitry Andric } 186*cb14a3feSDimitry Andric case MachO::LC_SUB_CLIENT: { 187*cb14a3feSDimitry Andric auto SCLC = Obj->getSubClientCommand(LCI); 188*cb14a3feSDimitry Andric BA.AllowableClients.emplace_back(Slice.copyString(LCI.Ptr + SCLC.client)); 189*cb14a3feSDimitry Andric break; 190*cb14a3feSDimitry Andric } 191*cb14a3feSDimitry Andric case MachO::LC_UUID: { 192*cb14a3feSDimitry Andric auto UUIDLC = Obj->getUuidCommand(LCI); 193*cb14a3feSDimitry Andric std::stringstream Stream; 194*cb14a3feSDimitry Andric for (unsigned I = 0; I < 16; ++I) { 195*cb14a3feSDimitry Andric if (I == 4 || I == 6 || I == 8 || I == 10) 196*cb14a3feSDimitry Andric Stream << '-'; 197*cb14a3feSDimitry Andric Stream << std::setfill('0') << std::setw(2) << std::uppercase 198*cb14a3feSDimitry Andric << std::hex << static_cast<int>(UUIDLC.uuid[I]); 199*cb14a3feSDimitry Andric } 200*cb14a3feSDimitry Andric BA.UUID = Slice.copyString(Stream.str()); 201*cb14a3feSDimitry Andric break; 202*cb14a3feSDimitry Andric } 203*cb14a3feSDimitry Andric case MachO::LC_RPATH: { 204*cb14a3feSDimitry Andric auto RPLC = Obj->getRpathCommand(LCI); 205*cb14a3feSDimitry Andric BA.RPaths.emplace_back(Slice.copyString(LCI.Ptr + RPLC.path)); 206*cb14a3feSDimitry Andric break; 207*cb14a3feSDimitry Andric } 208*cb14a3feSDimitry Andric case MachO::LC_SEGMENT_SPLIT_INFO: { 209*cb14a3feSDimitry Andric auto SSILC = Obj->getLinkeditDataLoadCommand(LCI); 210*cb14a3feSDimitry Andric if (SSILC.datasize == 0) 211*cb14a3feSDimitry Andric BA.OSLibNotForSharedCache = true; 212*cb14a3feSDimitry Andric break; 213*cb14a3feSDimitry Andric } 214*cb14a3feSDimitry Andric default: 215*cb14a3feSDimitry Andric break; 216*cb14a3feSDimitry Andric } 217*cb14a3feSDimitry Andric } 218*cb14a3feSDimitry Andric 219*cb14a3feSDimitry Andric for (auto &Sect : Obj->sections()) { 220*cb14a3feSDimitry Andric auto SectName = Sect.getName(); 221*cb14a3feSDimitry Andric if (!SectName) 222*cb14a3feSDimitry Andric return SectName.takeError(); 223*cb14a3feSDimitry Andric if (*SectName != "__objc_imageinfo" && *SectName != "__image_info") 224*cb14a3feSDimitry Andric continue; 225*cb14a3feSDimitry Andric 226*cb14a3feSDimitry Andric auto Content = Sect.getContents(); 227*cb14a3feSDimitry Andric if (!Content) 228*cb14a3feSDimitry Andric return Content.takeError(); 229*cb14a3feSDimitry Andric 230*cb14a3feSDimitry Andric if ((Content->size() >= 8) && (Content->front() == 0)) { 231*cb14a3feSDimitry Andric uint32_t Flags; 232*cb14a3feSDimitry Andric if (Obj->isLittleEndian()) { 233*cb14a3feSDimitry Andric auto *p = 234*cb14a3feSDimitry Andric reinterpret_cast<const support::ulittle32_t *>(Content->data() + 4); 235*cb14a3feSDimitry Andric Flags = *p; 236*cb14a3feSDimitry Andric } else { 237*cb14a3feSDimitry Andric auto *p = 238*cb14a3feSDimitry Andric reinterpret_cast<const support::ubig32_t *>(Content->data() + 4); 239*cb14a3feSDimitry Andric Flags = *p; 240*cb14a3feSDimitry Andric } 241*cb14a3feSDimitry Andric BA.SwiftABI = (Flags >> 8) & 0xFF; 242*cb14a3feSDimitry Andric } 243*cb14a3feSDimitry Andric } 244*cb14a3feSDimitry Andric return Error::success(); 245*cb14a3feSDimitry Andric } 246*cb14a3feSDimitry Andric 247*cb14a3feSDimitry Andric static Error readSymbols(MachOObjectFile *Obj, RecordsSlice &Slice, 248*cb14a3feSDimitry Andric const ParseOption &Opt) { 249*cb14a3feSDimitry Andric 250*cb14a3feSDimitry Andric auto parseExport = [](const auto ExportFlags, 251*cb14a3feSDimitry Andric auto Addr) -> std::tuple<SymbolFlags, RecordLinkage> { 252*cb14a3feSDimitry Andric SymbolFlags Flags = SymbolFlags::None; 253*cb14a3feSDimitry Andric switch (ExportFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) { 254*cb14a3feSDimitry Andric case MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR: 255*cb14a3feSDimitry Andric if (ExportFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION) 256*cb14a3feSDimitry Andric Flags |= SymbolFlags::WeakDefined; 257*cb14a3feSDimitry Andric break; 258*cb14a3feSDimitry Andric case MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL: 259*cb14a3feSDimitry Andric Flags |= SymbolFlags::ThreadLocalValue; 260*cb14a3feSDimitry Andric break; 261*cb14a3feSDimitry Andric } 262*cb14a3feSDimitry Andric 263*cb14a3feSDimitry Andric RecordLinkage Linkage = (ExportFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) 264*cb14a3feSDimitry Andric ? RecordLinkage::Rexported 265*cb14a3feSDimitry Andric : RecordLinkage::Exported; 266*cb14a3feSDimitry Andric return {Flags, Linkage}; 267*cb14a3feSDimitry Andric }; 268*cb14a3feSDimitry Andric 269*cb14a3feSDimitry Andric Error Err = Error::success(); 270*cb14a3feSDimitry Andric 271*cb14a3feSDimitry Andric StringMap<std::pair<SymbolFlags, RecordLinkage>> Exports; 272*cb14a3feSDimitry Andric // Collect symbols from export trie first. Sometimes, there are more exports 273*cb14a3feSDimitry Andric // in the trie than in n-list due to stripping. This is common for swift 274*cb14a3feSDimitry Andric // mangled symbols. 275*cb14a3feSDimitry Andric for (auto &Sym : Obj->exports(Err)) { 276*cb14a3feSDimitry Andric auto [Flags, Linkage] = parseExport(Sym.flags(), Sym.address()); 277*cb14a3feSDimitry Andric Slice.addRecord(Sym.name(), Flags, GlobalRecord::Kind::Unknown, Linkage); 278*cb14a3feSDimitry Andric Exports[Sym.name()] = {Flags, Linkage}; 279*cb14a3feSDimitry Andric } 280*cb14a3feSDimitry Andric 281*cb14a3feSDimitry Andric for (const auto &Sym : Obj->symbols()) { 282*cb14a3feSDimitry Andric auto FlagsOrErr = Sym.getFlags(); 283*cb14a3feSDimitry Andric if (!FlagsOrErr) 284*cb14a3feSDimitry Andric return FlagsOrErr.takeError(); 285*cb14a3feSDimitry Andric auto Flags = *FlagsOrErr; 286*cb14a3feSDimitry Andric 287*cb14a3feSDimitry Andric auto NameOrErr = Sym.getName(); 288*cb14a3feSDimitry Andric if (!NameOrErr) 289*cb14a3feSDimitry Andric return NameOrErr.takeError(); 290*cb14a3feSDimitry Andric auto Name = *NameOrErr; 291*cb14a3feSDimitry Andric 292*cb14a3feSDimitry Andric RecordLinkage Linkage = RecordLinkage::Unknown; 293*cb14a3feSDimitry Andric SymbolFlags RecordFlags = SymbolFlags::None; 294*cb14a3feSDimitry Andric 295*cb14a3feSDimitry Andric if (Opt.Undefineds && (Flags & SymbolRef::SF_Undefined)) { 296*cb14a3feSDimitry Andric Linkage = RecordLinkage::Undefined; 297*cb14a3feSDimitry Andric if (Flags & SymbolRef::SF_Weak) 298*cb14a3feSDimitry Andric RecordFlags |= SymbolFlags::WeakReferenced; 299*cb14a3feSDimitry Andric } else if (Flags & SymbolRef::SF_Exported) { 300*cb14a3feSDimitry Andric auto Exp = Exports.find(Name); 301*cb14a3feSDimitry Andric // This should never be possible when binaries are produced with Apple 302*cb14a3feSDimitry Andric // linkers. However it is possible to craft dylibs where the export trie 303*cb14a3feSDimitry Andric // is either malformed or has conflicting symbols compared to n_list. 304*cb14a3feSDimitry Andric if (Exp != Exports.end()) 305*cb14a3feSDimitry Andric std::tie(RecordFlags, Linkage) = Exp->second; 306*cb14a3feSDimitry Andric else 307*cb14a3feSDimitry Andric Linkage = RecordLinkage::Exported; 308*cb14a3feSDimitry Andric } else if (Flags & SymbolRef::SF_Hidden) { 309*cb14a3feSDimitry Andric Linkage = RecordLinkage::Internal; 310*cb14a3feSDimitry Andric } else 311*cb14a3feSDimitry Andric continue; 312*cb14a3feSDimitry Andric 313*cb14a3feSDimitry Andric auto TypeOrErr = Sym.getType(); 314*cb14a3feSDimitry Andric if (!TypeOrErr) 315*cb14a3feSDimitry Andric return TypeOrErr.takeError(); 316*cb14a3feSDimitry Andric auto Type = *TypeOrErr; 317*cb14a3feSDimitry Andric 318*cb14a3feSDimitry Andric GlobalRecord::Kind GV = (Type & SymbolRef::ST_Function) 319*cb14a3feSDimitry Andric ? GlobalRecord::Kind::Function 320*cb14a3feSDimitry Andric : GlobalRecord::Kind::Variable; 321*cb14a3feSDimitry Andric 322*cb14a3feSDimitry Andric if (GV == GlobalRecord::Kind::Function) 323*cb14a3feSDimitry Andric RecordFlags |= SymbolFlags::Text; 324*cb14a3feSDimitry Andric else 325*cb14a3feSDimitry Andric RecordFlags |= SymbolFlags::Data; 326*cb14a3feSDimitry Andric 327*cb14a3feSDimitry Andric Slice.addRecord(Name, RecordFlags, GV, Linkage); 328*cb14a3feSDimitry Andric } 329*cb14a3feSDimitry Andric return Err; 330*cb14a3feSDimitry Andric } 331*cb14a3feSDimitry Andric 332*cb14a3feSDimitry Andric static Error load(MachOObjectFile *Obj, RecordsSlice &Slice, 333*cb14a3feSDimitry Andric const ParseOption &Opt, const Architecture Arch) { 334*cb14a3feSDimitry Andric if (Arch == AK_unknown) 335*cb14a3feSDimitry Andric return make_error<TextAPIError>(TextAPIErrorCode::UnsupportedTarget); 336*cb14a3feSDimitry Andric 337*cb14a3feSDimitry Andric if (Opt.MachOHeader) 338*cb14a3feSDimitry Andric if (auto Err = readMachOHeader(Obj, Slice)) 339*cb14a3feSDimitry Andric return Err; 340*cb14a3feSDimitry Andric 341*cb14a3feSDimitry Andric if (Opt.SymbolTable) 342*cb14a3feSDimitry Andric if (auto Err = readSymbols(Obj, Slice, Opt)) 343*cb14a3feSDimitry Andric return Err; 344*cb14a3feSDimitry Andric 345*cb14a3feSDimitry Andric return Error::success(); 346*cb14a3feSDimitry Andric } 347*cb14a3feSDimitry Andric 348*cb14a3feSDimitry Andric Expected<Records> DylibReader::readFile(MemoryBufferRef Buffer, 349*cb14a3feSDimitry Andric const ParseOption &Opt) { 350*cb14a3feSDimitry Andric Records Results; 351*cb14a3feSDimitry Andric 352*cb14a3feSDimitry Andric auto BinOrErr = createBinary(Buffer); 353*cb14a3feSDimitry Andric if (!BinOrErr) 354*cb14a3feSDimitry Andric return BinOrErr.takeError(); 355*cb14a3feSDimitry Andric 356*cb14a3feSDimitry Andric Binary &Bin = *BinOrErr.get(); 357*cb14a3feSDimitry Andric if (auto *Obj = dyn_cast<MachOObjectFile>(&Bin)) { 358*cb14a3feSDimitry Andric const auto Arch = getArchitectureFromCpuType(Obj->getHeader().cputype, 359*cb14a3feSDimitry Andric Obj->getHeader().cpusubtype); 360*cb14a3feSDimitry Andric if (!Opt.Archs.has(Arch)) 361*cb14a3feSDimitry Andric return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture); 362*cb14a3feSDimitry Andric 363*cb14a3feSDimitry Andric auto Triples = constructTriples(Obj, Arch); 364*cb14a3feSDimitry Andric for (const auto &T : Triples) { 365*cb14a3feSDimitry Andric if (mapToPlatformType(T) == PLATFORM_UNKNOWN) 366*cb14a3feSDimitry Andric return make_error<TextAPIError>(TextAPIErrorCode::UnsupportedTarget); 367*cb14a3feSDimitry Andric Results.emplace_back(std::make_shared<RecordsSlice>(RecordsSlice({T}))); 368*cb14a3feSDimitry Andric if (auto Err = load(Obj, *Results.back(), Opt, Arch)) 369*cb14a3feSDimitry Andric return std::move(Err); 370*cb14a3feSDimitry Andric Results.back()->getBinaryAttrs().Path = Buffer.getBufferIdentifier(); 371*cb14a3feSDimitry Andric } 372*cb14a3feSDimitry Andric return Results; 373*cb14a3feSDimitry Andric } 374*cb14a3feSDimitry Andric 375*cb14a3feSDimitry Andric // Only expect MachO universal binaries at this point. 376*cb14a3feSDimitry Andric assert(isa<MachOUniversalBinary>(&Bin) && 377*cb14a3feSDimitry Andric "Expected a MachO universal binary."); 378*cb14a3feSDimitry Andric auto *UB = cast<MachOUniversalBinary>(&Bin); 379*cb14a3feSDimitry Andric 380*cb14a3feSDimitry Andric for (auto OI = UB->begin_objects(), OE = UB->end_objects(); OI != OE; ++OI) { 381*cb14a3feSDimitry Andric // Skip architecture if not requested. 382*cb14a3feSDimitry Andric auto Arch = 383*cb14a3feSDimitry Andric getArchitectureFromCpuType(OI->getCPUType(), OI->getCPUSubType()); 384*cb14a3feSDimitry Andric if (!Opt.Archs.has(Arch)) 385*cb14a3feSDimitry Andric continue; 386*cb14a3feSDimitry Andric 387*cb14a3feSDimitry Andric // Skip unknown architectures. 388*cb14a3feSDimitry Andric if (Arch == AK_unknown) 389*cb14a3feSDimitry Andric continue; 390*cb14a3feSDimitry Andric 391*cb14a3feSDimitry Andric // This can fail if the object is an archive. 392*cb14a3feSDimitry Andric auto ObjOrErr = OI->getAsObjectFile(); 393*cb14a3feSDimitry Andric 394*cb14a3feSDimitry Andric // Skip the archive and consume the error. 395*cb14a3feSDimitry Andric if (!ObjOrErr) { 396*cb14a3feSDimitry Andric consumeError(ObjOrErr.takeError()); 397*cb14a3feSDimitry Andric continue; 398*cb14a3feSDimitry Andric } 399*cb14a3feSDimitry Andric 400*cb14a3feSDimitry Andric auto &Obj = *ObjOrErr.get(); 401*cb14a3feSDimitry Andric switch (Obj.getHeader().filetype) { 402*cb14a3feSDimitry Andric default: 403*cb14a3feSDimitry Andric break; 404*cb14a3feSDimitry Andric case MachO::MH_BUNDLE: 405*cb14a3feSDimitry Andric case MachO::MH_DYLIB: 406*cb14a3feSDimitry Andric case MachO::MH_DYLIB_STUB: 407*cb14a3feSDimitry Andric for (const auto &T : constructTriples(&Obj, Arch)) { 408*cb14a3feSDimitry Andric Results.emplace_back(std::make_shared<RecordsSlice>(RecordsSlice({T}))); 409*cb14a3feSDimitry Andric if (auto Err = load(&Obj, *Results.back(), Opt, Arch)) 410*cb14a3feSDimitry Andric return std::move(Err); 411*cb14a3feSDimitry Andric } 412*cb14a3feSDimitry Andric break; 413*cb14a3feSDimitry Andric } 414*cb14a3feSDimitry Andric } 415*cb14a3feSDimitry Andric 416*cb14a3feSDimitry Andric if (Results.empty()) 417*cb14a3feSDimitry Andric return make_error<TextAPIError>(TextAPIErrorCode::EmptyResults); 418*cb14a3feSDimitry Andric return Results; 419*cb14a3feSDimitry Andric } 420*cb14a3feSDimitry Andric 421*cb14a3feSDimitry Andric Expected<std::unique_ptr<InterfaceFile>> 422*cb14a3feSDimitry Andric DylibReader::get(MemoryBufferRef Buffer) { 423*cb14a3feSDimitry Andric ParseOption Options; 424*cb14a3feSDimitry Andric auto SlicesOrErr = readFile(Buffer, Options); 425*cb14a3feSDimitry Andric if (!SlicesOrErr) 426*cb14a3feSDimitry Andric return SlicesOrErr.takeError(); 427*cb14a3feSDimitry Andric 428*cb14a3feSDimitry Andric return convertToInterfaceFile(*SlicesOrErr); 429*cb14a3feSDimitry Andric } 430