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
getFlags(const Symbol * Sym)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
TapiFile(MemoryBufferRef Source,const InterfaceFile & interface,Architecture Arch)40 TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
41 Architecture Arch)
42 : SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
43 for (const auto *Symbol : interface.symbols()) {
44 if (!Symbol->getArchitectures().has(Arch))
45 continue;
46
47 switch (Symbol->getKind()) {
48 case SymbolKind::GlobalSymbol:
49 Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
50 break;
51 case SymbolKind::ObjectiveCClass:
52 if (interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
53 Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
54 getFlags(Symbol));
55 } else {
56 Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
57 getFlags(Symbol));
58 Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
59 getFlags(Symbol));
60 }
61 break;
62 case SymbolKind::ObjectiveCClassEHType:
63 Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
64 getFlags(Symbol));
65 break;
66 case SymbolKind::ObjectiveCInstanceVariable:
67 Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
68 getFlags(Symbol));
69 break;
70 }
71 }
72 }
73
74 TapiFile::~TapiFile() = default;
75
moveSymbolNext(DataRefImpl & DRI) const76 void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
77
printSymbolName(raw_ostream & OS,DataRefImpl DRI) const78 Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
79 assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
80 const Symbol &Sym = Symbols[DRI.d.a];
81 OS << Sym.Prefix << Sym.Name;
82 return Error::success();
83 }
84
getSymbolFlags(DataRefImpl DRI) const85 Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
86 assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
87 return Symbols[DRI.d.a].Flags;
88 }
89
symbol_begin() const90 basic_symbol_iterator TapiFile::symbol_begin() const {
91 DataRefImpl DRI;
92 DRI.d.a = 0;
93 return BasicSymbolRef{DRI, this};
94 }
95
symbol_end() const96 basic_symbol_iterator TapiFile::symbol_end() const {
97 DataRefImpl DRI;
98 DRI.d.a = Symbols.size();
99 return BasicSymbolRef{DRI, this};
100 }
101