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
22using namespace llvm;
23using namespace MachO;
24using namespace object;
25
26static 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
39static 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
49TapiFile::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(args: StringRef(), args: Symbol->getName(), args: getFlags(Sym: Symbol),
60 args: ::getType(Sym: Symbol));
61 break;
62 case EncodeKind::ObjectiveCClass:
63 if (Interface.getPlatforms().count(V: PLATFORM_MACOS) && Arch == AK_i386) {
64 Symbols.emplace_back(args: ObjC1ClassNamePrefix, args: Symbol->getName(),
65 args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol));
66 } else {
67 Symbols.emplace_back(args: ObjC2ClassNamePrefix, args: Symbol->getName(),
68 args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol));
69 Symbols.emplace_back(args: ObjC2MetaClassNamePrefix, args: Symbol->getName(),
70 args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol));
71 }
72 break;
73 case EncodeKind::ObjectiveCClassEHType:
74 Symbols.emplace_back(args: ObjC2EHTypePrefix, args: Symbol->getName(),
75 args: getFlags(Sym: Symbol), args: ::getType(Sym: Symbol));
76 break;
77 case EncodeKind::ObjectiveCInstanceVariable:
78 Symbols.emplace_back(args: ObjC2IVarPrefix, args: Symbol->getName(), args: getFlags(Sym: Symbol),
79 args: ::getType(Sym: Symbol));
80 break;
81 }
82 }
83}
84
85TapiFile::~TapiFile() = default;
86
87void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
88
89Error 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
96Expected<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
101Expected<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
106basic_symbol_iterator TapiFile::symbol_begin() const {
107 DataRefImpl DRI;
108 DRI.d.a = 0;
109 return BasicSymbolRef{DRI, this};
110}
111
112basic_symbol_iterator TapiFile::symbol_end() const {
113 DataRefImpl DRI;
114 DRI.d.a = Symbols.size();
115 return BasicSymbolRef{DRI, this};
116}
117