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