/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/Arch/SPARCV9.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SPARCV9.cpp --------------------------------------------------------===// |
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 | | #include "InputFiles.h" |
10 | | #include "Symbols.h" |
11 | | #include "SyntheticSections.h" |
12 | | #include "Target.h" |
13 | | #include "lld/Common/ErrorHandler.h" |
14 | | #include "llvm/Support/Endian.h" |
15 | | |
16 | | using namespace llvm; |
17 | | using namespace llvm::support::endian; |
18 | | using namespace llvm::ELF; |
19 | | using namespace lld; |
20 | | using namespace lld::elf; |
21 | | |
22 | | namespace { |
23 | | class SPARCV9 final : public TargetInfo { |
24 | | public: |
25 | | SPARCV9(); |
26 | | RelExpr getRelExpr(RelType type, const Symbol &s, |
27 | | const uint8_t *loc) const override; |
28 | | void writePlt(uint8_t *buf, uint64_t gotEntryAddr, uint64_t pltEntryAddr, |
29 | | int32_t index, unsigned relOff) const override; |
30 | | void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; |
31 | | }; |
32 | | } // namespace |
33 | | |
34 | 1 | SPARCV9::SPARCV9() { |
35 | 1 | copyRel = R_SPARC_COPY; |
36 | 1 | gotRel = R_SPARC_GLOB_DAT; |
37 | 1 | noneRel = R_SPARC_NONE; |
38 | 1 | pltRel = R_SPARC_JMP_SLOT; |
39 | 1 | relativeRel = R_SPARC_RELATIVE; |
40 | 1 | symbolicRel = R_SPARC_64; |
41 | 1 | pltEntrySize = 32; |
42 | 1 | pltHeaderSize = 4 * pltEntrySize; |
43 | 1 | |
44 | 1 | defaultCommonPageSize = 8192; |
45 | 1 | defaultMaxPageSize = 0x100000; |
46 | 1 | defaultImageBase = 0x100000; |
47 | 1 | } |
48 | | |
49 | | RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, |
50 | | const uint8_t *loc) const { |
51 | | switch (type) { |
52 | | case R_SPARC_32: |
53 | | case R_SPARC_UA32: |
54 | | case R_SPARC_64: |
55 | | case R_SPARC_UA64: |
56 | | return R_ABS; |
57 | | case R_SPARC_PC10: |
58 | | case R_SPARC_PC22: |
59 | | case R_SPARC_DISP32: |
60 | | case R_SPARC_WDISP30: |
61 | | return R_PC; |
62 | | case R_SPARC_GOT10: |
63 | | return R_GOT_OFF; |
64 | | case R_SPARC_GOT22: |
65 | | return R_GOT_OFF; |
66 | | case R_SPARC_WPLT30: |
67 | | return R_PLT_PC; |
68 | | case R_SPARC_NONE: |
69 | | return R_NONE; |
70 | | default: |
71 | | error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + |
72 | | ") against symbol " + toString(s)); |
73 | | return R_NONE; |
74 | | } |
75 | | } |
76 | | |
77 | 0 | void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { |
78 | 0 | switch (type) { |
79 | 0 | case R_SPARC_32: |
80 | 0 | case R_SPARC_UA32: |
81 | 0 | // V-word32 |
82 | 0 | checkUInt(loc, val, 32, type); |
83 | 0 | write32be(loc, val); |
84 | 0 | break; |
85 | 0 | case R_SPARC_DISP32: |
86 | 0 | // V-disp32 |
87 | 0 | checkInt(loc, val, 32, type); |
88 | 0 | write32be(loc, val); |
89 | 0 | break; |
90 | 0 | case R_SPARC_WDISP30: |
91 | 0 | case R_SPARC_WPLT30: |
92 | 0 | // V-disp30 |
93 | 0 | checkInt(loc, val, 32, type); |
94 | 0 | write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); |
95 | 0 | break; |
96 | 0 | case R_SPARC_22: |
97 | 0 | // V-imm22 |
98 | 0 | checkUInt(loc, val, 22, type); |
99 | 0 | write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); |
100 | 0 | break; |
101 | 0 | case R_SPARC_GOT22: |
102 | 0 | case R_SPARC_PC22: |
103 | 0 | // T-imm22 |
104 | 0 | write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); |
105 | 0 | break; |
106 | 0 | case R_SPARC_WDISP19: |
107 | 0 | // V-disp19 |
108 | 0 | checkInt(loc, val, 21, type); |
109 | 0 | write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); |
110 | 0 | break; |
111 | 0 | case R_SPARC_GOT10: |
112 | 0 | case R_SPARC_PC10: |
113 | 0 | // T-simm10 |
114 | 0 | write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); |
115 | 0 | break; |
116 | 0 | case R_SPARC_64: |
117 | 0 | case R_SPARC_UA64: |
118 | 0 | // V-xword64 |
119 | 0 | write64be(loc, val); |
120 | 0 | break; |
121 | 0 | default: |
122 | 0 | llvm_unreachable("unknown relocation"); |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr, |
127 | | uint64_t pltEntryAddr, int32_t index, |
128 | 0 | unsigned relOff) const { |
129 | 0 | const uint8_t pltData[] = { |
130 | 0 | 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 |
131 | 0 | 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 |
132 | 0 | 0x01, 0x00, 0x00, 0x00, // nop |
133 | 0 | 0x01, 0x00, 0x00, 0x00, // nop |
134 | 0 | 0x01, 0x00, 0x00, 0x00, // nop |
135 | 0 | 0x01, 0x00, 0x00, 0x00, // nop |
136 | 0 | 0x01, 0x00, 0x00, 0x00, // nop |
137 | 0 | 0x01, 0x00, 0x00, 0x00 // nop |
138 | 0 | }; |
139 | 0 | memcpy(buf, pltData, sizeof(pltData)); |
140 | 0 |
|
141 | 0 | uint64_t off = pltHeaderSize + pltEntrySize * index; |
142 | 0 | relocateOne(buf, R_SPARC_22, off); |
143 | 0 | relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); |
144 | 0 | } |
145 | | |
146 | 2 | TargetInfo *elf::getSPARCV9TargetInfo() { |
147 | 2 | static SPARCV9 target; |
148 | 2 | return ⌖ |
149 | 2 | } |