1 /* BFD back-end for Zilog Z80 COFF binaries.
2 Copyright (C) 2005-2020 Free Software Foundation, Inc.
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. */
27 #include "coff/internal.h"
29 #include "libiberty.h"
31 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
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_howto_type howto_table[] =
43 BFD_EMPTY_HOWTO (BFD_RELOC_NONE, 0),
45 BFD_HOWTO (BFD_RELOC_32,
48 2, /* size (0 = byte, 1 = short, 2 = long) */
50 FALSE, /* pc_relative */
52 complain_overflow_bitfield, /* complain_on_overflow */
53 0, /* special_function */
55 FALSE, /* partial_inplace */
56 0xffffffff, /* src_mask */
57 0xffffffff, /* dst_mask */
58 FALSE), /* pcrel_offset */
60 BFD_HOWTO (BFD_RELOC_24,
63 1, /* size (0 = byte, 1 = short, 2 = long) */
65 FALSE, /* pc_relative */
67 complain_overflow_bitfield, /* complain_on_overflow */
68 0, /* special_function */
70 FALSE, /* partial_inplace */
71 0x00ffffff, /* src_mask */
72 0x00ffffff, /* dst_mask */
73 FALSE), /* pcrel_offset */
75 BFD_HOWTO (BFD_RELOC_16,
78 1, /* size (0 = byte, 1 = short, 2 = long) */
80 FALSE, /* pc_relative */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 0, /* special_function */
85 FALSE, /* partial_inplace */
86 0x0000ffff, /* src_mask */
87 0x0000ffff, /* dst_mask */
88 FALSE), /* pcrel_offset */
90 BFD_HOWTO (BFD_RELOC_8,
93 0, /* size (0 = byte, 1 = short, 2 = long) */
95 FALSE, /* pc_relative */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 0, /* special_function */
100 FALSE, /* partial_inplace */
101 0x000000ff, /* src_mask */
102 0x000000ff, /* dst_mask */
103 FALSE), /* pcrel_offset */
105 BFD_HOWTO (BFD_RELOC_8_PCREL,
108 0, /* size (0 = byte, 1 = short, 2 = long) */
110 TRUE, /* pc_relative */
112 complain_overflow_signed, /* complain_on_overflow */
113 0, /* special_function */
115 FALSE, /* partial_inplace */
118 TRUE), /* pcrel_offset */
120 BFD_HOWTO (BFD_RELOC_Z80_DISP8,
123 0, /* size (0 = byte, 1 = short, 2 = long) */
125 FALSE, /* pc_relative */
127 complain_overflow_signed, /* complain_on_overflow */
128 0, /* special_function */
130 FALSE, /* partial_inplace */
133 FALSE), /* pcrel_offset */
135 BFD_HOWTO (BFD_RELOC_Z80_BYTE0,
138 0, /* size (0 = byte, 1 = short, 2 = long) */
140 FALSE, /* pc_relative */
142 complain_overflow_dont, /* complain_on_overflow */
143 0, /* special_function */
144 "r_byte0", /* name */
145 FALSE, /* partial_inplace */
148 FALSE), /* pcrel_offset */
150 BFD_HOWTO (BFD_RELOC_Z80_BYTE1,
153 0, /* size (0 = byte, 1 = short, 2 = long) */
155 FALSE, /* pc_relative */
157 complain_overflow_dont, /* complain_on_overflow */
158 0, /* special_function */
159 "r_byte1", /* name */
160 FALSE, /* partial_inplace */
163 FALSE), /* pcrel_offset */
165 BFD_HOWTO (BFD_RELOC_Z80_BYTE2,
168 0, /* size (0 = byte, 1 = short, 2 = long) */
170 FALSE, /* pc_relative */
172 complain_overflow_dont, /* complain_on_overflow */
173 0, /* special_function */
174 "r_byte2", /* name */
175 FALSE, /* partial_inplace */
178 FALSE), /* pcrel_offset */
180 BFD_HOWTO (BFD_RELOC_Z80_BYTE3,
183 0, /* size (0 = byte, 1 = short, 2 = long) */
185 FALSE, /* pc_relative */
187 complain_overflow_dont, /* complain_on_overflow */
188 0, /* special_function */
189 "r_byte3", /* name */
190 FALSE, /* partial_inplace */
193 FALSE), /* pcrel_offset */
195 BFD_HOWTO (BFD_RELOC_Z80_WORD0,
198 0, /* size (0 = byte, 1 = short, 2 = long) */
200 FALSE, /* pc_relative */
202 complain_overflow_dont, /* complain_on_overflow */
203 0, /* special_function */
204 "r_word0", /* name */
205 FALSE, /* partial_inplace */
207 0xffff, /* dst_mask */
208 FALSE), /* pcrel_offset */
210 BFD_HOWTO (BFD_RELOC_Z80_WORD1,
213 0, /* size (0 = byte, 1 = short, 2 = long) */
215 FALSE, /* pc_relative */
217 complain_overflow_dont, /* complain_on_overflow */
218 0, /* special_function */
219 "r_word1", /* name */
220 FALSE, /* partial_inplace */
222 0xffff, /* dst_mask */
223 FALSE), /* pcrel_offset */
226 #define NUM_HOWTOS ARRAY_SIZE (howto_table)
228 #define BADMAG(x) Z80BADMAG(x)
229 #define Z80 1 /* Customize coffcode.h. */
230 #define __A_MAGIC_SET__
232 /* Code to swap in the reloc. */
234 #define SWAP_IN_RELOC_OFFSET H_GET_32
235 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
237 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
238 dst->r_stuff[0] = 'S'; \
239 dst->r_stuff[1] = 'C';
241 /* Code to turn a r_type into a howto ptr, uses the above howto table. */
243 rtype2howto (arelent *internal, struct internal_reloc *dst)
246 for (i = 0; i < NUM_HOWTOS; i++)
248 if (howto_table[i].howto.type == dst->r_type)
250 internal->howto = &howto_table[i].howto;
254 internal->howto = NULL;
257 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
259 static reloc_howto_type *
260 coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
261 bfd_reloc_code_real_type code)
264 for (i = 0; i < NUM_HOWTOS; i++)
265 if (howto_table[i].r_type == code)
266 return &howto_table[i].howto;
272 static reloc_howto_type *
273 coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
277 for (i = 0; i < NUM_HOWTOS; i++)
278 if (strcasecmp(howto_table[i].howto.name, r_name) == 0)
279 return &howto_table[i].howto;
284 /* Perform any necessary magic to the addend in a reloc entry. */
286 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
287 cache_ptr->addend = ext_reloc.r_offset;
289 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
290 reloc_processing(relent, reloc, symbols, abfd, section)
293 reloc_processing (arelent *relent,
294 struct internal_reloc *reloc,
299 relent->address = reloc->r_vaddr;
300 rtype2howto (relent, reloc);
302 if (reloc->r_symndx > 0)
303 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
305 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
307 relent->addend = reloc->r_offset;
308 relent->address -= section->vma;
312 extra_case (bfd *in_abfd,
313 struct bfd_link_info *link_info,
314 struct bfd_link_order *link_order,
317 unsigned int *src_ptr,
318 unsigned int *dst_ptr)
320 asection * input_section = link_order->u.indirect.section;
321 int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
323 switch (reloc->howto->type)
326 if (reloc->howto->partial_inplace)
327 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
328 & reloc->howto->src_mask);
329 if (val>127 || val<-128) /* Test for overflow. */
330 (*link_info->callbacks->reloc_overflow)
331 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
332 reloc->howto->name, reloc->addend, input_section->owner,
333 input_section, reloc->address);
335 bfd_put_8 (in_abfd, val, data + *dst_ptr);
341 bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
347 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
353 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
359 if (reloc->howto->partial_inplace)
360 val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
363 bfd_put_8 (in_abfd, val, data + *dst_ptr);
369 bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
375 if (reloc->howto->partial_inplace)
376 val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
379 bfd_put_16 (in_abfd, val, data + *dst_ptr);
385 if (reloc->howto->partial_inplace)
386 val += (bfd_get_16 ( in_abfd, data+*src_ptr)
387 + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16))
388 & reloc->howto->src_mask;
389 bfd_put_16 (in_abfd, val, data + *dst_ptr);
390 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
396 if (reloc->howto->partial_inplace)
397 val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
398 bfd_put_32 (in_abfd, val, data + *dst_ptr);
405 if (reloc->howto->partial_inplace)
406 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
407 & reloc->howto->src_mask);
408 bfd_vma dot = (*dst_ptr
409 + input_section->output_offset
410 + input_section->output_section->vma);
412 if (gap >= 128 || gap < -128)
413 (*link_info->callbacks->reloc_overflow)
414 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
415 reloc->howto->name, reloc->addend, input_section->owner,
416 input_section, reloc->address);
418 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
430 z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
433 return (name[0] == '.' && name[1] == 'L') ||
434 _bfd_coff_is_local_label_name (abfd, name);
437 #define coff_bfd_is_local_label_name z80_is_local_label_name
439 #define coff_reloc16_extra_cases extra_case
440 #define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
441 #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
443 #ifndef bfd_pe_print_pdata
444 #define bfd_pe_print_pdata NULL
447 #include "coffcode.h"
449 #undef coff_bfd_get_relocated_section_contents
450 #define coff_bfd_get_relocated_section_contents \
451 bfd_coff_reloc16_get_relocated_section_contents
453 #undef coff_bfd_relax_section
454 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
456 CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
457 SEC_CODE | SEC_DATA, '\0', NULL,