xref: /freebsd/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp (revision 044243fcc9b4c639cf5655e37b98478bcb312590)
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