Coverage Report

Created: 2017-10-03 07:32

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