Add support for RISC-V architecture.
[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          0xffffffff,                    /* 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          0xffffffff,                    /* 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          0x0,                           /* src_mask */
110          0x0,                           /* 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          0x0,                           /* src_mask */
124          0x0,                           /* 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          MINUS_ONE,                     /* 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          MINUS_ONE,                     /* 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          MINUS_ONE,                     /* 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          MINUS_ONE,                     /* 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          MINUS_ONE,                     /* 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          MINUS_ONE,                     /* 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                                         /* 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 */
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),
264                                         /* dst_mask */
265          TRUE),                         /* pcrel_offset */
266
267   /* 32-bit PC-relative function call (AUIPC/JALR).  */
268   HOWTO (R_RISCV_CALL_PLT,              /* type */
269          0,                             /* rightshift */
270          2,                             /* size */
271          64,                            /* bitsize */
272          TRUE,                          /* pc_relative */
273          0,                             /* bitpos */
274          complain_overflow_dont,        /* complain_on_overflow */
275          bfd_elf_generic_reloc,         /* special_function */
276          "R_RISCV_CALL_PLT",            /* name */
277          FALSE,                         /* partial_inplace */
278          0,                             /* src_mask */
279          ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
280                                         /* dst_mask */
281          TRUE),                         /* pcrel_offset */
282
283   /* High 20 bits of 32-bit PC-relative GOT access.  */
284   HOWTO (R_RISCV_GOT_HI20,              /* type */
285          0,                             /* rightshift */
286          2,                             /* size */
287          32,                            /* bitsize */
288          TRUE,                          /* pc_relative */
289          0,                             /* bitpos */
290          complain_overflow_dont,        /* complain_on_overflow */
291          bfd_elf_generic_reloc,         /* special_function */
292          "R_RISCV_GOT_HI20",            /* name */
293          FALSE,                         /* partial_inplace */
294          0,                             /* src_mask */
295          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
296          FALSE),                        /* pcrel_offset */
297
298   /* High 20 bits of 32-bit PC-relative TLS IE GOT access.  */
299   HOWTO (R_RISCV_TLS_GOT_HI20,          /* type */
300          0,                             /* rightshift */
301          2,                             /* size */
302          32,                            /* bitsize */
303          TRUE,                          /* pc_relative */
304          0,                             /* bitpos */
305          complain_overflow_dont,        /* complain_on_overflow */
306          bfd_elf_generic_reloc,         /* special_function */
307          "R_RISCV_TLS_GOT_HI20",        /* name */
308          FALSE,                         /* partial_inplace */
309          0,                             /* src_mask */
310          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
311          FALSE),                        /* pcrel_offset */
312
313   /* High 20 bits of 32-bit PC-relative TLS GD GOT reference.  */
314   HOWTO (R_RISCV_TLS_GD_HI20,           /* type */
315          0,                             /* rightshift */
316          2,                             /* size */
317          32,                            /* bitsize */
318          TRUE,                          /* pc_relative */
319          0,                             /* bitpos */
320          complain_overflow_dont,        /* complain_on_overflow */
321          bfd_elf_generic_reloc,         /* special_function */
322          "R_RISCV_TLS_GD_HI20",         /* name */
323          FALSE,                         /* partial_inplace */
324          0,                             /* src_mask */
325          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
326          FALSE),                        /* pcrel_offset */
327
328   /* High 20 bits of 32-bit PC-relative reference.  */
329   HOWTO (R_RISCV_PCREL_HI20,            /* type */
330          0,                             /* rightshift */
331          2,                             /* size */
332          32,                            /* bitsize */
333          TRUE,                          /* pc_relative */
334          0,                             /* bitpos */
335          complain_overflow_dont,        /* complain_on_overflow */
336          bfd_elf_generic_reloc,         /* special_function */
337          "R_RISCV_PCREL_HI20",          /* name */
338          FALSE,                         /* partial_inplace */
339          0,                             /* src_mask */
340          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
341          TRUE),                         /* pcrel_offset */
342
343   /* Low 12 bits of a 32-bit PC-relative load or add.  */
344   HOWTO (R_RISCV_PCREL_LO12_I,          /* type */
345          0,                             /* rightshift */
346          2,                             /* size */
347          32,                            /* bitsize */
348          FALSE,                         /* pc_relative */
349          0,                             /* bitpos */
350          complain_overflow_dont,        /* complain_on_overflow */
351          bfd_elf_generic_reloc,         /* special_function */
352          "R_RISCV_PCREL_LO12_I",        /* name */
353          FALSE,                         /* partial_inplace */
354          0,                             /* src_mask */
355          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
356          FALSE),                        /* pcrel_offset */
357
358   /* Low 12 bits of a 32-bit PC-relative store.  */
359   HOWTO (R_RISCV_PCREL_LO12_S,          /* type */
360          0,                             /* rightshift */
361          2,                             /* size */
362          32,                            /* bitsize */
363          FALSE,                         /* pc_relative */
364          0,                             /* bitpos */
365          complain_overflow_dont,        /* complain_on_overflow */
366          bfd_elf_generic_reloc,         /* special_function */
367          "R_RISCV_PCREL_LO12_S",        /* name */
368          FALSE,                         /* partial_inplace */
369          0,                             /* src_mask */
370          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
371          FALSE),                        /* pcrel_offset */
372
373   /* High 20 bits of 32-bit absolute address.  */
374   HOWTO (R_RISCV_HI20,                  /* type */
375          0,                             /* rightshift */
376          2,                             /* size */
377          32,                            /* bitsize */
378          FALSE,                         /* pc_relative */
379          0,                             /* bitpos */
380          complain_overflow_dont,        /* complain_on_overflow */
381          bfd_elf_generic_reloc,         /* special_function */
382          "R_RISCV_HI20",                /* name */
383          FALSE,                         /* partial_inplace */
384          0,                             /* src_mask */
385          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
386          FALSE),                        /* pcrel_offset */
387
388   /* High 12 bits of 32-bit load or add.  */
389   HOWTO (R_RISCV_LO12_I,                /* type */
390          0,                             /* rightshift */
391          2,                             /* size */
392          32,                            /* bitsize */
393          FALSE,                         /* pc_relative */
394          0,                             /* bitpos */
395          complain_overflow_dont,        /* complain_on_overflow */
396          bfd_elf_generic_reloc,         /* special_function */
397          "R_RISCV_LO12_I",              /* name */
398          FALSE,                         /* partial_inplace */
399          0,                             /* src_mask */
400          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
401          FALSE),                        /* pcrel_offset */
402
403   /* High 12 bits of 32-bit store.  */
404   HOWTO (R_RISCV_LO12_S,                /* type */
405          0,                             /* rightshift */
406          2,                             /* size */
407          32,                            /* bitsize */
408          FALSE,                         /* pc_relative */
409          0,                             /* bitpos */
410          complain_overflow_dont,        /* complain_on_overflow */
411          bfd_elf_generic_reloc,         /* special_function */
412          "R_RISCV_LO12_S",              /* name */
413          FALSE,                         /* partial_inplace */
414          0,                             /* src_mask */
415          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
416          FALSE),                        /* pcrel_offset */
417
418   /* High 20 bits of TLS LE thread pointer offset.  */
419   HOWTO (R_RISCV_TPREL_HI20,            /* type */
420          0,                             /* rightshift */
421          2,                             /* size */
422          32,                            /* bitsize */
423          FALSE,                         /* pc_relative */
424          0,                             /* bitpos */
425          complain_overflow_signed,      /* complain_on_overflow */
426          bfd_elf_generic_reloc,         /* special_function */
427          "R_RISCV_TPREL_HI20",          /* name */
428          TRUE,                          /* partial_inplace */
429          0,                             /* src_mask */
430          ENCODE_UTYPE_IMM (-1U),        /* dst_mask */
431          FALSE),                        /* pcrel_offset */
432
433   /* Low 12 bits of TLS LE thread pointer offset for loads and adds.  */
434   HOWTO (R_RISCV_TPREL_LO12_I,          /* type */
435          0,                             /* rightshift */
436          2,                             /* size */
437          32,                            /* bitsize */
438          FALSE,                         /* pc_relative */
439          0,                             /* bitpos */
440          complain_overflow_signed,      /* complain_on_overflow */
441          bfd_elf_generic_reloc,         /* special_function */
442          "R_RISCV_TPREL_LO12_I",        /* name */
443          FALSE,                         /* partial_inplace */
444          0,                             /* src_mask */
445          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
446          FALSE),                        /* pcrel_offset */
447
448   /* Low 12 bits of TLS LE thread pointer offset for stores.  */
449   HOWTO (R_RISCV_TPREL_LO12_S,          /* type */
450          0,                             /* rightshift */
451          2,                             /* size */
452          32,                            /* bitsize */
453          FALSE,                         /* pc_relative */
454          0,                             /* bitpos */
455          complain_overflow_signed,      /* complain_on_overflow */
456          bfd_elf_generic_reloc,         /* special_function */
457          "R_RISCV_TPREL_LO12_S",        /* name */
458          FALSE,                         /* partial_inplace */
459          0,                             /* src_mask */
460          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
461          FALSE),                        /* pcrel_offset */
462
463   /* TLS LE thread pointer usage.  */
464   HOWTO (R_RISCV_TPREL_ADD,             /* type */
465          0,                             /* rightshift */
466          2,                             /* size */
467          32,                            /* bitsize */
468          FALSE,                         /* pc_relative */
469          0,                             /* bitpos */
470          complain_overflow_dont,        /* complain_on_overflow */
471          bfd_elf_generic_reloc,         /* special_function */
472          "R_RISCV_TPREL_ADD",           /* name */
473          TRUE,                          /* partial_inplace */
474          0,                             /* src_mask */
475          0,                             /* dst_mask */
476          FALSE),                        /* pcrel_offset */
477
478   /* 8-bit in-place addition, for local label subtraction.  */
479   HOWTO (R_RISCV_ADD8,                  /* type */
480          0,                             /* rightshift */
481          0,                             /* size */
482          32,                            /* bitsize */
483          FALSE,                         /* pc_relative */
484          0,                             /* bitpos */
485          complain_overflow_dont,        /* complain_on_overflow */
486          bfd_elf_generic_reloc,         /* special_function */
487          "R_RISCV_ADD8",                /* name */
488          FALSE,                         /* partial_inplace */
489          0,                             /* src_mask */
490          MINUS_ONE,                     /* dst_mask */
491          FALSE),                        /* pcrel_offset */
492
493   /* 16-bit in-place addition, for local label subtraction.  */
494   HOWTO (R_RISCV_ADD16,                 /* type */
495          0,                             /* rightshift */
496          1,                             /* size */
497          16,                            /* bitsize */
498          FALSE,                         /* pc_relative */
499          0,                             /* bitpos */
500          complain_overflow_dont,        /* complain_on_overflow */
501          bfd_elf_generic_reloc,         /* special_function */
502          "R_RISCV_ADD16",               /* name */
503          FALSE,                         /* partial_inplace */
504          0,                             /* src_mask */
505          MINUS_ONE,                     /* dst_mask */
506          FALSE),                        /* pcrel_offset */
507
508   /* 32-bit in-place addition, for local label subtraction.  */
509   HOWTO (R_RISCV_ADD32,                 /* type */
510          0,                             /* rightshift */
511          2,                             /* size */
512          32,                            /* bitsize */
513          FALSE,                         /* pc_relative */
514          0,                             /* bitpos */
515          complain_overflow_dont,        /* complain_on_overflow */
516          bfd_elf_generic_reloc,         /* special_function */
517          "R_RISCV_ADD32",               /* name */
518          FALSE,                         /* partial_inplace */
519          0,                             /* src_mask */
520          MINUS_ONE,                     /* dst_mask */
521          FALSE),                        /* pcrel_offset */
522
523   /* 64-bit in-place addition, for local label subtraction.  */
524   HOWTO (R_RISCV_ADD64,                 /* type */
525          0,                             /* rightshift */
526          4,                             /* size */
527          64,                            /* bitsize */
528          FALSE,                         /* pc_relative */
529          0,                             /* bitpos */
530          complain_overflow_dont,        /* complain_on_overflow */
531          bfd_elf_generic_reloc,         /* special_function */
532          "R_RISCV_ADD64",               /* name */
533          FALSE,                         /* partial_inplace */
534          0,                             /* src_mask */
535          MINUS_ONE,                     /* dst_mask */
536          FALSE),                        /* pcrel_offset */
537
538   /* 8-bit in-place addition, for local label subtraction.  */
539   HOWTO (R_RISCV_SUB8,                  /* type */
540          0,                             /* rightshift */
541          0,                             /* size */
542          8,                             /* bitsize */
543          FALSE,                         /* pc_relative */
544          0,                             /* bitpos */
545          complain_overflow_dont,        /* complain_on_overflow */
546          bfd_elf_generic_reloc,         /* special_function */
547          "R_RISCV_SUB8",                /* name */
548          FALSE,                         /* partial_inplace */
549          0,                             /* src_mask */
550          MINUS_ONE,                     /* dst_mask */
551          FALSE),                        /* pcrel_offset */
552
553   /* 16-bit in-place addition, for local label subtraction.  */
554   HOWTO (R_RISCV_SUB16,                 /* type */
555          0,                             /* rightshift */
556          1,                             /* size */
557          16,                            /* bitsize */
558          FALSE,                         /* pc_relative */
559          0,                             /* bitpos */
560          complain_overflow_dont,        /* complain_on_overflow */
561          bfd_elf_generic_reloc,         /* special_function */
562          "R_RISCV_SUB16",               /* name */
563          FALSE,                         /* partial_inplace */
564          0,                             /* src_mask */
565          MINUS_ONE,                     /* dst_mask */
566          FALSE),                        /* pcrel_offset */
567
568   /* 32-bit in-place addition, for local label subtraction.  */
569   HOWTO (R_RISCV_SUB32,                 /* type */
570          0,                             /* rightshift */
571          2,                             /* size */
572          32,                            /* bitsize */
573          FALSE,                         /* pc_relative */
574          0,                             /* bitpos */
575          complain_overflow_dont,        /* complain_on_overflow */
576          bfd_elf_generic_reloc,         /* special_function */
577          "R_RISCV_SUB32",               /* name */
578          FALSE,                         /* partial_inplace */
579          0,                             /* src_mask */
580          MINUS_ONE,                     /* dst_mask */
581          FALSE),                        /* pcrel_offset */
582
583   /* 64-bit in-place addition, for local label subtraction.  */
584   HOWTO (R_RISCV_SUB64,                 /* type */
585          0,                             /* rightshift */
586          4,                             /* size */
587          64,                            /* bitsize */
588          FALSE,                         /* pc_relative */
589          0,                             /* bitpos */
590          complain_overflow_dont,        /* complain_on_overflow */
591          bfd_elf_generic_reloc,         /* special_function */
592          "R_RISCV_SUB64",               /* name */
593          FALSE,                         /* partial_inplace */
594          0,                             /* src_mask */
595          MINUS_ONE,                     /* dst_mask */
596          FALSE),                        /* pcrel_offset */
597
598   /* GNU extension to record C++ vtable hierarchy */
599   HOWTO (R_RISCV_GNU_VTINHERIT,         /* type */
600          0,                             /* rightshift */
601          4,                             /* size */
602          0,                             /* bitsize */
603          FALSE,                         /* pc_relative */
604          0,                             /* bitpos */
605          complain_overflow_dont,        /* complain_on_overflow */
606          NULL,                          /* special_function */
607          "R_RISCV_GNU_VTINHERIT",       /* name */
608          FALSE,                         /* partial_inplace */
609          0,                             /* src_mask */
610          0,                             /* dst_mask */
611          FALSE),                        /* pcrel_offset */
612
613   /* GNU extension to record C++ vtable member usage */
614   HOWTO (R_RISCV_GNU_VTENTRY,           /* type */
615          0,                             /* rightshift */
616          4,                             /* size */
617          0,                             /* bitsize */
618          FALSE,                         /* pc_relative */
619          0,                             /* bitpos */
620          complain_overflow_dont,        /* complain_on_overflow */
621          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
622          "R_RISCV_GNU_VTENTRY",         /* name */
623          FALSE,                         /* partial_inplace */
624          0,                             /* src_mask */
625          0,                             /* dst_mask */
626          FALSE),                        /* pcrel_offset */
627
628   /* Indicates an alignment statement.  The addend field encodes how many
629      bytes of NOPs follow the statement.  The desired alignment is the
630      addend rounded up to the next power of two.  */
631   HOWTO (R_RISCV_ALIGN,                 /* type */
632          0,                             /* rightshift */
633          2,                             /* size */
634          0,                             /* bitsize */
635          FALSE,                         /* pc_relative */
636          0,                             /* bitpos */
637          complain_overflow_dont,        /* complain_on_overflow */
638          bfd_elf_generic_reloc,         /* special_function */
639          "R_RISCV_ALIGN",               /* name */
640          FALSE,                         /* partial_inplace */
641          0,                             /* src_mask */
642          0,                             /* dst_mask */
643          TRUE),                         /* pcrel_offset */
644
645   /* 8-bit PC-relative branch offset.  */
646   HOWTO (R_RISCV_RVC_BRANCH,            /* type */
647          0,                             /* rightshift */
648          2,                             /* size */
649          32,                            /* bitsize */
650          TRUE,                          /* pc_relative */
651          0,                             /* bitpos */
652          complain_overflow_signed,      /* complain_on_overflow */
653          bfd_elf_generic_reloc,         /* special_function */
654          "R_RISCV_RVC_BRANCH",          /* name */
655          FALSE,                         /* partial_inplace */
656          0,                             /* src_mask */
657          ENCODE_RVC_B_IMM (-1U),        /* dst_mask */
658          TRUE),                         /* pcrel_offset */
659
660   /* 11-bit PC-relative jump offset.  */
661   HOWTO (R_RISCV_RVC_JUMP,              /* type */
662          0,                             /* rightshift */
663          2,                             /* size */
664          32,                            /* bitsize */
665          TRUE,                          /* pc_relative */
666          0,                             /* bitpos */
667          complain_overflow_dont,        /* complain_on_overflow */
668                                         /* This needs complex overflow
669                                            detection, because the upper 36
670                                            bits must match the PC + 4.  */
671          bfd_elf_generic_reloc,         /* special_function */
672          "R_RISCV_RVC_JUMP",            /* name */
673          FALSE,                         /* partial_inplace */
674          0,                             /* src_mask */
675          ENCODE_RVC_J_IMM (-1U),        /* dst_mask */
676          TRUE),                         /* pcrel_offset */
677
678   /* High 6 bits of 18-bit absolute address.  */
679   HOWTO (R_RISCV_RVC_LUI,               /* type */
680          0,                             /* rightshift */
681          2,                             /* size */
682          32,                            /* bitsize */
683          FALSE,                         /* pc_relative */
684          0,                             /* bitpos */
685          complain_overflow_dont,        /* complain_on_overflow */
686          bfd_elf_generic_reloc,         /* special_function */
687          "R_RISCV_RVC_LUI",             /* name */
688          FALSE,                         /* partial_inplace */
689          0,                             /* src_mask */
690          ENCODE_RVC_IMM (-1U),          /* dst_mask */
691          FALSE),                        /* pcrel_offset */
692
693   /* High 12 bits of 32-bit load or add.  */
694   HOWTO (R_RISCV_GPREL_I,               /* type */
695          0,                             /* rightshift */
696          2,                             /* size */
697          32,                            /* bitsize */
698          FALSE,                         /* pc_relative */
699          0,                             /* bitpos */
700          complain_overflow_dont,        /* complain_on_overflow */
701          bfd_elf_generic_reloc,         /* special_function */
702          "R_RISCV_GPREL_I",             /* name */
703          FALSE,                         /* partial_inplace */
704          0,                             /* src_mask */
705          ENCODE_ITYPE_IMM (-1U),        /* dst_mask */
706          FALSE),                        /* pcrel_offset */
707
708   /* High 12 bits of 32-bit store.  */
709   HOWTO (R_RISCV_GPREL_S,               /* type */
710          0,                             /* rightshift */
711          2,                             /* size */
712          32,                            /* bitsize */
713          FALSE,                         /* pc_relative */
714          0,                             /* bitpos */
715          complain_overflow_dont,        /* complain_on_overflow */
716          bfd_elf_generic_reloc,         /* special_function */
717          "R_RISCV_GPREL_S",             /* name */
718          FALSE,                         /* partial_inplace */
719          0,                             /* src_mask */
720          ENCODE_STYPE_IMM (-1U),        /* dst_mask */
721          FALSE),                        /* pcrel_offset */
722 };
723
724 /* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
725
726 struct elf_reloc_map
727 {
728   bfd_reloc_code_real_type bfd_val;
729   enum elf_riscv_reloc_type elf_val;
730 };
731
732 static const struct elf_reloc_map riscv_reloc_map[] =
733 {
734   { BFD_RELOC_NONE, R_RISCV_NONE },
735   { BFD_RELOC_32, R_RISCV_32 },
736   { BFD_RELOC_64, R_RISCV_64 },
737   { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
738   { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
739   { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
740   { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
741   { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
742   { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
743   { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
744   { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
745   { BFD_RELOC_CTOR, R_RISCV_64 },
746   { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
747   { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
748   { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
749   { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
750   { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
751   { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
752   { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
753   { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
754   { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
755   { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
756   { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
757   { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
758   { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
759   { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
760   { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
761   { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
762   { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
763   { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
764   { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
765   { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
766   { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
767   { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
768   { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
769   { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
770   { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
771   { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
772   { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
773   { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
774   { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
775 };
776
777 /* Given a BFD reloc type, return a howto structure.  */
778
779 reloc_howto_type *
780 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
781                          bfd_reloc_code_real_type code)
782 {
783   unsigned int i;
784
785   for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
786     if (riscv_reloc_map[i].bfd_val == code)
787       return &howto_table[(int) riscv_reloc_map[i].elf_val];
788
789   bfd_set_error (bfd_error_bad_value);
790   return NULL;
791 }
792
793 reloc_howto_type *
794 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
795 {
796   unsigned int i;
797
798   for (i = 0; i < ARRAY_SIZE (howto_table); i++)
799     if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
800       return &howto_table[i];
801
802   return NULL;
803 }
804
805 reloc_howto_type *
806 riscv_elf_rtype_to_howto (unsigned int r_type)
807 {
808   if (r_type >= ARRAY_SIZE (howto_table))
809     {
810       (*_bfd_error_handler) (_("unrecognized relocation (0x%x)"), r_type);
811       bfd_set_error (bfd_error_bad_value);
812       return NULL;
813     }
814   return &howto_table[r_type];
815 }