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>;
emplace(TripleVec & Container,Triple && T)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 
constructTriples(MachOObjectFile * Obj,const Architecture ArchT)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 
readMachOHeader(MachOObjectFile * Obj,RecordsSlice & Slice)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 
readSymbols(MachOObjectFile * Obj,RecordsSlice & Slice,const ParseOption & Opt)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 
load(MachOObjectFile * Obj,RecordsSlice & Slice,const ParseOption & Opt,const Architecture Arch)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 
readFile(MemoryBufferRef Buffer,const ParseOption & Opt)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>>
get(MemoryBufferRef Buffer)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