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
23using namespace llvm;
24using namespace MachO;
25using namespace object;
26
27static 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
40static 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
50TapiFile::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
86TapiFile::~TapiFile() = default;
87
88void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
89
90Error 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
97Expected<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
102Expected<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
107basic_symbol_iterator TapiFile::symbol_begin() const {
108 DataRefImpl DRI;
109 DRI.d.a = 0;
110 return BasicSymbolRef{DRI, this};
111}
112
113basic_symbol_iterator TapiFile::symbol_end() const {
114 DataRefImpl DRI;
115 DRI.d.a = Symbols.size();
116 return BasicSymbolRef{DRI, this};
117}
118