]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/coff-z80.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / coff-z80.c
CommitLineData
3c9b82ba 1/* BFD back-end for Zilog Z80 COFF binaries.
a2c58332 2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
3c9b82ba
NC
3 Contributed by Arnold Metselaar <arnold_m@operamail.com>
4
5 This file is part of BFD, the Binary File Descriptor library.
6
68ffbac6 7 This program is free software; you can redistribute it and/or modify
3c9b82ba 8 it under the terms of the GNU General Public License as published by
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
3c9b82ba
NC
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
3c9b82ba 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
3c9b82ba
NC
24#include "libbfd.h"
25#include "bfdlink.h"
26#include "coff/z80.h"
27#include "coff/internal.h"
28#include "libcoff.h"
6655dba2 29#include "libiberty.h"
3c9b82ba
NC
30
31#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
32
bd38246a 33typedef const struct {
6655dba2
SB
34 bfd_reloc_code_real_type r_type;
35 reloc_howto_type howto;
36} bfd_howto_type;
3c9b82ba 37
6655dba2
SB
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)}
3c9b82ba 40
6655dba2
SB
41static bfd_howto_type howto_table[] =
42{
43 BFD_EMPTY_HOWTO (BFD_RELOC_NONE, 0),
44
45 BFD_HOWTO (BFD_RELOC_32,
46 R_IMM32, /* type */
47 0, /* rightshift */
48 2, /* size (0 = byte, 1 = short, 2 = long) */
49 32, /* bitsize */
0a1b45a2 50 false, /* pc_relative */
6655dba2
SB
51 0, /* bitpos */
52 complain_overflow_bitfield, /* complain_on_overflow */
53 0, /* special_function */
54 "r_imm32", /* name */
0a1b45a2 55 false, /* partial_inplace */
6655dba2
SB
56 0xffffffff, /* src_mask */
57 0xffffffff, /* dst_mask */
0a1b45a2 58 false), /* pcrel_offset */
6655dba2
SB
59
60 BFD_HOWTO (BFD_RELOC_24,
61 R_IMM24, /* type */
62 0, /* rightshift */
63 1, /* size (0 = byte, 1 = short, 2 = long) */
64 24, /* bitsize */
0a1b45a2 65 false, /* pc_relative */
6655dba2
SB
66 0, /* bitpos */
67 complain_overflow_bitfield, /* complain_on_overflow */
68 0, /* special_function */
69 "r_imm24", /* name */
0a1b45a2 70 false, /* partial_inplace */
6655dba2
SB
71 0x00ffffff, /* src_mask */
72 0x00ffffff, /* dst_mask */
0a1b45a2 73 false), /* pcrel_offset */
6655dba2
SB
74
75 BFD_HOWTO (BFD_RELOC_16,
76 R_IMM16, /* type */
77 0, /* rightshift */
78 1, /* size (0 = byte, 1 = short, 2 = long) */
79 16, /* bitsize */
0a1b45a2 80 false, /* pc_relative */
6655dba2
SB
81 0, /* bitpos */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 0, /* special_function */
84 "r_imm16", /* name */
0a1b45a2 85 false, /* partial_inplace */
6655dba2
SB
86 0x0000ffff, /* src_mask */
87 0x0000ffff, /* dst_mask */
0a1b45a2 88 false), /* pcrel_offset */
6655dba2
SB
89
90 BFD_HOWTO (BFD_RELOC_8,
91 R_IMM8, /* type */
92 0, /* rightshift */
93 0, /* size (0 = byte, 1 = short, 2 = long) */
94 8, /* bitsize */
0a1b45a2 95 false, /* pc_relative */
6655dba2
SB
96 0, /* bitpos */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 0, /* special_function */
99 "r_imm8", /* name */
0a1b45a2 100 false, /* partial_inplace */
6655dba2
SB
101 0x000000ff, /* src_mask */
102 0x000000ff, /* dst_mask */
0a1b45a2 103 false), /* pcrel_offset */
6655dba2
SB
104
105 BFD_HOWTO (BFD_RELOC_8_PCREL,
106 R_JR, /* type */
107 0, /* rightshift */
108 0, /* size (0 = byte, 1 = short, 2 = long) */
109 8, /* bitsize */
0a1b45a2 110 true, /* pc_relative */
6655dba2
SB
111 0, /* bitpos */
112 complain_overflow_signed, /* complain_on_overflow */
113 0, /* special_function */
114 "r_jr", /* name */
0a1b45a2 115 false, /* partial_inplace */
6655dba2
SB
116 0, /* src_mask */
117 0xFF, /* dst_mask */
0a1b45a2 118 true), /* pcrel_offset */
6655dba2
SB
119
120 BFD_HOWTO (BFD_RELOC_Z80_DISP8,
121 R_OFF8, /* type */
122 0, /* rightshift */
123 0, /* size (0 = byte, 1 = short, 2 = long) */
124 8, /* bitsize */
0a1b45a2 125 false, /* pc_relative */
6655dba2
SB
126 0, /* bitpos */
127 complain_overflow_signed, /* complain_on_overflow */
128 0, /* special_function */
129 "r_off8", /* name */
0a1b45a2 130 false, /* partial_inplace */
6655dba2
SB
131 0, /* src_mask */
132 0xff, /* dst_mask */
0a1b45a2 133 false), /* pcrel_offset */
6655dba2
SB
134
135 BFD_HOWTO (BFD_RELOC_Z80_BYTE0,
136 R_BYTE0, /* type */
137 0, /* rightshift */
138 0, /* size (0 = byte, 1 = short, 2 = long) */
139 8, /* bitsize */
0a1b45a2 140 false, /* pc_relative */
6655dba2
SB
141 0, /* bitpos */
142 complain_overflow_dont, /* complain_on_overflow */
143 0, /* special_function */
144 "r_byte0", /* name */
0a1b45a2 145 false, /* partial_inplace */
6655dba2
SB
146 0, /* src_mask */
147 0xff, /* dst_mask */
0a1b45a2 148 false), /* pcrel_offset */
6655dba2
SB
149
150 BFD_HOWTO (BFD_RELOC_Z80_BYTE1,
151 R_BYTE1, /* type */
152 8, /* rightshift */
153 0, /* size (0 = byte, 1 = short, 2 = long) */
154 8, /* bitsize */
0a1b45a2 155 false, /* pc_relative */
6655dba2
SB
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 0, /* special_function */
159 "r_byte1", /* name */
0a1b45a2 160 false, /* partial_inplace */
6655dba2
SB
161 0, /* src_mask */
162 0xff, /* dst_mask */
0a1b45a2 163 false), /* pcrel_offset */
6655dba2
SB
164
165 BFD_HOWTO (BFD_RELOC_Z80_BYTE2,
166 R_BYTE2, /* type */
167 16, /* rightshift */
168 0, /* size (0 = byte, 1 = short, 2 = long) */
169 8, /* bitsize */
0a1b45a2 170 false, /* pc_relative */
6655dba2
SB
171 0, /* bitpos */
172 complain_overflow_dont, /* complain_on_overflow */
173 0, /* special_function */
174 "r_byte2", /* name */
0a1b45a2 175 false, /* partial_inplace */
6655dba2
SB
176 0, /* src_mask */
177 0xff, /* dst_mask */
0a1b45a2 178 false), /* pcrel_offset */
6655dba2
SB
179
180 BFD_HOWTO (BFD_RELOC_Z80_BYTE3,
181 R_BYTE3, /* type */
182 24, /* rightshift */
183 0, /* size (0 = byte, 1 = short, 2 = long) */
184 8, /* bitsize */
0a1b45a2 185 false, /* pc_relative */
6655dba2
SB
186 0, /* bitpos */
187 complain_overflow_dont, /* complain_on_overflow */
188 0, /* special_function */
189 "r_byte3", /* name */
0a1b45a2 190 false, /* partial_inplace */
6655dba2
SB
191 0, /* src_mask */
192 0xff, /* dst_mask */
0a1b45a2 193 false), /* pcrel_offset */
6655dba2
SB
194
195 BFD_HOWTO (BFD_RELOC_Z80_WORD0,
196 R_WORD0, /* type */
197 0, /* rightshift */
198 0, /* size (0 = byte, 1 = short, 2 = long) */
199 16, /* bitsize */
0a1b45a2 200 false, /* pc_relative */
6655dba2
SB
201 0, /* bitpos */
202 complain_overflow_dont, /* complain_on_overflow */
203 0, /* special_function */
204 "r_word0", /* name */
0a1b45a2 205 false, /* partial_inplace */
6655dba2
SB
206 0, /* src_mask */
207 0xffff, /* dst_mask */
0a1b45a2 208 false), /* pcrel_offset */
6655dba2
SB
209
210 BFD_HOWTO (BFD_RELOC_Z80_WORD1,
211 R_WORD1, /* type */
212 16, /* rightshift */
213 0, /* size (0 = byte, 1 = short, 2 = long) */
214 16, /* bitsize */
0a1b45a2 215 false, /* pc_relative */
6655dba2
SB
216 0, /* bitpos */
217 complain_overflow_dont, /* complain_on_overflow */
218 0, /* special_function */
219 "r_word1", /* name */
0a1b45a2 220 false, /* partial_inplace */
6655dba2
SB
221 0, /* src_mask */
222 0xffff, /* dst_mask */
0a1b45a2 223 false), /* pcrel_offset */
9fc0b501
SB
224
225 BFD_HOWTO (BFD_RELOC_Z80_16_BE,
226 R_IMM16BE, /* type */
227 0, /* rightshift */
228 1, /* size (0 = byte, 1 = short, 2 = long) */
229 16, /* bitsize */
0a1b45a2 230 false, /* pc_relative */
9fc0b501
SB
231 0, /* bitpos */
232 complain_overflow_bitfield, /* complain_on_overflow */
233 0, /* special_function */
234 "r_imm16be", /* name */
0a1b45a2 235 false, /* partial_inplace */
9fc0b501
SB
236 0x0000ffff, /* src_mask */
237 0x0000ffff, /* dst_mask */
0a1b45a2 238 false), /* pcrel_offset */
6655dba2
SB
239};
240
241#define NUM_HOWTOS ARRAY_SIZE (howto_table)
3c9b82ba
NC
242
243#define BADMAG(x) Z80BADMAG(x)
244#define Z80 1 /* Customize coffcode.h. */
245#define __A_MAGIC_SET__
246
247/* Code to swap in the reloc. */
248
249#define SWAP_IN_RELOC_OFFSET H_GET_32
250#define SWAP_OUT_RELOC_OFFSET H_PUT_32
251
252#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
253 dst->r_stuff[0] = 'S'; \
254 dst->r_stuff[1] = 'C';
255
256/* Code to turn a r_type into a howto ptr, uses the above howto table. */
3c9b82ba
NC
257static void
258rtype2howto (arelent *internal, struct internal_reloc *dst)
259{
6655dba2
SB
260 unsigned i;
261 for (i = 0; i < NUM_HOWTOS; i++)
3c9b82ba 262 {
6655dba2
SB
263 if (howto_table[i].howto.type == dst->r_type)
264 {
265 internal->howto = &howto_table[i].howto;
266 return;
267 }
3c9b82ba 268 }
6655dba2 269 internal->howto = NULL;
3c9b82ba
NC
270}
271
272#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
273
274static reloc_howto_type *
275coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
276 bfd_reloc_code_real_type code)
277{
6655dba2
SB
278 unsigned i;
279 for (i = 0; i < NUM_HOWTOS; i++)
280 if (howto_table[i].r_type == code)
281 return &howto_table[i].howto;
282
283 BFD_FAIL ();
284 return NULL;
3c9b82ba
NC
285}
286
157090f7
AM
287static reloc_howto_type *
288coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
289 const char *r_name)
290{
6655dba2
SB
291 unsigned i;
292 for (i = 0; i < NUM_HOWTOS; i++)
293 if (strcasecmp(howto_table[i].howto.name, r_name) == 0)
294 return &howto_table[i].howto;
157090f7
AM
295
296 return NULL;
297}
298
3c9b82ba
NC
299/* Perform any necessary magic to the addend in a reloc entry. */
300
301#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
302 cache_ptr->addend = ext_reloc.r_offset;
303
304#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
305 reloc_processing(relent, reloc, symbols, abfd, section)
306
307static void
308reloc_processing (arelent *relent,
07d6d2b8
AM
309 struct internal_reloc *reloc,
310 asymbol **symbols,
311 bfd *abfd,
312 asection *section)
3c9b82ba
NC
313{
314 relent->address = reloc->r_vaddr;
315 rtype2howto (relent, reloc);
316
e039f7ed
AM
317 if (reloc->r_symndx == -1)
318 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
319 else if (reloc->r_symndx >= 0 && reloc->r_symndx < obj_conv_table_size (abfd))
3c9b82ba
NC
320 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
321 else
e039f7ed
AM
322 {
323 _bfd_error_handler
324 /* xgettext:c-format */
325 (_("%pB: warning: illegal symbol index %ld in relocs"),
326 abfd, reloc->r_symndx);
327 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
328 }
3c9b82ba
NC
329 relent->addend = reloc->r_offset;
330 relent->address -= section->vma;
331}
332
333static void
334extra_case (bfd *in_abfd,
07d6d2b8
AM
335 struct bfd_link_info *link_info,
336 struct bfd_link_order *link_order,
337 arelent *reloc,
338 bfd_byte *data,
339 unsigned int *src_ptr,
340 unsigned int *dst_ptr)
3c9b82ba
NC
341{
342 asection * input_section = link_order->u.indirect.section;
6655dba2 343 int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
3c9b82ba
NC
344
345 switch (reloc->howto->type)
346 {
347 case R_OFF8:
6655dba2
SB
348 if (reloc->howto->partial_inplace)
349 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
350 & reloc->howto->src_mask);
351 if (val>127 || val<-128) /* Test for overflow. */
1a72702b
AM
352 (*link_info->callbacks->reloc_overflow)
353 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
354 reloc->howto->name, reloc->addend, input_section->owner,
355 input_section, reloc->address);
356
3c9b82ba
NC
357 bfd_put_8 (in_abfd, val, data + *dst_ptr);
358 (*dst_ptr) += 1;
359 (*src_ptr) += 1;
360 break;
361
6655dba2
SB
362 case R_BYTE3:
363 bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
364 (*dst_ptr) += 1;
365 (*src_ptr) += 1;
366 break;
367
368 case R_BYTE2:
369 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
370 (*dst_ptr) += 1;
371 (*src_ptr) += 1;
372 break;
373
374 case R_BYTE1:
375 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
376 (*dst_ptr) += 1;
377 (*src_ptr) += 1;
378 break;
379
3c9b82ba 380 case R_IMM8:
6655dba2
SB
381 if (reloc->howto->partial_inplace)
382 val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
279edac5 383 /* Fall through. */
6655dba2 384 case R_BYTE0:
3c9b82ba
NC
385 bfd_put_8 (in_abfd, val, data + *dst_ptr);
386 (*dst_ptr) += 1;
387 (*src_ptr) += 1;
388 break;
389
6655dba2
SB
390 case R_WORD1:
391 bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
392 (*dst_ptr) += 2;
393 (*src_ptr) += 2;
394 break;
395
3c9b82ba 396 case R_IMM16:
6655dba2
SB
397 if (reloc->howto->partial_inplace)
398 val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
279edac5 399 /* Fall through. */
6655dba2 400 case R_WORD0:
3c9b82ba
NC
401 bfd_put_16 (in_abfd, val, data + *dst_ptr);
402 (*dst_ptr) += 2;
403 (*src_ptr) += 2;
404 break;
405
134dcee5 406 case R_IMM24:
6655dba2
SB
407 if (reloc->howto->partial_inplace)
408 val += (bfd_get_16 ( in_abfd, data+*src_ptr)
409 + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16))
410 & reloc->howto->src_mask;
134dcee5
AM
411 bfd_put_16 (in_abfd, val, data + *dst_ptr);
412 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
413 (*dst_ptr) += 3;
414 (*src_ptr) += 3;
415 break;
416
3c9b82ba 417 case R_IMM32:
6655dba2
SB
418 if (reloc->howto->partial_inplace)
419 val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
3c9b82ba
NC
420 bfd_put_32 (in_abfd, val, data + *dst_ptr);
421 (*dst_ptr) += 4;
422 (*src_ptr) += 4;
423 break;
424
425 case R_JR:
426 {
6655dba2
SB
427 if (reloc->howto->partial_inplace)
428 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
429 & reloc->howto->src_mask);
44da2da1
AM
430 bfd_vma dot = (*dst_ptr
431 + input_section->output_offset
3c9b82ba 432 + input_section->output_section->vma);
6655dba2 433 int gap = val - dot;
3c9b82ba 434 if (gap >= 128 || gap < -128)
1a72702b
AM
435 (*link_info->callbacks->reloc_overflow)
436 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
437 reloc->howto->name, reloc->addend, input_section->owner,
438 input_section, reloc->address);
439
3c9b82ba
NC
440 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
441 (*dst_ptr)++;
442 (*src_ptr)++;
443 break;
444 }
445
9fc0b501
SB
446 case R_IMM16BE:
447 if (reloc->howto->partial_inplace)
448 val += (bfd_get_8 ( in_abfd, data+*src_ptr+0) * 0x100 +
449 bfd_get_8 ( in_abfd, data+*src_ptr+1)) & reloc->howto->src_mask;
450
451 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr+0);
452 bfd_put_8 (in_abfd, val, data + *dst_ptr+1);
453 (*dst_ptr) += 2;
454 (*src_ptr) += 2;
455 break;
456
3c9b82ba
NC
457 default:
458 abort ();
459 }
460}
461
0a1b45a2 462static bool
6655dba2
SB
463z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
464 const char * name)
465{
466 return (name[0] == '.' && name[1] == 'L') ||
467 _bfd_coff_is_local_label_name (abfd, name);
468}
469
470#define coff_bfd_is_local_label_name z80_is_local_label_name
471
3c9b82ba
NC
472#define coff_reloc16_extra_cases extra_case
473#define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
157090f7 474#define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
3c9b82ba 475
2b5c217d
NC
476#ifndef bfd_pe_print_pdata
477#define bfd_pe_print_pdata NULL
478#endif
479
3c9b82ba
NC
480#include "coffcode.h"
481
482#undef coff_bfd_get_relocated_section_contents
483#define coff_bfd_get_relocated_section_contents \
484 bfd_coff_reloc16_get_relocated_section_contents
485
486#undef coff_bfd_relax_section
487#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
488
6d00b590 489CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
68ffbac6 490 SEC_CODE | SEC_DATA, '\0', NULL,
3c9b82ba
NC
491 COFF_SWAP_TABLE)
492