gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / coff-z80.c
1 /* BFD back-end for Zilog Z80 COFF binaries.
2 Copyright (C) 2005-2020 Free Software Foundation, Inc.
3 Contributed by Arnold Metselaar <arnold_m@operamail.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 "libbfd.h"
25 #include "bfdlink.h"
26 #include "coff/z80.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29 #include "libiberty.h"
30
31 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
32
33 typedef 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_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 */
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 */
239 };
240
241 #define NUM_HOWTOS ARRAY_SIZE (howto_table)
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. */
257 static void
258 rtype2howto (arelent *internal, struct internal_reloc *dst)
259 {
260 unsigned i;
261 for (i = 0; i < NUM_HOWTOS; i++)
262 {
263 if (howto_table[i].howto.type == dst->r_type)
264 {
265 internal->howto = &howto_table[i].howto;
266 return;
267 }
268 }
269 internal->howto = NULL;
270 }
271
272 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
273
274 static reloc_howto_type *
275 coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
276 bfd_reloc_code_real_type code)
277 {
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;
285 }
286
287 static reloc_howto_type *
288 coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
289 const char *r_name)
290 {
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;
295
296 return NULL;
297 }
298
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
307 static void
308 reloc_processing (arelent *relent,
309 struct internal_reloc *reloc,
310 asymbol **symbols,
311 bfd *abfd,
312 asection *section)
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
326 static void
327 extra_case (bfd *in_abfd,
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)
334 {
335 asection * input_section = link_order->u.indirect.section;
336 int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
337
338 switch (reloc->howto->type)
339 {
340 case R_OFF8:
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. */
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
350 bfd_put_8 (in_abfd, val, data + *dst_ptr);
351 (*dst_ptr) += 1;
352 (*src_ptr) += 1;
353 break;
354
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
373 case R_IMM8:
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:
378 bfd_put_8 (in_abfd, val, data + *dst_ptr);
379 (*dst_ptr) += 1;
380 (*src_ptr) += 1;
381 break;
382
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
389 case R_IMM16:
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:
394 bfd_put_16 (in_abfd, val, data + *dst_ptr);
395 (*dst_ptr) += 2;
396 (*src_ptr) += 2;
397 break;
398
399 case R_IMM24:
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;
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
410 case R_IMM32:
411 if (reloc->howto->partial_inplace)
412 val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
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 {
420 if (reloc->howto->partial_inplace)
421 val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
422 & reloc->howto->src_mask);
423 bfd_vma dot = (*dst_ptr
424 + input_section->output_offset
425 + input_section->output_section->vma);
426 int gap = val - dot;
427 if (gap >= 128 || gap < -128)
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
433 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
434 (*dst_ptr)++;
435 (*src_ptr)++;
436 break;
437 }
438
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
450 default:
451 abort ();
452 }
453 }
454
455 static int
456 z80_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
465 #define coff_reloc16_extra_cases extra_case
466 #define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
467 #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
468
469 #ifndef bfd_pe_print_pdata
470 #define bfd_pe_print_pdata NULL
471 #endif
472
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
482 CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
483 SEC_CODE | SEC_DATA, '\0', NULL,
484 COFF_SWAP_TABLE)
485
This page took 0.041745 seconds and 4 git commands to generate.