18bcb0991SDimitry Andric //===- TapiFile.cpp -------------------------------------------------------===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric //
98bcb0991SDimitry Andric // This file defines the Text-based Dynamcic Library Stub format.
108bcb0991SDimitry Andric //
118bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
128bcb0991SDimitry Andric 
138bcb0991SDimitry Andric #include "llvm/Object/TapiFile.h"
148bcb0991SDimitry Andric #include "llvm/ADT/StringRef.h"
1581ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
168bcb0991SDimitry Andric #include "llvm/Object/Error.h"
1781ad6265SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
1881ad6265SDimitry Andric #include "llvm/TextAPI/ArchitectureSet.h"
1981ad6265SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
2081ad6265SDimitry Andric #include "llvm/TextAPI/Platform.h"
21fe6060f1SDimitry Andric #include "llvm/TextAPI/Symbol.h"
228bcb0991SDimitry Andric 
238bcb0991SDimitry Andric using namespace llvm;
248bcb0991SDimitry Andric using namespace MachO;
258bcb0991SDimitry Andric using namespace object;
268bcb0991SDimitry Andric 
getFlags(const Symbol * Sym)278bcb0991SDimitry Andric static uint32_t getFlags(const Symbol *Sym) {
288bcb0991SDimitry Andric   uint32_t Flags = BasicSymbolRef::SF_Global;
298bcb0991SDimitry Andric   if (Sym->isUndefined())
308bcb0991SDimitry Andric     Flags |= BasicSymbolRef::SF_Undefined;
318bcb0991SDimitry Andric   else
328bcb0991SDimitry Andric     Flags |= BasicSymbolRef::SF_Exported;
338bcb0991SDimitry Andric 
348bcb0991SDimitry Andric   if (Sym->isWeakDefined() || Sym->isWeakReferenced())
358bcb0991SDimitry Andric     Flags |= BasicSymbolRef::SF_Weak;
368bcb0991SDimitry Andric 
378bcb0991SDimitry Andric   return Flags;
388bcb0991SDimitry Andric }
398bcb0991SDimitry Andric 
getType(const Symbol * Sym)4006c3fb27SDimitry Andric static SymbolRef::Type getType(const Symbol *Sym) {
4106c3fb27SDimitry Andric   SymbolRef::Type Type = SymbolRef::ST_Unknown;
4206c3fb27SDimitry Andric   if (Sym->isData())
4306c3fb27SDimitry Andric     Type = SymbolRef::ST_Data;
4406c3fb27SDimitry Andric   else if (Sym->isText())
4506c3fb27SDimitry Andric     Type = SymbolRef::ST_Function;
4606c3fb27SDimitry Andric 
4706c3fb27SDimitry Andric   return Type;
4806c3fb27SDimitry Andric }
4906c3fb27SDimitry Andric 
TapiFile(MemoryBufferRef Source,const InterfaceFile & Interface,Architecture Arch)5006c3fb27SDimitry Andric TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
518bcb0991SDimitry Andric                    Architecture Arch)
52*5f757f3fSDimitry Andric     : SymbolicFile(ID_TapiFile, Source), Arch(Arch),
53*5f757f3fSDimitry Andric       FileKind(Interface.getFileType()) {
5406c3fb27SDimitry Andric   for (const auto *Symbol : Interface.symbols()) {
558bcb0991SDimitry Andric     if (!Symbol->getArchitectures().has(Arch))
568bcb0991SDimitry Andric       continue;
578bcb0991SDimitry Andric 
588bcb0991SDimitry Andric     switch (Symbol->getKind()) {
598bcb0991SDimitry Andric     case SymbolKind::GlobalSymbol:
6006c3fb27SDimitry Andric       Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol),
6106c3fb27SDimitry Andric                            ::getType(Symbol));
628bcb0991SDimitry Andric       break;
638bcb0991SDimitry Andric     case SymbolKind::ObjectiveCClass:
6406c3fb27SDimitry Andric       if (Interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
658bcb0991SDimitry Andric         Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
6606c3fb27SDimitry Andric                              getFlags(Symbol), ::getType(Symbol));
678bcb0991SDimitry Andric       } else {
688bcb0991SDimitry Andric         Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
6906c3fb27SDimitry Andric                              getFlags(Symbol), ::getType(Symbol));
708bcb0991SDimitry Andric         Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
7106c3fb27SDimitry Andric                              getFlags(Symbol), ::getType(Symbol));
728bcb0991SDimitry Andric       }
738bcb0991SDimitry Andric       break;
748bcb0991SDimitry Andric     case SymbolKind::ObjectiveCClassEHType:
758bcb0991SDimitry Andric       Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
7606c3fb27SDimitry Andric                            getFlags(Symbol), ::getType(Symbol));
778bcb0991SDimitry Andric       break;
788bcb0991SDimitry Andric     case SymbolKind::ObjectiveCInstanceVariable:
7906c3fb27SDimitry Andric       Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(), getFlags(Symbol),
8006c3fb27SDimitry Andric                            ::getType(Symbol));
818bcb0991SDimitry Andric       break;
828bcb0991SDimitry Andric     }
838bcb0991SDimitry Andric   }
848bcb0991SDimitry Andric }
858bcb0991SDimitry Andric 
868bcb0991SDimitry Andric TapiFile::~TapiFile() = default;
878bcb0991SDimitry Andric 
moveSymbolNext(DataRefImpl & DRI) const885ffd83dbSDimitry Andric void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
898bcb0991SDimitry Andric 
printSymbolName(raw_ostream & OS,DataRefImpl DRI) const908bcb0991SDimitry Andric Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
915ffd83dbSDimitry Andric   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
925ffd83dbSDimitry Andric   const Symbol &Sym = Symbols[DRI.d.a];
935ffd83dbSDimitry Andric   OS << Sym.Prefix << Sym.Name;
948bcb0991SDimitry Andric   return Error::success();
958bcb0991SDimitry Andric }
968bcb0991SDimitry Andric 
getSymbolType(DataRefImpl DRI) const9706c3fb27SDimitry Andric Expected<SymbolRef::Type> TapiFile::getSymbolType(DataRefImpl DRI) const {
9806c3fb27SDimitry Andric   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
9906c3fb27SDimitry Andric   return Symbols[DRI.d.a].Type;
10006c3fb27SDimitry Andric }
10106c3fb27SDimitry Andric 
getSymbolFlags(DataRefImpl DRI) const1025ffd83dbSDimitry Andric Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
1035ffd83dbSDimitry Andric   assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
1045ffd83dbSDimitry Andric   return Symbols[DRI.d.a].Flags;
1058bcb0991SDimitry Andric }
1068bcb0991SDimitry Andric 
symbol_begin() const1078bcb0991SDimitry Andric basic_symbol_iterator TapiFile::symbol_begin() const {
1088bcb0991SDimitry Andric   DataRefImpl DRI;
1095ffd83dbSDimitry Andric   DRI.d.a = 0;
1108bcb0991SDimitry Andric   return BasicSymbolRef{DRI, this};
1118bcb0991SDimitry Andric }
1128bcb0991SDimitry Andric 
symbol_end() const1138bcb0991SDimitry Andric basic_symbol_iterator TapiFile::symbol_end() const {
1148bcb0991SDimitry Andric   DataRefImpl DRI;
1155ffd83dbSDimitry Andric   DRI.d.a = Symbols.size();
1168bcb0991SDimitry Andric   return BasicSymbolRef{DRI, this};
1178bcb0991SDimitry Andric }
118