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