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