Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/MachO/TLVPass.cpp
Line
Count
Source (jump to first uncovered line)
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
1
      : SimpleDefinedAtom(file), _is64(is64), _name(name) {}
31
32
1
  ~TLVPEntryAtom() override = default;
33
34
9
  ContentType contentType() const override {
35
9
    return DefinedAtom::typeTLVInitializerPtr;
36
9
  }
37
38
2
  Alignment alignment() const override {
39
2
    return _is64 ? 8 : 
40
;
40
2
  }
41
42
7
  uint64_t size() const override {
43
7
    return _is64 ? 8 : 
40
;
44
7
  }
45
46
1
  ContentPermissions permissions() const override {
47
1
    return DefinedAtom::permRW_;
48
1
  }
49
50
3
  ArrayRef<uint8_t> rawContent() const override {
51
3
    static const uint8_t zeros[] =
52
3
      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
53
3
    return llvm::makeArrayRef(zeros, size());
54
3
  }
55
56
0
  StringRef slotName() const {
57
0
    return _name;
58
0
  }
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()),
69
97
        _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) {
70
97
    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
71
97
  }
72
73
private:
74
97
  llvm::Error perform(SimpleFile &mergedFile) override {
75
97
    bool allowTLV = _ctx.minOS("10.7", "1.0");
76
97
77
552
    for (const DefinedAtom *atom : mergedFile.defined()) {
78
552
      for (const Reference *ref : *atom) {
79
415
        if (!_archHandler.isTLVAccess(*ref))
80
413
          continue;
81
2
82
2
        if (!allowTLV)
83
1
          return llvm::make_error<GenericError>(
84
1
            "targeted OS version does not support use of thread local "
85
1
            "variables in " + atom->name() + " for architecture " +
86
1
            _ctx.archName());
87
1
88
1
        const Atom *target = ref->target();
89
1
        assert(target != nullptr);
90
1
91
1
        const DefinedAtom *tlvpEntry = makeTLVPEntry(target);
92
1
        const_cast<Reference*>(ref)->setTarget(tlvpEntry);
93
1
        _archHandler.updateReferenceToTLV(ref);
94
1
      }
95
552
    }
96
97
97
97
    std::vector<const TLVPEntryAtom*> entries;
98
96
    entries.reserve(_targetToTLVP.size());
99
96
    for (auto &it : _targetToTLVP)
100
1
      entries.push_back(it.second);
101
96
    std::sort(entries.begin(), entries.end(),
102
96
              [](const TLVPEntryAtom *lhs, const TLVPEntryAtom *rhs) {
103
0
                return (lhs->slotName().compare(rhs->slotName()) < 0);
104
0
              });
105
96
106
96
    for (const TLVPEntryAtom *slot : entries)
107
1
      mergedFile.addAtom(*slot);
108
96
109
96
    return llvm::Error::success();
110
97
  }
111
112
1
  const DefinedAtom *makeTLVPEntry(const Atom *target) {
113
1
    auto pos = _targetToTLVP.find(target);
114
1
115
1
    if (pos != _targetToTLVP.end())
116
0
      return pos->second;
117
1
118
1
    auto *tlvpEntry = new (_file.allocator())
119
1
      TLVPEntryAtom(_file, _ctx.is64Bit(), target->name());
120
1
    _targetToTLVP[target] = tlvpEntry;
121
1
    const ArchHandler::ReferenceInfo &nlInfo =
122
1
      _archHandler.stubInfo().nonLazyPointerReferenceToBinder;
123
1
    tlvpEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
124
1
                            nlInfo.kind, 0, target, 0);
125
1
    return tlvpEntry;
126
1
  }
127
128
  const MachOLinkingContext &_ctx;
129
  mach_o::ArchHandler &_archHandler;
130
  MachOFile           &_file;
131
  llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP;
132
};
133
134
97
void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) {
135
97
  assert(ctx.needsTLVPass());
136
97
  pm.add(llvm::make_unique<TLVPass>(ctx));
137
97
}
138
139
} // end namesapce mach_o
140
} // end namesapce lld