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/BinaryFormat/MachO.h"
16 #include "llvm/Object/Error.h"
17 #include "llvm/Support/MemoryBufferRef.h"
18 #include "llvm/TextAPI/ArchitectureSet.h"
19 #include "llvm/TextAPI/InterfaceFile.h"
20 #include "llvm/TextAPI/Platform.h"
21 #include "llvm/TextAPI/Symbol.h"
22 
23 using namespace llvm;
24 using namespace MachO;
25 using namespace object;
26 
27 static uint32_t getFlags(const Symbol *Sym) {
28   uint32_t Flags = BasicSymbolRef::SF_Global;
29   if (Sym->isUndefined())
30     Flags |= BasicSymbolRef::SF_Undefined;
31   else
32     Flags |= BasicSymbolRef::SF_Exported;
33 
34   if (Sym->isWeakDefined() || Sym->isWeakReferenced())
35     Flags |= BasicSymbolRef::SF_Weak;
36 
37   return Flags;
38 }
39 
40 static SymbolRef::Type getType(const Symbol *Sym) {
41   SymbolRef::Type Type = SymbolRef::ST_Unknown;
42   if (Sym->isData())
43     Type = SymbolRef::ST_Data;
44   else if (Sym->isText())
45     Type = SymbolRef::ST_Function;
46 
47   return Type;
48 }
49 
50 TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
51                    Architecture Arch)
52     : SymbolicFile(ID_TapiFile, Source), Arch(Arch),
53       FileKind(Interface.getFileType()) {
54   for (const auto *Symbol : Interface.symbols()) {
55     if (!Symbol->getArchitectures().has(Arch))
56       continue;
57 
58     switch (Symbol->getKind()) {
59     case SymbolKind::GlobalSymbol:
60       Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol),
61                            ::getType(Symbol));
62       break;
63     case SymbolKind::ObjectiveCClass:
64       if (Interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
65         Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
66                              getFlags(Symbol), ::getType(Symbol));
67       } else {
68         Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
69                              getFlags(Symbol), ::getType(Symbol));
70         Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
71                              getFlags(Symbol), ::getType(Symbol));
72       }
73       break;
74     case SymbolKind::ObjectiveCClassEHType:
75       Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
76                            getFlags(Symbol), ::getType(Symbol));
77       break;
78     case SymbolKind::ObjectiveCInstanceVariable:
79       Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(), getFlags(Symbol),
80                            ::getType(Symbol));
81       break;
82     }
83   }
84 }
85 
86 TapiFile::~TapiFile() = default;
87 
88 void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
89 
90 Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
91   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
92   const Symbol &Sym = Symbols[DRI.d.a];
93   OS << Sym.Prefix << Sym.Name;
94   return Error::success();
95 }
96 
97 Expected<SymbolRef::Type> TapiFile::getSymbolType(DataRefImpl DRI) const {
98   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
99   return Symbols[DRI.d.a].Type;
100 }
101 
102 Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
103   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
104   return Symbols[DRI.d.a].Flags;
105 }
106 
107 basic_symbol_iterator TapiFile::symbol_begin() const {
108   DataRefImpl DRI;
109   DRI.d.a = 0;
110   return BasicSymbolRef{DRI, this};
111 }
112 
113 basic_symbol_iterator TapiFile::symbol_end() const {
114   DataRefImpl DRI;
115   DRI.d.a = Symbols.size();
116   return BasicSymbolRef{DRI, this};
117 }
118