/src/binutils-gdb/bfd/elf32-z80.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Zilog (e)Z80-specific support for 32-bit ELF |
2 | | Copyright (C) 1999-2025 Free Software Foundation, Inc. |
3 | | (Heavily copied from the S12Z port by Sergey Belyashov (sergey.belyashov@gmail.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/z80.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 | | typedef const struct { |
34 | | bfd_reloc_code_real_type r_type; |
35 | | reloc_howto_type howto; |
36 | | } bfd_howto_type; |
37 | | |
38 | | #define BFD_EMPTY_HOWTO(rt,x) {rt, EMPTY_HOWTO(x)} |
39 | | #define BFD_HOWTO(rt,a,b,c,d,e,f,g,h,i,j,k,l,m) {rt, HOWTO(a,b,c,d,e,f,g,h,i,j,k,l,m)} |
40 | | |
41 | | static bfd_reloc_status_type |
42 | | z80_elf_16_be_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
43 | | void *data, asection *input_section, bfd *output_bfd, |
44 | | char **error_message); |
45 | | |
46 | | static const |
47 | | bfd_howto_type elf_z80_howto_table[] = |
48 | | { |
49 | | /* This reloc does nothing. */ |
50 | | BFD_HOWTO (BFD_RELOC_NONE, |
51 | | R_Z80_NONE, /* type */ |
52 | | 0, /* rightshift */ |
53 | | 0, /* size */ |
54 | | 0, /* bitsize */ |
55 | | false, /* pc_relative */ |
56 | | 0, /* bitpos */ |
57 | | complain_overflow_dont,/* complain_on_overflow */ |
58 | | bfd_elf_generic_reloc, /* special_function */ |
59 | | "R_NONE", /* name */ |
60 | | false, /* partial_inplace */ |
61 | | 0, /* src_mask */ |
62 | | 0, /* dst_mask */ |
63 | | false), /* pcrel_offset */ |
64 | | |
65 | | /* A 8 bit relocation */ |
66 | | BFD_HOWTO (BFD_RELOC_8, |
67 | | R_Z80_8, /* type */ |
68 | | 0, /* rightshift */ |
69 | | 1, /* size */ |
70 | | 8, /* bitsize */ |
71 | | false, /* pc_relative */ |
72 | | 0, /* bitpos */ |
73 | | complain_overflow_bitfield, /* complain_on_overflow */ |
74 | | bfd_elf_generic_reloc, /* special_function */ |
75 | | "r_imm8", /* name */ |
76 | | false, /* partial_inplace */ |
77 | | 0x00, /* src_mask */ |
78 | | 0xff, /* dst_mask */ |
79 | | false), /* pcrel_offset */ |
80 | | |
81 | | /* A 8 bit index register displacement relocation */ |
82 | | BFD_HOWTO (BFD_RELOC_Z80_DISP8, |
83 | | R_Z80_8_DIS, /* type */ |
84 | | 0, /* rightshift */ |
85 | | 1, /* size */ |
86 | | 8, /* bitsize */ |
87 | | false, /* pc_relative */ |
88 | | 0, /* bitpos */ |
89 | | complain_overflow_signed, /* complain_on_overflow */ |
90 | | bfd_elf_generic_reloc, /* special_function */ |
91 | | "r_off", /* name */ |
92 | | false, /* partial_inplace */ |
93 | | 0x00, /* src_mask */ |
94 | | 0xff, /* dst_mask */ |
95 | | false), /* pcrel_offset */ |
96 | | |
97 | | /* A 8 bit PC-rel relocation */ |
98 | | BFD_HOWTO (BFD_RELOC_8_PCREL, |
99 | | R_Z80_8_PCREL, /* type */ |
100 | | 0, /* rightshift */ |
101 | | 1, /* size */ |
102 | | 8, /* bitsize */ |
103 | | true, /* pc_relative */ |
104 | | 0, /* bitpos */ |
105 | | complain_overflow_signed, /* complain_on_overflow */ |
106 | | bfd_elf_generic_reloc, /* special_function */ |
107 | | "r_jr", /* name */ |
108 | | false, /* partial_inplace */ |
109 | | 0x00, /* src_mask */ |
110 | | 0xff, /* dst_mask */ |
111 | | true), /* pcrel_offset */ |
112 | | |
113 | | /* An 16 bit absolute relocation */ |
114 | | BFD_HOWTO (BFD_RELOC_16, |
115 | | R_Z80_16, /* type */ |
116 | | 0, /* rightshift */ |
117 | | 2, /* size */ |
118 | | 16, /* bitsize */ |
119 | | false, /* pc_relative */ |
120 | | 0, /* bitpos */ |
121 | | complain_overflow_bitfield, /* complain_on_overflow */ |
122 | | bfd_elf_generic_reloc, /* special_function */ |
123 | | "r_imm16", /* name */ |
124 | | false, /* partial_inplace */ |
125 | | 0x00000000, /* src_mask */ |
126 | | 0x0000ffff, /* dst_mask */ |
127 | | false), /* pcrel_offset */ |
128 | | |
129 | | /* A 24 bit absolute relocation emitted by ADL mode operands */ |
130 | | BFD_HOWTO (BFD_RELOC_24, |
131 | | R_Z80_24, /* type */ |
132 | | 0, /* rightshift */ |
133 | | 3, /* size */ |
134 | | 24, /* bitsize */ |
135 | | false, /* pc_relative */ |
136 | | 0, /* bitpos */ |
137 | | complain_overflow_bitfield, /* complain_on_overflow */ |
138 | | bfd_elf_generic_reloc, /* special_function */ |
139 | | "r_imm24", /* name */ |
140 | | false, /* partial_inplace */ |
141 | | 0x00000000, /* src_mask */ |
142 | | 0x00ffffff, /* dst_mask */ |
143 | | false), /* pcrel_offset */ |
144 | | |
145 | | BFD_HOWTO (BFD_RELOC_32, |
146 | | R_Z80_32, /* type */ |
147 | | 0, /* rightshift */ |
148 | | 4, /* size */ |
149 | | 32, /* bitsize */ |
150 | | false, /* pc_relative */ |
151 | | 0, /* bitpos */ |
152 | | complain_overflow_dont,/* complain_on_overflow */ |
153 | | bfd_elf_generic_reloc, /* special_function */ |
154 | | "r_imm32", /* name */ |
155 | | false, /* partial_inplace */ |
156 | | 0x00000000, /* src_mask */ |
157 | | 0xffffffff, /* dst_mask */ |
158 | | false), /* pcrel_offset */ |
159 | | |
160 | | /* First (lowest) 8 bits of multibyte relocation */ |
161 | | BFD_HOWTO (BFD_RELOC_Z80_BYTE0, |
162 | | R_Z80_BYTE0, /* type */ |
163 | | 0, /* rightshift */ |
164 | | 1, /* size */ |
165 | | 32, /* bitsize */ |
166 | | false, /* pc_relative */ |
167 | | 0, /* bitpos */ |
168 | | complain_overflow_dont,/* complain_on_overflow */ |
169 | | bfd_elf_generic_reloc, /* special_function */ |
170 | | "r_byte0", /* name */ |
171 | | false, /* partial_inplace */ |
172 | | 0, /* src_mask */ |
173 | | 0xff, /* dst_mask */ |
174 | | false), /* pcrel_offset */ |
175 | | |
176 | | /* Second 8 bits of multibyte relocation */ |
177 | | BFD_HOWTO (BFD_RELOC_Z80_BYTE1, |
178 | | R_Z80_BYTE1, /* type */ |
179 | | 8, /* rightshift */ |
180 | | 1, /* size */ |
181 | | 32, /* bitsize */ |
182 | | false, /* pc_relative */ |
183 | | 0, /* bitpos */ |
184 | | complain_overflow_dont,/* complain_on_overflow */ |
185 | | bfd_elf_generic_reloc, /* special_function */ |
186 | | "r_byte1", /* name */ |
187 | | false, /* partial_inplace */ |
188 | | 0, /* src_mask */ |
189 | | 0xff, /* dst_mask */ |
190 | | false), /* pcrel_offset */ |
191 | | |
192 | | /* Third 8 bits of multibyte relocation */ |
193 | | BFD_HOWTO (BFD_RELOC_Z80_BYTE2, |
194 | | R_Z80_BYTE2, /* type */ |
195 | | 16, /* rightshift */ |
196 | | 1, /* size */ |
197 | | 32, /* bitsize */ |
198 | | false, /* pc_relative */ |
199 | | 0, /* bitpos */ |
200 | | complain_overflow_dont,/* complain_on_overflow */ |
201 | | bfd_elf_generic_reloc, /* special_function */ |
202 | | "r_byte2", /* name */ |
203 | | false, /* partial_inplace */ |
204 | | 0, /* src_mask */ |
205 | | 0xff, /* dst_mask */ |
206 | | false), /* pcrel_offset */ |
207 | | |
208 | | /* Fourth (highest) 8 bits of multibyte relocation */ |
209 | | BFD_HOWTO (BFD_RELOC_Z80_BYTE3, |
210 | | R_Z80_BYTE3, /* type */ |
211 | | 24, /* rightshift */ |
212 | | 1, /* size */ |
213 | | 32, /* bitsize */ |
214 | | false, /* pc_relative */ |
215 | | 0, /* bitpos */ |
216 | | complain_overflow_dont,/* complain_on_overflow */ |
217 | | bfd_elf_generic_reloc, /* special_function */ |
218 | | "r_byte3", /* name */ |
219 | | false, /* partial_inplace */ |
220 | | 0, /* src_mask */ |
221 | | 0xff, /* dst_mask */ |
222 | | false), /* pcrel_offset */ |
223 | | |
224 | | /* An 16 bit absolute relocation of lower word of multibyte value */ |
225 | | BFD_HOWTO (BFD_RELOC_Z80_WORD0, |
226 | | R_Z80_WORD0, /* type */ |
227 | | 0, /* rightshift */ |
228 | | 2, /* size */ |
229 | | 32, /* bitsize */ |
230 | | false, /* pc_relative */ |
231 | | 0, /* bitpos */ |
232 | | complain_overflow_dont,/* complain_on_overflow */ |
233 | | bfd_elf_generic_reloc, /* special_function */ |
234 | | "r_word0", /* name */ |
235 | | false, /* partial_inplace */ |
236 | | 0, /* src_mask */ |
237 | | 0xffff, /* dst_mask */ |
238 | | false), /* pcrel_offset */ |
239 | | |
240 | | /* An 16 bit absolute relocation of higher word of multibyte value */ |
241 | | BFD_HOWTO (BFD_RELOC_Z80_WORD1, |
242 | | R_Z80_WORD1, /* type */ |
243 | | 16, /* rightshift */ |
244 | | 2, /* size */ |
245 | | 32, /* bitsize */ |
246 | | false, /* pc_relative */ |
247 | | 0, /* bitpos */ |
248 | | complain_overflow_dont,/* complain_on_overflow */ |
249 | | bfd_elf_generic_reloc, /* special_function */ |
250 | | "r_word1", /* name */ |
251 | | false, /* partial_inplace */ |
252 | | 0, /* src_mask */ |
253 | | 0xffff, /* dst_mask */ |
254 | | false), /* pcrel_offset */ |
255 | | |
256 | | /* An 16 bit big endian absolute relocation */ |
257 | | BFD_HOWTO (BFD_RELOC_Z80_16_BE, |
258 | | R_Z80_16_BE, /* type */ |
259 | | 0, /* rightshift */ |
260 | | 2, /* size */ |
261 | | 16, /* bitsize */ |
262 | | false, /* pc_relative */ |
263 | | 0, /* bitpos */ |
264 | | complain_overflow_bitfield, /* complain_on_overflow */ |
265 | | z80_elf_16_be_reloc, /* special_function */ |
266 | | "r_imm16be", /* name */ |
267 | | false, /* partial_inplace */ |
268 | | 0x00000000, /* src_mask */ |
269 | | 0x0000ffff, /* dst_mask */ |
270 | | false), /* pcrel_offset */ |
271 | | }; |
272 | | |
273 | | static reloc_howto_type * |
274 | | z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
275 | | bfd_reloc_code_real_type code) |
276 | 0 | { |
277 | 0 | enum |
278 | 0 | { |
279 | 0 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) |
280 | 0 | }; |
281 | 0 | unsigned int i; |
282 | |
|
283 | 0 | for (i = 0; i < table_size; i++) |
284 | 0 | { |
285 | 0 | if (elf_z80_howto_table[i].r_type == code) |
286 | 0 | return &elf_z80_howto_table[i].howto; |
287 | 0 | } |
288 | | |
289 | 0 | printf ("%s:%d Not found BFD reloc type %d\n", __FILE__, __LINE__, code); |
290 | |
|
291 | 0 | return NULL; |
292 | 0 | } |
293 | | |
294 | | static reloc_howto_type * |
295 | | z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) |
296 | 0 | { |
297 | 0 | enum |
298 | 0 | { |
299 | 0 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) |
300 | 0 | }; |
301 | 0 | unsigned int i; |
302 | |
|
303 | 0 | for (i = 0; i < table_size; i++) |
304 | 0 | { |
305 | 0 | if (elf_z80_howto_table[i].howto.name != NULL |
306 | 0 | && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0) |
307 | 0 | return &elf_z80_howto_table[i].howto; |
308 | 0 | } |
309 | | |
310 | 0 | printf ("%s:%d Not found ELF reloc name `%s'\n", __FILE__, __LINE__, r_name); |
311 | |
|
312 | 0 | return NULL; |
313 | 0 | } |
314 | | |
315 | | static reloc_howto_type * |
316 | | z80_rtype_to_howto (bfd *abfd, unsigned r_type) |
317 | 45 | { |
318 | 45 | enum |
319 | 45 | { |
320 | 45 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) |
321 | 45 | }; |
322 | 45 | unsigned int i; |
323 | | |
324 | 108 | for (i = 0; i < table_size; i++) |
325 | 104 | { |
326 | 104 | if (elf_z80_howto_table[i].howto.type == r_type) |
327 | 41 | return &elf_z80_howto_table[i].howto; |
328 | 104 | } |
329 | | |
330 | | /* xgettext:c-format */ |
331 | 4 | _bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
332 | 4 | abfd, r_type); |
333 | 4 | return NULL; |
334 | 45 | } |
335 | | |
336 | | /* Set the howto pointer for an z80 ELF reloc. */ |
337 | | |
338 | | static bool |
339 | | z80_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) |
340 | 45 | { |
341 | 45 | unsigned int r_type = ELF32_R_TYPE (dst->r_info); |
342 | 45 | reloc_howto_type *howto = z80_rtype_to_howto (abfd, r_type); |
343 | 45 | if (howto != NULL) |
344 | 41 | { |
345 | 41 | cache_ptr->howto = howto; |
346 | 41 | return true; |
347 | 41 | } |
348 | 4 | bfd_set_error (bfd_error_bad_value); |
349 | 4 | return false; |
350 | 45 | } |
351 | | |
352 | | static bfd_reloc_status_type |
353 | | z80_elf_final_link_relocate (unsigned long r_type, |
354 | | bfd *input_bfd, |
355 | | bfd *output_bfd ATTRIBUTE_UNUSED, |
356 | | asection *input_section ATTRIBUTE_UNUSED, |
357 | | bfd_byte *contents, |
358 | | bfd_vma offset, |
359 | | bfd_vma value, |
360 | | bfd_vma addend, |
361 | | struct bfd_link_info *info ATTRIBUTE_UNUSED, |
362 | | asection *sym_sec ATTRIBUTE_UNUSED, |
363 | | int is_local ATTRIBUTE_UNUSED) |
364 | 0 | { |
365 | 0 | bool r; |
366 | 0 | reloc_howto_type *howto; |
367 | |
|
368 | 0 | switch (r_type) |
369 | 0 | { |
370 | 0 | case R_Z80_16_BE: |
371 | 0 | value += addend; |
372 | 0 | bfd_put_8 (input_bfd, value >> 8, contents + offset + 0); |
373 | 0 | bfd_put_8 (input_bfd, value >> 0, contents + offset + 1); |
374 | 0 | return bfd_reloc_ok; |
375 | 0 | } |
376 | | |
377 | 0 | howto = z80_rtype_to_howto (input_bfd, r_type); |
378 | 0 | if (howto == NULL) |
379 | 0 | return bfd_reloc_notsupported; |
380 | | |
381 | 0 | r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, |
382 | 0 | offset, value, addend); |
383 | 0 | return r ? bfd_reloc_ok : bfd_reloc_notsupported; |
384 | 0 | } |
385 | | |
386 | | static int |
387 | | z80_elf_relocate_section (bfd *output_bfd, |
388 | | struct bfd_link_info *info, |
389 | | bfd *input_bfd, |
390 | | asection *input_section, |
391 | | bfd_byte *contents, |
392 | | Elf_Internal_Rela *relocs, |
393 | | Elf_Internal_Sym *local_syms, |
394 | | asection **local_sections) |
395 | 0 | { |
396 | 0 | Elf_Internal_Shdr *symtab_hdr; |
397 | 0 | struct elf_link_hash_entry **sym_hashes; |
398 | 0 | Elf_Internal_Rela *rel, *relend; |
399 | |
|
400 | 0 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
401 | 0 | sym_hashes = elf_sym_hashes (input_bfd); |
402 | |
|
403 | 0 | rel = relocs; |
404 | 0 | relend = relocs + input_section->reloc_count; |
405 | 0 | for (; rel < relend; rel++) |
406 | 0 | { |
407 | 0 | unsigned int r_type; |
408 | 0 | unsigned long r_symndx; |
409 | 0 | Elf_Internal_Sym *sym; |
410 | 0 | asection *sec; |
411 | 0 | struct elf_link_hash_entry *h; |
412 | 0 | bfd_vma relocation; |
413 | | |
414 | | /* This is a final link. */ |
415 | 0 | r_symndx = ELF32_R_SYM (rel->r_info); |
416 | 0 | r_type = ELF32_R_TYPE (rel->r_info); |
417 | 0 | h = NULL; |
418 | 0 | sym = NULL; |
419 | 0 | sec = NULL; |
420 | 0 | if (r_symndx < symtab_hdr->sh_info) |
421 | 0 | { |
422 | 0 | sym = local_syms + r_symndx; |
423 | 0 | sec = local_sections[r_symndx]; |
424 | 0 | relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
425 | 0 | } |
426 | 0 | else |
427 | 0 | { |
428 | 0 | bool unresolved_reloc, warned, ignored; |
429 | |
|
430 | 0 | RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
431 | 0 | r_symndx, symtab_hdr, sym_hashes, |
432 | 0 | h, sec, relocation, |
433 | 0 | unresolved_reloc, warned, ignored); |
434 | 0 | } |
435 | | |
436 | 0 | if (sec != NULL && discarded_section (sec)) |
437 | 0 | { |
438 | | /* For relocs against symbols from removed linkonce sections, |
439 | | or sections discarded by a linker script, we just want the |
440 | | section contents cleared. Avoid any special processing. */ |
441 | 0 | reloc_howto_type *howto; |
442 | 0 | howto = z80_rtype_to_howto (input_bfd, r_type); |
443 | 0 | RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
444 | 0 | rel, 1, relend, howto, 0, contents); |
445 | 0 | } |
446 | | |
447 | 0 | if (bfd_link_relocatable (info)) |
448 | 0 | continue; |
449 | | |
450 | | |
451 | 0 | z80_elf_final_link_relocate (r_type, input_bfd, output_bfd, |
452 | 0 | input_section, |
453 | 0 | contents, rel->r_offset, |
454 | 0 | relocation, rel->r_addend, |
455 | 0 | info, sec, h == NULL); |
456 | 0 | } |
457 | | |
458 | 0 | return true; |
459 | 0 | } |
460 | | |
461 | | /* The final processing done just before writing out a Z80 ELF object |
462 | | file. This gets the Z80 architecture right based on the machine |
463 | | number. */ |
464 | | |
465 | | static bool |
466 | | z80_elf_final_write_processing (bfd *abfd) |
467 | 0 | { |
468 | 0 | unsigned long val = bfd_get_mach (abfd); |
469 | |
|
470 | 0 | switch (val) |
471 | 0 | { |
472 | 0 | default: |
473 | 0 | _bfd_error_handler (_("%pB: unsupported bfd mach %#lx"), |
474 | 0 | abfd, val); |
475 | | /* fall through */ |
476 | 0 | case bfd_mach_z80: |
477 | 0 | case bfd_mach_z80full: |
478 | 0 | case bfd_mach_z80strict: |
479 | 0 | val = EF_Z80_MACH_Z80; |
480 | 0 | break; |
481 | 0 | case bfd_mach_gbz80: |
482 | 0 | val = EF_Z80_MACH_GBZ80; |
483 | 0 | break; |
484 | 0 | case bfd_mach_z80n: |
485 | 0 | val = EF_Z80_MACH_Z80N; |
486 | 0 | break; |
487 | 0 | case bfd_mach_z180: |
488 | 0 | val = EF_Z80_MACH_Z180; |
489 | 0 | break; |
490 | 0 | case bfd_mach_ez80_z80: |
491 | 0 | val = EF_Z80_MACH_EZ80_Z80; |
492 | 0 | break; |
493 | 0 | case bfd_mach_ez80_adl: |
494 | 0 | val = EF_Z80_MACH_EZ80_ADL; |
495 | 0 | break; |
496 | 0 | case bfd_mach_r800: |
497 | 0 | val = EF_Z80_MACH_R800; |
498 | 0 | break; |
499 | 0 | } |
500 | 0 | elf_elfheader (abfd)->e_machine = EM_Z80; |
501 | 0 | elf_elfheader (abfd)->e_flags &= ~EF_Z80_MACH_MSK; |
502 | 0 | elf_elfheader (abfd)->e_flags |= val; |
503 | 0 | return _bfd_elf_final_write_processing (abfd); |
504 | 0 | } |
505 | | |
506 | | /* Set the right machine number. */ |
507 | | static bool |
508 | | z80_elf_object_p (bfd *abfd) |
509 | 8.33k | { |
510 | 8.33k | unsigned int mach; |
511 | | |
512 | 8.33k | if (elf_elfheader (abfd)->e_machine == EM_Z80) |
513 | 8.33k | { |
514 | 8.33k | int e_mach = elf_elfheader (abfd)->e_flags & EF_Z80_MACH_MSK; |
515 | 8.33k | switch (e_mach) |
516 | 8.33k | { |
517 | 1.98k | default: |
518 | 1.98k | _bfd_error_handler (_("%pB: unsupported mach %#x"), |
519 | 1.98k | abfd, e_mach); |
520 | | /* fall through */ |
521 | 3.39k | case EF_Z80_MACH_Z80: |
522 | 3.39k | mach = bfd_mach_z80; |
523 | 3.39k | break; |
524 | 1.19k | case EF_Z80_MACH_GBZ80: |
525 | 1.19k | mach = bfd_mach_gbz80; |
526 | 1.19k | break; |
527 | 671 | case EF_Z80_MACH_Z180: |
528 | 671 | mach = bfd_mach_z180; |
529 | 671 | break; |
530 | 1.19k | case EF_Z80_MACH_EZ80_Z80: |
531 | 1.19k | mach = bfd_mach_ez80_z80; |
532 | 1.19k | break; |
533 | 475 | case EF_Z80_MACH_EZ80_ADL: |
534 | 475 | mach = bfd_mach_ez80_adl; |
535 | 475 | break; |
536 | 671 | case EF_Z80_MACH_R800: |
537 | 671 | mach = bfd_mach_r800; |
538 | 671 | break; |
539 | 732 | case EF_Z80_MACH_Z80N: |
540 | 732 | mach = bfd_mach_z80n; |
541 | 732 | break; |
542 | 8.33k | } |
543 | 8.33k | } |
544 | 0 | else |
545 | 0 | { |
546 | 0 | _bfd_error_handler (_("%pB: unsupported arch %#x"), |
547 | 0 | abfd, elf_elfheader (abfd)->e_machine); |
548 | 0 | mach = bfd_mach_z80; |
549 | 0 | } |
550 | 8.33k | return bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach); |
551 | 8.33k | } |
552 | | |
553 | | static bool |
554 | | z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, |
555 | | const char * name) |
556 | 0 | { |
557 | 0 | return (name[0] == '.' && name[1] == 'L') || |
558 | 0 | _bfd_elf_is_local_label_name (abfd, name); |
559 | 0 | } |
560 | | |
561 | | static bfd_reloc_status_type |
562 | | z80_elf_16_be_reloc (bfd *abfd, |
563 | | arelent *reloc_entry, |
564 | | asymbol *symbol, |
565 | | void *data, |
566 | | asection *input_section, |
567 | | bfd *output_bfd, |
568 | | char **error_message) |
569 | 0 | { |
570 | 0 | bfd_vma val; |
571 | 0 | long x; |
572 | 0 | bfd_size_type octets = (reloc_entry->address |
573 | 0 | * OCTETS_PER_BYTE (abfd, input_section)); |
574 | | |
575 | | /* If this is a relocatable link (output_bfd test tells us), just |
576 | | call the generic function. Any adjustment will be done at final |
577 | | link time. */ |
578 | 0 | if (output_bfd != NULL) |
579 | 0 | return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
580 | 0 | input_section, output_bfd, error_message); |
581 | | |
582 | | /* Get symbol value. */ |
583 | 0 | val = 0; |
584 | 0 | if (!bfd_is_com_section (symbol->section)) |
585 | 0 | val = symbol->value; |
586 | 0 | val += symbol->section->output_offset + input_section->output_offset; |
587 | 0 | if (symbol->section->output_section) |
588 | 0 | val += symbol->section->output_section->vma; |
589 | |
|
590 | 0 | val += reloc_entry->addend; |
591 | 0 | if (reloc_entry->howto->partial_inplace) |
592 | 0 | { |
593 | 0 | x = bfd_get_8 (abfd, (bfd_byte *) data + octets + 0) * 0x100; |
594 | 0 | x += bfd_get_8 (abfd, (bfd_byte *) data + octets + 1); |
595 | 0 | x &= ~reloc_entry->howto->src_mask; |
596 | 0 | } |
597 | 0 | else |
598 | 0 | x = 0; |
599 | |
|
600 | 0 | x |= val & reloc_entry->howto->dst_mask; |
601 | 0 | if (x < -0x8000 || x >= 0x10000) |
602 | 0 | return bfd_reloc_outofrange; |
603 | | |
604 | 0 | bfd_put_8 (abfd, x >> 8, (bfd_byte *) data + octets + 0); |
605 | 0 | bfd_put_8 (abfd, x >> 0, (bfd_byte *) data + octets + 1); |
606 | 0 | return bfd_reloc_ok; |
607 | 0 | } |
608 | | |
609 | | #define ELF_ARCH bfd_arch_z80 |
610 | | #define ELF_MACHINE_CODE EM_Z80 |
611 | | #define ELF_MAXPAGESIZE 0x10000 |
612 | | |
613 | | #define TARGET_LITTLE_SYM z80_elf32_vec |
614 | | #define TARGET_LITTLE_NAME "elf32-z80" |
615 | | |
616 | | #define elf_backend_can_refcount 1 |
617 | | #define elf_backend_can_gc_sections 1 |
618 | | #define elf_backend_stack_align 1 |
619 | | #define elf_backend_rela_normal 1 |
620 | | |
621 | | #define elf_info_to_howto z80_info_to_howto_rela |
622 | | #define elf_info_to_howto_rel z80_info_to_howto_rela |
623 | | |
624 | | #define elf_backend_final_write_processing z80_elf_final_write_processing |
625 | | #define elf_backend_object_p z80_elf_object_p |
626 | | #define elf_backend_relocate_section z80_elf_relocate_section |
627 | | |
628 | | #define bfd_elf32_bfd_reloc_type_lookup z80_reloc_type_lookup |
629 | | #define bfd_elf32_bfd_reloc_name_lookup z80_reloc_name_lookup |
630 | | #define bfd_elf32_bfd_is_local_label_name z80_is_local_label_name |
631 | | |
632 | | #include "elf32-target.h" |