elf32-ft32.c revision 1.1.1.2 1 1.1 christos /* ft32-specific support for 32-bit ELF.
2 1.1.1.2 christos Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Copied from elf32-moxie.c which is..
5 1.1.1.2 christos Copyright (C) 2009-2016 Free Software Foundation, Inc.
6 1.1 christos Free Software Foundation, Inc.
7 1.1 christos
8 1.1 christos This file is part of BFD, the Binary File Descriptor library.
9 1.1 christos
10 1.1 christos This program is free software; you can redistribute it and/or modify
11 1.1 christos it under the terms of the GNU General Public License as published by
12 1.1 christos the Free Software Foundation; either version 3 of the License, or
13 1.1 christos (at your option) any later version.
14 1.1 christos
15 1.1 christos This program is distributed in the hope that it will be useful,
16 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
17 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 1.1 christos GNU General Public License for more details.
19 1.1 christos
20 1.1 christos You should have received a copy of the GNU General Public License
21 1.1 christos along with this program; if not, write to the Free Software
22 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 1.1 christos MA 02110-1301, USA. */
24 1.1 christos
25 1.1 christos #include "sysdep.h"
26 1.1 christos #include "bfd.h"
27 1.1 christos #include "libbfd.h"
28 1.1 christos #include "elf-bfd.h"
29 1.1 christos #include "elf/ft32.h"
30 1.1 christos
31 1.1 christos /* Forward declarations. */
32 1.1 christos
33 1.1 christos static reloc_howto_type ft32_elf_howto_table [] =
34 1.1 christos {
35 1.1 christos /* This reloc does nothing. */
36 1.1 christos HOWTO (R_FT32_NONE, /* type */
37 1.1 christos 0, /* rightshift */
38 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
39 1.1 christos 32, /* bitsize */
40 1.1 christos FALSE, /* pc_relative */
41 1.1 christos 0, /* bitpos */
42 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
43 1.1 christos bfd_elf_generic_reloc, /* special_function */
44 1.1 christos "R_FT32_NONE", /* name */
45 1.1 christos FALSE, /* partial_inplace */
46 1.1 christos 0, /* src_mask */
47 1.1 christos 0, /* dst_mask */
48 1.1 christos FALSE), /* pcrel_offset */
49 1.1 christos
50 1.1 christos /* A 32 bit absolute relocation. */
51 1.1 christos
52 1.1 christos HOWTO (R_FT32_32, /* type */
53 1.1 christos 0, /* rightshift */
54 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
55 1.1 christos 32, /* bitsize */
56 1.1 christos FALSE, /* pc_relative */
57 1.1 christos 0, /* bitpos */
58 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
59 1.1 christos bfd_elf_generic_reloc, /* special_function */
60 1.1 christos "R_FT32_32", /* name */
61 1.1 christos FALSE, /* partial_inplace */
62 1.1 christos 0x00000000, /* src_mask */
63 1.1 christos 0xffffffff, /* dst_mask */
64 1.1 christos FALSE), /* pcrel_offset */
65 1.1 christos
66 1.1 christos HOWTO (R_FT32_16, /* type */
67 1.1 christos 0, /* rightshift */
68 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
69 1.1 christos 16, /* bitsize */
70 1.1 christos FALSE, /* pc_relative */
71 1.1 christos 0, /* bitpos */
72 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
73 1.1 christos bfd_elf_generic_reloc, /* special_function */
74 1.1 christos "R_FT32_16", /* name */
75 1.1 christos FALSE, /* partial_inplace */
76 1.1 christos 0x00000000, /* src_mask */
77 1.1 christos 0x0000ffff, /* dst_mask */
78 1.1 christos FALSE), /* pcrel_offset */
79 1.1 christos
80 1.1 christos HOWTO (R_FT32_8, /* type */
81 1.1 christos 0, /* rightshift */
82 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
83 1.1 christos 8, /* bitsize */
84 1.1 christos FALSE, /* pc_relative */
85 1.1 christos 0, /* bitpos */
86 1.1 christos complain_overflow_signed, /* complain_on_overflow */
87 1.1 christos bfd_elf_generic_reloc, /* special_function */
88 1.1 christos "R_FT32_8", /* name */
89 1.1 christos FALSE, /* partial_inplace */
90 1.1 christos 0x00000000, /* src_mask */
91 1.1 christos 0x000000ff, /* dst_mask */
92 1.1 christos FALSE), /* pcrel_offset */
93 1.1 christos
94 1.1 christos HOWTO (R_FT32_10, /* type */
95 1.1 christos 0, /* rightshift */
96 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
97 1.1 christos 10, /* bitsize */
98 1.1 christos FALSE, /* pc_relative */
99 1.1 christos 4, /* bitpos */
100 1.1 christos complain_overflow_signed, /* complain_on_overflow */
101 1.1 christos bfd_elf_generic_reloc, /* special_function */
102 1.1 christos "R_FT32_10", /* name */
103 1.1 christos FALSE, /* partial_inplace */
104 1.1 christos 0x00000000, /* src_mask */
105 1.1 christos 0x00003ff0, /* dst_mask */
106 1.1 christos FALSE), /* pcrel_offset */
107 1.1 christos
108 1.1 christos HOWTO (R_FT32_20, /* type */
109 1.1 christos 0, /* rightshift */
110 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
111 1.1 christos 20, /* bitsize */
112 1.1 christos FALSE, /* pc_relative */
113 1.1 christos 0, /* bitpos */
114 1.1 christos complain_overflow_dont, /* complain_on_overflow */
115 1.1 christos bfd_elf_generic_reloc, /* special_function */
116 1.1 christos "R_FT32_20", /* name */
117 1.1 christos FALSE, /* partial_inplace */
118 1.1 christos 0x00000000, /* src_mask */
119 1.1 christos 0x000fffff, /* dst_mask */
120 1.1 christos FALSE), /* pcrel_offset */
121 1.1 christos
122 1.1 christos HOWTO (R_FT32_17, /* type */
123 1.1 christos 0, /* rightshift */
124 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
125 1.1 christos 17, /* bitsize */
126 1.1 christos FALSE, /* pc_relative */
127 1.1 christos 0, /* bitpos */
128 1.1 christos complain_overflow_dont, /* complain_on_overflow */
129 1.1 christos bfd_elf_generic_reloc, /* special_function */
130 1.1 christos "R_FT32_17", /* name */
131 1.1 christos FALSE, /* partial_inplace */
132 1.1 christos 0x00000000, /* src_mask */
133 1.1 christos 0x0001ffff, /* dst_mask */
134 1.1 christos FALSE), /* pcrel_offset */
135 1.1 christos
136 1.1 christos HOWTO (R_FT32_18, /* type */
137 1.1 christos 2, /* rightshift */
138 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
139 1.1 christos 18, /* bitsize */
140 1.1 christos FALSE, /* pc_relative */
141 1.1 christos 0, /* bitpos */
142 1.1 christos complain_overflow_signed, /* complain_on_overflow */
143 1.1 christos bfd_elf_generic_reloc, /* special_function */
144 1.1 christos "R_FT32_18", /* name */
145 1.1 christos FALSE, /* partial_inplace */
146 1.1 christos 0x00000000, /* src_mask */
147 1.1 christos 0x0003ffff, /* dst_mask */
148 1.1 christos FALSE), /* pcrel_offset */
149 1.1 christos
150 1.1 christos };
151 1.1 christos
152 1.1 christos /* Map BFD reloc types to FT32 ELF reloc types. */
154 1.1 christos
155 1.1 christos struct ft32_reloc_map
156 1.1 christos {
157 1.1 christos bfd_reloc_code_real_type bfd_reloc_val;
158 1.1 christos unsigned int ft32_reloc_val;
159 1.1 christos };
160 1.1 christos
161 1.1 christos static const struct ft32_reloc_map ft32_reloc_map [] =
162 1.1 christos {
163 1.1.1.2 christos { BFD_RELOC_NONE, R_FT32_NONE },
164 1.1 christos { BFD_RELOC_32, R_FT32_32 },
165 1.1 christos { BFD_RELOC_16, R_FT32_16 },
166 1.1 christos { BFD_RELOC_8, R_FT32_8 },
167 1.1 christos { BFD_RELOC_FT32_10, R_FT32_10 },
168 1.1 christos { BFD_RELOC_FT32_20, R_FT32_20 },
169 1.1 christos { BFD_RELOC_FT32_17, R_FT32_17 },
170 1.1 christos { BFD_RELOC_FT32_18, R_FT32_18 },
171 1.1 christos };
172 1.1 christos
173 1.1 christos static reloc_howto_type *
174 1.1 christos ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
175 1.1 christos bfd_reloc_code_real_type code)
176 1.1 christos {
177 1.1 christos unsigned int i;
178 1.1 christos
179 1.1 christos for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
180 1.1 christos --i;)
181 1.1 christos if (ft32_reloc_map [i].bfd_reloc_val == code)
182 1.1 christos return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
183 1.1 christos
184 1.1 christos return NULL;
185 1.1 christos }
186 1.1 christos
187 1.1 christos static reloc_howto_type *
188 1.1 christos ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
189 1.1 christos {
190 1.1 christos unsigned int i;
191 1.1 christos
192 1.1 christos for (i = 0;
193 1.1 christos i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
194 1.1 christos i++)
195 1.1 christos if (ft32_elf_howto_table[i].name != NULL
196 1.1 christos && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
197 1.1 christos return &ft32_elf_howto_table[i];
198 1.1 christos
199 1.1 christos return NULL;
200 1.1 christos }
201 1.1 christos
202 1.1 christos /* Set the howto pointer for an FT32 ELF reloc. */
203 1.1 christos
204 1.1 christos static void
205 1.1 christos ft32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
206 1.1 christos arelent *cache_ptr,
207 1.1 christos Elf_Internal_Rela *dst)
208 1.1 christos {
209 1.1 christos unsigned int r_type;
210 1.1 christos
211 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
212 1.1 christos BFD_ASSERT (r_type < (unsigned int) R_FT32_max);
213 1.1 christos cache_ptr->howto = & ft32_elf_howto_table [r_type];
214 1.1 christos }
215 1.1 christos
216 1.1 christos /* Relocate an FT32 ELF section.
218 1.1 christos
219 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
220 1.1 christos to handle the relocations for a section.
221 1.1 christos
222 1.1 christos The relocs are always passed as Rela structures; if the section
223 1.1 christos actually uses Rel structures, the r_addend field will always be
224 1.1 christos zero.
225 1.1 christos
226 1.1 christos This function is responsible for adjusting the section contents as
227 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
228 1.1 christos output file) adjusting the reloc addend as necessary.
229 1.1 christos
230 1.1 christos This function does not have to worry about setting the reloc
231 1.1 christos address or the reloc symbol index.
232 1.1 christos
233 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
234 1.1 christos
235 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
236 1.1 christos corresponding to the st_shndx field of each local symbol.
237 1.1 christos
238 1.1 christos The global hash table entry for the global symbols can be found
239 1.1 christos via elf_sym_hashes (input_bfd).
240 1.1 christos
241 1.1 christos When generating relocatable output, this function must handle
242 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
243 1.1 christos going to be the section symbol corresponding to the output
244 1.1 christos section, which means that the addend must be adjusted
245 1.1 christos accordingly. */
246 1.1 christos
247 1.1 christos static bfd_boolean
248 1.1 christos ft32_elf_relocate_section (bfd *output_bfd,
249 1.1 christos struct bfd_link_info *info,
250 1.1 christos bfd *input_bfd,
251 1.1 christos asection *input_section,
252 1.1 christos bfd_byte *contents,
253 1.1 christos Elf_Internal_Rela *relocs,
254 1.1 christos Elf_Internal_Sym *local_syms,
255 1.1 christos asection **local_sections)
256 1.1 christos {
257 1.1 christos Elf_Internal_Shdr *symtab_hdr;
258 1.1 christos struct elf_link_hash_entry **sym_hashes;
259 1.1 christos Elf_Internal_Rela *rel;
260 1.1 christos Elf_Internal_Rela *relend;
261 1.1 christos
262 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
263 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
264 1.1 christos relend = relocs + input_section->reloc_count;
265 1.1 christos
266 1.1 christos for (rel = relocs; rel < relend; rel ++)
267 1.1 christos {
268 1.1 christos reloc_howto_type *howto;
269 1.1 christos unsigned long r_symndx;
270 1.1 christos Elf_Internal_Sym *sym;
271 1.1 christos asection *sec;
272 1.1 christos struct elf_link_hash_entry *h;
273 1.1 christos bfd_vma relocation;
274 1.1 christos bfd_reloc_status_type r;
275 1.1 christos const char *name;
276 1.1 christos int r_type;
277 1.1 christos
278 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
279 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
280 1.1 christos howto = ft32_elf_howto_table + r_type;
281 1.1 christos h = NULL;
282 1.1 christos sym = NULL;
283 1.1 christos sec = NULL;
284 1.1 christos
285 1.1 christos if (r_symndx < symtab_hdr->sh_info)
286 1.1 christos {
287 1.1 christos sym = local_syms + r_symndx;
288 1.1 christos sec = local_sections [r_symndx];
289 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
290 1.1 christos
291 1.1 christos name = bfd_elf_string_from_elf_section
292 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
293 1.1 christos name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
294 1.1 christos }
295 1.1 christos else
296 1.1 christos {
297 1.1 christos bfd_boolean unresolved_reloc, warned, ignored;
298 1.1 christos
299 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
300 1.1 christos r_symndx, symtab_hdr, sym_hashes,
301 1.1 christos h, sec, relocation,
302 1.1 christos unresolved_reloc, warned, ignored);
303 1.1 christos
304 1.1 christos name = h->root.root.string;
305 1.1 christos }
306 1.1 christos
307 1.1 christos if (sec != NULL && discarded_section (sec))
308 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
309 1.1.1.2 christos rel, 1, relend, howto, 0, contents);
310 1.1 christos
311 1.1 christos if (bfd_link_relocatable (info))
312 1.1 christos continue;
313 1.1 christos
314 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
315 1.1 christos contents, rel->r_offset,
316 1.1 christos relocation, rel->r_addend);
317 1.1 christos
318 1.1 christos if (r != bfd_reloc_ok)
319 1.1 christos {
320 1.1 christos const char * msg = NULL;
321 1.1 christos
322 1.1 christos switch (r)
323 1.1.1.2 christos {
324 1.1 christos case bfd_reloc_overflow:
325 1.1 christos (*info->callbacks->reloc_overflow)
326 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
327 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
328 1.1 christos break;
329 1.1.1.2 christos
330 1.1.1.2 christos case bfd_reloc_undefined:
331 1.1 christos (*info->callbacks->undefined_symbol)
332 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, TRUE);
333 1.1 christos break;
334 1.1 christos
335 1.1 christos case bfd_reloc_outofrange:
336 1.1 christos msg = _("internal error: out of range error");
337 1.1 christos break;
338 1.1 christos
339 1.1 christos case bfd_reloc_notsupported:
340 1.1 christos msg = _("internal error: unsupported relocation error");
341 1.1 christos break;
342 1.1 christos
343 1.1 christos case bfd_reloc_dangerous:
344 1.1 christos msg = _("internal error: dangerous relocation");
345 1.1 christos break;
346 1.1 christos
347 1.1 christos default:
348 1.1 christos msg = _("internal error: unknown error");
349 1.1 christos break;
350 1.1 christos }
351 1.1.1.2 christos
352 1.1.1.2 christos if (msg)
353 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
354 1.1 christos input_section, rel->r_offset);
355 1.1 christos }
356 1.1 christos }
357 1.1 christos
358 1.1 christos return TRUE;
359 1.1 christos }
360 1.1 christos
361 1.1 christos #define ELF_ARCH bfd_arch_ft32
363 1.1 christos #define ELF_MACHINE_CODE EM_FT32
364 1.1 christos #define ELF_MAXPAGESIZE 0x1
365 1.1 christos
366 1.1 christos #define TARGET_LITTLE_SYM ft32_elf32_vec
367 1.1 christos #define TARGET_LITTLE_NAME "elf32-ft32"
368 1.1 christos
369 1.1 christos #define elf_info_to_howto_rel NULL
370 1.1 christos #define elf_info_to_howto ft32_info_to_howto_rela
371 1.1 christos #define elf_backend_relocate_section ft32_elf_relocate_section
372 1.1 christos
373 1.1 christos #define elf_backend_can_gc_sections 1
374 1.1 christos #define elf_backend_rela_normal 1
375 1.1 christos
376 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup ft32_reloc_type_lookup
377 #define bfd_elf32_bfd_reloc_name_lookup ft32_reloc_name_lookup
378
379 #include "elf32-target.h"
380