1 /* Zilog (e)Z80-specific support for 32-bit ELF
2 Copyright (C) 1999-2024 Free Software Foundation, Inc.
3 (Heavily copied from the S12Z port by Sergey Belyashov (sergey.belyashov@gmail.com))
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
30 /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
31 #define OCTETS_PER_BYTE(ABFD, SEC) 1
33 typedef const struct {
34 bfd_reloc_code_real_type r_type
;
35 reloc_howto_type howto
;
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)}
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
);
47 bfd_howto_type elf_z80_howto_table
[] =
49 /* This reloc does nothing. */
50 BFD_HOWTO (BFD_RELOC_NONE
,
51 R_Z80_NONE
, /* type */
55 false, /* pc_relative */
57 complain_overflow_dont
,/* complain_on_overflow */
58 bfd_elf_generic_reloc
, /* special_function */
60 false, /* partial_inplace */
63 false), /* pcrel_offset */
65 /* A 8 bit relocation */
66 BFD_HOWTO (BFD_RELOC_8
,
71 false, /* pc_relative */
73 complain_overflow_bitfield
, /* complain_on_overflow */
74 bfd_elf_generic_reloc
, /* special_function */
76 false, /* partial_inplace */
79 false), /* pcrel_offset */
81 /* A 8 bit index register displacement relocation */
82 BFD_HOWTO (BFD_RELOC_Z80_DISP8
,
83 R_Z80_8_DIS
, /* type */
87 false, /* pc_relative */
89 complain_overflow_signed
, /* complain_on_overflow */
90 bfd_elf_generic_reloc
, /* special_function */
92 false, /* partial_inplace */
95 false), /* pcrel_offset */
97 /* A 8 bit PC-rel relocation */
98 BFD_HOWTO (BFD_RELOC_8_PCREL
,
99 R_Z80_8_PCREL
, /* type */
103 true, /* pc_relative */
105 complain_overflow_signed
, /* complain_on_overflow */
106 bfd_elf_generic_reloc
, /* special_function */
108 false, /* partial_inplace */
111 true), /* pcrel_offset */
113 /* An 16 bit absolute relocation */
114 BFD_HOWTO (BFD_RELOC_16
,
119 false, /* pc_relative */
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 */
129 /* A 24 bit absolute relocation emitted by ADL mode operands */
130 BFD_HOWTO (BFD_RELOC_24
,
135 false, /* pc_relative */
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 */
145 BFD_HOWTO (BFD_RELOC_32
,
150 false, /* pc_relative */
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 */
160 /* First (lowest) 8 bits of multibyte relocation */
161 BFD_HOWTO (BFD_RELOC_Z80_BYTE0
,
162 R_Z80_BYTE0
, /* type */
166 false, /* pc_relative */
168 complain_overflow_dont
,/* complain_on_overflow */
169 bfd_elf_generic_reloc
, /* special_function */
170 "r_byte0", /* name */
171 false, /* partial_inplace */
174 false), /* pcrel_offset */
176 /* Second 8 bits of multibyte relocation */
177 BFD_HOWTO (BFD_RELOC_Z80_BYTE1
,
178 R_Z80_BYTE1
, /* type */
182 false, /* pc_relative */
184 complain_overflow_dont
,/* complain_on_overflow */
185 bfd_elf_generic_reloc
, /* special_function */
186 "r_byte1", /* name */
187 false, /* partial_inplace */
190 false), /* pcrel_offset */
192 /* Third 8 bits of multibyte relocation */
193 BFD_HOWTO (BFD_RELOC_Z80_BYTE2
,
194 R_Z80_BYTE2
, /* type */
198 false, /* pc_relative */
200 complain_overflow_dont
,/* complain_on_overflow */
201 bfd_elf_generic_reloc
, /* special_function */
202 "r_byte2", /* name */
203 false, /* partial_inplace */
206 false), /* pcrel_offset */
208 /* Fourth (highest) 8 bits of multibyte relocation */
209 BFD_HOWTO (BFD_RELOC_Z80_BYTE3
,
210 R_Z80_BYTE3
, /* type */
214 false, /* pc_relative */
216 complain_overflow_dont
,/* complain_on_overflow */
217 bfd_elf_generic_reloc
, /* special_function */
218 "r_byte3", /* name */
219 false, /* partial_inplace */
222 false), /* pcrel_offset */
224 /* An 16 bit absolute relocation of lower word of multibyte value */
225 BFD_HOWTO (BFD_RELOC_Z80_WORD0
,
226 R_Z80_WORD0
, /* type */
230 false, /* pc_relative */
232 complain_overflow_dont
,/* complain_on_overflow */
233 bfd_elf_generic_reloc
, /* special_function */
234 "r_word0", /* name */
235 false, /* partial_inplace */
237 0xffff, /* dst_mask */
238 false), /* pcrel_offset */
240 /* An 16 bit absolute relocation of higher word of multibyte value */
241 BFD_HOWTO (BFD_RELOC_Z80_WORD1
,
242 R_Z80_WORD1
, /* type */
246 false, /* pc_relative */
248 complain_overflow_dont
,/* complain_on_overflow */
249 bfd_elf_generic_reloc
, /* special_function */
250 "r_word1", /* name */
251 false, /* partial_inplace */
253 0xffff, /* dst_mask */
254 false), /* pcrel_offset */
256 /* An 16 bit big endian absolute relocation */
257 BFD_HOWTO (BFD_RELOC_Z80_16_BE
,
258 R_Z80_16_BE
, /* type */
262 false, /* pc_relative */
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 */
273 static reloc_howto_type
*
274 z80_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
275 bfd_reloc_code_real_type code
)
279 table_size
= sizeof (elf_z80_howto_table
) / sizeof (elf_z80_howto_table
[0])
283 for (i
= 0; i
< table_size
; i
++)
285 if (elf_z80_howto_table
[i
].r_type
== code
)
286 return &elf_z80_howto_table
[i
].howto
;
289 printf ("%s:%d Not found BFD reloc type %d\n", __FILE__
, __LINE__
, code
);
294 static reloc_howto_type
*
295 z80_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
299 table_size
= sizeof (elf_z80_howto_table
) / sizeof (elf_z80_howto_table
[0])
303 for (i
= 0; i
< table_size
; i
++)
305 if (elf_z80_howto_table
[i
].howto
.name
!= NULL
306 && strcasecmp (elf_z80_howto_table
[i
].howto
.name
, r_name
) == 0)
307 return &elf_z80_howto_table
[i
].howto
;
310 printf ("%s:%d Not found ELF reloc name `%s'\n", __FILE__
, __LINE__
, r_name
);
315 static reloc_howto_type
*
316 z80_rtype_to_howto (bfd
*abfd
, unsigned r_type
)
320 table_size
= sizeof (elf_z80_howto_table
) / sizeof (elf_z80_howto_table
[0])
324 for (i
= 0; i
< table_size
; i
++)
326 if (elf_z80_howto_table
[i
].howto
.type
== r_type
)
327 return &elf_z80_howto_table
[i
].howto
;
330 /* xgettext:c-format */
331 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
336 /* Set the howto pointer for an z80 ELF reloc. */
339 z80_info_to_howto_rela (bfd
*abfd
, arelent
*cache_ptr
, Elf_Internal_Rela
*dst
)
341 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
342 reloc_howto_type
*howto
= z80_rtype_to_howto (abfd
, r_type
);
345 cache_ptr
->howto
= howto
;
348 bfd_set_error (bfd_error_bad_value
);
352 static bfd_reloc_status_type
353 z80_elf_final_link_relocate (unsigned long r_type
,
355 bfd
*output_bfd ATTRIBUTE_UNUSED
,
356 asection
*input_section ATTRIBUTE_UNUSED
,
361 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
362 asection
*sym_sec ATTRIBUTE_UNUSED
,
363 int is_local ATTRIBUTE_UNUSED
)
366 reloc_howto_type
*howto
;
372 bfd_put_8 (input_bfd
, value
>> 8, contents
+ offset
+ 0);
373 bfd_put_8 (input_bfd
, value
>> 0, contents
+ offset
+ 1);
377 howto
= z80_rtype_to_howto (input_bfd
, r_type
);
379 return bfd_reloc_notsupported
;
381 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
, contents
,
382 offset
, value
, addend
);
383 return r
? bfd_reloc_ok
: bfd_reloc_notsupported
;
387 z80_elf_relocate_section (bfd
*output_bfd
,
388 struct bfd_link_info
*info
,
390 asection
*input_section
,
392 Elf_Internal_Rela
*relocs
,
393 Elf_Internal_Sym
*local_syms
,
394 asection
**local_sections
)
396 Elf_Internal_Shdr
*symtab_hdr
;
397 struct elf_link_hash_entry
**sym_hashes
;
398 Elf_Internal_Rela
*rel
, *relend
;
400 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
401 sym_hashes
= elf_sym_hashes (input_bfd
);
404 relend
= relocs
+ input_section
->reloc_count
;
405 for (; rel
< relend
; rel
++)
408 unsigned long r_symndx
;
409 Elf_Internal_Sym
*sym
;
411 struct elf_link_hash_entry
*h
;
414 /* This is a final link. */
415 r_symndx
= ELF32_R_SYM (rel
->r_info
);
416 r_type
= ELF32_R_TYPE (rel
->r_info
);
420 if (r_symndx
< symtab_hdr
->sh_info
)
422 sym
= local_syms
+ r_symndx
;
423 sec
= local_sections
[r_symndx
];
424 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
428 bool unresolved_reloc
, warned
, ignored
;
430 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
431 r_symndx
, symtab_hdr
, sym_hashes
,
433 unresolved_reloc
, warned
, ignored
);
436 if (sec
!= NULL
&& discarded_section (sec
))
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 reloc_howto_type
*howto
;
442 howto
= z80_rtype_to_howto (input_bfd
, r_type
);
443 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
444 rel
, 1, relend
, howto
, 0, contents
);
447 if (bfd_link_relocatable (info
))
451 z80_elf_final_link_relocate (r_type
, input_bfd
, output_bfd
,
453 contents
, rel
->r_offset
,
454 relocation
, rel
->r_addend
,
455 info
, sec
, h
== NULL
);
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
466 z80_elf_final_write_processing (bfd
*abfd
)
468 unsigned long val
= bfd_get_mach (abfd
);
473 _bfd_error_handler (_("%pB: unsupported bfd mach %#lx"),
477 case bfd_mach_z80full
:
478 case bfd_mach_z80strict
:
479 val
= EF_Z80_MACH_Z80
;
482 val
= EF_Z80_MACH_GBZ80
;
485 val
= EF_Z80_MACH_Z80N
;
488 val
= EF_Z80_MACH_Z180
;
490 case bfd_mach_ez80_z80
:
491 val
= EF_Z80_MACH_EZ80_Z80
;
493 case bfd_mach_ez80_adl
:
494 val
= EF_Z80_MACH_EZ80_ADL
;
497 val
= EF_Z80_MACH_R800
;
500 elf_elfheader (abfd
)->e_machine
= EM_Z80
;
501 elf_elfheader (abfd
)->e_flags
&= ~EF_Z80_MACH_MSK
;
502 elf_elfheader (abfd
)->e_flags
|= val
;
503 return _bfd_elf_final_write_processing (abfd
);
506 /* Set the right machine number. */
508 z80_elf_object_p (bfd
*abfd
)
512 if (elf_elfheader (abfd
)->e_machine
== EM_Z80
)
514 int e_mach
= elf_elfheader (abfd
)->e_flags
& EF_Z80_MACH_MSK
;
518 _bfd_error_handler (_("%pB: unsupported mach %#x"),
521 case EF_Z80_MACH_Z80
:
524 case EF_Z80_MACH_GBZ80
:
525 mach
= bfd_mach_gbz80
;
527 case EF_Z80_MACH_Z180
:
528 mach
= bfd_mach_z180
;
530 case EF_Z80_MACH_EZ80_Z80
:
531 mach
= bfd_mach_ez80_z80
;
533 case EF_Z80_MACH_EZ80_ADL
:
534 mach
= bfd_mach_ez80_adl
;
536 case EF_Z80_MACH_R800
:
537 mach
= bfd_mach_r800
;
539 case EF_Z80_MACH_Z80N
:
540 mach
= bfd_mach_z80n
;
546 _bfd_error_handler (_("%pB: unsupported arch %#x"),
547 abfd
, elf_elfheader (abfd
)->e_machine
);
550 return bfd_default_set_arch_mach (abfd
, bfd_arch_z80
, mach
);
554 z80_is_local_label_name (bfd
* abfd ATTRIBUTE_UNUSED
,
557 return (name
[0] == '.' && name
[1] == 'L') ||
558 _bfd_elf_is_local_label_name (abfd
, name
);
561 static bfd_reloc_status_type
562 z80_elf_16_be_reloc (bfd
*abfd
,
563 arelent
*reloc_entry
,
566 asection
*input_section
,
568 char **error_message
)
572 bfd_size_type octets
= (reloc_entry
->address
573 * OCTETS_PER_BYTE (abfd
, input_section
));
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
578 if (output_bfd
!= NULL
)
579 return bfd_elf_generic_reloc (abfd
, reloc_entry
, symbol
, data
,
580 input_section
, output_bfd
, error_message
);
582 /* Get symbol value. */
584 if (!bfd_is_com_section (symbol
->section
))
586 val
+= symbol
->section
->output_offset
+ input_section
->output_offset
;
587 if (symbol
->section
->output_section
)
588 val
+= symbol
->section
->output_section
->vma
;
590 val
+= reloc_entry
->addend
;
591 if (reloc_entry
->howto
->partial_inplace
)
593 x
= bfd_get_8 (abfd
, (bfd_byte
*) data
+ octets
+ 0) * 0x100;
594 x
+= bfd_get_8 (abfd
, (bfd_byte
*) data
+ octets
+ 1);
595 x
&= ~reloc_entry
->howto
->src_mask
;
600 x
|= val
& reloc_entry
->howto
->dst_mask
;
601 if (x
< -0x8000 || x
>= 0x10000)
602 return bfd_reloc_outofrange
;
604 bfd_put_8 (abfd
, x
>> 8, (bfd_byte
*) data
+ octets
+ 0);
605 bfd_put_8 (abfd
, x
>> 0, (bfd_byte
*) data
+ octets
+ 1);
609 #define ELF_ARCH bfd_arch_z80
610 #define ELF_MACHINE_CODE EM_Z80
611 #define ELF_MAXPAGESIZE 0x10000
613 #define TARGET_LITTLE_SYM z80_elf32_vec
614 #define TARGET_LITTLE_NAME "elf32-z80"
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
621 #define elf_info_to_howto z80_info_to_howto_rela
622 #define elf_info_to_howto_rel z80_info_to_howto_rela
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
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
632 #include "elf32-target.h"