1/* RISC-V-specific support for ELF.
2   Copyright (C) 2011-2017 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
37static 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  /* TP-relative TLS LE load.  */
718  HOWTO (R_RISCV_TPREL_I,		/* type */
719	 0,				/* rightshift */
720	 2,				/* size */
721	 32,				/* bitsize */
722	 FALSE,				/* pc_relative */
723	 0,				/* bitpos */
724	 complain_overflow_signed,	/* complain_on_overflow */
725	 bfd_elf_generic_reloc,		/* special_function */
726	 "R_RISCV_TPREL_I",		/* name */
727	 FALSE,				/* partial_inplace */
728	 0,				/* src_mask */
729	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
730	 FALSE),			/* pcrel_offset */
731
732  /* TP-relative TLS LE store.  */
733  HOWTO (R_RISCV_TPREL_S,		/* type */
734	 0,				/* rightshift */
735	 2,				/* size */
736	 32,				/* bitsize */
737	 FALSE,				/* pc_relative */
738	 0,				/* bitpos */
739	 complain_overflow_signed,	/* complain_on_overflow */
740	 bfd_elf_generic_reloc,		/* special_function */
741	 "R_RISCV_TPREL_S",		/* name */
742	 FALSE,				/* partial_inplace */
743	 0,				/* src_mask */
744	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
745	 FALSE),			/* pcrel_offset */
746
747  /* The paired relocation may be relaxed.  */
748  HOWTO (R_RISCV_RELAX,			/* type */
749	 0,				/* rightshift */
750	 3,				/* size */
751	 0,				/* bitsize */
752	 FALSE,				/* pc_relative */
753	 0,				/* bitpos */
754	 complain_overflow_dont,	/* complain_on_overflow */
755	 bfd_elf_generic_reloc,		/* special_function */
756	 "R_RISCV_RELAX",		/* name */
757	 FALSE,				/* partial_inplace */
758	 0,				/* src_mask */
759	 0,				/* dst_mask */
760	 FALSE),			/* pcrel_offset */
761
762  /* 6-bit in-place addition, for local label subtraction.  */
763  HOWTO (R_RISCV_SUB6,			/* type */
764	 0,				/* rightshift */
765	 0,				/* size */
766	 8,				/* bitsize */
767	 FALSE,				/* pc_relative */
768	 0,				/* bitpos */
769	 complain_overflow_dont,	/* complain_on_overflow */
770	 bfd_elf_generic_reloc,		/* special_function */
771	 "R_RISCV_SUB6",		/* name */
772	 FALSE,				/* partial_inplace */
773	 0,				/* src_mask */
774	 0x3f,				/* dst_mask */
775	 FALSE),			/* pcrel_offset */
776
777  /* 6-bit in-place setting, for local label subtraction.  */
778  HOWTO (R_RISCV_SET6,			/* type */
779	 0,				/* rightshift */
780	 0,				/* size */
781	 8,				/* bitsize */
782	 FALSE,				/* pc_relative */
783	 0,				/* bitpos */
784	 complain_overflow_dont,	/* complain_on_overflow */
785	 bfd_elf_generic_reloc,		/* special_function */
786	 "R_RISCV_SET6",		/* name */
787	 FALSE,				/* partial_inplace */
788	 0,				/* src_mask */
789	 0x3f,				/* dst_mask */
790	 FALSE),			/* pcrel_offset */
791
792  /* 8-bit in-place setting, for local label subtraction.  */
793  HOWTO (R_RISCV_SET8,			/* type */
794	 0,				/* rightshift */
795	 0,				/* size */
796	 8,				/* bitsize */
797	 FALSE,				/* pc_relative */
798	 0,				/* bitpos */
799	 complain_overflow_dont,	/* complain_on_overflow */
800	 bfd_elf_generic_reloc,		/* special_function */
801	 "R_RISCV_SET8",		/* name */
802	 FALSE,				/* partial_inplace */
803	 0,				/* src_mask */
804	 MINUS_ONE,			/* dst_mask */
805	 FALSE),			/* pcrel_offset */
806
807  /* 16-bit in-place setting, for local label subtraction.  */
808  HOWTO (R_RISCV_SET16,			/* type */
809	 0,				/* rightshift */
810	 1,				/* size */
811	 16,				/* bitsize */
812	 FALSE,				/* pc_relative */
813	 0,				/* bitpos */
814	 complain_overflow_dont,	/* complain_on_overflow */
815	 bfd_elf_generic_reloc,		/* special_function */
816	 "R_RISCV_SET16",		/* name */
817	 FALSE,				/* partial_inplace */
818	 0,				/* src_mask */
819	 MINUS_ONE,			/* dst_mask */
820	 FALSE),			/* pcrel_offset */
821
822  /* 32-bit in-place setting, for local label subtraction.  */
823  HOWTO (R_RISCV_SET32,			/* type */
824	 0,				/* rightshift */
825	 2,				/* size */
826	 32,				/* bitsize */
827	 FALSE,				/* pc_relative */
828	 0,				/* bitpos */
829	 complain_overflow_dont,	/* complain_on_overflow */
830	 bfd_elf_generic_reloc,		/* special_function */
831	 "R_RISCV_SET32",		/* name */
832	 FALSE,				/* partial_inplace */
833	 0,				/* src_mask */
834	 MINUS_ONE,			/* dst_mask */
835	 FALSE),			/* pcrel_offset */
836};
837
838/* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
839
840struct elf_reloc_map
841{
842  bfd_reloc_code_real_type bfd_val;
843  enum elf_riscv_reloc_type elf_val;
844};
845
846static const struct elf_reloc_map riscv_reloc_map[] =
847{
848  { BFD_RELOC_NONE, R_RISCV_NONE },
849  { BFD_RELOC_32, R_RISCV_32 },
850  { BFD_RELOC_64, R_RISCV_64 },
851  { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
852  { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
853  { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
854  { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
855  { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
856  { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
857  { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
858  { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
859  { BFD_RELOC_CTOR, R_RISCV_64 },
860  { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
861  { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
862  { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
863  { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
864  { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
865  { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
866  { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
867  { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
868  { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
869  { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
870  { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
871  { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
872  { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
873  { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
874  { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
875  { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
876  { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
877  { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
878  { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
879  { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
880  { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
881  { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
882  { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
883  { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
884  { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
885  { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
886  { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
887  { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
888  { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
889  { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
890  { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
891  { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
892  { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
893  { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
894  { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
895  { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
896  { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
897};
898
899/* Given a BFD reloc type, return a howto structure.  */
900
901reloc_howto_type *
902riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
903			 bfd_reloc_code_real_type code)
904{
905  unsigned int i;
906
907  for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
908    if (riscv_reloc_map[i].bfd_val == code)
909      return &howto_table[(int) riscv_reloc_map[i].elf_val];
910
911  bfd_set_error (bfd_error_bad_value);
912  return NULL;
913}
914
915reloc_howto_type *
916riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
917{
918  unsigned int i;
919
920  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
921    if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
922      return &howto_table[i];
923
924  return NULL;
925}
926
927reloc_howto_type *
928riscv_elf_rtype_to_howto (unsigned int r_type)
929{
930  if (r_type >= ARRAY_SIZE (howto_table))
931    {
932      (*_bfd_error_handler) (_("unrecognized relocation (0x%x)"), r_type);
933      bfd_set_error (bfd_error_bad_value);
934      return NULL;
935    }
936  return &howto_table[r_type];
937}
938