/src/binutils-gdb/bfd/elf32-s12z.c
Line | Count | Source |
1 | | /* Freescale S12Z-specific support for 32-bit ELF |
2 | | Copyright (C) 1999-2026 Free Software Foundation, Inc. |
3 | | (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.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, Boston, |
20 | | MA 02110-1301, USA. */ |
21 | | |
22 | | #include "sysdep.h" |
23 | | #include "bfd.h" |
24 | | #include "bfdlink.h" |
25 | | #include "libbfd.h" |
26 | | #include "elf-bfd.h" |
27 | | |
28 | | #include "elf/s12z.h" |
29 | | |
30 | | /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ |
31 | 0 | #define OCTETS_PER_BYTE(ABFD, SEC) 1 |
32 | | |
33 | | /* Relocation functions. */ |
34 | | static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup |
35 | | (bfd *, bfd_reloc_code_real_type); |
36 | | static bool s12z_info_to_howto_rel |
37 | | (bfd *, arelent *, Elf_Internal_Rela *); |
38 | | |
39 | | static bfd_reloc_status_type |
40 | | opru18_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol, |
41 | | void *data, asection *input_section ATTRIBUTE_UNUSED, |
42 | | bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED) |
43 | 0 | { |
44 | | /* This reloc is used for 18 bit General Operand Addressing Postbyte in the |
45 | | INST opru18 form. This is an 18 bit reloc, but the most significant bit |
46 | | is shifted one place to the left of where it would normally be. See |
47 | | Appendix A.4 of the S12Z reference manual. */ |
48 | |
|
49 | 0 | bfd_size_type octets = (reloc_entry->address |
50 | 0 | * OCTETS_PER_BYTE (abfd, input_section)); |
51 | 0 | if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, |
52 | 0 | input_section, octets)) |
53 | 0 | return bfd_reloc_outofrange; |
54 | 0 | bfd_vma result = bfd_get_24 (abfd, (unsigned char *) data + octets); |
55 | 0 | bfd_vma val = bfd_asymbol_value (symbol); |
56 | | |
57 | | /* Keep the wanted bits and discard the rest. */ |
58 | 0 | result &= 0xFA0000; |
59 | |
|
60 | 0 | val += symbol->section->output_section->vma; |
61 | 0 | val += symbol->section->output_offset; |
62 | | |
63 | | /* The lowest 17 bits are copied verbatim. */ |
64 | 0 | result |= val & 0x1FFFF; |
65 | | |
66 | | /* The 18th bit is put into the 19th position. */ |
67 | 0 | result |= (val & 0x020000) << 1; |
68 | |
|
69 | 0 | bfd_put_24 (abfd, result, (unsigned char *) data + octets); |
70 | |
|
71 | 0 | return bfd_reloc_ok; |
72 | 0 | } |
73 | | |
74 | | |
75 | | static bfd_reloc_status_type |
76 | | shift_addend_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol ATTRIBUTE_UNUSED, |
77 | | void *data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED, |
78 | | bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED) |
79 | 0 | { |
80 | | /* This is a really peculiar reloc, which is done for compatibility |
81 | | with the Freescale toolchain. |
82 | | |
83 | | That toolchain appears to (ab)use the lowest 15 bits of the addend for |
84 | | the purpose of holding flags. The purpose of these flags are unknown. |
85 | | So in this function, when writing the bfd we left shift the addend by |
86 | | 15, and when reading we right shift it by 15 (discarding the lower bits). |
87 | | |
88 | | This allows the linker to work with object files generated by Freescale, |
89 | | as well as by Gas. */ |
90 | |
|
91 | 0 | if (abfd->is_linker_input) |
92 | 0 | reloc_entry->addend >>= 15; |
93 | 0 | else |
94 | 0 | reloc_entry->addend <<= 15; |
95 | |
|
96 | 0 | return bfd_reloc_continue; |
97 | 0 | } |
98 | | |
99 | | #define USE_REL 0 |
100 | | |
101 | | static reloc_howto_type elf_s12z_howto_table[] = |
102 | | { |
103 | | /* This reloc does nothing. */ |
104 | | HOWTO (R_S12Z_NONE, /* type */ |
105 | | 0, /* rightshift */ |
106 | | 0, /* size */ |
107 | | 0, /* bitsize */ |
108 | | false, /* pc_relative */ |
109 | | 0, /* bitpos */ |
110 | | complain_overflow_dont,/* complain_on_overflow */ |
111 | | bfd_elf_generic_reloc, /* special_function */ |
112 | | "R_S12Z_NONE", /* name */ |
113 | | false, /* partial_inplace */ |
114 | | 0, /* src_mask */ |
115 | | 0, /* dst_mask */ |
116 | | false), /* pcrel_offset */ |
117 | | |
118 | | /* A 24 bit absolute relocation emitted by the OPR mode operands */ |
119 | | HOWTO (R_S12Z_OPR, /* type */ |
120 | | 0, /* rightshift */ |
121 | | 3, /* size */ |
122 | | 24, /* bitsize */ |
123 | | false, /* pc_relative */ |
124 | | 0, /* bitpos */ |
125 | | complain_overflow_bitfield, /* complain_on_overflow */ |
126 | | shift_addend_reloc, |
127 | | "R_S12Z_OPR", /* name */ |
128 | | false, /* partial_inplace */ |
129 | | 0x00ffffff, /* src_mask */ |
130 | | 0x00ffffff, /* dst_mask */ |
131 | | false), /* pcrel_offset */ |
132 | | |
133 | | /* The purpose of this reloc is not known */ |
134 | | HOWTO (R_S12Z_UKNWN_2, /* type */ |
135 | | 0, /* rightshift */ |
136 | | 0, /* size */ |
137 | | 0, /* bitsize */ |
138 | | false, /* pc_relative */ |
139 | | 0, /* bitpos */ |
140 | | complain_overflow_dont,/* complain_on_overflow */ |
141 | | bfd_elf_generic_reloc, /* special_function */ |
142 | | "R_S12Z_UKNWN_2", /* name */ |
143 | | false, /* partial_inplace */ |
144 | | 0, /* src_mask */ |
145 | | 0, /* dst_mask */ |
146 | | false), /* pcrel_offset */ |
147 | | |
148 | | /* A 15 bit PC-rel relocation */ |
149 | | HOWTO (R_S12Z_PCREL_7_15, /* type */ |
150 | | 0, /* rightshift */ |
151 | | 2, /* size */ |
152 | | 15, /* bitsize */ |
153 | | true, /* pc_relative */ |
154 | | 0, /* bitpos */ |
155 | | complain_overflow_bitfield, /* complain_on_overflow */ |
156 | | shift_addend_reloc, |
157 | | "R_S12Z_PCREL_7_15", /* name */ |
158 | | false, /* partial_inplace */ |
159 | | 0x00, /* src_mask */ |
160 | | 0x007fff, /* dst_mask */ |
161 | | true), /* pcrel_offset */ |
162 | | |
163 | | /* A 24 bit absolute relocation emitted by EXT24 mode operands */ |
164 | | HOWTO (R_S12Z_EXT24, /* type */ |
165 | | 0, /* rightshift */ |
166 | | 3, /* size */ |
167 | | 24, /* bitsize */ |
168 | | false, /* pc_relative */ |
169 | | 0, /* bitpos */ |
170 | | complain_overflow_bitfield, /* complain_on_overflow */ |
171 | | bfd_elf_generic_reloc, /* special_function */ |
172 | | "R_S12Z_EXT24", /* name */ |
173 | | false, /* partial_inplace */ |
174 | | 0x00000000, /* src_mask */ |
175 | | 0x00ffffff, /* dst_mask */ |
176 | | false), /* pcrel_offset */ |
177 | | |
178 | | /* An 18 bit absolute relocation */ |
179 | | HOWTO (R_S12Z_EXT18, /* type */ |
180 | | 0, /* rightshift */ |
181 | | 3, /* size */ |
182 | | 18, /* bitsize */ |
183 | | false, /* pc_relative */ |
184 | | 0, /* bitpos */ |
185 | | complain_overflow_bitfield, /* complain_on_overflow */ |
186 | | opru18_reloc, /* special_function */ |
187 | | "R_S12Z_EXT18", /* name */ |
188 | | false, /* partial_inplace */ |
189 | | 0x00000000, /* src_mask */ |
190 | | 0x0005ffff, /* dst_mask */ |
191 | | false), /* pcrel_offset */ |
192 | | |
193 | | /* A 32 bit absolute relocation. This kind of relocation is |
194 | | schizophrenic - Although they appear in sections named .rela.debug.* |
195 | | in some sections they behave as RELA relocs, but in others they have |
196 | | an added of zero and behave as REL. |
197 | | |
198 | | It is not recommended that new code emits this reloc. It is here |
199 | | only to support existing elf files generated by third party |
200 | | applications. */ |
201 | | |
202 | | HOWTO (R_S12Z_CW32, /* type */ |
203 | | 0, /* rightshift */ |
204 | | 4, /* size */ |
205 | | 32, /* bitsize */ |
206 | | false, /* pc_relative */ |
207 | | 0, /* bitpos */ |
208 | | complain_overflow_bitfield, /* complain_on_overflow */ |
209 | | bfd_elf_generic_reloc, /* special_function */ |
210 | | "R_S12Z_CW32", /* name */ |
211 | | false, /* partial_inplace */ |
212 | | 0xffffffff, /* src_mask */ |
213 | | 0xffffffff, /* dst_mask */ |
214 | | false), /* pcrel_offset */ |
215 | | |
216 | | /* A 32 bit absolute relocation */ |
217 | | HOWTO (R_S12Z_EXT32, /* type */ |
218 | | 0, /* rightshift */ |
219 | | 4, /* size */ |
220 | | 32, /* bitsize */ |
221 | | false, /* pc_relative */ |
222 | | 0, /* bitpos */ |
223 | | complain_overflow_bitfield, /* complain_on_overflow */ |
224 | | bfd_elf_generic_reloc, /* special_function */ |
225 | | "R_S12Z_EXT32", /* name */ |
226 | | false, /* partial_inplace */ |
227 | | 0x00000000, /* src_mask */ |
228 | | 0xffffffff, /* dst_mask */ |
229 | | false), /* pcrel_offset */ |
230 | | }; |
231 | | |
232 | | /* Map BFD reloc types to S12Z ELF reloc types. */ |
233 | | |
234 | | struct s12z_reloc_map |
235 | | { |
236 | | bfd_reloc_code_real_type bfd_reloc_val; |
237 | | unsigned char elf_reloc_val; |
238 | | }; |
239 | | |
240 | | static const struct s12z_reloc_map s12z_reloc_map[] = |
241 | | { |
242 | | /* bfd reloc val */ /* elf reloc val */ |
243 | | {BFD_RELOC_NONE, R_S12Z_NONE}, |
244 | | {BFD_RELOC_32, R_S12Z_EXT32}, |
245 | | {BFD_RELOC_24, R_S12Z_EXT24}, |
246 | | {BFD_RELOC_16_PCREL, R_S12Z_PCREL_7_15}, |
247 | | {BFD_RELOC_S12Z_OPR, R_S12Z_OPR} |
248 | | }; |
249 | | |
250 | | static reloc_howto_type * |
251 | | bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
252 | | bfd_reloc_code_real_type code) |
253 | 0 | { |
254 | 0 | unsigned int i; |
255 | |
|
256 | 0 | for (i = 0; |
257 | 0 | i < sizeof (s12z_reloc_map) / sizeof (struct s12z_reloc_map); |
258 | 0 | i++) |
259 | 0 | { |
260 | 0 | if (s12z_reloc_map[i].bfd_reloc_val == code) |
261 | 0 | { |
262 | 0 | return &elf_s12z_howto_table[s12z_reloc_map[i].elf_reloc_val]; |
263 | 0 | } |
264 | 0 | } |
265 | | |
266 | 0 | printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code); |
267 | |
|
268 | 0 | return NULL; |
269 | 0 | } |
270 | | |
271 | | static reloc_howto_type * |
272 | | bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
273 | | const char *r_name) |
274 | 0 | { |
275 | 0 | unsigned int i; |
276 | |
|
277 | 0 | for (i = 0; |
278 | 0 | i < (sizeof (elf_s12z_howto_table) |
279 | 0 | / sizeof (elf_s12z_howto_table[0])); |
280 | 0 | i++) |
281 | 0 | if (elf_s12z_howto_table[i].name != NULL |
282 | 0 | && strcasecmp (elf_s12z_howto_table[i].name, r_name) == 0) |
283 | 0 | return &elf_s12z_howto_table[i]; |
284 | | |
285 | 0 | return NULL; |
286 | 0 | } |
287 | | |
288 | | /* Set the howto pointer for an S12Z ELF reloc. */ |
289 | | |
290 | | static bool |
291 | | s12z_info_to_howto_rel (bfd *abfd, |
292 | | arelent *cache_ptr, Elf_Internal_Rela *dst) |
293 | 0 | { |
294 | 0 | unsigned int r_type = ELF32_R_TYPE (dst->r_info); |
295 | |
|
296 | 0 | if (r_type >= (unsigned int) R_S12Z_max) |
297 | 0 | { |
298 | | /* xgettext:c-format */ |
299 | 0 | _bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
300 | 0 | abfd, r_type); |
301 | 0 | bfd_set_error (bfd_error_bad_value); |
302 | 0 | return false; |
303 | 0 | } |
304 | | |
305 | 0 | cache_ptr->howto = &elf_s12z_howto_table[r_type]; |
306 | 0 | return true; |
307 | 0 | } |
308 | | |
309 | | static bool |
310 | | s12z_elf_set_mach_from_flags (bfd *abfd) |
311 | 521 | { |
312 | 521 | bfd_default_set_arch_mach (abfd, bfd_arch_s12z, 0); |
313 | | |
314 | | return true; |
315 | 521 | } |
316 | | |
317 | | #define ELF_ARCH bfd_arch_s12z |
318 | | #define ELF_MACHINE_CODE EM_S12Z |
319 | | #define ELF_MAXPAGESIZE 0x1000 |
320 | | |
321 | | #define TARGET_BIG_SYM s12z_elf32_vec |
322 | | #define TARGET_BIG_NAME "elf32-s12z" |
323 | | |
324 | | #define elf_info_to_howto NULL |
325 | | #define elf_info_to_howto_rel s12z_info_to_howto_rel |
326 | | #define elf_backend_object_p s12z_elf_set_mach_from_flags |
327 | | |
328 | | #include "elf32-target.h" |