xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elfxx-riscv.c (revision fdd524d4ccd2bb0c6f67401e938dabf773eb0372)
1 /* RISC-V-specific support for ELF.
2    Copyright 2011-2014 Free Software Foundation, Inc.
3 
4    Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
5    Based on TILE-Gx and MIPS targets.
6 
7    This file is part of BFD, the Binary File Descriptor library.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22    MA 02110-1301, USA.  */
23 
24 #include "sysdep.h"
25 #include "bfd.h"
26 #include "libbfd.h"
27 #include "elf-bfd.h"
28 #include "elf/riscv.h"
29 #include "opcode/riscv.h"
30 #include "libiberty.h"
31 #include "elfxx-riscv.h"
32 #include <stdint.h>
33 
34 #define MINUS_ONE ((bfd_vma)0 - 1)
35 
36 /* The relocation table used for SHT_RELA sections.  */
37 
38 static reloc_howto_type howto_table[] =
39 {
40   /* No relocation.  */
41   HOWTO (R_RISCV_NONE,		/* type */
42 	 0,			/* rightshift */
43 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
44 	 0,			/* bitsize */
45 	 FALSE,			/* pc_relative */
46 	 0,			/* bitpos */
47 	 complain_overflow_dont, /* complain_on_overflow */
48 	 bfd_elf_generic_reloc,	/* special_function */
49 	 "R_RISCV_NONE",	/* name */
50 	 FALSE,			/* partial_inplace */
51 	 0,			/* src_mask */
52 	 0,			/* dst_mask */
53 	 FALSE),		/* pcrel_offset */
54 
55   /* 32 bit relocation.  */
56   HOWTO (R_RISCV_32,		/* type */
57 	 0,			/* rightshift */
58 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
59 	 32,			/* bitsize */
60 	 FALSE,			/* pc_relative */
61 	 0,			/* bitpos */
62 	 complain_overflow_dont, /* complain_on_overflow */
63 	 bfd_elf_generic_reloc,	/* special_function */
64 	 "R_RISCV_32",		/* name */
65 	 FALSE,			/* partial_inplace */
66 	 0,			/* src_mask */
67 	 0xffffffff,		/* dst_mask */
68 	 FALSE),		/* pcrel_offset */
69 
70   /* 64 bit relocation.  */
71   HOWTO (R_RISCV_64,		/* type */
72 	 0,			/* rightshift */
73 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
74 	 64,			/* bitsize */
75 	 FALSE,			/* pc_relative */
76 	 0,			/* bitpos */
77 	 complain_overflow_dont, /* complain_on_overflow */
78 	 bfd_elf_generic_reloc,	/* special_function */
79 	 "R_RISCV_64",		/* name */
80 	 FALSE,			/* partial_inplace */
81 	 0,			/* src_mask */
82 	 MINUS_ONE,		/* dst_mask */
83 	 FALSE),		/* pcrel_offset */
84 
85   /* Relocation against a local symbol in a shared object.  */
86   HOWTO (R_RISCV_RELATIVE,	/* type */
87 	 0,			/* rightshift */
88 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
89 	 32,			/* bitsize */
90 	 FALSE,			/* pc_relative */
91 	 0,			/* bitpos */
92 	 complain_overflow_dont, /* complain_on_overflow */
93 	 bfd_elf_generic_reloc,	/* special_function */
94 	 "R_RISCV_RELATIVE",	/* name */
95 	 FALSE,			/* partial_inplace */
96 	 0,			/* src_mask */
97 	 0xffffffff,		/* dst_mask */
98 	 FALSE),		/* pcrel_offset */
99 
100   HOWTO (R_RISCV_COPY,		/* type */
101 	 0,			/* rightshift */
102 	 0,			/* this one is variable size */
103 	 0,			/* bitsize */
104 	 FALSE,			/* pc_relative */
105 	 0,			/* bitpos */
106 	 complain_overflow_bitfield, /* complain_on_overflow */
107 	 bfd_elf_generic_reloc,	/* special_function */
108 	 "R_RISCV_COPY",		/* name */
109 	 FALSE,			/* partial_inplace */
110 	 0x0,         		/* src_mask */
111 	 0x0,		        /* dst_mask */
112 	 FALSE),		/* pcrel_offset */
113 
114   HOWTO (R_RISCV_JUMP_SLOT,	/* type */
115 	 0,			/* rightshift */
116 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
117 	 64,			/* bitsize */
118 	 FALSE,			/* pc_relative */
119 	 0,			/* bitpos */
120 	 complain_overflow_bitfield, /* complain_on_overflow */
121 	 bfd_elf_generic_reloc,	/* special_function */
122 	 "R_RISCV_JUMP_SLOT",	/* name */
123 	 FALSE,			/* partial_inplace */
124 	 0x0,         		/* src_mask */
125 	 0x0,		        /* dst_mask */
126 	 FALSE),		/* pcrel_offset */
127 
128   /* Dynamic TLS relocations.  */
129   HOWTO (R_RISCV_TLS_DTPMOD32,	/* type */
130 	 0,			/* rightshift */
131 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
132 	 32,			/* bitsize */
133 	 FALSE,			/* pc_relative */
134 	 0,			/* bitpos */
135 	 complain_overflow_dont, /* complain_on_overflow */
136 	 bfd_elf_generic_reloc, /* special_function */
137 	 "R_RISCV_TLS_DTPMOD32", /* name */
138 	 FALSE,			/* partial_inplace */
139 	 MINUS_ONE,		/* src_mask */
140 	 MINUS_ONE,		/* dst_mask */
141 	 FALSE),		/* pcrel_offset */
142 
143   HOWTO (R_RISCV_TLS_DTPMOD64,	/* type */
144 	 0,			/* rightshift */
145 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
146 	 64,			/* bitsize */
147 	 FALSE,			/* pc_relative */
148 	 0,			/* bitpos */
149 	 complain_overflow_dont, /* complain_on_overflow */
150 	 bfd_elf_generic_reloc, /* special_function */
151 	 "R_RISCV_TLS_DTPMOD64", /* name */
152 	 FALSE,			/* partial_inplace */
153 	 MINUS_ONE,		/* src_mask */
154 	 MINUS_ONE,		/* dst_mask */
155 	 FALSE),		/* pcrel_offset */
156 
157   HOWTO (R_RISCV_TLS_DTPREL32,	/* type */
158 	 0,			/* rightshift */
159 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
160 	 32,			/* bitsize */
161 	 FALSE,			/* pc_relative */
162 	 0,			/* bitpos */
163 	 complain_overflow_dont, /* complain_on_overflow */
164 	 bfd_elf_generic_reloc, /* special_function */
165 	 "R_RISCV_TLS_DTPREL32",	/* name */
166 	 TRUE,			/* partial_inplace */
167 	 MINUS_ONE,		/* src_mask */
168 	 MINUS_ONE,		/* dst_mask */
169 	 FALSE),		/* pcrel_offset */
170 
171   HOWTO (R_RISCV_TLS_DTPREL64,	/* type */
172 	 0,			/* rightshift */
173 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
174 	 64,			/* bitsize */
175 	 FALSE,			/* pc_relative */
176 	 0,			/* bitpos */
177 	 complain_overflow_dont, /* complain_on_overflow */
178 	 bfd_elf_generic_reloc, /* special_function */
179 	 "R_RISCV_TLS_DTPREL64",	/* name */
180 	 TRUE,			/* partial_inplace */
181 	 MINUS_ONE,		/* src_mask */
182 	 MINUS_ONE,		/* dst_mask */
183 	 FALSE),		/* pcrel_offset */
184 
185   HOWTO (R_RISCV_TLS_TPREL32,	/* type */
186 	 0,			/* rightshift */
187 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
188 	 32,			/* bitsize */
189 	 FALSE,			/* pc_relative */
190 	 0,			/* bitpos */
191 	 complain_overflow_dont, /* complain_on_overflow */
192 	 bfd_elf_generic_reloc, /* special_function */
193 	 "R_RISCV_TLS_TPREL32",	/* name */
194 	 FALSE,			/* partial_inplace */
195 	 MINUS_ONE,		/* src_mask */
196 	 MINUS_ONE,		/* dst_mask */
197 	 FALSE),		/* pcrel_offset */
198 
199   HOWTO (R_RISCV_TLS_TPREL64,	/* type */
200 	 0,			/* rightshift */
201 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
202 	 64,			/* bitsize */
203 	 FALSE,			/* pc_relative */
204 	 0,			/* bitpos */
205 	 complain_overflow_dont, /* complain_on_overflow */
206 	 bfd_elf_generic_reloc, /* special_function */
207 	 "R_RISCV_TLS_TPREL64",	/* name */
208 	 FALSE,			/* partial_inplace */
209 	 MINUS_ONE,		/* src_mask */
210 	 MINUS_ONE,		/* dst_mask */
211 	 FALSE),		/* pcrel_offset */
212 
213   EMPTY_HOWTO (12),
214   EMPTY_HOWTO (13),
215   EMPTY_HOWTO (14),
216   EMPTY_HOWTO (15),
217 
218   /* 12-bit PC-relative branch offset.  */
219   HOWTO (R_RISCV_BRANCH,	/* type */
220 	 0,			/* rightshift */
221 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
222 	 32,			/* bitsize */
223 	 TRUE,			/* pc_relative */
224 	 0,			/* bitpos */
225 	 complain_overflow_signed, /* complain_on_overflow */
226 	 bfd_elf_generic_reloc,	/* special_function */
227 	 "R_RISCV_BRANCH",	/* name */
228 	 FALSE,			/* partial_inplace */
229 	 0,			/* src_mask */
230 	 ENCODE_SBTYPE_IMM(-1U),/* dst_mask */
231 	 TRUE),			/* pcrel_offset */
232 
233   /* 20-bit PC-relative jump offset.  */
234   HOWTO (R_RISCV_JAL,		/* type */
235 	 0,			/* rightshift */
236 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
237 	 32,			/* bitsize */
238 	 TRUE,			/* pc_relative */
239 	 0,			/* bitpos */
240 	 complain_overflow_dont, /* complain_on_overflow */
241 				/* This needs complex overflow
242 				   detection, because the upper 36
243 				   bits must match the PC + 4.  */
244 	 bfd_elf_generic_reloc,	/* special_function */
245 	 "R_RISCV_JAL",		/* name */
246 	 FALSE,			/* partial_inplace */
247 	 0,			/* src_mask */
248 	 ENCODE_UJTYPE_IMM(-1U),	/* dst_mask */
249 	 TRUE),		/* pcrel_offset */
250 
251   /* 32-bit PC-relative function call (AUIPC/JALR).  */
252   HOWTO (R_RISCV_CALL,		/* type */
253 	 0,			/* rightshift */
254 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
255 	 64,			/* bitsize */
256 	 TRUE,			/* pc_relative */
257 	 0,			/* bitpos */
258 	 complain_overflow_dont, /* complain_on_overflow */
259 	 bfd_elf_generic_reloc,	/* special_function */
260 	 "R_RISCV_CALL",	/* name */
261 	 FALSE,			/* partial_inplace */
262 	 0,			/* src_mask */
263 	 ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32),	/* dst_mask */
264 	 TRUE),			/* pcrel_offset */
265 
266   /* 32-bit PC-relative function call (AUIPC/JALR).  */
267   HOWTO (R_RISCV_CALL_PLT,	/* type */
268 	 0,			/* rightshift */
269 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
270 	 64,			/* bitsize */
271 	 TRUE,			/* pc_relative */
272 	 0,			/* bitpos */
273 	 complain_overflow_dont, /* complain_on_overflow */
274 	 bfd_elf_generic_reloc,	/* special_function */
275 	 "R_RISCV_CALL_PLT",	/* name */
276 	 FALSE,			/* partial_inplace */
277 	 0,			/* src_mask */
278 	 ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32),	/* dst_mask */
279 	 TRUE),			/* pcrel_offset */
280 
281   /* High 20 bits of 32-bit PC-relative GOT access.  */
282   HOWTO (R_RISCV_GOT_HI20,	/* type */
283 	 0,			/* rightshift */
284 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
285 	 32,			/* bitsize */
286 	 TRUE,			/* pc_relative */
287 	 0,			/* bitpos */
288 	 complain_overflow_dont, /* complain_on_overflow */
289 	 bfd_elf_generic_reloc,	/* special_function */
290 	 "R_RISCV_GOT_HI20",	/* name */
291 	 FALSE,			/* partial_inplace */
292 	 0,			/* src_mask */
293 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
294 	 FALSE),		/* pcrel_offset */
295 
296   /* High 20 bits of 32-bit PC-relative TLS IE GOT access.  */
297   HOWTO (R_RISCV_TLS_GOT_HI20,	/* type */
298 	 0,			/* rightshift */
299 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
300 	 32,			/* bitsize */
301 	 TRUE,			/* pc_relative */
302 	 0,			/* bitpos */
303 	 complain_overflow_dont, /* complain_on_overflow */
304 	 bfd_elf_generic_reloc,	/* special_function */
305 	 "R_RISCV_TLS_GOT_HI20",	/* name */
306 	 FALSE,			/* partial_inplace */
307 	 0,			/* src_mask */
308 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
309 	 FALSE),		/* pcrel_offset */
310 
311   /* High 20 bits of 32-bit PC-relative TLS GD GOT reference.  */
312   HOWTO (R_RISCV_TLS_GD_HI20,	/* type */
313 	 0,			/* rightshift */
314 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
315 	 32,			/* bitsize */
316 	 TRUE,			/* pc_relative */
317 	 0,			/* bitpos */
318 	 complain_overflow_dont, /* complain_on_overflow */
319 	 bfd_elf_generic_reloc,	/* special_function */
320 	 "R_RISCV_TLS_GD_HI20",	/* name */
321 	 FALSE,			/* partial_inplace */
322 	 0,			/* src_mask */
323 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
324 	 FALSE),		/* pcrel_offset */
325 
326   /* High 20 bits of 32-bit PC-relative reference.  */
327   HOWTO (R_RISCV_PCREL_HI20,	/* type */
328 	 0,			/* rightshift */
329 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
330 	 32,			/* bitsize */
331 	 TRUE,			/* pc_relative */
332 	 0,			/* bitpos */
333 	 complain_overflow_dont, /* complain_on_overflow */
334 	 bfd_elf_generic_reloc,	/* special_function */
335 	 "R_RISCV_PCREL_HI20",	/* name */
336 	 FALSE,			/* partial_inplace */
337 	 0,			/* src_mask */
338 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
339 	 TRUE),			/* pcrel_offset */
340 
341   /* Low 12 bits of a 32-bit PC-relative load or add.  */
342   HOWTO (R_RISCV_PCREL_LO12_I,	/* type */
343 	 0,			/* rightshift */
344 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
345 	 32,			/* bitsize */
346 	 FALSE,			/* pc_relative */
347 	 0,			/* bitpos */
348 	 complain_overflow_dont, /* complain_on_overflow */
349 	 bfd_elf_generic_reloc,	/* special_function */
350 	 "R_RISCV_PCREL_LO12_I",/* name */
351 	 FALSE,			/* partial_inplace */
352 	 0,			/* src_mask */
353 	 ENCODE_ITYPE_IMM(-1U),	/* dst_mask */
354 	 FALSE),		/* pcrel_offset */
355 
356   /* Low 12 bits of a 32-bit PC-relative store.  */
357   HOWTO (R_RISCV_PCREL_LO12_S,	/* type */
358 	 0,			/* rightshift */
359 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
360 	 32,			/* bitsize */
361 	 FALSE,			/* pc_relative */
362 	 0,			/* bitpos */
363 	 complain_overflow_dont, /* complain_on_overflow */
364 	 bfd_elf_generic_reloc,	/* special_function */
365 	 "R_RISCV_PCREL_LO12_S",/* name */
366 	 FALSE,			/* partial_inplace */
367 	 0,			/* src_mask */
368 	 ENCODE_STYPE_IMM(-1U),	/* dst_mask */
369 	 FALSE),		/* pcrel_offset */
370 
371   /* High 20 bits of 32-bit absolute address.  */
372   HOWTO (R_RISCV_HI20,		/* type */
373 	 0,			/* rightshift */
374 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
375 	 32,			/* bitsize */
376 	 FALSE,			/* pc_relative */
377 	 0,			/* bitpos */
378 	 complain_overflow_dont, /* complain_on_overflow */
379 	 bfd_elf_generic_reloc,	/* special_function */
380 	 "R_RISCV_HI20",		/* name */
381 	 FALSE,			/* partial_inplace */
382 	 0,			/* src_mask */
383 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
384 	 FALSE),		/* pcrel_offset */
385 
386   /* High 12 bits of 32-bit load or add.  */
387   HOWTO (R_RISCV_LO12_I,	/* type */
388 	 0,			/* rightshift */
389 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
390 	 32,			/* bitsize */
391 	 FALSE,			/* pc_relative */
392 	 0,			/* bitpos */
393 	 complain_overflow_dont, /* complain_on_overflow */
394 	 bfd_elf_generic_reloc,	/* special_function */
395 	 "R_RISCV_LO12_I",	/* name */
396 	 FALSE,			/* partial_inplace */
397 	 0,			/* src_mask */
398 	 ENCODE_ITYPE_IMM(-1U),	/* dst_mask */
399 	 FALSE),		/* pcrel_offset */
400 
401   /* High 12 bits of 32-bit store.  */
402   HOWTO (R_RISCV_LO12_S,	/* type */
403 	 0,			/* rightshift */
404 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
405 	 32,			/* bitsize */
406 	 FALSE,			/* pc_relative */
407 	 0,			/* bitpos */
408 	 complain_overflow_dont, /* complain_on_overflow */
409 	 bfd_elf_generic_reloc,	/* special_function */
410 	 "R_RISCV_LO12_S",	/* name */
411 	 FALSE,			/* partial_inplace */
412 	 0,			/* src_mask */
413 	 ENCODE_STYPE_IMM(-1U),	/* dst_mask */
414 	 FALSE),		/* pcrel_offset */
415 
416   /* High 20 bits of TLS LE thread pointer offset.  */
417   HOWTO (R_RISCV_TPREL_HI20,	/* type */
418 	 0,			/* rightshift */
419 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
420 	 32,	/* bitsize */
421 	 FALSE,			/* pc_relative */
422 	 0,			/* bitpos */
423 	 complain_overflow_signed, /* complain_on_overflow */
424 	 bfd_elf_generic_reloc, /* special_function */
425 	 "R_RISCV_TPREL_HI20",	/* name */
426 	 TRUE,			/* partial_inplace */
427 	 0,			/* src_mask */
428 	 ENCODE_UTYPE_IMM(-1U),	/* dst_mask */
429 	 FALSE),		/* pcrel_offset */
430 
431   /* Low 12 bits of TLS LE thread pointer offset for loads and adds.  */
432   HOWTO (R_RISCV_TPREL_LO12_I,	/* type */
433 	 0,			/* rightshift */
434 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
435 	 32,			/* bitsize */
436 	 FALSE,			/* pc_relative */
437 	 0,			/* bitpos */
438 	 complain_overflow_signed, /* complain_on_overflow */
439 	 bfd_elf_generic_reloc, /* special_function */
440 	 "R_RISCV_TPREL_LO12_I",/* name */
441 	 FALSE,			/* partial_inplace */
442 	 0,			/* src_mask */
443 	 ENCODE_ITYPE_IMM(-1U),	/* dst_mask */
444 	 FALSE),		/* pcrel_offset */
445 
446   /* Low 12 bits of TLS LE thread pointer offset for stores.  */
447   HOWTO (R_RISCV_TPREL_LO12_S,	/* type */
448 	 0,			/* rightshift */
449 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
450 	 32,			/* bitsize */
451 	 FALSE,			/* pc_relative */
452 	 0,			/* bitpos */
453 	 complain_overflow_signed, /* complain_on_overflow */
454 	 bfd_elf_generic_reloc, /* special_function */
455 	 "R_RISCV_TPREL_LO12_S",/* name */
456 	 FALSE,			/* partial_inplace */
457 	 0,			/* src_mask */
458 	 ENCODE_STYPE_IMM(-1U),	/* dst_mask */
459 	 FALSE),		/* pcrel_offset */
460 
461   /* TLS LE thread pointer usage.  */
462   HOWTO (R_RISCV_TPREL_ADD,	/* type */
463 	 0,			/* rightshift */
464 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
465 	 32,			/* bitsize */
466 	 FALSE,			/* pc_relative */
467 	 0,			/* bitpos */
468 	 complain_overflow_dont,/* complain_on_overflow */
469 	 bfd_elf_generic_reloc, /* special_function */
470 	 "R_RISCV_TPREL_ADD",	/* name */
471 	 TRUE,			/* partial_inplace */
472 	 0,			/* src_mask */
473 	 0,			/* dst_mask */
474 	 FALSE),		/* pcrel_offset */
475 
476   /* 8-bit in-place addition, for local label subtraction.  */
477   HOWTO (R_RISCV_ADD8,		/* type */
478 	 0,			/* rightshift */
479 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
480 	 32,			/* bitsize */
481 	 FALSE,			/* pc_relative */
482 	 0,			/* bitpos */
483 	 complain_overflow_dont, /* complain_on_overflow */
484 	 bfd_elf_generic_reloc,	/* special_function */
485 	 "R_RISCV_ADD8",	/* name */
486 	 FALSE,			/* partial_inplace */
487 	 0,			/* src_mask */
488 	 MINUS_ONE,		/* dst_mask */
489 	 FALSE),		/* pcrel_offset */
490 
491   /* 16-bit in-place addition, for local label subtraction.  */
492   HOWTO (R_RISCV_ADD16,		/* type */
493 	 0,			/* rightshift */
494 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
495 	 16,			/* bitsize */
496 	 FALSE,			/* pc_relative */
497 	 0,			/* bitpos */
498 	 complain_overflow_dont, /* complain_on_overflow */
499 	 bfd_elf_generic_reloc,	/* special_function */
500 	 "R_RISCV_ADD16",	/* name */
501 	 FALSE,			/* partial_inplace */
502 	 0,			/* src_mask */
503 	 MINUS_ONE,		/* dst_mask */
504 	 FALSE),		/* pcrel_offset */
505 
506   /* 32-bit in-place addition, for local label subtraction.  */
507   HOWTO (R_RISCV_ADD32,		/* type */
508 	 0,			/* rightshift */
509 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
510 	 32,			/* bitsize */
511 	 FALSE,			/* pc_relative */
512 	 0,			/* bitpos */
513 	 complain_overflow_dont, /* complain_on_overflow */
514 	 bfd_elf_generic_reloc,	/* special_function */
515 	 "R_RISCV_ADD32",	/* name */
516 	 FALSE,			/* partial_inplace */
517 	 0,			/* src_mask */
518 	 MINUS_ONE,		/* dst_mask */
519 	 FALSE),		/* pcrel_offset */
520 
521   /* 64-bit in-place addition, for local label subtraction.  */
522   HOWTO (R_RISCV_ADD64,		/* type */
523 	 0,			/* rightshift */
524 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
525 	 64,			/* bitsize */
526 	 FALSE,			/* pc_relative */
527 	 0,			/* bitpos */
528 	 complain_overflow_dont, /* complain_on_overflow */
529 	 bfd_elf_generic_reloc,	/* special_function */
530 	 "R_RISCV_ADD64",	/* name */
531 	 FALSE,			/* partial_inplace */
532 	 0,			/* src_mask */
533 	 MINUS_ONE,		/* dst_mask */
534 	 FALSE),		/* pcrel_offset */
535 
536   /* 8-bit in-place addition, for local label subtraction.  */
537   HOWTO (R_RISCV_SUB8,		/* type */
538 	 0,			/* rightshift */
539 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
540 	 8,			/* bitsize */
541 	 FALSE,			/* pc_relative */
542 	 0,			/* bitpos */
543 	 complain_overflow_dont, /* complain_on_overflow */
544 	 bfd_elf_generic_reloc,	/* special_function */
545 	 "R_RISCV_SUB8",	/* name */
546 	 FALSE,			/* partial_inplace */
547 	 0,			/* src_mask */
548 	 MINUS_ONE,		/* dst_mask */
549 	 FALSE),		/* pcrel_offset */
550 
551   /* 16-bit in-place addition, for local label subtraction.  */
552   HOWTO (R_RISCV_SUB16,		/* type */
553 	 0,			/* rightshift */
554 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
555 	 16,			/* bitsize */
556 	 FALSE,			/* pc_relative */
557 	 0,			/* bitpos */
558 	 complain_overflow_dont, /* complain_on_overflow */
559 	 bfd_elf_generic_reloc,	/* special_function */
560 	 "R_RISCV_SUB16",	/* name */
561 	 FALSE,			/* partial_inplace */
562 	 0,			/* src_mask */
563 	 MINUS_ONE,		/* dst_mask */
564 	 FALSE),		/* pcrel_offset */
565 
566   /* 32-bit in-place addition, for local label subtraction.  */
567   HOWTO (R_RISCV_SUB32,		/* type */
568 	 0,			/* rightshift */
569 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
570 	 32,			/* bitsize */
571 	 FALSE,			/* pc_relative */
572 	 0,			/* bitpos */
573 	 complain_overflow_dont, /* complain_on_overflow */
574 	 bfd_elf_generic_reloc,	/* special_function */
575 	 "R_RISCV_SUB32",	/* name */
576 	 FALSE,			/* partial_inplace */
577 	 0,			/* src_mask */
578 	 MINUS_ONE,		/* dst_mask */
579 	 FALSE),		/* pcrel_offset */
580 
581   /* 64-bit in-place addition, for local label subtraction.  */
582   HOWTO (R_RISCV_SUB64,		/* type */
583 	 0,			/* rightshift */
584 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
585 	 64,			/* bitsize */
586 	 FALSE,			/* pc_relative */
587 	 0,			/* bitpos */
588 	 complain_overflow_dont, /* complain_on_overflow */
589 	 bfd_elf_generic_reloc,	/* special_function */
590 	 "R_RISCV_SUB64",	/* name */
591 	 FALSE,			/* partial_inplace */
592 	 0,			/* src_mask */
593 	 MINUS_ONE,		/* dst_mask */
594 	 FALSE),		/* pcrel_offset */
595 
596   /* GNU extension to record C++ vtable hierarchy */
597   HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
598 	 0,			/* rightshift */
599 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
600 	 0,			/* bitsize */
601 	 FALSE,			/* pc_relative */
602 	 0,			/* bitpos */
603 	 complain_overflow_dont,/* complain_on_overflow */
604 	 NULL,			/* special_function */
605 	 "R_RISCV_GNU_VTINHERIT", /* name */
606 	 FALSE,			/* partial_inplace */
607 	 0,			/* src_mask */
608 	 0,			/* dst_mask */
609 	 FALSE),		/* pcrel_offset */
610 
611   /* GNU extension to record C++ vtable member usage */
612   HOWTO (R_RISCV_GNU_VTENTRY,	/* type */
613 	 0,			/* rightshift */
614 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
615 	 0,			/* bitsize */
616 	 FALSE,			/* pc_relative */
617 	 0,			/* bitpos */
618 	 complain_overflow_dont,/* complain_on_overflow */
619 	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
620 	 "R_RISCV_GNU_VTENTRY",	/* name */
621 	 FALSE,			/* partial_inplace */
622 	 0,			/* src_mask */
623 	 0,			/* dst_mask */
624 	 FALSE),		/* pcrel_offset */
625 
626   /* Indicates an alignment statement.  The addend field encodes how many
627      bytes of NOPs follow the statement.  The desired alignment is the
628      addend rounded up to the next power of two.  */
629   HOWTO (R_RISCV_ALIGN,		/* type */
630 	 0,			/* rightshift */
631 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
632 	 0,			/* bitsize */
633 	 FALSE,			/* pc_relative */
634 	 0,			/* bitpos */
635 	 complain_overflow_dont, /* complain_on_overflow */
636 	 bfd_elf_generic_reloc,	/* special_function */
637 	 "R_RISCV_ALIGN",	/* name */
638 	 FALSE,			/* partial_inplace */
639 	 0,			/* src_mask */
640 	 0,			/* dst_mask */
641 	 TRUE),			/* pcrel_offset */
642 };
643 
644 /* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
645 
646 struct elf_reloc_map {
647   bfd_reloc_code_real_type bfd_val;
648   enum elf_riscv_reloc_type elf_val;
649 };
650 
651 static const struct elf_reloc_map riscv_reloc_map[] =
652 {
653   { BFD_RELOC_NONE, R_RISCV_NONE },
654   { BFD_RELOC_32, R_RISCV_32 },
655   { BFD_RELOC_64, R_RISCV_64 },
656   { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
657   { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
658   { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
659   { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
660   { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
661   { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
662   { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
663   { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
664   { BFD_RELOC_CTOR, R_RISCV_64 },
665   { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
666   { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
667   { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
668   { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
669   { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
670   { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
671   { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
672   { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
673   { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
674   { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
675   { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
676   { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
677   { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
678   { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
679   { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
680   { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
681   { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
682   { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
683   { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
684   { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
685   { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
686   { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
687   { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
688   { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
689 };
690 
691 /* Given a BFD reloc type, return a howto structure.  */
692 
693 reloc_howto_type *
694 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
695 				 bfd_reloc_code_real_type code)
696 {
697   unsigned int i;
698 
699   for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
700     if (riscv_reloc_map[i].bfd_val == code)
701       return &howto_table[(int) riscv_reloc_map[i].elf_val];
702 
703   bfd_set_error (bfd_error_bad_value);
704   return NULL;
705 }
706 
707 reloc_howto_type *
708 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
709 				 const char *r_name)
710 {
711   unsigned int i;
712 
713   for (i = 0; i < ARRAY_SIZE (howto_table); i++)
714     if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
715       return &howto_table[i];
716 
717   return NULL;
718 }
719 
720 reloc_howto_type *
721 riscv_elf_rtype_to_howto (unsigned int r_type)
722 {
723   if ((unsigned int)r_type >= ARRAY_SIZE (howto_table))
724     {
725       (*_bfd_error_handler)(_("unrecognized relocation (0x%x)"), r_type);
726       bfd_set_error (bfd_error_bad_value);
727       return NULL;
728     }
729   return &howto_table[r_type];
730 }
731