1 //===- TapiFile.cpp -------------------------------------------------------===//
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 //
9 // This file defines the Text-based Dynamcic Library Stub format.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Object/TapiFile.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Object/Error.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/TextAPI/Symbol.h"
18 
19 using namespace llvm;
20 using namespace MachO;
21 using namespace object;
22 
23 static uint32_t getFlags(const Symbol *Sym) {
24   uint32_t Flags = BasicSymbolRef::SF_Global;
25   if (Sym->isUndefined())
26     Flags |= BasicSymbolRef::SF_Undefined;
27   else
28     Flags |= BasicSymbolRef::SF_Exported;
29 
30   if (Sym->isWeakDefined() || Sym->isWeakReferenced())
31     Flags |= BasicSymbolRef::SF_Weak;
32 
33   return Flags;
34 }
35 
36 TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
37                    Architecture Arch)
38     : SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
39   for (const auto *Symbol : interface.symbols()) {
40     if (!Symbol->getArchitectures().has(Arch))
41       continue;
42 
43     switch (Symbol->getKind()) {
44     case SymbolKind::GlobalSymbol:
45       Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
46       break;
47     case SymbolKind::ObjectiveCClass:
48       if (interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
49         Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
50                              getFlags(Symbol));
51       } else {
52         Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
53                              getFlags(Symbol));
54         Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
55                              getFlags(Symbol));
56       }
57       break;
58     case SymbolKind::ObjectiveCClassEHType:
59       Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
60                            getFlags(Symbol));
61       break;
62     case SymbolKind::ObjectiveCInstanceVariable:
63       Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
64                            getFlags(Symbol));
65       break;
66     }
67   }
68 }
69 
70 TapiFile::~TapiFile() = default;
71 
72 void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
73 
74 Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
75   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
76   const Symbol &Sym = Symbols[DRI.d.a];
77   OS << Sym.Prefix << Sym.Name;
78   return Error::success();
79 }
80 
81 Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
82   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
83   return Symbols[DRI.d.a].Flags;
84 }
85 
86 basic_symbol_iterator TapiFile::symbol_begin() const {
87   DataRefImpl DRI;
88   DRI.d.a = 0;
89   return BasicSymbolRef{DRI, this};
90 }
91 
92 basic_symbol_iterator TapiFile::symbol_end() const {
93   DataRefImpl DRI;
94   DRI.d.a = Symbols.size();
95   return BasicSymbolRef{DRI, this};
96 }
97