/src/keystone/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- AArch64ELFObjectWriter.cpp - AArch64 ELF Writer -------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file handles ELF-specific object emission, converting LLVM's internal |
11 | | // fixups into the appropriate relocations. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "MCTargetDesc/AArch64FixupKinds.h" |
16 | | #include "MCTargetDesc/AArch64MCExpr.h" |
17 | | #include "MCTargetDesc/AArch64MCTargetDesc.h" |
18 | | #include "llvm/MC/MCELFObjectWriter.h" |
19 | | #include "llvm/MC/MCValue.h" |
20 | | #include "llvm/Support/ErrorHandling.h" |
21 | | |
22 | | using namespace llvm_ks; |
23 | | |
24 | | namespace { |
25 | | class AArch64ELFObjectWriter : public MCELFObjectTargetWriter { |
26 | | public: |
27 | | AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian); |
28 | | |
29 | | ~AArch64ELFObjectWriter() override; |
30 | | |
31 | | protected: |
32 | | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
33 | | const MCFixup &Fixup, bool IsPCRel) const override; |
34 | | |
35 | | private: |
36 | | }; |
37 | | } |
38 | | |
39 | | AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, |
40 | | bool IsLittleEndian) |
41 | 1.58k | : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, |
42 | 1.58k | /*HasRelocationAddend*/ true) {} |
43 | | |
44 | | AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {} |
45 | | |
46 | | unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, |
47 | | const MCValue &Target, |
48 | | const MCFixup &Fixup, |
49 | 4.80k | bool IsPCRel) const { |
50 | 4.80k | AArch64MCExpr::VariantKind RefKind = |
51 | 4.80k | static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind()); |
52 | 4.80k | AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind); |
53 | 4.80k | bool IsNC = AArch64MCExpr::isNotChecked(RefKind); |
54 | | |
55 | 4.80k | assert((!Target.getSymA() || |
56 | 4.80k | Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) && |
57 | 4.80k | "Should only be expression-level modifiers here"); |
58 | | |
59 | 4.80k | assert((!Target.getSymB() || |
60 | 4.80k | Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) && |
61 | 4.80k | "Should only be expression-level modifiers here"); |
62 | | |
63 | 4.80k | if (IsPCRel) { |
64 | 487 | switch ((unsigned)Fixup.getKind()) { |
65 | 0 | case FK_Data_2: |
66 | 0 | return ELF::R_AARCH64_PREL16; |
67 | 426 | case FK_Data_4: |
68 | 426 | return ELF::R_AARCH64_PREL32; |
69 | 0 | case FK_Data_8: |
70 | 0 | return ELF::R_AARCH64_PREL64; |
71 | 0 | case AArch64::fixup_aarch64_pcrel_adr_imm21: |
72 | 0 | assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation"); |
73 | 0 | return ELF::R_AARCH64_ADR_PREL_LO21; |
74 | 0 | case AArch64::fixup_aarch64_pcrel_adrp_imm21: |
75 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC) |
76 | 0 | return ELF::R_AARCH64_ADR_PREL_PG_HI21; |
77 | 0 | if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) |
78 | 0 | return ELF::R_AARCH64_ADR_GOT_PAGE; |
79 | 0 | if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC) |
80 | 0 | return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21; |
81 | 0 | if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) |
82 | 0 | return ELF::R_AARCH64_TLSDESC_ADR_PAGE21; |
83 | 0 | llvm_unreachable("invalid symbol kind for ADRP relocation"); |
84 | 0 | case AArch64::fixup_aarch64_pcrel_branch26: |
85 | 0 | return ELF::R_AARCH64_JUMP26; |
86 | 32 | case AArch64::fixup_aarch64_pcrel_call26: |
87 | 32 | return ELF::R_AARCH64_CALL26; |
88 | 0 | case AArch64::fixup_aarch64_ldr_pcrel_imm19: |
89 | 0 | if (SymLoc == AArch64MCExpr::VK_GOTTPREL) |
90 | 0 | return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19; |
91 | 0 | return ELF::R_AARCH64_LD_PREL_LO19; |
92 | 0 | case AArch64::fixup_aarch64_pcrel_branch14: |
93 | 0 | return ELF::R_AARCH64_TSTBR14; |
94 | 29 | case AArch64::fixup_aarch64_pcrel_branch19: |
95 | 29 | return ELF::R_AARCH64_CONDBR19; |
96 | 0 | default: |
97 | 0 | llvm_unreachable("Unsupported pc-relative fixup kind"); |
98 | 487 | } |
99 | 4.31k | } else { |
100 | 4.31k | switch ((unsigned)Fixup.getKind()) { |
101 | 0 | case FK_Data_2: |
102 | 0 | return ELF::R_AARCH64_ABS16; |
103 | 4.31k | case FK_Data_4: |
104 | 4.31k | return ELF::R_AARCH64_ABS32; |
105 | 0 | case FK_Data_8: |
106 | 0 | return ELF::R_AARCH64_ABS64; |
107 | 0 | case AArch64::fixup_aarch64_add_imm12: |
108 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_HI12) |
109 | 0 | return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12; |
110 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_HI12) |
111 | 0 | return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12; |
112 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC) |
113 | 0 | return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC; |
114 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_LO12) |
115 | 0 | return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12; |
116 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC) |
117 | 0 | return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC; |
118 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_LO12) |
119 | 0 | return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12; |
120 | 0 | if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12) |
121 | 0 | return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC; |
122 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
123 | 0 | return ELF::R_AARCH64_ADD_ABS_LO12_NC; |
124 | | |
125 | 0 | report_fatal_error("invalid fixup for add (uimm12) instruction"); |
126 | 0 | return 0; |
127 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale1: |
128 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
129 | 0 | return ELF::R_AARCH64_LDST8_ABS_LO12_NC; |
130 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) |
131 | 0 | return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12; |
132 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) |
133 | 0 | return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC; |
134 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) |
135 | 0 | return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12; |
136 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) |
137 | 0 | return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC; |
138 | | |
139 | 0 | report_fatal_error("invalid fixup for 8-bit load/store instruction"); |
140 | 0 | return 0; |
141 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale2: |
142 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
143 | 0 | return ELF::R_AARCH64_LDST16_ABS_LO12_NC; |
144 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) |
145 | 0 | return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12; |
146 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) |
147 | 0 | return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC; |
148 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) |
149 | 0 | return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12; |
150 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) |
151 | 0 | return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC; |
152 | | |
153 | 0 | report_fatal_error("invalid fixup for 16-bit load/store instruction"); |
154 | 0 | return 0; |
155 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale4: |
156 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
157 | 0 | return ELF::R_AARCH64_LDST32_ABS_LO12_NC; |
158 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) |
159 | 0 | return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12; |
160 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) |
161 | 0 | return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC; |
162 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) |
163 | 0 | return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12; |
164 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) |
165 | 0 | return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC; |
166 | | |
167 | 0 | report_fatal_error("invalid fixup for 32-bit load/store instruction"); |
168 | 0 | return 0; |
169 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale8: |
170 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
171 | 0 | return ELF::R_AARCH64_LDST64_ABS_LO12_NC; |
172 | 0 | if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) |
173 | 0 | return ELF::R_AARCH64_LD64_GOT_LO12_NC; |
174 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) |
175 | 0 | return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12; |
176 | 0 | if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) |
177 | 0 | return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC; |
178 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) |
179 | 0 | return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12; |
180 | 0 | if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) |
181 | 0 | return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC; |
182 | 0 | if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) |
183 | 0 | return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; |
184 | 0 | if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC) |
185 | 0 | return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC; |
186 | | |
187 | 0 | report_fatal_error("invalid fixup for 64-bit load/store instruction"); |
188 | 0 | return 0; |
189 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale16: |
190 | 0 | if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) |
191 | 0 | return ELF::R_AARCH64_LDST128_ABS_LO12_NC; |
192 | | |
193 | 0 | report_fatal_error("invalid fixup for 128-bit load/store instruction"); |
194 | 0 | return 0; |
195 | 0 | case AArch64::fixup_aarch64_movw: |
196 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G3) |
197 | 0 | return ELF::R_AARCH64_MOVW_UABS_G3; |
198 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G2) |
199 | 0 | return ELF::R_AARCH64_MOVW_UABS_G2; |
200 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G2_S) |
201 | 0 | return ELF::R_AARCH64_MOVW_SABS_G2; |
202 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G2_NC) |
203 | 0 | return ELF::R_AARCH64_MOVW_UABS_G2_NC; |
204 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G1) |
205 | 0 | return ELF::R_AARCH64_MOVW_UABS_G1; |
206 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G1_S) |
207 | 0 | return ELF::R_AARCH64_MOVW_SABS_G1; |
208 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G1_NC) |
209 | 0 | return ELF::R_AARCH64_MOVW_UABS_G1_NC; |
210 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G0) |
211 | 0 | return ELF::R_AARCH64_MOVW_UABS_G0; |
212 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G0_S) |
213 | 0 | return ELF::R_AARCH64_MOVW_SABS_G0; |
214 | 0 | if (RefKind == AArch64MCExpr::VK_ABS_G0_NC) |
215 | 0 | return ELF::R_AARCH64_MOVW_UABS_G0_NC; |
216 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_G2) |
217 | 0 | return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2; |
218 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_G1) |
219 | 0 | return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1; |
220 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC) |
221 | 0 | return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC; |
222 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_G0) |
223 | 0 | return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0; |
224 | 0 | if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC) |
225 | 0 | return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC; |
226 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_G2) |
227 | 0 | return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2; |
228 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_G1) |
229 | 0 | return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1; |
230 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC) |
231 | 0 | return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC; |
232 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_G0) |
233 | 0 | return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0; |
234 | 0 | if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC) |
235 | 0 | return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC; |
236 | 0 | if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1) |
237 | 0 | return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1; |
238 | 0 | if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC) |
239 | 0 | return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC; |
240 | 0 | report_fatal_error("invalid fixup for movz/movk instruction"); |
241 | 0 | return 0; |
242 | 0 | case AArch64::fixup_aarch64_tlsdesc_call: |
243 | 0 | return ELF::R_AARCH64_TLSDESC_CALL; |
244 | 0 | default: |
245 | 0 | llvm_unreachable("Unknown ELF relocation type"); |
246 | 4.31k | } |
247 | 4.31k | } |
248 | | |
249 | 4.80k | llvm_unreachable("Unimplemented fixup -> relocation"); |
250 | 4.80k | } |
251 | | |
252 | | MCObjectWriter *llvm_ks::createAArch64ELFObjectWriter(raw_pwrite_stream &OS, |
253 | | uint8_t OSABI, |
254 | 1.58k | bool IsLittleEndian) { |
255 | 1.58k | MCELFObjectTargetWriter *MOTW = |
256 | 1.58k | new AArch64ELFObjectWriter(OSABI, IsLittleEndian); |
257 | 1.58k | return createELFObjectWriter(MOTW, OS, IsLittleEndian); |
258 | 1.58k | } |