Formatting changes for RISC-V
[external/binutils.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2    Copyright 2011-2016 Free Software Foundation, Inc.
3
4    Contributed by Andrew Waterman (andrew@sifive.com).
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; see the file COPYING3. If not,
21    see <http://www.gnu.org/licenses/>.  */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include <stdint.h>
32
33 #define MINUS_ONE ((bfd_vma)0 - 1)
34
35 /* The relocation table used for SHT_RELA sections.  */
36
37 static reloc_howto_type howto_table[] =
38 {
39   /* No relocation.  */
40   HOWTO (R_RISCV_NONE,                  /* type */
41          0,                             /* rightshift */
42          3,                             /* size */
43          0,                             /* bitsize */
44          FALSE,                         /* pc_relative */
45          0,                             /* bitpos */
46          complain_overflow_dont,        /* complain_on_overflow */
47          bfd_elf_generic_reloc,         /* special_function */
48          "R_RISCV_NONE",                /* name */
49          FALSE,                         /* partial_inplace */
50          0,                             /* src_mask */
51          0,                             /* dst_mask */
52          FALSE),                        /* pcrel_offset */
53
54   /* 32 bit relocation.  */
55   HOWTO (R_RISCV_32,                    /* type */
56          0,                             /* rightshift */
57          2,                             /* size */
58          32,                            /* bitsize */
59          FALSE,                         /* pc_relative */
60          0,                             /* bitpos */
61          complain_overflow_dont,        /* complain_on_overflow */
62          bfd_elf_generic_reloc,         /* special_function */
63          "R_RISCV_32",                  /* name */
64          FALSE,                         /* partial_inplace */
65          0,                             /* src_mask */
66          MINUS_ONE,                     /* dst_mask */
67          FALSE),                        /* pcrel_offset */
68
69   /* 64 bit relocation.  */
70   HOWTO (R_RISCV_64,                    /* type */
71          0,                             /* rightshift */
72          4,                             /* size */
73          64,                            /* bitsize */
74          FALSE,                         /* pc_relative */
75          0,                             /* bitpos */
76          complain_overflow_dont,        /* complain_on_overflow */
77          bfd_elf_generic_reloc,         /* special_function */
78          "R_RISCV_64",                  /* name */
79          FALSE,                         /* partial_inplace */
80          0,                             /* src_mask */
81          MINUS_ONE,                     /* dst_mask */
82          FALSE),                        /* pcrel_offset */
83
84   /* Relocation against a local symbol in a shared object.  */
85   HOWTO (R_RISCV_RELATIVE,              /* type */
86          0,                             /* rightshift */
87          2,                             /* size */
88          32,                            /* bitsize */
89          FALSE,                         /* pc_relative */
90          0,                             /* bitpos */
91          complain_overflow_dont,        /* complain_on_overflow */
92          bfd_elf_generic_reloc,         /* special_function */
93          "R_RISCV_RELATIVE",            /* name */
94          FALSE,                         /* partial_inplace */
95          0,                             /* src_mask */
96          MINUS_ONE,                     /* dst_mask */
97          FALSE),                        /* pcrel_offset */
98
99   HOWTO (R_RISCV_COPY,                  /* type */
100          0,                             /* rightshift */
101          0,                             /* this one is variable size */
102          0,                             /* bitsize */
103          FALSE,                         /* pc_relative */
104          0,                             /* bitpos */
105          complain_overflow_bitfield,    /* complain_on_overflow */
106          bfd_elf_generic_reloc,         /* special_function */
107          "R_RISCV_COPY",                /* name */
108          FALSE,                         /* partial_inplace */
109          0,                             /* src_mask */
110          0,                             /* dst_mask */
111          FALSE),                        /* pcrel_offset */
112
113   HOWTO (R_RISCV_JUMP_SLOT,             /* type */
114          0,                             /* rightshift */
115          4,                             /* size */
116          64,                            /* bitsize */
117          FALSE,                         /* pc_relative */
118          0,                             /* bitpos */
119          complain_overflow_bitfield,    /* complain_on_overflow */
120          bfd_elf_generic_reloc,         /* special_function */
121          "R_RISCV_JUMP_SLOT",           /* name */
122          FALSE,                         /* partial_inplace */
123          0,                             /* src_mask */
124          0,                             /* dst_mask */
125          FALSE),                        /* pcrel_offset */
126
127   /* Dynamic TLS relocations.  */
128   HOWTO (R_RISCV_TLS_DTPMOD32,          /* type */
129          0,                             /* rightshift */
130          4,                             /* size */
131          32,                            /* bitsize */
132          FALSE,                         /* pc_relative */
133          0,                             /* bitpos */
134          complain_overflow_dont,        /* complain_on_overflow */
135          bfd_elf_generic_reloc,         /* special_function */
136          "R_RISCV_TLS_DTPMOD32",        /* name */
137          FALSE,                         /* partial_inplace */
138          0,                             /* src_mask */
139          MINUS_ONE,                     /* dst_mask */
140          FALSE),                        /* pcrel_offset */
141
142   HOWTO (R_RISCV_TLS_DTPMOD64,          /* type */
143          0,                             /* rightshift */
144          4,                             /* size */
145          64,                            /* bitsize */
146          FALSE,                         /* pc_relative */
147          0,                             /* bitpos */
148          complain_overflow_dont,        /* complain_on_overflow */
149          bfd_elf_generic_reloc,         /* special_function */
150          "R_RISCV_TLS_DTPMOD64",        /* name */
151          FALSE,                         /* partial_inplace */
152          0,                             /* src_mask */
153          MINUS_ONE,                     /* dst_mask */
154          FALSE),                        /* pcrel_offset */
155
156   HOWTO (R_RISCV_TLS_DTPREL32,          /* type */
157          0,                             /* rightshift */
158          4,                             /* size */
159          32,                            /* bitsize */
160          FALSE,                         /* pc_relative */
161          0,                             /* bitpos */
162          complain_overflow_dont,        /* complain_on_overflow */
163          bfd_elf_generic_reloc,         /* special_function */
164          "R_RISCV_TLS_DTPREL32",        /* name */
165          TRUE,                          /* partial_inplace */
166          0,                             /* src_mask */
167          MINUS_ONE,                     /* dst_mask */
168          FALSE),                        /* pcrel_offset */
169
170   HOWTO (R_RISCV_TLS_DTPREL64,          /* type */
171          0,                             /* rightshift */
172          4,                             /* size */
173          64,                            /* bitsize */
174          FALSE,                         /* pc_relative */
175          0,                             /* bitpos */
176          complain_overflow_dont,        /* complain_on_overflow */
177          bfd_elf_generic_reloc,         /* special_function */
178          "R_RISCV_TLS_DTPREL64",        /* name */
179          TRUE,                          /* partial_inplace */
180          0,                             /* src_mask */
181          MINUS_ONE,                     /* dst_mask */
182          FALSE),                        /* pcrel_offset */
183
184   HOWTO (R_RISCV_TLS_TPREL32,           /* type */
185          0,                             /* rightshift */
186          2,                             /* size */
187          32,                            /* bitsize */
188          FALSE,                         /* pc_relative */
189          0,                             /* bitpos */
190          complain_overflow_dont,        /* complain_on_overflow */
191          bfd_elf_generic_reloc,         /* special_function */
192          "R_RISCV_TLS_TPREL32",         /* name */
193          FALSE,                         /* partial_inplace */
194          0,                             /* src_mask */
195          MINUS_ONE,                     /* dst_mask */
196          FALSE),                        /* pcrel_offset */
197
198   HOWTO (R_RISCV_TLS_TPREL64,           /* type */
199          0,                             /* rightshift */
200          4,                             /* size */
201          64,                            /* bitsize */
202          FALSE,                         /* pc_relative */
203          0,                             /* bitpos */
204          complain_overflow_dont,        /* complain_on_overflow */
205          bfd_elf_generic_reloc,         /* special_function */
206          "R_RISCV_TLS_TPREL64",         /* name */
207          FALSE,                         /* partial_inplace */
208          0,                             /* src_mask */
209          MINUS_ONE,                     /* dst_mask */
210          FALSE),                        /* pcrel_offset */
211
212   /* Reserved for future relocs that the dynamic linker must understand.  */
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 */
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 */
237          32,                            /* bitsize */
238          TRUE,                          /* pc_relative */
239          0,                             /* bitpos */
240          complain_overflow_dont,        /* complain_on_overflow */
241          bfd_elf_generic_reloc,         /* special_function */
242          "R_RISCV_JAL",                 /* name */
243          FALSE,                         /* partial_inplace */
244          0,                             /* src_mask */
245          ENCODE_UJTYPE_IMM (-1U),       /* dst_mask */
246          TRUE),                         /* pcrel_offset */
247
248   /* 32-bit PC-relative function call (AUIPC/JALR).  */
249   HOWTO (R_RISCV_CALL,                  /* type */
250          0,                             /* rightshift */
251          2,                             /* size */
252          64,                            /* bitsize */
253          TRUE,                          /* pc_relative */
254          0,                             /* bitpos */
255          complain_overflow_dont,        /* complain_on_overflow */
256          bfd_elf_generic_reloc,         /* special_function */
257          "R_RISCV_CALL",                /* name */
258          FALSE,                         /* partial_inplace */
259          0,                             /* src_mask */
260          ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
261                                         /* dst_mask */
262          TRUE),                         /* pcrel_offset */
263
264   /* Like R_RISCV_CALL, but not locally binding.  */
265   HOWTO (R_RISCV_CALL_PLT,              /* type */
266          0,                             /* rightshift */
267          2,                             /* size */
268          64,                            /* bitsize */
269          TRUE,                          /* pc_relative */
270          0,                             /* bitpos */
271          complain_overflow_dont,        /* complain_on_overflow */
272          bfd_elf_generic_reloc,         /* special_function */
273          "R_RISCV_CALL_PLT",            /* name */
274          FALSE,                         /* partial_inplace */
275          0,                             /* src_mask */
276          ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
277                                         /* dst_mask */
278          TRUE),                         /* pcrel_offset */
279
280   /* High 20 bits of 32-bit PC-relative GOT access.  */
281   HOWTO (R_RISCV_GOT_HI20,              /* type */
282          0,                             /* rightshift */
283          2,                             /* size */
284          32,                            /* bitsize */
285          TRUE,                          /* pc_relative */
286          0,                             /* bitpos */
287          complain_overflow_dont,        /* complain_on_overflow */
288          bfd_elf_generic_reloc,         /* special_function */
289          "R_RISCV_GOT_HI20",            /* name */
290          FALSE,                         /* partial_inplace */
291          0,                             /* src_mask */
292          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
293          FALSE),                        /* pcrel_offset */
294
295   /* High 20 bits of 32-bit PC-relative TLS IE GOT access.  */
296   HOWTO (R_RISCV_TLS_GOT_HI20,          /* type */
297          0,                             /* rightshift */
298          2,                             /* size */
299          32,                            /* bitsize */
300          TRUE,                          /* pc_relative */
301          0,                             /* bitpos */
302          complain_overflow_dont,        /* complain_on_overflow */
303          bfd_elf_generic_reloc,         /* special_function */
304          "R_RISCV_TLS_GOT_HI20",        /* name */
305          FALSE,                         /* partial_inplace */
306          0,                             /* src_mask */
307          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
308          FALSE),                        /* pcrel_offset */
309
310   /* High 20 bits of 32-bit PC-relative TLS GD GOT reference.  */
311   HOWTO (R_RISCV_TLS_GD_HI20,           /* type */
312          0,                             /* rightshift */
313          2,                             /* size */
314          32,                            /* bitsize */
315          TRUE,                          /* pc_relative */
316          0,                             /* bitpos */
317          complain_overflow_dont,        /* complain_on_overflow */
318          bfd_elf_generic_reloc,         /* special_function */
319          "R_RISCV_TLS_GD_HI20",         /* name */
320          FALSE,                         /* partial_inplace */
321          0,                             /* src_mask */
322          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
323          FALSE),                        /* pcrel_offset */
324
325   /* High 20 bits of 32-bit PC-relative reference.  */
326   HOWTO (R_RISCV_PCREL_HI20,            /* type */
327          0,                             /* rightshift */
328          2,                             /* size */
329          32,                            /* bitsize */
330          TRUE,                          /* pc_relative */
331          0,                             /* bitpos */
332          complain_overflow_dont,        /* complain_on_overflow */
333          bfd_elf_generic_reloc,         /* special_function */
334          "R_RISCV_PCREL_HI20",          /* name */
335          FALSE,                         /* partial_inplace */
336          0,                             /* src_mask */
337          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
338          TRUE),                         /* pcrel_offset */
339
340   /* Low 12 bits of a 32-bit PC-relative load or add.  */
341   HOWTO (R_RISCV_PCREL_LO12_I,          /* type */
342          0,                             /* rightshift */
343          2,                             /* size */
344          32,                            /* bitsize */
345          FALSE,                         /* pc_relative */
346          0,                             /* bitpos */
347          complain_overflow_dont,        /* complain_on_overflow */
348          bfd_elf_generic_reloc,         /* special_function */
349          "R_RISCV_PCREL_LO12_I",        /* name */
350          FALSE,                         /* partial_inplace */
351          0,                             /* src_mask */
352          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
353          FALSE),                        /* pcrel_offset */
354
355   /* Low 12 bits of a 32-bit PC-relative store.  */
356   HOWTO (R_RISCV_PCREL_LO12_S,          /* type */
357          0,                             /* rightshift */
358          2,                             /* size */
359          32,                            /* bitsize */
360          FALSE,                         /* pc_relative */
361          0,                             /* bitpos */
362          complain_overflow_dont,        /* complain_on_overflow */
363          bfd_elf_generic_reloc,         /* special_function */
364          "R_RISCV_PCREL_LO12_S",        /* name */
365          FALSE,                         /* partial_inplace */
366          0,                             /* src_mask */
367          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
368          FALSE),                        /* pcrel_offset */
369
370   /* High 20 bits of 32-bit absolute address.  */
371   HOWTO (R_RISCV_HI20,                  /* type */
372          0,                             /* rightshift */
373          2,                             /* size */
374          32,                            /* bitsize */
375          FALSE,                         /* pc_relative */
376          0,                             /* bitpos */
377          complain_overflow_dont,        /* complain_on_overflow */
378          bfd_elf_generic_reloc,         /* special_function */
379          "R_RISCV_HI20",                /* name */
380          FALSE,                         /* partial_inplace */
381          0,                             /* src_mask */
382          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
383          FALSE),                        /* pcrel_offset */
384
385   /* High 12 bits of 32-bit load or add.  */
386   HOWTO (R_RISCV_LO12_I,                /* type */
387          0,                             /* rightshift */
388          2,                             /* size */
389          32,                            /* bitsize */
390          FALSE,                         /* pc_relative */
391          0,                             /* bitpos */
392          complain_overflow_dont,        /* complain_on_overflow */
393          bfd_elf_generic_reloc,         /* special_function */
394          "R_RISCV_LO12_I",              /* name */
395          FALSE,                         /* partial_inplace */
396          0,                             /* src_mask */
397          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
398          FALSE),                        /* pcrel_offset */
399
400   /* High 12 bits of 32-bit store.  */
401   HOWTO (R_RISCV_LO12_S,                /* type */
402          0,                             /* rightshift */
403          2,                             /* size */
404          32,                            /* bitsize */
405          FALSE,                         /* pc_relative */
406          0,                             /* bitpos */
407          complain_overflow_dont,        /* complain_on_overflow */
408          bfd_elf_generic_reloc,         /* special_function */
409          "R_RISCV_LO12_S",              /* name */
410          FALSE,                         /* partial_inplace */
411          0,                             /* src_mask */
412          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
413          FALSE),                        /* pcrel_offset */
414
415   /* High 20 bits of TLS LE thread pointer offset.  */
416   HOWTO (R_RISCV_TPREL_HI20,            /* type */
417          0,                             /* rightshift */
418          2,                             /* size */
419          32,                            /* bitsize */
420          FALSE,                         /* pc_relative */
421          0,                             /* bitpos */
422          complain_overflow_signed,      /* complain_on_overflow */
423          bfd_elf_generic_reloc,         /* special_function */
424          "R_RISCV_TPREL_HI20",          /* name */
425          TRUE,                          /* partial_inplace */
426          0,                             /* src_mask */
427          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
428          FALSE),                        /* pcrel_offset */
429
430   /* Low 12 bits of TLS LE thread pointer offset for loads and adds.  */
431   HOWTO (R_RISCV_TPREL_LO12_I,          /* type */
432          0,                             /* rightshift */
433          2,                             /* size */
434          32,                            /* bitsize */
435          FALSE,                         /* pc_relative */
436          0,                             /* bitpos */
437          complain_overflow_signed,      /* complain_on_overflow */
438          bfd_elf_generic_reloc,         /* special_function */
439          "R_RISCV_TPREL_LO12_I",        /* name */
440          FALSE,                         /* partial_inplace */
441          0,                             /* src_mask */
442          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
443          FALSE),                        /* pcrel_offset */
444
445   /* Low 12 bits of TLS LE thread pointer offset for stores.  */
446   HOWTO (R_RISCV_TPREL_LO12_S,          /* type */
447          0,                             /* rightshift */
448          2,                             /* size */
449          32,                            /* bitsize */
450          FALSE,                         /* pc_relative */
451          0,                             /* bitpos */
452          complain_overflow_signed,      /* complain_on_overflow */
453          bfd_elf_generic_reloc,         /* special_function */
454          "R_RISCV_TPREL_LO12_S",        /* name */
455          FALSE,                         /* partial_inplace */
456          0,                             /* src_mask */
457          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
458          FALSE),                        /* pcrel_offset */
459
460   /* TLS LE thread pointer usage.  May be relaxed.  */
461   HOWTO (R_RISCV_TPREL_ADD,             /* type */
462          0,                             /* rightshift */
463          2,                             /* size */
464          32,                            /* bitsize */
465          FALSE,                         /* pc_relative */
466          0,                             /* bitpos */
467          complain_overflow_dont,        /* complain_on_overflow */
468          bfd_elf_generic_reloc,         /* special_function */
469          "R_RISCV_TPREL_ADD",           /* name */
470          TRUE,                          /* partial_inplace */
471          0,                             /* src_mask */
472          0,                             /* dst_mask */
473          FALSE),                        /* pcrel_offset */
474
475   /* 8-bit in-place addition, for local label subtraction.  */
476   HOWTO (R_RISCV_ADD8,                  /* type */
477          0,                             /* rightshift */
478          0,                             /* size */
479          8,                             /* bitsize */
480          FALSE,                         /* pc_relative */
481          0,                             /* bitpos */
482          complain_overflow_dont,        /* complain_on_overflow */
483          bfd_elf_generic_reloc,         /* special_function */
484          "R_RISCV_ADD8",                /* name */
485          FALSE,                         /* partial_inplace */
486          0,                             /* src_mask */
487          MINUS_ONE,                     /* dst_mask */
488          FALSE),                        /* pcrel_offset */
489
490   /* 16-bit in-place addition, for local label subtraction.  */
491   HOWTO (R_RISCV_ADD16,                 /* type */
492          0,                             /* rightshift */
493          1,                             /* size */
494          16,                            /* bitsize */
495          FALSE,                         /* pc_relative */
496          0,                             /* bitpos */
497          complain_overflow_dont,        /* complain_on_overflow */
498          bfd_elf_generic_reloc,         /* special_function */
499          "R_RISCV_ADD16",               /* name */
500          FALSE,                         /* partial_inplace */
501          0,                             /* src_mask */
502          MINUS_ONE,                     /* dst_mask */
503          FALSE),                        /* pcrel_offset */
504
505   /* 32-bit in-place addition, for local label subtraction.  */
506   HOWTO (R_RISCV_ADD32,                 /* type */
507          0,                             /* rightshift */
508          2,                             /* size */
509          32,                            /* bitsize */
510          FALSE,                         /* pc_relative */
511          0,                             /* bitpos */
512          complain_overflow_dont,        /* complain_on_overflow */
513          bfd_elf_generic_reloc,         /* special_function */
514          "R_RISCV_ADD32",               /* name */
515          FALSE,                         /* partial_inplace */
516          0,                             /* src_mask */
517          MINUS_ONE,                     /* dst_mask */
518          FALSE),                        /* pcrel_offset */
519
520   /* 64-bit in-place addition, for local label subtraction.  */
521   HOWTO (R_RISCV_ADD64,                 /* type */
522          0,                             /* rightshift */
523          4,                             /* size */
524          64,                            /* bitsize */
525          FALSE,                         /* pc_relative */
526          0,                             /* bitpos */
527          complain_overflow_dont,        /* complain_on_overflow */
528          bfd_elf_generic_reloc,         /* special_function */
529          "R_RISCV_ADD64",               /* name */
530          FALSE,                         /* partial_inplace */
531          0,                             /* src_mask */
532          MINUS_ONE,                     /* dst_mask */
533          FALSE),                        /* pcrel_offset */
534
535   /* 8-bit in-place addition, for local label subtraction.  */
536   HOWTO (R_RISCV_SUB8,                  /* type */
537          0,                             /* rightshift */
538          0,                             /* size */
539          8,                             /* bitsize */
540          FALSE,                         /* pc_relative */
541          0,                             /* bitpos */
542          complain_overflow_dont,        /* complain_on_overflow */
543          bfd_elf_generic_reloc,         /* special_function */
544          "R_RISCV_SUB8",                /* name */
545          FALSE,                         /* partial_inplace */
546          0,                             /* src_mask */
547          MINUS_ONE,                     /* dst_mask */
548          FALSE),                        /* pcrel_offset */
549
550   /* 16-bit in-place addition, for local label subtraction.  */
551   HOWTO (R_RISCV_SUB16,                 /* type */
552          0,                             /* rightshift */
553          1,                             /* size */
554          16,                            /* bitsize */
555          FALSE,                         /* pc_relative */
556          0,                             /* bitpos */
557          complain_overflow_dont,        /* complain_on_overflow */
558          bfd_elf_generic_reloc,         /* special_function */
559          "R_RISCV_SUB16",               /* name */
560          FALSE,                         /* partial_inplace */
561          0,                             /* src_mask */
562          MINUS_ONE,                     /* dst_mask */
563          FALSE),                        /* pcrel_offset */
564
565   /* 32-bit in-place addition, for local label subtraction.  */
566   HOWTO (R_RISCV_SUB32,                 /* type */
567          0,                             /* rightshift */
568          2,                             /* size */
569          32,                            /* bitsize */
570          FALSE,                         /* pc_relative */
571          0,                             /* bitpos */
572          complain_overflow_dont,        /* complain_on_overflow */
573          bfd_elf_generic_reloc,         /* special_function */
574          "R_RISCV_SUB32",               /* name */
575          FALSE,                         /* partial_inplace */
576          0,                             /* src_mask */
577          MINUS_ONE,                     /* dst_mask */
578          FALSE),                        /* pcrel_offset */
579
580   /* 64-bit in-place addition, for local label subtraction.  */
581   HOWTO (R_RISCV_SUB64,                 /* type */
582          0,                             /* rightshift */
583          4,                             /* size */
584          64,                            /* bitsize */
585          FALSE,                         /* pc_relative */
586          0,                             /* bitpos */
587          complain_overflow_dont,        /* complain_on_overflow */
588          bfd_elf_generic_reloc,         /* special_function */
589          "R_RISCV_SUB64",               /* name */
590          FALSE,                         /* partial_inplace */
591          0,                             /* src_mask */
592          MINUS_ONE,                     /* dst_mask */
593          FALSE),                        /* pcrel_offset */
594
595   /* GNU extension to record C++ vtable hierarchy */
596   HOWTO (R_RISCV_GNU_VTINHERIT,         /* type */
597          0,                             /* rightshift */
598          4,                             /* size */
599          0,                             /* bitsize */
600          FALSE,                         /* pc_relative */
601          0,                             /* bitpos */
602          complain_overflow_dont,        /* complain_on_overflow */
603          NULL,                          /* special_function */
604          "R_RISCV_GNU_VTINHERIT",       /* name */
605          FALSE,                         /* partial_inplace */
606          0,                             /* src_mask */
607          0,                             /* dst_mask */
608          FALSE),                        /* pcrel_offset */
609
610   /* GNU extension to record C++ vtable member usage */
611   HOWTO (R_RISCV_GNU_VTENTRY,           /* type */
612          0,                             /* rightshift */
613          4,                             /* size */
614          0,                             /* bitsize */
615          FALSE,                         /* pc_relative */
616          0,                             /* bitpos */
617          complain_overflow_dont,        /* complain_on_overflow */
618          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
619          "R_RISCV_GNU_VTENTRY",         /* name */
620          FALSE,                         /* partial_inplace */
621          0,                             /* src_mask */
622          0,                             /* dst_mask */
623          FALSE),                        /* pcrel_offset */
624
625   /* Indicates an alignment statement.  The addend field encodes how many
626      bytes of NOPs follow the statement.  The desired alignment is the
627      addend rounded up to the next power of two.  */
628   HOWTO (R_RISCV_ALIGN,                 /* type */
629          0,                             /* rightshift */
630          2,                             /* size */
631          0,                             /* bitsize */
632          FALSE,                         /* pc_relative */
633          0,                             /* bitpos */
634          complain_overflow_dont,        /* complain_on_overflow */
635          bfd_elf_generic_reloc,         /* special_function */
636          "R_RISCV_ALIGN",               /* name */
637          FALSE,                         /* partial_inplace */
638          0,                             /* src_mask */
639          0,                             /* dst_mask */
640          TRUE),                         /* pcrel_offset */
641
642   /* 8-bit PC-relative branch offset.  */
643   HOWTO (R_RISCV_RVC_BRANCH,            /* type */
644          0,                             /* rightshift */
645          2,                             /* size */
646          32,                            /* bitsize */
647          TRUE,                          /* pc_relative */
648          0,                             /* bitpos */
649          complain_overflow_signed,      /* complain_on_overflow */
650          bfd_elf_generic_reloc,         /* special_function */
651          "R_RISCV_RVC_BRANCH",          /* name */
652          FALSE,                         /* partial_inplace */
653          0,                             /* src_mask */
654          ENCODE_RVC_B_IMM (-1U),        /* dst_mask */
655          TRUE),                         /* pcrel_offset */
656
657   /* 11-bit PC-relative jump offset.  */
658   HOWTO (R_RISCV_RVC_JUMP,              /* type */
659          0,                             /* rightshift */
660          2,                             /* size */
661          32,                            /* bitsize */
662          TRUE,                          /* pc_relative */
663          0,                             /* bitpos */
664          complain_overflow_dont,        /* complain_on_overflow */
665          bfd_elf_generic_reloc,         /* special_function */
666          "R_RISCV_RVC_JUMP",            /* name */
667          FALSE,                         /* partial_inplace */
668          0,                             /* src_mask */
669          ENCODE_RVC_J_IMM (-1U),        /* dst_mask */
670          TRUE),                         /* pcrel_offset */
671
672   /* High 6 bits of 18-bit absolute address.  */
673   HOWTO (R_RISCV_RVC_LUI,               /* type */
674          0,                             /* rightshift */
675          2,                             /* size */
676          32,                            /* bitsize */
677          FALSE,                         /* pc_relative */
678          0,                             /* bitpos */
679          complain_overflow_dont,        /* complain_on_overflow */
680          bfd_elf_generic_reloc,         /* special_function */
681          "R_RISCV_RVC_LUI",             /* name */
682          FALSE,                         /* partial_inplace */
683          0,                             /* src_mask */
684          ENCODE_RVC_IMM (-1U),          /* dst_mask */
685          FALSE),                        /* pcrel_offset */
686
687   /* GP-relative load.  */
688   HOWTO (R_RISCV_GPREL_I,               /* type */
689          0,                             /* rightshift */
690          2,                             /* size */
691          32,                            /* bitsize */
692          FALSE,                         /* pc_relative */
693          0,                             /* bitpos */
694          complain_overflow_dont,        /* complain_on_overflow */
695          bfd_elf_generic_reloc,         /* special_function */
696          "R_RISCV_GPREL_I",             /* name */
697          FALSE,                         /* partial_inplace */
698          0,                             /* src_mask */
699          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
700          FALSE),                        /* pcrel_offset */
701
702   /* GP-relative store.  */
703   HOWTO (R_RISCV_GPREL_S,               /* type */
704          0,                             /* rightshift */
705          2,                             /* size */
706          32,                            /* bitsize */
707          FALSE,                         /* pc_relative */
708          0,                             /* bitpos */
709          complain_overflow_dont,        /* complain_on_overflow */
710          bfd_elf_generic_reloc,         /* special_function */
711          "R_RISCV_GPREL_S",             /* name */
712          FALSE,                         /* partial_inplace */
713          0,                             /* src_mask */
714          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
715          FALSE),                        /* pcrel_offset */
716 };
717
718 /* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
719
720 struct elf_reloc_map
721 {
722   bfd_reloc_code_real_type bfd_val;
723   enum elf_riscv_reloc_type elf_val;
724 };
725
726 static const struct elf_reloc_map riscv_reloc_map[] =
727 {
728   { BFD_RELOC_NONE, R_RISCV_NONE },
729   { BFD_RELOC_32, R_RISCV_32 },
730   { BFD_RELOC_64, R_RISCV_64 },
731   { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
732   { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
733   { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
734   { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
735   { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
736   { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
737   { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
738   { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
739   { BFD_RELOC_CTOR, R_RISCV_64 },
740   { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
741   { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
742   { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
743   { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
744   { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
745   { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
746   { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
747   { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
748   { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
749   { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
750   { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
751   { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
752   { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
753   { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
754   { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
755   { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
756   { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
757   { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
758   { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
759   { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
760   { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
761   { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
762   { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
763   { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
764   { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
765   { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
766   { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
767   { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
768   { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
769 };
770
771 /* Given a BFD reloc type, return a howto structure.  */
772
773 reloc_howto_type *
774 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
775                          bfd_reloc_code_real_type code)
776 {
777   unsigned int i;
778
779   for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
780     if (riscv_reloc_map[i].bfd_val == code)
781       return &howto_table[(int) riscv_reloc_map[i].elf_val];
782
783   bfd_set_error (bfd_error_bad_value);
784   return NULL;
785 }
786
787 reloc_howto_type *
788 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
789 {
790   unsigned int i;
791
792   for (i = 0; i < ARRAY_SIZE (howto_table); i++)
793     if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
794       return &howto_table[i];
795
796   return NULL;
797 }
798
799 reloc_howto_type *
800 riscv_elf_rtype_to_howto (unsigned int r_type)
801 {
802   if (r_type >= ARRAY_SIZE (howto_table))
803     {
804       (*_bfd_error_handler) (_("unrecognized relocation (0x%x)"), r_type);
805       bfd_set_error (bfd_error_bad_value);
806       return NULL;
807     }
808   return &howto_table[r_type];
809 }