xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elf64-nfp.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* NFP-specific support for 64-bit ELF
2    Copyright (C) 2017-2020 Free Software Foundation, Inc.
3    Contributed by Francois H. Theron <francois.theron@netronome.com>
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/nfp.h"
27 
28 
29 static bfd_reloc_status_type
30 elf64_nfp_reloc (bfd * abfd ATTRIBUTE_UNUSED,
31 		 arelent * reloc_entry,
32 		 asymbol * symbol,
33 		 void *data ATTRIBUTE_UNUSED,
34 		 asection * input_section,
35 		 bfd * output_bfd,
36 		 char **error_message ATTRIBUTE_UNUSED);
37 
38 /* We don't actually apply any relocations in this toolset
39    so we make them all do nothing, but at least display useful
40    names.
41    Most of these are mainly used by the NFP toolchain to resolve things
42    before the final ELF file is created.  */
43 static reloc_howto_type elf_nfp_howto_table[] =
44 {
45   HOWTO (R_NFP_NOTYPE,		/* Type.  */
46 	 0,			/* Rightshift.  */
47 	 3,			/* Size.  */
48 	 0,			/* Bitsize.  */
49 	 FALSE,			/* PC_relative.  */
50 	 0,			/* Bitpos.  */
51 	 complain_overflow_dont,/* Complain_on_overflow.  */
52 	 elf64_nfp_reloc,	/* Special_function.  */
53 	 "R_NFP_NOTYPE",	/* Name.  */
54 	 FALSE,			/* Partial_inplace.  */
55 	 0,			/* Src_mask.  */
56 	 0,			/* Dst_mask.  */
57 	 FALSE),		/* PCrel_offset.  */
58   HOWTO (R_NFP_W32LE, 0, 3, 0, FALSE, 0,
59 	 complain_overflow_dont, elf64_nfp_reloc,
60 	 "R_NFP_W32LE",
61 	 FALSE, 0, 0, FALSE),
62   HOWTO (R_NFP_SRC8_A, 0, 3, 0, FALSE, 0,
63 	 complain_overflow_dont, elf64_nfp_reloc,
64 	 "R_NFP_SRC8_A",
65 	 FALSE, 0, 0, FALSE),
66   HOWTO (R_NFP_SRC8_B, 0, 3, 0, FALSE, 0,
67 	 complain_overflow_dont, elf64_nfp_reloc,
68 	 "R_NFP_SRC8_B",
69 	 FALSE, 0, 0, FALSE),
70   HOWTO (R_NFP_IMMED8_I, 0, 3, 0, FALSE, 0,
71 	 complain_overflow_dont, elf64_nfp_reloc,
72 	 "R_NFP_IMMED8_I",
73 	 FALSE, 0, 0, FALSE),
74   HOWTO (R_NFP_SC, 0, 3, 0, FALSE, 0,
75 	 complain_overflow_dont, elf64_nfp_reloc,
76 	 "R_NFP_SC",
77 	 FALSE, 0, 0, FALSE),
78   HOWTO (R_NFP_IMMED_LO16_I_A, 0, 3, 0, FALSE, 0,
79 	 complain_overflow_dont, elf64_nfp_reloc,
80 	 "R_NFP_IMMED_LO16_I_A",
81 	 FALSE, 0, 0, FALSE),
82   HOWTO (R_NFP_IMMED_LO16_I_B, 0, 3, 0, FALSE, 0,
83 	 complain_overflow_dont, elf64_nfp_reloc,
84 	 "R_NFP_IMMED_LO16_I_B",
85 	 TRUE, 0, 0, FALSE),
86   HOWTO (R_NFP_SRC7_B, 0, 3, 0, FALSE, 0,
87 	 complain_overflow_dont, elf64_nfp_reloc,
88 	 "R_NFP_SRC7_B",
89 	 FALSE, 0, 0, FALSE),
90   HOWTO (R_NFP_SRC7_A, 0, 3, 0, FALSE, 0,
91 	 complain_overflow_dont, elf64_nfp_reloc,
92 	 "R_NFP_SRC7_A",
93 	 FALSE, 0, 0, FALSE),
94   HOWTO (R_NFP_SRC8_I_B, 0, 3, 0, FALSE, 0,
95 	 complain_overflow_dont, elf64_nfp_reloc,
96 	 "R_NFP_SRC8_I_B",
97 	 FALSE, 0, 0, FALSE),
98   HOWTO (R_NFP_SRC8_I_A, 0, 3, 0, FALSE, 0,
99 	 complain_overflow_dont, elf64_nfp_reloc,
100 	 "R_NFP_SRC8_I_A",
101 	 FALSE, 0, 0, FALSE),
102   HOWTO (R_NFP_IMMED_HI16_I_A, 0, 3, 0, FALSE, 0,
103 	 complain_overflow_dont, elf64_nfp_reloc,
104 	 "R_NFP_IMMED_HI16_I_A",
105 	 FALSE, 0, 0, FALSE),
106   HOWTO (R_NFP_IMMED_HI16_I_B, 0, 3, 0, FALSE, 0,
107 	 complain_overflow_dont, elf64_nfp_reloc,
108 	 "R_NFP_IMMED_HI16_I_B",
109 	 FALSE, 0, 0, FALSE),
110   HOWTO (R_NFP_W64LE, 0, 3, 0, FALSE, 0,
111 	 complain_overflow_dont, elf64_nfp_reloc,
112 	 "R_NFP_W64LE",
113 	 FALSE, 0, 0, FALSE),
114   HOWTO (R_NFP_SH_INFO, 0, 3, 0, FALSE, 0,
115 	 complain_overflow_dont, elf64_nfp_reloc,
116 	 "R_NFP_SH_INFO",
117 	 FALSE, 0, 0, FALSE),
118   HOWTO (R_NFP_W32BE, 0, 3, 0, FALSE, 0,
119 	 complain_overflow_dont, elf64_nfp_reloc,
120 	 "R_NFP_W32BE",
121 	 FALSE, 0, 0, FALSE),
122   HOWTO (R_NFP_W64BE, 0, 3, 0, FALSE, 0,
123 	 complain_overflow_dont, elf64_nfp_reloc,
124 	 "R_NFP_W64BE",
125 	 FALSE, 0, 0, FALSE),
126   HOWTO (R_NFP_W32_29_24, 0, 3, 0, FALSE, 0,
127 	 complain_overflow_dont, elf64_nfp_reloc,
128 	 "R_NFP_W32_29_24",
129 	 FALSE, 0, 0, FALSE),
130   HOWTO (R_NFP_W32LE_AND, 0, 3, 0, FALSE, 0,
131 	 complain_overflow_dont, elf64_nfp_reloc,
132 	 "R_NFP_W32LE_AND",
133 	 FALSE, 0, 0, FALSE),
134   HOWTO (R_NFP_W32BE_AND, 0, 3, 0, FALSE, 0,
135 	 complain_overflow_dont, elf64_nfp_reloc,
136 	 "R_NFP_W32BE_AND",
137 	 FALSE, 0, 0, FALSE),
138   HOWTO (R_NFP_W32LE_OR, 0, 3, 0, FALSE, 0,
139 	 complain_overflow_dont, elf64_nfp_reloc,
140 	 "R_NFP_W32LE_OR",
141 	 FALSE, 0, 0, FALSE),
142   HOWTO (R_NFP_W32BE_OR, 0, 3, 0, FALSE, 0,
143 	 complain_overflow_dont, elf64_nfp_reloc,
144 	 "R_NFP_W32BE_OR",
145 	 FALSE, 0, 0, FALSE),
146   HOWTO (R_NFP_W64LE_AND, 0, 3, 0, FALSE, 0,
147 	 complain_overflow_dont, elf64_nfp_reloc,
148 	 "R_NFP_W64LE_AND",
149 	 FALSE, 0, 0, FALSE),
150   HOWTO (R_NFP_W64BE_AND, 0, 3, 0, FALSE, 0,
151 	 complain_overflow_dont, elf64_nfp_reloc,
152 	 "R_NFP_W64BE_AND",
153 	 FALSE, 0, 0, FALSE),
154   HOWTO (R_NFP_W64LE_OR, 0, 3, 0, FALSE, 0,
155 	 complain_overflow_dont, elf64_nfp_reloc,
156 	 "R_NFP_W64LE_OR",
157 	 FALSE, 0, 0, FALSE),
158   HOWTO (R_NFP_W64BE_OR, 0, 3, 0, FALSE, 0,
159 	 complain_overflow_dont, elf64_nfp_reloc,
160 	 "R_NFP_W64BE_OR",
161 	 FALSE, 0, 0, FALSE)
162 };
163 
164 static bfd_boolean
165 elf64_nfp_object_p (bfd * abfd)
166 {
167   /* If the e_machine value is one of the unofficial ones, we convert
168      it first and set e_flags accordingly for later consistency.  */
169   if (elf_elfheader (abfd)->e_machine == E_NFP_MACH_3200)
170     {
171       elf_elfheader (abfd)->e_machine = EM_NFP;
172       elf_elfheader (abfd)->e_flags &= ~EF_NFP_SET_MACH (~0);
173       elf_elfheader (abfd)->e_flags |= EF_NFP_SET_MACH (E_NFP_MACH_3200);
174     }
175   else if (elf_elfheader (abfd)->e_machine == E_NFP_MACH_6000)
176     {
177       elf_elfheader (abfd)->e_machine = EM_NFP;
178       elf_elfheader (abfd)->e_flags &= ~EF_NFP_SET_MACH (~0);
179       elf_elfheader (abfd)->e_flags |= EF_NFP_SET_MACH (E_NFP_MACH_6000);
180     }
181 
182   if (elf_elfheader (abfd)->e_machine == EM_NFP)
183     {
184       int e_mach = EF_NFP_MACH (elf_elfheader (abfd)->e_flags);
185 
186       switch (e_mach)
187 	{
188 	case E_NFP_MACH_3200:
189 	case E_NFP_MACH_6000:
190 	  if (!bfd_default_set_arch_mach (abfd, bfd_arch_nfp, e_mach))
191 	    return FALSE;
192 	default:
193 	  break;
194 	}
195     }
196 
197   return TRUE;
198 }
199 
200 static bfd_boolean
201 elf64_nfp_section_from_shdr (bfd * abfd,
202 			     Elf_Internal_Shdr * hdr,
203 			     const char *name, int shindex)
204 {
205   switch (hdr->sh_type)
206     {
207     case SHT_NFP_INITREG:
208     case SHT_NFP_MECONFIG:
209     case SHT_NFP_UDEBUG:
210       return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
211     default:
212       return FALSE;
213     }
214 }
215 
216 bfd_reloc_status_type
217 elf64_nfp_reloc (bfd * abfd ATTRIBUTE_UNUSED,
218 		 arelent * reloc_entry ATTRIBUTE_UNUSED,
219 		 asymbol * symbol ATTRIBUTE_UNUSED,
220 		 void *data ATTRIBUTE_UNUSED,
221 		 asection * input_section ATTRIBUTE_UNUSED,
222 		 bfd * output_bfd ATTRIBUTE_UNUSED,
223 		 char **error_message ATTRIBUTE_UNUSED)
224 {
225   return bfd_reloc_ok;
226 }
227 
228 static bfd_boolean
229 elf64_nfp_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
230 			 arelent * cache_ptr, Elf_Internal_Rela * dst)
231 {
232   unsigned int r_type;
233 
234   r_type = ELF64_R_TYPE (dst->r_info);
235   if (r_type >= R_NFP_MAX)
236     {
237       /* xgettext:c-format */
238       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
239 			  abfd, r_type);
240       bfd_set_error (bfd_error_bad_value);
241       return FALSE;
242     }
243   cache_ptr->howto = &elf_nfp_howto_table[r_type];
244   return TRUE;
245 }
246 
247 static reloc_howto_type *
248 elf64_nfp_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
249 			     bfd_reloc_code_real_type code ATTRIBUTE_UNUSED)
250 {
251   return NULL;
252 }
253 
254 static reloc_howto_type *
255 elf64_nfp_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED,
256 			     const char *r_name ATTRIBUTE_UNUSED)
257 {
258   return NULL;
259 }
260 
261 #define ELF_ARCH		bfd_arch_nfp
262 #define ELF_MACHINE_CODE	EM_NFP
263 #define ELF_MACHINE_ALT1	E_NFP_MACH_6000
264 #define ELF_MACHINE_ALT2	E_NFP_MACH_3200
265 #define ELF_MAXPAGESIZE		1
266 #define TARGET_LITTLE_NAME	"elf64-nfp"
267 #define TARGET_LITTLE_SYM       nfp_elf64_vec
268 
269 #define elf_backend_object_p		elf64_nfp_object_p
270 #define elf_backend_section_from_shdr   elf64_nfp_section_from_shdr
271 #define elf_info_to_howto		elf64_nfp_info_to_howto
272 #define bfd_elf64_bfd_reloc_type_lookup	     elf64_nfp_reloc_type_lookup
273 #define bfd_elf64_bfd_reloc_name_lookup      elf64_nfp_reloc_name_lookup
274 
275 #include "elf64-target.h"
276