xref: /freebsd/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp (revision d70886d063166786ded0007af8cdcbf57b7b4827)
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/Object/Error.h"
16  #include "llvm/Support/MemoryBuffer.h"
17  
18  using namespace llvm;
19  using namespace MachO;
20  using namespace object;
21  
22  static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
23  static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
24  static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
25  static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
26  static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
27  
28  static uint32_t getFlags(const Symbol *Sym) {
29    uint32_t Flags = BasicSymbolRef::SF_Global;
30    if (Sym->isUndefined())
31      Flags |= BasicSymbolRef::SF_Undefined;
32    else
33      Flags |= BasicSymbolRef::SF_Exported;
34  
35    if (Sym->isWeakDefined() || Sym->isWeakReferenced())
36      Flags |= BasicSymbolRef::SF_Weak;
37  
38    return Flags;
39  }
40  
41  TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
42                     Architecture Arch)
43      : SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
44    for (const auto *Symbol : interface.symbols()) {
45      if (!Symbol->getArchitectures().has(Arch))
46        continue;
47  
48      switch (Symbol->getKind()) {
49      case SymbolKind::GlobalSymbol:
50        Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
51        break;
52      case SymbolKind::ObjectiveCClass:
53        if (interface.getPlatforms().count(PlatformKind::macOS) &&
54            Arch == AK_i386) {
55          Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
56                               getFlags(Symbol));
57        } else {
58          Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
59                               getFlags(Symbol));
60          Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
61                               getFlags(Symbol));
62        }
63        break;
64      case SymbolKind::ObjectiveCClassEHType:
65        Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
66                             getFlags(Symbol));
67        break;
68      case SymbolKind::ObjectiveCInstanceVariable:
69        Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
70                             getFlags(Symbol));
71        break;
72      }
73    }
74  }
75  
76  TapiFile::~TapiFile() = default;
77  
78  void TapiFile::moveSymbolNext(DataRefImpl &DRI) const { DRI.d.a++; }
79  
80  Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
81    assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
82    const Symbol &Sym = Symbols[DRI.d.a];
83    OS << Sym.Prefix << Sym.Name;
84    return Error::success();
85  }
86  
87  Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
88    assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
89    return Symbols[DRI.d.a].Flags;
90  }
91  
92  basic_symbol_iterator TapiFile::symbol_begin() const {
93    DataRefImpl DRI;
94    DRI.d.a = 0;
95    return BasicSymbolRef{DRI, this};
96  }
97  
98  basic_symbol_iterator TapiFile::symbol_end() const {
99    DataRefImpl DRI;
100    DRI.d.a = Symbols.size();
101    return BasicSymbolRef{DRI, this};
102  }
103