]>
Commit | Line | Data |
---|---|---|
6655dba2 | 1 | /* Zilog (e)Z80-specific support for 32-bit ELF |
250d07de | 2 | Copyright (C) 1999-2021 Free Software Foundation, Inc. |
6655dba2 SB |
3 | (Heavily copied from the S12Z port by Sergey Belyashov ([email protected])) |
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 "bfdlink.h" | |
25 | #include "libbfd.h" | |
26 | #include "elf-bfd.h" | |
27 | ||
28 | #include "elf/z80.h" | |
29 | ||
30 | /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ | |
31 | #define OCTETS_PER_BYTE(ABFD, SEC) 1 | |
32 | ||
bd38246a | 33 | typedef const struct { |
6655dba2 SB |
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 | ||
9fc0b501 SB |
41 | static bfd_reloc_status_type |
42 | z80_elf_16_be_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, | |
43 | void *data, asection *input_section, bfd *output_bfd, | |
44 | char **error_message); | |
45 | ||
6655dba2 SB |
46 | static const |
47 | bfd_howto_type elf_z80_howto_table[] = | |
48 | { | |
49 | /* This reloc does nothing. */ | |
50 | BFD_HOWTO (BFD_RELOC_NONE, | |
51 | R_Z80_NONE, /* type */ | |
52 | 0, /* rightshift */ | |
53 | 3, /* size (0 = byte, 1 = short, 2 = long) */ | |
54 | 0, /* bitsize */ | |
55 | FALSE, /* pc_relative */ | |
56 | 0, /* bitpos */ | |
57 | complain_overflow_dont,/* complain_on_overflow */ | |
58 | bfd_elf_generic_reloc, /* special_function */ | |
59 | "R_NONE", /* name */ | |
60 | FALSE, /* partial_inplace */ | |
61 | 0, /* src_mask */ | |
62 | 0, /* dst_mask */ | |
63 | FALSE), /* pcrel_offset */ | |
64 | ||
65 | /* A 8 bit relocation */ | |
66 | BFD_HOWTO (BFD_RELOC_8, | |
67 | R_Z80_8, /* type */ | |
68 | 0, /* rightshift */ | |
69 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
70 | 8, /* bitsize */ | |
71 | FALSE, /* pc_relative */ | |
72 | 0, /* bitpos */ | |
73 | complain_overflow_bitfield, /* complain_on_overflow */ | |
74 | bfd_elf_generic_reloc, /* special_function */ | |
75 | "r_imm8", /* name */ | |
76 | FALSE, /* partial_inplace */ | |
77 | 0x00, /* src_mask */ | |
78 | 0xff, /* dst_mask */ | |
79 | FALSE), /* pcrel_offset */ | |
80 | ||
81 | /* A 8 bit index register displacement relocation */ | |
82 | BFD_HOWTO (BFD_RELOC_Z80_DISP8, | |
83 | R_Z80_8_DIS, /* type */ | |
84 | 0, /* rightshift */ | |
85 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
86 | 8, /* bitsize */ | |
87 | FALSE, /* pc_relative */ | |
88 | 0, /* bitpos */ | |
89 | complain_overflow_signed, /* complain_on_overflow */ | |
90 | bfd_elf_generic_reloc, /* special_function */ | |
91 | "r_off", /* name */ | |
92 | FALSE, /* partial_inplace */ | |
93 | 0x00, /* src_mask */ | |
94 | 0xff, /* dst_mask */ | |
95 | FALSE), /* pcrel_offset */ | |
96 | ||
97 | /* A 8 bit PC-rel relocation */ | |
98 | BFD_HOWTO (BFD_RELOC_8_PCREL, | |
99 | R_Z80_8_PCREL, /* type */ | |
100 | 0, /* rightshift */ | |
101 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
102 | 8, /* bitsize */ | |
103 | TRUE, /* pc_relative */ | |
104 | 0, /* bitpos */ | |
105 | complain_overflow_signed, /* complain_on_overflow */ | |
106 | bfd_elf_generic_reloc, /* special_function */ | |
107 | "r_jr", /* name */ | |
108 | FALSE, /* partial_inplace */ | |
109 | 0x00, /* src_mask */ | |
110 | 0xff, /* dst_mask */ | |
111 | TRUE), /* pcrel_offset */ | |
112 | ||
113 | /* An 16 bit absolute relocation */ | |
114 | BFD_HOWTO (BFD_RELOC_16, | |
115 | R_Z80_16, /* type */ | |
116 | 0, /* rightshift */ | |
117 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
118 | 16, /* bitsize */ | |
119 | FALSE, /* pc_relative */ | |
120 | 0, /* bitpos */ | |
121 | complain_overflow_bitfield, /* complain_on_overflow */ | |
122 | bfd_elf_generic_reloc, /* special_function */ | |
123 | "r_imm16", /* name */ | |
124 | FALSE, /* partial_inplace */ | |
125 | 0x00000000, /* src_mask */ | |
126 | 0x0000ffff, /* dst_mask */ | |
127 | FALSE), /* pcrel_offset */ | |
128 | ||
129 | /* A 24 bit absolute relocation emitted by ADL mode operands */ | |
130 | BFD_HOWTO (BFD_RELOC_24, | |
131 | R_Z80_24, /* type */ | |
132 | 0, /* rightshift */ | |
133 | 5, /* size (0 = byte, 1 = short, 2 = long) */ | |
134 | 24, /* bitsize */ | |
135 | FALSE, /* pc_relative */ | |
136 | 0, /* bitpos */ | |
137 | complain_overflow_bitfield, /* complain_on_overflow */ | |
138 | bfd_elf_generic_reloc, /* special_function */ | |
139 | "r_imm24", /* name */ | |
140 | FALSE, /* partial_inplace */ | |
141 | 0x00000000, /* src_mask */ | |
142 | 0x00ffffff, /* dst_mask */ | |
143 | FALSE), /* pcrel_offset */ | |
144 | ||
145 | BFD_HOWTO (BFD_RELOC_32, | |
146 | R_Z80_32, /* type */ | |
147 | 0, /* rightshift */ | |
148 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
149 | 32, /* bitsize */ | |
150 | FALSE, /* pc_relative */ | |
151 | 0, /* bitpos */ | |
152 | complain_overflow_dont,/* complain_on_overflow */ | |
153 | bfd_elf_generic_reloc, /* special_function */ | |
154 | "r_imm32", /* name */ | |
155 | FALSE, /* partial_inplace */ | |
156 | 0x00000000, /* src_mask */ | |
157 | 0xffffffff, /* dst_mask */ | |
158 | FALSE), /* pcrel_offset */ | |
159 | ||
160 | /* First (lowest) 8 bits of multibyte relocation */ | |
161 | BFD_HOWTO (BFD_RELOC_Z80_BYTE0, | |
162 | R_Z80_BYTE0, /* type */ | |
163 | 0, /* rightshift */ | |
164 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
165 | 32, /* bitsize */ | |
166 | FALSE, /* pc_relative */ | |
167 | 0, /* bitpos */ | |
168 | complain_overflow_dont,/* complain_on_overflow */ | |
169 | bfd_elf_generic_reloc, /* special_function */ | |
170 | "r_byte0", /* name */ | |
171 | FALSE, /* partial_inplace */ | |
172 | 0, /* src_mask */ | |
173 | 0xff, /* dst_mask */ | |
174 | FALSE), /* pcrel_offset */ | |
175 | ||
176 | /* Second 8 bits of multibyte relocation */ | |
177 | BFD_HOWTO (BFD_RELOC_Z80_BYTE1, | |
178 | R_Z80_BYTE1, /* type */ | |
179 | 8, /* rightshift */ | |
180 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
181 | 32, /* bitsize */ | |
182 | FALSE, /* pc_relative */ | |
183 | 0, /* bitpos */ | |
184 | complain_overflow_dont,/* complain_on_overflow */ | |
185 | bfd_elf_generic_reloc, /* special_function */ | |
186 | "r_byte1", /* name */ | |
187 | FALSE, /* partial_inplace */ | |
188 | 0, /* src_mask */ | |
189 | 0xff, /* dst_mask */ | |
190 | FALSE), /* pcrel_offset */ | |
191 | ||
192 | /* Third 8 bits of multibyte relocation */ | |
193 | BFD_HOWTO (BFD_RELOC_Z80_BYTE2, | |
194 | R_Z80_BYTE2, /* type */ | |
195 | 16, /* rightshift */ | |
196 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
197 | 32, /* bitsize */ | |
198 | FALSE, /* pc_relative */ | |
199 | 0, /* bitpos */ | |
200 | complain_overflow_dont,/* complain_on_overflow */ | |
201 | bfd_elf_generic_reloc, /* special_function */ | |
202 | "r_byte2", /* name */ | |
203 | FALSE, /* partial_inplace */ | |
204 | 0, /* src_mask */ | |
205 | 0xff, /* dst_mask */ | |
206 | FALSE), /* pcrel_offset */ | |
207 | ||
208 | /* Fourth (highest) 8 bits of multibyte relocation */ | |
209 | BFD_HOWTO (BFD_RELOC_Z80_BYTE3, | |
210 | R_Z80_BYTE3, /* type */ | |
211 | 24, /* rightshift */ | |
212 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
213 | 32, /* bitsize */ | |
214 | FALSE, /* pc_relative */ | |
215 | 0, /* bitpos */ | |
216 | complain_overflow_dont,/* complain_on_overflow */ | |
217 | bfd_elf_generic_reloc, /* special_function */ | |
218 | "r_byte3", /* name */ | |
219 | FALSE, /* partial_inplace */ | |
220 | 0, /* src_mask */ | |
221 | 0xff, /* dst_mask */ | |
222 | FALSE), /* pcrel_offset */ | |
223 | ||
224 | /* An 16 bit absolute relocation of lower word of multibyte value */ | |
225 | BFD_HOWTO (BFD_RELOC_Z80_WORD0, | |
226 | R_Z80_WORD0, /* type */ | |
227 | 0, /* rightshift */ | |
228 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
229 | 32, /* bitsize */ | |
230 | FALSE, /* pc_relative */ | |
231 | 0, /* bitpos */ | |
232 | complain_overflow_dont,/* complain_on_overflow */ | |
233 | bfd_elf_generic_reloc, /* special_function */ | |
234 | "r_word0", /* name */ | |
235 | FALSE, /* partial_inplace */ | |
236 | 0, /* src_mask */ | |
237 | 0xffff, /* dst_mask */ | |
238 | FALSE), /* pcrel_offset */ | |
239 | ||
240 | /* An 16 bit absolute relocation of higher word of multibyte value */ | |
241 | BFD_HOWTO (BFD_RELOC_Z80_WORD1, | |
242 | R_Z80_WORD1, /* type */ | |
243 | 16, /* rightshift */ | |
244 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
245 | 32, /* bitsize */ | |
246 | FALSE, /* pc_relative */ | |
247 | 0, /* bitpos */ | |
248 | complain_overflow_dont,/* complain_on_overflow */ | |
249 | bfd_elf_generic_reloc, /* special_function */ | |
250 | "r_word1", /* name */ | |
251 | FALSE, /* partial_inplace */ | |
252 | 0, /* src_mask */ | |
253 | 0xffff, /* dst_mask */ | |
254 | FALSE), /* pcrel_offset */ | |
9fc0b501 SB |
255 | |
256 | /* An 16 bit big endian absolute relocation */ | |
257 | BFD_HOWTO (BFD_RELOC_Z80_16_BE, | |
258 | R_Z80_16_BE, /* type */ | |
259 | 0, /* rightshift */ | |
260 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
261 | 16, /* bitsize */ | |
262 | FALSE, /* pc_relative */ | |
263 | 0, /* bitpos */ | |
264 | complain_overflow_bitfield, /* complain_on_overflow */ | |
265 | z80_elf_16_be_reloc, /* special_function */ | |
266 | "r_imm16be", /* name */ | |
267 | FALSE, /* partial_inplace */ | |
268 | 0x00000000, /* src_mask */ | |
269 | 0x0000ffff, /* dst_mask */ | |
270 | FALSE), /* pcrel_offset */ | |
6655dba2 SB |
271 | }; |
272 | ||
273 | static reloc_howto_type * | |
9fc0b501 SB |
274 | z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
275 | bfd_reloc_code_real_type code) | |
6655dba2 SB |
276 | { |
277 | enum | |
278 | { | |
279 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) | |
280 | }; | |
281 | unsigned int i; | |
282 | ||
283 | for (i = 0; i < table_size; i++) | |
284 | { | |
285 | if (elf_z80_howto_table[i].r_type == code) | |
9fc0b501 | 286 | return &elf_z80_howto_table[i].howto; |
6655dba2 SB |
287 | } |
288 | ||
9fc0b501 | 289 | printf ("%s:%d Not found BFD reloc type %d\n", __FILE__, __LINE__, code); |
6655dba2 SB |
290 | |
291 | return NULL; | |
292 | } | |
293 | ||
294 | static reloc_howto_type * | |
9fc0b501 | 295 | z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) |
6655dba2 SB |
296 | { |
297 | enum | |
298 | { | |
299 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) | |
300 | }; | |
301 | unsigned int i; | |
302 | ||
303 | for (i = 0; i < table_size; i++) | |
304 | { | |
305 | if (elf_z80_howto_table[i].howto.name != NULL | |
9fc0b501 SB |
306 | && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0) |
307 | return &elf_z80_howto_table[i].howto; | |
6655dba2 SB |
308 | } |
309 | ||
9fc0b501 SB |
310 | printf ("%s:%d Not found ELF reloc name `%s'\n", __FILE__, __LINE__, r_name); |
311 | ||
6655dba2 SB |
312 | return NULL; |
313 | } | |
314 | ||
9fc0b501 SB |
315 | static reloc_howto_type * |
316 | z80_rtype_to_howto (bfd *abfd, unsigned r_type) | |
6655dba2 SB |
317 | { |
318 | enum | |
319 | { | |
320 | table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) | |
321 | }; | |
9fc0b501 | 322 | unsigned int i; |
6655dba2 SB |
323 | |
324 | for (i = 0; i < table_size; i++) | |
325 | { | |
326 | if (elf_z80_howto_table[i].howto.type == r_type) | |
9fc0b501 | 327 | return &elf_z80_howto_table[i].howto; |
6655dba2 SB |
328 | } |
329 | ||
330 | /* xgettext:c-format */ | |
331 | _bfd_error_handler (_("%pB: unsupported relocation type %#x"), | |
9fc0b501 SB |
332 | abfd, r_type); |
333 | return NULL; | |
334 | } | |
335 | ||
336 | /* Set the howto pointer for an z80 ELF reloc. */ | |
337 | ||
338 | static bfd_boolean | |
339 | z80_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) | |
340 | { | |
341 | unsigned int r_type = ELF32_R_TYPE (dst->r_info); | |
342 | reloc_howto_type *howto = z80_rtype_to_howto (abfd, r_type); | |
343 | if (howto != NULL) | |
344 | { | |
345 | cache_ptr->howto = howto; | |
346 | return TRUE; | |
347 | } | |
6655dba2 SB |
348 | bfd_set_error (bfd_error_bad_value); |
349 | return FALSE; | |
350 | } | |
351 | ||
9fc0b501 SB |
352 | static bfd_reloc_status_type |
353 | z80_elf_final_link_relocate (unsigned long r_type, | |
354 | bfd *input_bfd, | |
355 | bfd *output_bfd ATTRIBUTE_UNUSED, | |
356 | asection *input_section ATTRIBUTE_UNUSED, | |
357 | bfd_byte *contents, | |
358 | bfd_vma offset, | |
359 | bfd_vma value, | |
360 | bfd_vma addend, | |
361 | struct bfd_link_info *info ATTRIBUTE_UNUSED, | |
362 | asection *sym_sec ATTRIBUTE_UNUSED, | |
363 | int is_local ATTRIBUTE_UNUSED) | |
364 | { | |
365 | bfd_boolean r; | |
366 | reloc_howto_type *howto; | |
367 | ||
368 | switch (r_type) | |
369 | { | |
370 | case R_Z80_16_BE: | |
371 | value += addend; | |
372 | bfd_put_8 (input_bfd, value >> 8, contents + offset + 0); | |
373 | bfd_put_8 (input_bfd, value >> 0, contents + offset + 1); | |
374 | return bfd_reloc_ok; | |
375 | } | |
376 | ||
377 | howto = z80_rtype_to_howto (input_bfd, r_type); | |
378 | if (howto == NULL) | |
379 | return bfd_reloc_notsupported; | |
380 | ||
381 | r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, | |
382 | offset, value, addend); | |
383 | return r ? bfd_reloc_ok : bfd_reloc_notsupported; | |
384 | } | |
385 | ||
386 | static bfd_boolean | |
387 | z80_elf_relocate_section (bfd *output_bfd, | |
388 | struct bfd_link_info *info, | |
389 | bfd *input_bfd, | |
390 | asection *input_section, | |
391 | bfd_byte *contents, | |
392 | Elf_Internal_Rela *relocs, | |
393 | Elf_Internal_Sym *local_syms, | |
394 | asection **local_sections) | |
395 | { | |
396 | Elf_Internal_Shdr *symtab_hdr; | |
397 | struct elf_link_hash_entry **sym_hashes; | |
398 | Elf_Internal_Rela *rel, *relend; | |
399 | ||
400 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | |
401 | sym_hashes = elf_sym_hashes (input_bfd); | |
402 | ||
403 | rel = relocs; | |
404 | relend = relocs + input_section->reloc_count; | |
405 | for (; rel < relend; rel++) | |
406 | { | |
407 | unsigned int r_type; | |
408 | unsigned long r_symndx; | |
409 | Elf_Internal_Sym *sym; | |
410 | asection *sec; | |
411 | struct elf_link_hash_entry *h; | |
412 | bfd_vma relocation; | |
413 | ||
414 | /* This is a final link. */ | |
415 | r_symndx = ELF32_R_SYM (rel->r_info); | |
416 | r_type = ELF32_R_TYPE (rel->r_info); | |
417 | h = NULL; | |
418 | sym = NULL; | |
419 | sec = NULL; | |
420 | if (r_symndx < symtab_hdr->sh_info) | |
421 | { | |
422 | sym = local_syms + r_symndx; | |
423 | sec = local_sections[r_symndx]; | |
424 | relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); | |
425 | } | |
426 | else | |
427 | { | |
428 | bfd_boolean unresolved_reloc, warned, ignored; | |
429 | ||
430 | RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, | |
431 | r_symndx, symtab_hdr, sym_hashes, | |
432 | h, sec, relocation, | |
433 | unresolved_reloc, warned, ignored); | |
434 | } | |
435 | ||
436 | if (sec != NULL && discarded_section (sec)) | |
437 | { | |
438 | /* For relocs against symbols from removed linkonce sections, | |
439 | or sections discarded by a linker script, we just want the | |
440 | section contents cleared. Avoid any special processing. */ | |
441 | reloc_howto_type *howto; | |
442 | howto = z80_rtype_to_howto (input_bfd, r_type); | |
443 | RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, | |
444 | rel, 1, relend, howto, 0, contents); | |
445 | } | |
446 | ||
447 | if (bfd_link_relocatable (info)) | |
448 | continue; | |
449 | ||
450 | ||
451 | z80_elf_final_link_relocate (r_type, input_bfd, output_bfd, | |
452 | input_section, | |
453 | contents, rel->r_offset, | |
454 | relocation, rel->r_addend, | |
455 | info, sec, h == NULL); | |
456 | } | |
457 | ||
458 | return TRUE; | |
459 | } | |
460 | ||
461 | /* The final processing done just before writing out a Z80 ELF object | |
462 | file. This gets the Z80 architecture right based on the machine | |
463 | number. */ | |
464 | ||
6655dba2 | 465 | static bfd_boolean |
9fc0b501 | 466 | z80_elf_final_write_processing (bfd *abfd) |
6655dba2 | 467 | { |
9fc0b501 SB |
468 | unsigned long val = bfd_get_mach (abfd); |
469 | ||
470 | switch (val) | |
6655dba2 | 471 | { |
9fc0b501 SB |
472 | default: |
473 | _bfd_error_handler (_("%pB: unsupported bfd mach %#lx"), | |
474 | abfd, val); | |
475 | /* fall through */ | |
476 | case bfd_mach_z80: | |
477 | case bfd_mach_z80full: | |
478 | case bfd_mach_z80strict: | |
479 | val = EF_Z80_MACH_Z80; | |
6655dba2 | 480 | break; |
9fc0b501 SB |
481 | case bfd_mach_gbz80: |
482 | val = EF_Z80_MACH_GBZ80; | |
6655dba2 | 483 | break; |
9fc0b501 SB |
484 | case bfd_mach_z80n: |
485 | val = EF_Z80_MACH_Z80N; | |
6655dba2 | 486 | break; |
9fc0b501 SB |
487 | case bfd_mach_z180: |
488 | val = EF_Z80_MACH_Z180; | |
6655dba2 | 489 | break; |
9fc0b501 SB |
490 | case bfd_mach_ez80_z80: |
491 | val = EF_Z80_MACH_EZ80_Z80; | |
6655dba2 | 492 | break; |
9fc0b501 SB |
493 | case bfd_mach_ez80_adl: |
494 | val = EF_Z80_MACH_EZ80_ADL; | |
6655dba2 | 495 | break; |
9fc0b501 SB |
496 | case bfd_mach_r800: |
497 | val = EF_Z80_MACH_R800; | |
6655dba2 SB |
498 | break; |
499 | } | |
9fc0b501 SB |
500 | elf_elfheader (abfd)->e_machine = EM_Z80; |
501 | elf_elfheader (abfd)->e_flags &= ~EF_Z80_MACH_MSK; | |
502 | elf_elfheader (abfd)->e_flags |= val; | |
503 | return _bfd_elf_final_write_processing (abfd); | |
504 | } | |
6655dba2 | 505 | |
9fc0b501 SB |
506 | /* Set the right machine number. */ |
507 | static bfd_boolean | |
508 | z80_elf_object_p (bfd *abfd) | |
509 | { | |
510 | unsigned int mach; | |
511 | ||
512 | if (elf_elfheader (abfd)->e_machine == EM_Z80) | |
513 | { | |
514 | int e_mach = elf_elfheader (abfd)->e_flags & EF_Z80_MACH_MSK; | |
515 | switch (e_mach) | |
516 | { | |
517 | default: | |
518 | _bfd_error_handler (_("%pB: unsupported mach %#x"), | |
519 | abfd, e_mach); | |
520 | /* fall through */ | |
521 | case EF_Z80_MACH_Z80: | |
522 | mach = bfd_mach_z80; | |
523 | break; | |
524 | case EF_Z80_MACH_GBZ80: | |
525 | mach = bfd_mach_gbz80; | |
526 | break; | |
527 | case EF_Z80_MACH_Z180: | |
528 | mach = bfd_mach_z180; | |
529 | break; | |
530 | case EF_Z80_MACH_EZ80_Z80: | |
531 | mach = bfd_mach_ez80_z80; | |
532 | break; | |
533 | case EF_Z80_MACH_EZ80_ADL: | |
534 | mach = bfd_mach_ez80_adl; | |
535 | break; | |
536 | case EF_Z80_MACH_R800: | |
537 | mach = bfd_mach_r800; | |
538 | break; | |
539 | case EF_Z80_MACH_Z80N: | |
540 | mach = bfd_mach_z80n; | |
541 | break; | |
542 | } | |
543 | } | |
544 | else | |
545 | { | |
546 | _bfd_error_handler (_("%pB: unsupported arch %#x"), | |
547 | abfd, elf_elfheader (abfd)->e_machine); | |
548 | mach = bfd_mach_z80; | |
549 | } | |
550 | return bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach); | |
6655dba2 SB |
551 | } |
552 | ||
553 | static int | |
9fc0b501 SB |
554 | z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, |
555 | const char * name) | |
6655dba2 SB |
556 | { |
557 | return (name[0] == '.' && name[1] == 'L') || | |
9fc0b501 | 558 | _bfd_elf_is_local_label_name (abfd, name); |
6655dba2 SB |
559 | } |
560 | ||
9fc0b501 SB |
561 | static bfd_reloc_status_type |
562 | z80_elf_16_be_reloc (bfd *abfd, | |
563 | arelent *reloc_entry, | |
564 | asymbol *symbol, | |
565 | void *data, | |
566 | asection *input_section, | |
567 | bfd *output_bfd, | |
568 | char **error_message) | |
569 | { | |
570 | bfd_vma val; | |
571 | long x; | |
572 | bfd_size_type octets = (reloc_entry->address | |
573 | * OCTETS_PER_BYTE (abfd, input_section)); | |
574 | ||
575 | /* If this is a relocatable link (output_bfd test tells us), just | |
576 | call the generic function. Any adjustment will be done at final | |
577 | link time. */ | |
578 | if (output_bfd != NULL) | |
579 | return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | |
580 | input_section, output_bfd, error_message); | |
581 | ||
582 | /* Get symbol value. */ | |
583 | val = 0; | |
584 | if (!bfd_is_com_section (symbol->section)) | |
585 | val = symbol->value; | |
586 | val += symbol->section->output_offset + input_section->output_offset; | |
587 | if (symbol->section->output_section) | |
588 | val += symbol->section->output_section->vma; | |
589 | ||
590 | val += reloc_entry->addend; | |
591 | if (reloc_entry->howto->partial_inplace) | |
592 | { | |
593 | x = bfd_get_8 (abfd, (bfd_byte *) data + octets + 0) * 0x100; | |
594 | x += bfd_get_8 (abfd, (bfd_byte *) data + octets + 1); | |
595 | x &= ~reloc_entry->howto->src_mask; | |
596 | } | |
597 | else | |
598 | x = 0; | |
599 | ||
600 | x |= val & reloc_entry->howto->dst_mask; | |
601 | if (x < -0x8000 || x >= 0x10000) | |
602 | return bfd_reloc_outofrange; | |
603 | ||
604 | bfd_put_8 (abfd, x >> 8, (bfd_byte *) data + octets + 0); | |
605 | bfd_put_8 (abfd, x >> 0, (bfd_byte *) data + octets + 1); | |
606 | return bfd_reloc_ok; | |
607 | } | |
6655dba2 SB |
608 | |
609 | #define ELF_ARCH bfd_arch_z80 | |
610 | #define ELF_MACHINE_CODE EM_Z80 | |
611 | #define ELF_MAXPAGESIZE 0x10000 | |
612 | ||
613 | #define TARGET_LITTLE_SYM z80_elf32_vec | |
614 | #define TARGET_LITTLE_NAME "elf32-z80" | |
615 | ||
9fc0b501 SB |
616 | #define elf_backend_can_refcount 1 |
617 | #define elf_backend_can_gc_sections 1 | |
618 | #define elf_backend_stack_align 1 | |
619 | #define elf_backend_rela_normal 1 | |
620 | ||
621 | #define elf_info_to_howto z80_info_to_howto_rela | |
622 | #define elf_info_to_howto_rel z80_info_to_howto_rela | |
623 | ||
624 | #define elf_backend_final_write_processing z80_elf_final_write_processing | |
625 | #define elf_backend_object_p z80_elf_object_p | |
626 | #define elf_backend_relocate_section z80_elf_relocate_section | |
627 | ||
628 | #define bfd_elf32_bfd_reloc_type_lookup z80_reloc_type_lookup | |
629 | #define bfd_elf32_bfd_reloc_name_lookup z80_reloc_name_lookup | |
6655dba2 SB |
630 | #define bfd_elf32_bfd_is_local_label_name z80_is_local_label_name |
631 | ||
632 | #include "elf32-target.h" |