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 EncodeKind::GlobalSymbol: |
60 | Symbols.emplace_back(args: StringRef(), args: Symbol->getName(), args: getFlags(Sym: Symbol), |
61 | args: ::getType(Sym: Symbol)); |
62 | break; |
63 | case EncodeKind::ObjectiveCClass: |
64 | if (Interface.getPlatforms().count(V: PLATFORM_MACOS) && Arch == AK_i386) { |
65 | Symbols.emplace_back(args: ObjC1ClassNamePrefix, args: Symbol->getName(), |
66 | args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol)); |
67 | } else { |
68 | Symbols.emplace_back(args: ObjC2ClassNamePrefix, args: Symbol->getName(), |
69 | args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol)); |
70 | Symbols.emplace_back(args: ObjC2MetaClassNamePrefix, args: Symbol->getName(), |
71 | args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol)); |
72 | } |
73 | break; |
74 | case EncodeKind::ObjectiveCClassEHType: |
75 | Symbols.emplace_back(args: ObjC2EHTypePrefix, args: Symbol->getName(), |
76 | args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol)); |
77 | break; |
78 | case EncodeKind::ObjectiveCInstanceVariable: |
79 | Symbols.emplace_back(args: ObjC2IVarPrefix, args: Symbol->getName(), args: getFlags(Sym: Symbol), |
80 | args: ::getType(Sym: 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 | |