1 /* ft32-specific support for 32-bit ELF.
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 Copied from elf32-moxie.c which is..
5 Copyright (C) 2009-2017 Free Software Foundation, Inc.
6 Free Software Foundation, Inc.
8 This file is part of BFD, the Binary File Descriptor library.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
31 /* Forward declarations. */
33 static reloc_howto_type ft32_elf_howto_table
[] =
35 /* This reloc does nothing. */
36 HOWTO (R_FT32_NONE
, /* type */
38 2, /* size (0 = byte, 1 = short, 2 = long) */
40 FALSE
, /* pc_relative */
42 complain_overflow_bitfield
, /* complain_on_overflow */
43 bfd_elf_generic_reloc
, /* special_function */
44 "R_FT32_NONE", /* name */
45 FALSE
, /* partial_inplace */
48 FALSE
), /* pcrel_offset */
50 /* A 32 bit absolute relocation. */
52 HOWTO (R_FT32_32
, /* type */
54 2, /* size (0 = byte, 1 = short, 2 = long) */
56 FALSE
, /* pc_relative */
58 complain_overflow_bitfield
, /* complain_on_overflow */
59 bfd_elf_generic_reloc
, /* special_function */
60 "R_FT32_32", /* name */
61 FALSE
, /* partial_inplace */
62 0x00000000, /* src_mask */
63 0xffffffff, /* dst_mask */
64 FALSE
), /* pcrel_offset */
66 HOWTO (R_FT32_16
, /* type */
68 1, /* size (0 = byte, 1 = short, 2 = long) */
70 FALSE
, /* pc_relative */
72 complain_overflow_bitfield
, /* complain_on_overflow */
73 bfd_elf_generic_reloc
, /* special_function */
74 "R_FT32_16", /* name */
75 FALSE
, /* partial_inplace */
76 0x00000000, /* src_mask */
77 0x0000ffff, /* dst_mask */
78 FALSE
), /* pcrel_offset */
80 HOWTO (R_FT32_8
, /* type */
82 0, /* size (0 = byte, 1 = short, 2 = long) */
84 FALSE
, /* pc_relative */
86 complain_overflow_signed
, /* complain_on_overflow */
87 bfd_elf_generic_reloc
, /* special_function */
88 "R_FT32_8", /* name */
89 FALSE
, /* partial_inplace */
90 0x00000000, /* src_mask */
91 0x000000ff, /* dst_mask */
92 FALSE
), /* pcrel_offset */
94 HOWTO (R_FT32_10
, /* type */
96 1, /* size (0 = byte, 1 = short, 2 = long) */
98 FALSE
, /* pc_relative */
100 complain_overflow_signed
, /* complain_on_overflow */
101 bfd_elf_generic_reloc
, /* special_function */
102 "R_FT32_10", /* name */
103 FALSE
, /* partial_inplace */
104 0x00000000, /* src_mask */
105 0x00003ff0, /* dst_mask */
106 FALSE
), /* pcrel_offset */
108 HOWTO (R_FT32_20
, /* type */
110 2, /* size (0 = byte, 1 = short, 2 = long) */
112 FALSE
, /* pc_relative */
114 complain_overflow_dont
, /* complain_on_overflow */
115 bfd_elf_generic_reloc
, /* special_function */
116 "R_FT32_20", /* name */
117 FALSE
, /* partial_inplace */
118 0x00000000, /* src_mask */
119 0x000fffff, /* dst_mask */
120 FALSE
), /* pcrel_offset */
122 HOWTO (R_FT32_17
, /* type */
124 2, /* size (0 = byte, 1 = short, 2 = long) */
126 FALSE
, /* pc_relative */
128 complain_overflow_dont
, /* complain_on_overflow */
129 bfd_elf_generic_reloc
, /* special_function */
130 "R_FT32_17", /* name */
131 FALSE
, /* partial_inplace */
132 0x00000000, /* src_mask */
133 0x0001ffff, /* dst_mask */
134 FALSE
), /* pcrel_offset */
136 HOWTO (R_FT32_18
, /* type */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
140 FALSE
, /* pc_relative */
142 complain_overflow_dont
, /* complain_on_overflow */
143 bfd_elf_generic_reloc
, /* special_function */
144 "R_FT32_18", /* name */
145 FALSE
, /* partial_inplace */
146 0x00000000, /* src_mask */
147 0x0003ffff, /* dst_mask */
148 FALSE
), /* pcrel_offset */
150 HOWTO (R_FT32_15
, /* type */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
154 FALSE
, /* pc_relative */
156 complain_overflow_dont
, /* complain_on_overflow */
157 bfd_elf_generic_reloc
, /* special_function */
158 "R_FT32_15", /* name */
159 FALSE
, /* partial_inplace */
160 0x00000000, /* src_mask */
161 0x00007fff, /* dst_mask */
162 FALSE
), /* pcrel_offset */
165 /* Map BFD reloc types to FT32 ELF reloc types. */
167 struct ft32_reloc_map
169 bfd_reloc_code_real_type bfd_reloc_val
;
170 unsigned int ft32_reloc_val
;
173 static const struct ft32_reloc_map ft32_reloc_map
[] =
175 { BFD_RELOC_NONE
, R_FT32_NONE
},
176 { BFD_RELOC_32
, R_FT32_32
},
177 { BFD_RELOC_16
, R_FT32_16
},
178 { BFD_RELOC_8
, R_FT32_8
},
179 { BFD_RELOC_FT32_10
, R_FT32_10
},
180 { BFD_RELOC_FT32_20
, R_FT32_20
},
181 { BFD_RELOC_FT32_17
, R_FT32_17
},
182 { BFD_RELOC_FT32_18
, R_FT32_18
},
183 { BFD_RELOC_FT32_15
, R_FT32_15
},
186 static reloc_howto_type
*
187 ft32_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
188 bfd_reloc_code_real_type code
)
192 for (i
= sizeof (ft32_reloc_map
) / sizeof (ft32_reloc_map
[0]);
194 if (ft32_reloc_map
[i
].bfd_reloc_val
== code
)
195 return & ft32_elf_howto_table
[ft32_reloc_map
[i
].ft32_reloc_val
];
200 static reloc_howto_type
*
201 ft32_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
206 i
< sizeof (ft32_elf_howto_table
) / sizeof (ft32_elf_howto_table
[0]);
208 if (ft32_elf_howto_table
[i
].name
!= NULL
209 && strcasecmp (ft32_elf_howto_table
[i
].name
, r_name
) == 0)
210 return &ft32_elf_howto_table
[i
];
215 /* Set the howto pointer for an FT32 ELF reloc. */
218 ft32_info_to_howto_rela (bfd
*abfd ATTRIBUTE_UNUSED
,
220 Elf_Internal_Rela
*dst
)
224 r_type
= ELF32_R_TYPE (dst
->r_info
);
225 BFD_ASSERT (r_type
< (unsigned int) R_FT32_max
);
226 cache_ptr
->howto
= & ft32_elf_howto_table
[r_type
];
229 /* Relocate an FT32 ELF section.
231 The RELOCATE_SECTION function is called by the new ELF backend linker
232 to handle the relocations for a section.
234 The relocs are always passed as Rela structures; if the section
235 actually uses Rel structures, the r_addend field will always be
238 This function is responsible for adjusting the section contents as
239 necessary, and (if using Rela relocs and generating a relocatable
240 output file) adjusting the reloc addend as necessary.
242 This function does not have to worry about setting the reloc
243 address or the reloc symbol index.
245 LOCAL_SYMS is a pointer to the swapped in local symbols.
247 LOCAL_SECTIONS is an array giving the section in the input file
248 corresponding to the st_shndx field of each local symbol.
250 The global hash table entry for the global symbols can be found
251 via elf_sym_hashes (input_bfd).
253 When generating relocatable output, this function must handle
254 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
255 going to be the section symbol corresponding to the output
256 section, which means that the addend must be adjusted
260 ft32_elf_relocate_section (bfd
*output_bfd
,
261 struct bfd_link_info
*info
,
263 asection
*input_section
,
265 Elf_Internal_Rela
*relocs
,
266 Elf_Internal_Sym
*local_syms
,
267 asection
**local_sections
)
269 Elf_Internal_Shdr
*symtab_hdr
;
270 struct elf_link_hash_entry
**sym_hashes
;
271 Elf_Internal_Rela
*rel
;
272 Elf_Internal_Rela
*relend
;
274 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
275 sym_hashes
= elf_sym_hashes (input_bfd
);
276 relend
= relocs
+ input_section
->reloc_count
;
278 for (rel
= relocs
; rel
< relend
; rel
++)
280 reloc_howto_type
*howto
;
281 unsigned long r_symndx
;
282 Elf_Internal_Sym
*sym
;
284 struct elf_link_hash_entry
*h
;
286 bfd_reloc_status_type r
;
290 r_type
= ELF32_R_TYPE (rel
->r_info
);
291 r_symndx
= ELF32_R_SYM (rel
->r_info
);
292 howto
= ft32_elf_howto_table
+ r_type
;
297 if (r_symndx
< symtab_hdr
->sh_info
)
299 sym
= local_syms
+ r_symndx
;
300 sec
= local_sections
[r_symndx
];
301 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
303 name
= bfd_elf_string_from_elf_section
304 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
305 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
309 bfd_boolean unresolved_reloc
, warned
, ignored
;
311 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
312 r_symndx
, symtab_hdr
, sym_hashes
,
314 unresolved_reloc
, warned
, ignored
);
316 name
= h
->root
.root
.string
;
319 if (sec
!= NULL
&& discarded_section (sec
))
320 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
321 rel
, 1, relend
, howto
, 0, contents
);
323 if (bfd_link_relocatable (info
))
326 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
327 contents
, rel
->r_offset
,
328 relocation
, rel
->r_addend
);
330 if (r
!= bfd_reloc_ok
)
332 const char * msg
= NULL
;
336 case bfd_reloc_overflow
:
337 (*info
->callbacks
->reloc_overflow
)
338 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
339 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
342 case bfd_reloc_undefined
:
343 (*info
->callbacks
->undefined_symbol
)
344 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
347 case bfd_reloc_outofrange
:
348 msg
= _("internal error: out of range error");
351 case bfd_reloc_notsupported
:
352 msg
= _("internal error: unsupported relocation error");
355 case bfd_reloc_dangerous
:
356 msg
= _("internal error: dangerous relocation");
360 msg
= _("internal error: unknown error");
365 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
366 input_section
, rel
->r_offset
);
373 #define ELF_ARCH bfd_arch_ft32
374 #define ELF_MACHINE_CODE EM_FT32
375 #define ELF_MAXPAGESIZE 0x1
377 #define TARGET_LITTLE_SYM ft32_elf32_vec
378 #define TARGET_LITTLE_NAME "elf32-ft32"
380 #define elf_info_to_howto_rel NULL
381 #define elf_info_to_howto ft32_info_to_howto_rela
382 #define elf_backend_relocate_section ft32_elf_relocate_section
384 #define elf_backend_can_gc_sections 1
385 #define elf_backend_rela_normal 1
387 #define bfd_elf32_bfd_reloc_type_lookup ft32_reloc_type_lookup
388 #define bfd_elf32_bfd_reloc_name_lookup ft32_reloc_name_lookup
390 #include "elf32-target.h"