Eugene Zelenko | 4154794 | 2015-11-10 22:37:38 +0000 | [diff] [blame] | 1 | //===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===// |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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 | |
Pete Cooper | 8ad55fb | 2016-03-22 17:15:50 +0000 | [diff] [blame] | 32 | ~TLVPEntryAtom() override = default; |
| 33 | |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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 | |
| 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 | }; |
| 64 | |
| 65 | class TLVPass : public Pass { |
| 66 | public: |
| 67 | TLVPass(const MachOLinkingContext &context) |
| 68 | : _ctx(context), _archHandler(_ctx.archHandler()), |
Pete Cooper | c0c464c | 2016-03-21 23:17:47 +0000 | [diff] [blame] | 69 | _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) { |
Pete Cooper | c7d4035 | 2016-02-02 01:52:40 +0000 | [diff] [blame] | 70 | _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); |
| 71 | } |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 72 | |
| 73 | private: |
Pete Cooper | c73c9d2 | 2016-03-30 20:36:31 +0000 | [diff] [blame] | 74 | llvm::Error perform(SimpleFile &mergedFile) override { |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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) |
Pete Cooper | c73c9d2 | 2016-03-30 20:36:31 +0000 | [diff] [blame] | 83 | return llvm::make_error<GenericError>( |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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 | |
Mehdi Amini | c1edf56 | 2016-11-11 04:29:25 +0000 | [diff] [blame] | 109 | return llvm::Error::success(); |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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 | |
Eugene Zelenko | 4154794 | 2015-11-10 22:37:38 +0000 | [diff] [blame] | 118 | auto *tlvpEntry = new (_file.allocator()) |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 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; |
Pete Cooper | c0c464c | 2016-03-21 23:17:47 +0000 | [diff] [blame] | 130 | MachOFile &_file; |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 131 | llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP; |
| 132 | }; |
| 133 | |
| 134 | void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) { |
| 135 | assert(ctx.needsTLVPass()); |
Jonas Devlieghere | 6ba7992 | 2019-08-14 22:28:17 +0000 | [diff] [blame] | 136 | pm.add(std::make_unique<TLVPass>(ctx)); |
Lang Hames | 4904703 | 2015-06-23 20:35:31 +0000 | [diff] [blame] | 137 | } |
| 138 | |
Kazuaki Ishizaki | 7c5fcb3 | 2020-04-02 01:21:08 +0900 | [diff] [blame] | 139 | } // end namespace mach_o |
| 140 | } // end namespace lld |