1*c20d1f90SCyndy Ishida //===- TapiFile.cpp -------------------------------------------------------===//
2*c20d1f90SCyndy Ishida //
3*c20d1f90SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c20d1f90SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
5*c20d1f90SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c20d1f90SCyndy Ishida //
7*c20d1f90SCyndy Ishida //===----------------------------------------------------------------------===//
8*c20d1f90SCyndy Ishida //
9*c20d1f90SCyndy Ishida // This file defines the Text-based Dynamcic Library Stub format.
10*c20d1f90SCyndy Ishida //
11*c20d1f90SCyndy Ishida //===----------------------------------------------------------------------===//
12*c20d1f90SCyndy Ishida 
13*c20d1f90SCyndy Ishida #include "llvm/Object/TapiFile.h"
14*c20d1f90SCyndy Ishida #include "llvm/ADT/StringRef.h"
15*c20d1f90SCyndy Ishida #include "llvm/Object/Error.h"
16*c20d1f90SCyndy Ishida #include "llvm/Support/MemoryBuffer.h"
17*c20d1f90SCyndy Ishida 
18*c20d1f90SCyndy Ishida using namespace llvm;
19*c20d1f90SCyndy Ishida using namespace MachO;
20*c20d1f90SCyndy Ishida using namespace object;
21*c20d1f90SCyndy Ishida 
22*c20d1f90SCyndy Ishida static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
23*c20d1f90SCyndy Ishida static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
24*c20d1f90SCyndy Ishida static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
25*c20d1f90SCyndy Ishida static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
26*c20d1f90SCyndy Ishida static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
27*c20d1f90SCyndy Ishida 
28*c20d1f90SCyndy Ishida static uint32_t getFlags(const Symbol *Sym) {
29*c20d1f90SCyndy Ishida   uint32_t Flags = BasicSymbolRef::SF_Global;
30*c20d1f90SCyndy Ishida   if (Sym->isUndefined())
31*c20d1f90SCyndy Ishida     Flags |= BasicSymbolRef::SF_Undefined;
32*c20d1f90SCyndy Ishida   else
33*c20d1f90SCyndy Ishida     Flags |= BasicSymbolRef::SF_Exported;
34*c20d1f90SCyndy Ishida 
35*c20d1f90SCyndy Ishida   if (Sym->isWeakDefined() || Sym->isWeakReferenced())
36*c20d1f90SCyndy Ishida     Flags |= BasicSymbolRef::SF_Weak;
37*c20d1f90SCyndy Ishida 
38*c20d1f90SCyndy Ishida   return Flags;
39*c20d1f90SCyndy Ishida }
40*c20d1f90SCyndy Ishida 
41*c20d1f90SCyndy Ishida TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
42*c20d1f90SCyndy Ishida                    Architecture Arch)
43*c20d1f90SCyndy Ishida     : SymbolicFile(ID_TapiFile, Source) {
44*c20d1f90SCyndy Ishida   for (const auto *Symbol : interface.symbols()) {
45*c20d1f90SCyndy Ishida     if (!Symbol->getArchitectures().has(Arch))
46*c20d1f90SCyndy Ishida       continue;
47*c20d1f90SCyndy Ishida 
48*c20d1f90SCyndy Ishida     auto PlatformKind = interface.getPlatform();
49*c20d1f90SCyndy Ishida     switch (Symbol->getKind()) {
50*c20d1f90SCyndy Ishida     case SymbolKind::GlobalSymbol:
51*c20d1f90SCyndy Ishida       Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
52*c20d1f90SCyndy Ishida       break;
53*c20d1f90SCyndy Ishida     case SymbolKind::ObjectiveCClass:
54*c20d1f90SCyndy Ishida       if (PlatformKind == PlatformKind::macOS && Arch == AK_i386) {
55*c20d1f90SCyndy Ishida         Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
56*c20d1f90SCyndy Ishida                              getFlags(Symbol));
57*c20d1f90SCyndy Ishida       } else {
58*c20d1f90SCyndy Ishida         Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
59*c20d1f90SCyndy Ishida                              getFlags(Symbol));
60*c20d1f90SCyndy Ishida         Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
61*c20d1f90SCyndy Ishida                              getFlags(Symbol));
62*c20d1f90SCyndy Ishida       }
63*c20d1f90SCyndy Ishida       break;
64*c20d1f90SCyndy Ishida     case SymbolKind::ObjectiveCClassEHType:
65*c20d1f90SCyndy Ishida       Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
66*c20d1f90SCyndy Ishida                            getFlags(Symbol));
67*c20d1f90SCyndy Ishida       break;
68*c20d1f90SCyndy Ishida     case SymbolKind::ObjectiveCInstanceVariable:
69*c20d1f90SCyndy Ishida       Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
70*c20d1f90SCyndy Ishida                            getFlags(Symbol));
71*c20d1f90SCyndy Ishida       break;
72*c20d1f90SCyndy Ishida     }
73*c20d1f90SCyndy Ishida   }
74*c20d1f90SCyndy Ishida }
75*c20d1f90SCyndy Ishida 
76*c20d1f90SCyndy Ishida TapiFile::~TapiFile() = default;
77*c20d1f90SCyndy Ishida 
78*c20d1f90SCyndy Ishida void TapiFile::moveSymbolNext(DataRefImpl &DRI) const {
79*c20d1f90SCyndy Ishida   const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
80*c20d1f90SCyndy Ishida   DRI.p = reinterpret_cast<uintptr_t>(++Sym);
81*c20d1f90SCyndy Ishida }
82*c20d1f90SCyndy Ishida 
83*c20d1f90SCyndy Ishida Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
84*c20d1f90SCyndy Ishida   const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
85*c20d1f90SCyndy Ishida   OS << Sym->Prefix << Sym->Name;
86*c20d1f90SCyndy Ishida   return Error::success();
87*c20d1f90SCyndy Ishida }
88*c20d1f90SCyndy Ishida 
89*c20d1f90SCyndy Ishida uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const {
90*c20d1f90SCyndy Ishida   const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
91*c20d1f90SCyndy Ishida   return Sym->Flags;
92*c20d1f90SCyndy Ishida }
93*c20d1f90SCyndy Ishida 
94*c20d1f90SCyndy Ishida basic_symbol_iterator TapiFile::symbol_begin() const {
95*c20d1f90SCyndy Ishida   DataRefImpl DRI;
96*c20d1f90SCyndy Ishida   DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.begin());
97*c20d1f90SCyndy Ishida   return BasicSymbolRef{DRI, this};
98*c20d1f90SCyndy Ishida }
99*c20d1f90SCyndy Ishida 
100*c20d1f90SCyndy Ishida basic_symbol_iterator TapiFile::symbol_end() const {
101*c20d1f90SCyndy Ishida   DataRefImpl DRI;
102*c20d1f90SCyndy Ishida   DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.end());
103*c20d1f90SCyndy Ishida   return BasicSymbolRef{DRI, this};
104*c20d1f90SCyndy Ishida }
105