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