11d5ae102SDimitry Andric //===- TapiFile.cpp -------------------------------------------------------===//
21d5ae102SDimitry Andric //
31d5ae102SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d5ae102SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51d5ae102SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d5ae102SDimitry Andric //
71d5ae102SDimitry Andric //===----------------------------------------------------------------------===//
81d5ae102SDimitry Andric //
91d5ae102SDimitry Andric // This file defines the Text-based Dynamcic Library Stub format.
101d5ae102SDimitry Andric //
111d5ae102SDimitry Andric //===----------------------------------------------------------------------===//
121d5ae102SDimitry Andric
131d5ae102SDimitry Andric #include "llvm/Object/TapiFile.h"
141d5ae102SDimitry Andric #include "llvm/ADT/StringRef.h"
15145449b1SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
161d5ae102SDimitry Andric #include "llvm/Object/Error.h"
17145449b1SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
18145449b1SDimitry Andric #include "llvm/TextAPI/ArchitectureSet.h"
19145449b1SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
20145449b1SDimitry Andric #include "llvm/TextAPI/Platform.h"
21344a3780SDimitry Andric #include "llvm/TextAPI/Symbol.h"
221d5ae102SDimitry Andric
231d5ae102SDimitry Andric using namespace llvm;
241d5ae102SDimitry Andric using namespace MachO;
251d5ae102SDimitry Andric using namespace object;
261d5ae102SDimitry Andric
getFlags(const Symbol * Sym)271d5ae102SDimitry Andric static uint32_t getFlags(const Symbol *Sym) {
281d5ae102SDimitry Andric uint32_t Flags = BasicSymbolRef::SF_Global;
291d5ae102SDimitry Andric if (Sym->isUndefined())
301d5ae102SDimitry Andric Flags |= BasicSymbolRef::SF_Undefined;
311d5ae102SDimitry Andric else
321d5ae102SDimitry Andric Flags |= BasicSymbolRef::SF_Exported;
331d5ae102SDimitry Andric
341d5ae102SDimitry Andric if (Sym->isWeakDefined() || Sym->isWeakReferenced())
351d5ae102SDimitry Andric Flags |= BasicSymbolRef::SF_Weak;
361d5ae102SDimitry Andric
371d5ae102SDimitry Andric return Flags;
381d5ae102SDimitry Andric }
391d5ae102SDimitry Andric
getType(const Symbol * Sym)407fa27ce4SDimitry Andric static SymbolRef::Type getType(const Symbol *Sym) {
417fa27ce4SDimitry Andric SymbolRef::Type Type = SymbolRef::ST_Unknown;
427fa27ce4SDimitry Andric if (Sym->isData())
437fa27ce4SDimitry Andric Type = SymbolRef::ST_Data;
447fa27ce4SDimitry Andric else if (Sym->isText())
457fa27ce4SDimitry Andric Type = SymbolRef::ST_Function;
467fa27ce4SDimitry Andric
477fa27ce4SDimitry Andric return Type;
487fa27ce4SDimitry Andric }
497fa27ce4SDimitry Andric
TapiFile(MemoryBufferRef Source,const InterfaceFile & Interface,Architecture Arch)507fa27ce4SDimitry Andric TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
511d5ae102SDimitry Andric Architecture Arch)
52b1c73532SDimitry Andric : SymbolicFile(ID_TapiFile, Source), Arch(Arch),
53b1c73532SDimitry Andric FileKind(Interface.getFileType()) {
547fa27ce4SDimitry Andric for (const auto *Symbol : Interface.symbols()) {
551d5ae102SDimitry Andric if (!Symbol->getArchitectures().has(Arch))
561d5ae102SDimitry Andric continue;
571d5ae102SDimitry Andric
581d5ae102SDimitry Andric switch (Symbol->getKind()) {
59ac9a064cSDimitry Andric case EncodeKind::GlobalSymbol:
607fa27ce4SDimitry Andric Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol),
617fa27ce4SDimitry Andric ::getType(Symbol));
621d5ae102SDimitry Andric break;
63ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClass:
647fa27ce4SDimitry Andric if (Interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
651d5ae102SDimitry Andric Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
667fa27ce4SDimitry Andric getFlags(Symbol), ::getType(Symbol));
671d5ae102SDimitry Andric } else {
681d5ae102SDimitry Andric Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
697fa27ce4SDimitry Andric getFlags(Symbol), ::getType(Symbol));
701d5ae102SDimitry Andric Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
717fa27ce4SDimitry Andric getFlags(Symbol), ::getType(Symbol));
721d5ae102SDimitry Andric }
731d5ae102SDimitry Andric break;
74ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClassEHType:
751d5ae102SDimitry Andric Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
767fa27ce4SDimitry Andric getFlags(Symbol), ::getType(Symbol));
771d5ae102SDimitry Andric break;
78ac9a064cSDimitry Andric case EncodeKind::ObjectiveCInstanceVariable:
797fa27ce4SDimitry Andric Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(), getFlags(Symbol),
807fa27ce4SDimitry Andric ::getType(Symbol));
811d5ae102SDimitry Andric break;
821d5ae102SDimitry Andric }
831d5ae102SDimitry Andric }
841d5ae102SDimitry Andric }
851d5ae102SDimitry Andric
861d5ae102SDimitry Andric TapiFile::~TapiFile() = default;
871d5ae102SDimitry Andric
moveSymbolNext(DataRefImpl & DRI) const88cfca06d7SDimitry Andric void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
891d5ae102SDimitry Andric
printSymbolName(raw_ostream & OS,DataRefImpl DRI) const901d5ae102SDimitry Andric Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
91cfca06d7SDimitry Andric assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
92cfca06d7SDimitry Andric const Symbol &Sym = Symbols[DRI.d.a];
93cfca06d7SDimitry Andric OS << Sym.Prefix << Sym.Name;
941d5ae102SDimitry Andric return Error::success();
951d5ae102SDimitry Andric }
961d5ae102SDimitry Andric
getSymbolType(DataRefImpl DRI) const977fa27ce4SDimitry Andric Expected<SymbolRef::Type> TapiFile::getSymbolType(DataRefImpl DRI) const {
987fa27ce4SDimitry Andric assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
997fa27ce4SDimitry Andric return Symbols[DRI.d.a].Type;
1007fa27ce4SDimitry Andric }
1017fa27ce4SDimitry Andric
getSymbolFlags(DataRefImpl DRI) const102cfca06d7SDimitry Andric Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
103cfca06d7SDimitry Andric assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
104cfca06d7SDimitry Andric return Symbols[DRI.d.a].Flags;
1051d5ae102SDimitry Andric }
1061d5ae102SDimitry Andric
symbol_begin() const1071d5ae102SDimitry Andric basic_symbol_iterator TapiFile::symbol_begin() const {
1081d5ae102SDimitry Andric DataRefImpl DRI;
109cfca06d7SDimitry Andric DRI.d.a = 0;
1101d5ae102SDimitry Andric return BasicSymbolRef{DRI, this};
1111d5ae102SDimitry Andric }
1121d5ae102SDimitry Andric
symbol_end() const1131d5ae102SDimitry Andric basic_symbol_iterator TapiFile::symbol_end() const {
1141d5ae102SDimitry Andric DataRefImpl DRI;
115cfca06d7SDimitry Andric DRI.d.a = Symbols.size();
1161d5ae102SDimitry Andric return BasicSymbolRef{DRI, this};
1171d5ae102SDimitry Andric }
118