1 //===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===// 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 /// \file 10 /// This linker pass transforms all TLV references to real references. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "ArchHandler.h" 15 #include "File.h" 16 #include "MachOPasses.h" 17 #include "lld/Core/Simple.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/Support/Debug.h" 20 21 namespace lld { 22 namespace mach_o { 23 24 // 25 // TLVP Entry Atom created by the TLV pass. 26 // 27 class TLVPEntryAtom : public SimpleDefinedAtom { 28 public: 29 TLVPEntryAtom(const File &file, bool is64, StringRef name) 30 : SimpleDefinedAtom(file), _is64(is64), _name(name) {} 31 32 ~TLVPEntryAtom() override = default; 33 34 ContentType contentType() const override { 35 return DefinedAtom::typeTLVInitializerPtr; 36 } 37 38 Alignment alignment() const override { 39 return _is64 ? 8 : 4; 40 } 41 42 uint64_t size() const override { 43 return _is64 ? 8 : 4; 44 } 45 46 ContentPermissions permissions() const override { 47 return DefinedAtom::permRW_; 48 } 49 main_browser_core_init_factories(void)50 ArrayRef<uint8_t> rawContent() const override { 51 static const uint8_t zeros[] = 52 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 53 return llvm::makeArrayRef(zeros, size()); 54 } 55 56 StringRef slotName() const { 57 return _name; 58 } 59 60 private: 61 const bool _is64; 62 StringRef _name; 63 }; output_data_model(GdaDataModel * model)64 65 class TLVPass : public Pass { 66 public: 67 TLVPass(const MachOLinkingContext &context) 68 : _ctx(context), _archHandler(_ctx.archHandler()), 69 _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) { 70 _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); 71 } 72 73 private: 74 llvm::Error perform(SimpleFile &mergedFile) override { 75 bool allowTLV = _ctx.minOS("10.7", "1.0"); 76 77 for (const DefinedAtom *atom : mergedFile.defined()) { 78 for (const Reference *ref : *atom) { 79 if (!_archHandler.isTLVAccess(*ref)) 80 continue; 81 82 if (!allowTLV) 83 return llvm::make_error<GenericError>( 84 "targeted OS version does not support use of thread local " 85 "variables in " + atom->name() + " for architecture " + 86 _ctx.archName()); 87 88 const Atom *target = ref->target(); 89 assert(target != nullptr); 90 91 const DefinedAtom *tlvpEntry = makeTLVPEntry(target); 92 const_cast<Reference*>(ref)->setTarget(tlvpEntry); 93 _archHandler.updateReferenceToTLV(ref); 94 } 95 } 96 97 std::vector<const TLVPEntryAtom*> entries; 98 entries.reserve(_targetToTLVP.size()); 99 for (auto &it : _targetToTLVP) 100 entries.push_back(it.second); 101 std::sort(entries.begin(), entries.end(), 102 [](const TLVPEntryAtom *lhs, const TLVPEntryAtom *rhs) { 103 return (lhs->slotName().compare(rhs->slotName()) < 0); 104 }); 105 106 for (const TLVPEntryAtom *slot : entries) 107 mergedFile.addAtom(*slot); 108 109 return llvm::Error::success(); 110 } 111 112 const DefinedAtom *makeTLVPEntry(const Atom *target) { 113 auto pos = _targetToTLVP.find(target); 114 115 if (pos != _targetToTLVP.end()) 116 return pos->second; 117 118 auto *tlvpEntry = new (_file.allocator()) 119 TLVPEntryAtom(_file, _ctx.is64Bit(), target->name()); 120 _targetToTLVP[target] = tlvpEntry; 121 const ArchHandler::ReferenceInfo &nlInfo = 122 _archHandler.stubInfo().nonLazyPointerReferenceToBinder; 123 tlvpEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch, 124 nlInfo.kind, 0, target, 0); 125 return tlvpEntry; 126 } 127 128 const MachOLinkingContext &_ctx; 129 mach_o::ArchHandler &_archHandler; 130 MachOFile &_file; 131 llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP; 132 }; 133 134 void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) { 135 assert(ctx.needsTLVPass()); 136 pm.add(std::make_unique<TLVPass>(ctx)); 137 } 138 139 } // end namespace mach_o 140 } // end namespace lld 141