gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / coff-z80.c
CommitLineData
3c9b82ba 1/* BFD back-end for Zilog Z80 COFF binaries.
b3adc24a 2 Copyright (C) 2005-2020 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
6655dba2
SB
33typedef struct {
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 */
50 FALSE, /* pc_relative */
51 0, /* bitpos */
52 complain_overflow_bitfield, /* complain_on_overflow */
53 0, /* special_function */
54 "r_imm32", /* name */
55 FALSE, /* partial_inplace */
56 0xffffffff, /* src_mask */
57 0xffffffff, /* dst_mask */
58 FALSE), /* pcrel_offset */
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 */
65 FALSE, /* pc_relative */
66 0, /* bitpos */
67 complain_overflow_bitfield, /* complain_on_overflow */
68 0, /* special_function */
69 "r_imm24", /* name */
70 FALSE, /* partial_inplace */
71 0x00ffffff, /* src_mask */
72 0x00ffffff, /* dst_mask */
73 FALSE), /* pcrel_offset */
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 */
80 FALSE, /* pc_relative */
81 0, /* bitpos */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 0, /* special_function */
84 "r_imm16", /* name */
85 FALSE, /* partial_inplace */
86 0x0000ffff, /* src_mask */
87 0x0000ffff, /* dst_mask */
88 FALSE), /* pcrel_offset */
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 */
95 FALSE, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 0, /* special_function */
99 "r_imm8", /* name */
100 FALSE, /* partial_inplace */
101 0x000000ff, /* src_mask */
102 0x000000ff, /* dst_mask */
103 FALSE), /* pcrel_offset */
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 */
110 TRUE, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_signed, /* complain_on_overflow */
113 0, /* special_function */
114 "r_jr", /* name */
115 FALSE, /* partial_inplace */
116 0, /* src_mask */
117 0xFF, /* dst_mask */
118 TRUE), /* pcrel_offset */
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 */
125 FALSE, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_signed, /* complain_on_overflow */
128 0, /* special_function */
129 "r_off8", /* name */
130 FALSE, /* partial_inplace */
131 0, /* src_mask */
132 0xff, /* dst_mask */
133 FALSE), /* pcrel_offset */
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 */
140 FALSE, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_dont, /* complain_on_overflow */
143 0, /* special_function */
144 "r_byte0", /* name */
145 FALSE, /* partial_inplace */
146 0, /* src_mask */
147 0xff, /* dst_mask */
148 FALSE), /* pcrel_offset */
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 */
155 FALSE, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 0, /* special_function */
159 "r_byte1", /* name */
160 FALSE, /* partial_inplace */
161 0, /* src_mask */
162 0xff, /* dst_mask */
163 FALSE), /* pcrel_offset */
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 */
170 FALSE, /* pc_relative */
171 0, /* bitpos */
172 complain_overflow_dont, /* complain_on_overflow */
173 0, /* special_function */
174 "r_byte2", /* name */
175 FALSE, /* partial_inplace */
176 0, /* src_mask */
177 0xff, /* dst_mask */
178 FALSE), /* pcrel_offset */
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 */
185 FALSE, /* pc_relative */
186 0, /* bitpos */
187 complain_overflow_dont, /* complain_on_overflow */
188 0, /* special_function */
189 "r_byte3", /* name */
190 FALSE, /* partial_inplace */
191 0, /* src_mask */
192 0xff, /* dst_mask */
193 FALSE), /* pcrel_offset */
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 */
200 FALSE, /* pc_relative */
201 0, /* bitpos */
202 complain_overflow_dont, /* complain_on_overflow */
203 0, /* special_function */
204 "r_word0", /* name */
205 FALSE, /* partial_inplace */
206 0, /* src_mask */
207 0xffff, /* dst_mask */
208 FALSE), /* pcrel_offset */
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 */
215 FALSE, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_dont, /* complain_on_overflow */
218 0, /* special_function */
219 "r_word1", /* name */
220 FALSE, /* partial_inplace */
221 0, /* src_mask */
222 0xffff, /* dst_mask */
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 */
230 FALSE, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_bitfield, /* complain_on_overflow */
233 0, /* special_function */
234 "r_imm16be", /* name */
235 FALSE, /* partial_inplace */
236 0x0000ffff, /* src_mask */
237 0x0000ffff, /* dst_mask */
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
317 if (reloc->r_symndx > 0)
318 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
319 else
320 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
321
322 relent->addend = reloc->r_offset;
323 relent->address -= section->vma;
324}
325
326static void
327extra_case (bfd *in_abfd,
07d6d2b8
AM
328 struct bfd_link_info *link_info,
329 struct bfd_link_order *link_order,
330 arelent *reloc,
331 bfd_byte *data,
332 unsigned int *src_ptr,
333 unsigned int *dst_ptr)
3c9b82ba
NC
334{
335 asection * input_section = link_order->u.indirect.section;
6655dba2 336 int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
3c9b82ba
NC
337
338 switch (reloc->howto->type)
339 {
340 case R_OFF8:
6655dba2
SB
341 if (reloc->howto->partial_inplace)
342 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
343 & reloc->howto->src_mask);
344 if (val>127 || val<-128) /* Test for overflow. */
1a72702b
AM
345 (*link_info->callbacks->reloc_overflow)
346 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
347 reloc->howto->name, reloc->addend, input_section->owner,
348 input_section, reloc->address);
349
3c9b82ba
NC
350 bfd_put_8 (in_abfd, val, data + *dst_ptr);
351 (*dst_ptr) += 1;
352 (*src_ptr) += 1;
353 break;
354
6655dba2
SB
355 case R_BYTE3:
356 bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
357 (*dst_ptr) += 1;
358 (*src_ptr) += 1;
359 break;
360
361 case R_BYTE2:
362 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
363 (*dst_ptr) += 1;
364 (*src_ptr) += 1;
365 break;
366
367 case R_BYTE1:
368 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
369 (*dst_ptr) += 1;
370 (*src_ptr) += 1;
371 break;
372
3c9b82ba 373 case R_IMM8:
6655dba2
SB
374 if (reloc->howto->partial_inplace)
375 val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
376 //fallthrough
377 case R_BYTE0:
3c9b82ba
NC
378 bfd_put_8 (in_abfd, val, data + *dst_ptr);
379 (*dst_ptr) += 1;
380 (*src_ptr) += 1;
381 break;
382
6655dba2
SB
383 case R_WORD1:
384 bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
385 (*dst_ptr) += 2;
386 (*src_ptr) += 2;
387 break;
388
3c9b82ba 389 case R_IMM16:
6655dba2
SB
390 if (reloc->howto->partial_inplace)
391 val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
392 //fallthrough
393 case R_WORD0:
3c9b82ba
NC
394 bfd_put_16 (in_abfd, val, data + *dst_ptr);
395 (*dst_ptr) += 2;
396 (*src_ptr) += 2;
397 break;
398
134dcee5 399 case R_IMM24:
6655dba2
SB
400 if (reloc->howto->partial_inplace)
401 val += (bfd_get_16 ( in_abfd, data+*src_ptr)
402 + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16))
403 & reloc->howto->src_mask;
134dcee5
AM
404 bfd_put_16 (in_abfd, val, data + *dst_ptr);
405 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
406 (*dst_ptr) += 3;
407 (*src_ptr) += 3;
408 break;
409
3c9b82ba 410 case R_IMM32:
6655dba2
SB
411 if (reloc->howto->partial_inplace)
412 val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
3c9b82ba
NC
413 bfd_put_32 (in_abfd, val, data + *dst_ptr);
414 (*dst_ptr) += 4;
415 (*src_ptr) += 4;
416 break;
417
418 case R_JR:
419 {
6655dba2
SB
420 if (reloc->howto->partial_inplace)
421 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
422 & reloc->howto->src_mask);
44da2da1
AM
423 bfd_vma dot = (*dst_ptr
424 + input_section->output_offset
3c9b82ba 425 + input_section->output_section->vma);
6655dba2 426 int gap = val - dot;
3c9b82ba 427 if (gap >= 128 || gap < -128)
1a72702b
AM
428 (*link_info->callbacks->reloc_overflow)
429 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
430 reloc->howto->name, reloc->addend, input_section->owner,
431 input_section, reloc->address);
432
3c9b82ba
NC
433 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
434 (*dst_ptr)++;
435 (*src_ptr)++;
436 break;
437 }
438
9fc0b501
SB
439 case R_IMM16BE:
440 if (reloc->howto->partial_inplace)
441 val += (bfd_get_8 ( in_abfd, data+*src_ptr+0) * 0x100 +
442 bfd_get_8 ( in_abfd, data+*src_ptr+1)) & reloc->howto->src_mask;
443
444 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr+0);
445 bfd_put_8 (in_abfd, val, data + *dst_ptr+1);
446 (*dst_ptr) += 2;
447 (*src_ptr) += 2;
448 break;
449
3c9b82ba
NC
450 default:
451 abort ();
452 }
453}
454
6655dba2
SB
455static int
456z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
457 const char * name)
458{
459 return (name[0] == '.' && name[1] == 'L') ||
460 _bfd_coff_is_local_label_name (abfd, name);
461}
462
463#define coff_bfd_is_local_label_name z80_is_local_label_name
464
3c9b82ba
NC
465#define coff_reloc16_extra_cases extra_case
466#define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
157090f7 467#define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
3c9b82ba 468
2b5c217d
NC
469#ifndef bfd_pe_print_pdata
470#define bfd_pe_print_pdata NULL
471#endif
472
3c9b82ba
NC
473#include "coffcode.h"
474
475#undef coff_bfd_get_relocated_section_contents
476#define coff_bfd_get_relocated_section_contents \
477 bfd_coff_reloc16_get_relocated_section_contents
478
479#undef coff_bfd_relax_section
480#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
481
6d00b590 482CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
68ffbac6 483 SEC_CODE | SEC_DATA, '\0', NULL,
3c9b82ba
NC
484 COFF_SWAP_TABLE)
485
This page took 0.66318 seconds and 4 git commands to generate.