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
18 using namespace llvm;
19 using namespace MachO;
20 using namespace object;
21
22 static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
23 static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
24 static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
25 static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
26 static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
27
getFlags(const Symbol * Sym)28 static uint32_t getFlags(const Symbol *Sym) {
29 uint32_t Flags = BasicSymbolRef::SF_Global;
30 if (Sym->isUndefined())
31 Flags |= BasicSymbolRef::SF_Undefined;
32 else
33 Flags |= BasicSymbolRef::SF_Exported;
34
35 if (Sym->isWeakDefined() || Sym->isWeakReferenced())
36 Flags |= BasicSymbolRef::SF_Weak;
37
38 return Flags;
39 }
40
TapiFile(MemoryBufferRef Source,const InterfaceFile & interface,Architecture Arch)41 TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
42 Architecture Arch)
43 : SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
44 for (const auto *Symbol : interface.symbols()) {
45 if (!Symbol->getArchitectures().has(Arch))
46 continue;
47
48 switch (Symbol->getKind()) {
49 case SymbolKind::GlobalSymbol:
50 Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
51 break;
52 case SymbolKind::ObjectiveCClass:
53 if (interface.getPlatforms().count(PlatformKind::macOS) &&
54 Arch == AK_i386) {
55 Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
56 getFlags(Symbol));
57 } else {
58 Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
59 getFlags(Symbol));
60 Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
61 getFlags(Symbol));
62 }
63 break;
64 case SymbolKind::ObjectiveCClassEHType:
65 Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
66 getFlags(Symbol));
67 break;
68 case SymbolKind::ObjectiveCInstanceVariable:
69 Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
70 getFlags(Symbol));
71 break;
72 }
73 }
74 }
75
76 TapiFile::~TapiFile() = default;
77
moveSymbolNext(DataRefImpl & DRI) const78 void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
79
printSymbolName(raw_ostream & OS,DataRefImpl DRI) const80 Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
81 assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
82 const Symbol &Sym = Symbols[DRI.d.a];
83 OS << Sym.Prefix << Sym.Name;
84 return Error::success();
85 }
86
getSymbolFlags(DataRefImpl DRI) const87 Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
88 assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
89 return Symbols[DRI.d.a].Flags;
90 }
91
symbol_begin() const92 basic_symbol_iterator TapiFile::symbol_begin() const {
93 DataRefImpl DRI;
94 DRI.d.a = 0;
95 return BasicSymbolRef{DRI, this};
96 }
97
symbol_end() const98 basic_symbol_iterator TapiFile::symbol_end() const {
99 DataRefImpl DRI;
100 DRI.d.a = Symbols.size();
101 return BasicSymbolRef{DRI, this};
102 }
103