]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/ELF/Arch/SPARCV9.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / ELF / Arch / SPARCV9.cpp
1 //===- SPARCV9.cpp --------------------------------------------------------===//
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 #include "InputFiles.h"
11 #include "Symbols.h"
12 #include "SyntheticSections.h"
13 #include "Target.h"
14 #include "lld/Common/ErrorHandler.h"
15 #include "llvm/Support/Endian.h"
16
17 using namespace llvm;
18 using namespace llvm::support::endian;
19 using namespace llvm::ELF;
20 using namespace lld;
21 using namespace lld::elf;
22
23 namespace {
24 class SPARCV9 final : public TargetInfo {
25 public:
26   SPARCV9();
27   RelExpr getRelExpr(RelType Type, const Symbol &S,
28                      const uint8_t *Loc) const override;
29   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
30                 int32_t Index, unsigned RelOff) const override;
31   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
32 };
33 } // namespace
34
35 SPARCV9::SPARCV9() {
36   CopyRel = R_SPARC_COPY;
37   GotRel = R_SPARC_GLOB_DAT;
38   PltRel = R_SPARC_JMP_SLOT;
39   RelativeRel = R_SPARC_RELATIVE;
40   GotEntrySize = 8;
41   PltEntrySize = 32;
42   PltHeaderSize = 4 * PltEntrySize;
43
44   PageSize = 8192;
45   DefaultMaxPageSize = 0x100000;
46   DefaultImageBase = 0x100000;
47 }
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     return R_INVALID;
72   }
73 }
74
75 void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
76   switch (Type) {
77   case R_SPARC_32:
78   case R_SPARC_UA32:
79     // V-word32
80     checkUInt(Loc, Val, 32, Type);
81     write32be(Loc, Val);
82     break;
83   case R_SPARC_DISP32:
84     // V-disp32
85     checkInt(Loc, Val, 32, Type);
86     write32be(Loc, Val);
87     break;
88   case R_SPARC_WDISP30:
89   case R_SPARC_WPLT30:
90     // V-disp30
91     checkInt(Loc, Val, 32, Type);
92     write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff));
93     break;
94   case R_SPARC_22:
95     // V-imm22
96     checkUInt(Loc, Val, 22, Type);
97     write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff));
98     break;
99   case R_SPARC_GOT22:
100   case R_SPARC_PC22:
101     // T-imm22
102     write32be(Loc, (read32be(Loc) & ~0x003fffff) | ((Val >> 10) & 0x003fffff));
103     break;
104   case R_SPARC_WDISP19:
105     // V-disp19
106     checkInt(Loc, Val, 21, Type);
107     write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff));
108     break;
109   case R_SPARC_GOT10:
110   case R_SPARC_PC10:
111     // T-simm10
112     write32be(Loc, (read32be(Loc) & ~0x000003ff) | (Val & 0x000003ff));
113     break;
114   case R_SPARC_64:
115   case R_SPARC_UA64:
116   case R_SPARC_GLOB_DAT:
117     // V-xword64
118     write64be(Loc, Val);
119     break;
120   default:
121     error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
122   }
123 }
124
125 void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
126                        uint64_t PltEntryAddr, int32_t Index,
127                        unsigned RelOff) const {
128   const uint8_t PltData[] = {
129       0x03, 0x00, 0x00, 0x00, // sethi   (. - .PLT0), %g1
130       0x30, 0x68, 0x00, 0x00, // ba,a    %xcc, .PLT1
131       0x01, 0x00, 0x00, 0x00, // nop
132       0x01, 0x00, 0x00, 0x00, // nop
133       0x01, 0x00, 0x00, 0x00, // nop
134       0x01, 0x00, 0x00, 0x00, // nop
135       0x01, 0x00, 0x00, 0x00, // nop
136       0x01, 0x00, 0x00, 0x00  // nop
137   };
138   memcpy(Buf, PltData, sizeof(PltData));
139
140   uint64_t Off = getPltEntryOffset(Index);
141   relocateOne(Buf, R_SPARC_22, Off);
142   relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize));
143 }
144
145 TargetInfo *elf::getSPARCV9TargetInfo() {
146   static SPARCV9 Target;
147   return &Target;
148 }