Switch the inferior too in switch_to_program_space_and_thread
[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
226 #define NUM_HOWTOS ARRAY_SIZE (howto_table)
227
228 #define BADMAG(x) Z80BADMAG(x)
229 #define Z80 1 /* Customize coffcode.h. */
230 #define __A_MAGIC_SET__
231
232 /* Code to swap in the reloc. */
233
234 #define SWAP_IN_RELOC_OFFSET H_GET_32
235 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
236
237 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
238 dst->r_stuff[0] = 'S'; \
239 dst->r_stuff[1] = 'C';
240
241 /* Code to turn a r_type into a howto ptr, uses the above howto table. */
242 static void
243 rtype2howto (arelent *internal, struct internal_reloc *dst)
244 {
245 unsigned i;
246 for (i = 0; i < NUM_HOWTOS; i++)
247 {
248 if (howto_table[i].howto.type == dst->r_type)
249 {
250 internal->howto = &howto_table[i].howto;
251 return;
252 }
253 }
254 internal->howto = NULL;
255 }
256
257 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
258
259 static reloc_howto_type *
260 coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
261 bfd_reloc_code_real_type code)
262 {
263 unsigned i;
264 for (i = 0; i < NUM_HOWTOS; i++)
265 if (howto_table[i].r_type == code)
266 return &howto_table[i].howto;
267
268 BFD_FAIL ();
269 return NULL;
270 }
271
272 static reloc_howto_type *
273 coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
274 const char *r_name)
275 {
276 unsigned i;
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;
280
281 return NULL;
282 }
283
284 /* Perform any necessary magic to the addend in a reloc entry. */
285
286 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
287 cache_ptr->addend = ext_reloc.r_offset;
288
289 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
290 reloc_processing(relent, reloc, symbols, abfd, section)
291
292 static void
293 reloc_processing (arelent *relent,
294 struct internal_reloc *reloc,
295 asymbol **symbols,
296 bfd *abfd,
297 asection *section)
298 {
299 relent->address = reloc->r_vaddr;
300 rtype2howto (relent, reloc);
301
302 if (reloc->r_symndx > 0)
303 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
304 else
305 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
306
307 relent->addend = reloc->r_offset;
308 relent->address -= section->vma;
309 }
310
311 static void
312 extra_case (bfd *in_abfd,
313 struct bfd_link_info *link_info,
314 struct bfd_link_order *link_order,
315 arelent *reloc,
316 bfd_byte *data,
317 unsigned int *src_ptr,
318 unsigned int *dst_ptr)
319 {
320 asection * input_section = link_order->u.indirect.section;
321 int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
322
323 switch (reloc->howto->type)
324 {
325 case R_OFF8:
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);
334
335 bfd_put_8 (in_abfd, val, data + *dst_ptr);
336 (*dst_ptr) += 1;
337 (*src_ptr) += 1;
338 break;
339
340 case R_BYTE3:
341 bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
342 (*dst_ptr) += 1;
343 (*src_ptr) += 1;
344 break;
345
346 case R_BYTE2:
347 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
348 (*dst_ptr) += 1;
349 (*src_ptr) += 1;
350 break;
351
352 case R_BYTE1:
353 bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
354 (*dst_ptr) += 1;
355 (*src_ptr) += 1;
356 break;
357
358 case R_IMM8:
359 if (reloc->howto->partial_inplace)
360 val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
361 //fallthrough
362 case R_BYTE0:
363 bfd_put_8 (in_abfd, val, data + *dst_ptr);
364 (*dst_ptr) += 1;
365 (*src_ptr) += 1;
366 break;
367
368 case R_WORD1:
369 bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
370 (*dst_ptr) += 2;
371 (*src_ptr) += 2;
372 break;
373
374 case R_IMM16:
375 if (reloc->howto->partial_inplace)
376 val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
377 //fallthrough
378 case R_WORD0:
379 bfd_put_16 (in_abfd, val, data + *dst_ptr);
380 (*dst_ptr) += 2;
381 (*src_ptr) += 2;
382 break;
383
384 case R_IMM24:
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);
391 (*dst_ptr) += 3;
392 (*src_ptr) += 3;
393 break;
394
395 case R_IMM32:
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);
399 (*dst_ptr) += 4;
400 (*src_ptr) += 4;
401 break;
402
403 case R_JR:
404 {
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);
411 int gap = val - dot;
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);
417
418 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
419 (*dst_ptr)++;
420 (*src_ptr)++;
421 break;
422 }
423
424 default:
425 abort ();
426 }
427 }
428
429 static int
430 z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
431 const char * name)
432 {
433 return (name[0] == '.' && name[1] == 'L') ||
434 _bfd_coff_is_local_label_name (abfd, name);
435 }
436
437 #define coff_bfd_is_local_label_name z80_is_local_label_name
438
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
442
443 #ifndef bfd_pe_print_pdata
444 #define bfd_pe_print_pdata NULL
445 #endif
446
447 #include "coffcode.h"
448
449 #undef coff_bfd_get_relocated_section_contents
450 #define coff_bfd_get_relocated_section_contents \
451 bfd_coff_reloc16_get_relocated_section_contents
452
453 #undef coff_bfd_relax_section
454 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
455
456 CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
457 SEC_CODE | SEC_DATA, '\0', NULL,
458 COFF_SWAP_TABLE)
459
This page took 0.038225 seconds and 4 git commands to generate.