coff-z80.c revision 1.1.1.4 1 1.1 skrll /* BFD back-end for Zilog Z80 COFF binaries.
2 1.1.1.4 christos Copyright (C) 2005-2016 Free Software Foundation, Inc.
3 1.1 skrll Contributed by Arnold Metselaar <arnold_m (at) operamail.com>
4 1.1 skrll
5 1.1 skrll This file is part of BFD, the Binary File Descriptor library.
6 1.1 skrll
7 1.1.1.3 christos This program is free software; you can redistribute it and/or modify
8 1.1 skrll it under the terms of the GNU General Public License as published by
9 1.1 skrll the Free Software Foundation; either version 3 of the License, or
10 1.1 skrll (at your option) any later version.
11 1.1 skrll
12 1.1 skrll This program is distributed in the hope that it will be useful,
13 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 skrll GNU General Public License for more details.
16 1.1 skrll
17 1.1 skrll You should have received a copy of the GNU General Public License
18 1.1 skrll along with this program; if not, write to the Free Software
19 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 skrll MA 02110-1301, USA. */
21 1.1 skrll
22 1.1 skrll #include "sysdep.h"
23 1.1 skrll #include "bfd.h"
24 1.1 skrll #include "libbfd.h"
25 1.1 skrll #include "bfdlink.h"
26 1.1 skrll #include "coff/z80.h"
27 1.1 skrll #include "coff/internal.h"
28 1.1 skrll #include "libcoff.h"
29 1.1 skrll
30 1.1 skrll #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
31 1.1 skrll
32 1.1 skrll static reloc_howto_type r_imm32 =
33 1.1.1.2 christos HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
34 1.1 skrll complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
35 1.1 skrll FALSE);
36 1.1 skrll
37 1.1 skrll static reloc_howto_type r_imm24 =
38 1.1 skrll HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
39 1.1 skrll complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
40 1.1 skrll FALSE);
41 1.1 skrll
42 1.1 skrll static reloc_howto_type r_imm16 =
43 1.1 skrll HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
44 1.1 skrll complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
45 1.1 skrll FALSE);
46 1.1 skrll
47 1.1 skrll static reloc_howto_type r_imm8 =
48 1.1 skrll HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
49 1.1 skrll complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
50 1.1 skrll FALSE);
51 1.1 skrll
52 1.1 skrll static reloc_howto_type r_jr =
53 1.1.1.3 christos HOWTO (R_JR, 0, 0, 8, TRUE, 0,
54 1.1 skrll complain_overflow_signed, 0, "r_jr", FALSE, 0, 0xFF,
55 1.1 skrll FALSE);
56 1.1 skrll
57 1.1 skrll static reloc_howto_type r_off8 =
58 1.1.1.3 christos HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
59 1.1 skrll complain_overflow_signed, 0,"r_off8", FALSE, 0, 0xff,
60 1.1 skrll FALSE);
61 1.1 skrll
62 1.1 skrll
63 1.1 skrll #define BADMAG(x) Z80BADMAG(x)
64 1.1 skrll #define Z80 1 /* Customize coffcode.h. */
65 1.1 skrll #define __A_MAGIC_SET__
66 1.1 skrll
67 1.1 skrll /* Code to swap in the reloc. */
68 1.1 skrll
69 1.1 skrll #define SWAP_IN_RELOC_OFFSET H_GET_32
70 1.1 skrll #define SWAP_OUT_RELOC_OFFSET H_PUT_32
71 1.1 skrll
72 1.1 skrll #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
73 1.1 skrll dst->r_stuff[0] = 'S'; \
74 1.1 skrll dst->r_stuff[1] = 'C';
75 1.1 skrll
76 1.1 skrll /* Code to turn a r_type into a howto ptr, uses the above howto table. */
77 1.1 skrll
78 1.1 skrll static void
79 1.1 skrll rtype2howto (arelent *internal, struct internal_reloc *dst)
80 1.1 skrll {
81 1.1 skrll switch (dst->r_type)
82 1.1 skrll {
83 1.1 skrll default:
84 1.1.1.3 christos internal->howto = NULL;
85 1.1 skrll break;
86 1.1 skrll case R_IMM8:
87 1.1 skrll internal->howto = &r_imm8;
88 1.1 skrll break;
89 1.1 skrll case R_IMM16:
90 1.1 skrll internal->howto = &r_imm16;
91 1.1 skrll break;
92 1.1 skrll case R_IMM24:
93 1.1 skrll internal->howto = &r_imm24;
94 1.1 skrll break;
95 1.1 skrll case R_IMM32:
96 1.1 skrll internal->howto = &r_imm32;
97 1.1 skrll break;
98 1.1 skrll case R_JR:
99 1.1 skrll internal->howto = &r_jr;
100 1.1 skrll break;
101 1.1 skrll case R_OFF8:
102 1.1 skrll internal->howto = &r_off8;
103 1.1 skrll break;
104 1.1 skrll }
105 1.1 skrll }
106 1.1 skrll
107 1.1 skrll #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
108 1.1 skrll
109 1.1 skrll static reloc_howto_type *
110 1.1 skrll coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
111 1.1 skrll bfd_reloc_code_real_type code)
112 1.1 skrll {
113 1.1 skrll switch (code)
114 1.1 skrll {
115 1.1 skrll case BFD_RELOC_8: return & r_imm8;
116 1.1 skrll case BFD_RELOC_16: return & r_imm16;
117 1.1 skrll case BFD_RELOC_24: return & r_imm24;
118 1.1 skrll case BFD_RELOC_32: return & r_imm32;
119 1.1 skrll case BFD_RELOC_8_PCREL: return & r_jr;
120 1.1 skrll case BFD_RELOC_Z80_DISP8: return & r_off8;
121 1.1 skrll default: BFD_FAIL ();
122 1.1 skrll return NULL;
123 1.1 skrll }
124 1.1 skrll }
125 1.1 skrll
126 1.1 skrll static reloc_howto_type *
127 1.1 skrll coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
128 1.1 skrll const char *r_name)
129 1.1 skrll {
130 1.1 skrll if (strcasecmp (r_imm8.name, r_name) == 0)
131 1.1 skrll return &r_imm8;
132 1.1 skrll if (strcasecmp (r_imm16.name, r_name) == 0)
133 1.1 skrll return &r_imm16;
134 1.1 skrll if (strcasecmp (r_imm24.name, r_name) == 0)
135 1.1 skrll return &r_imm24;
136 1.1 skrll if (strcasecmp (r_imm32.name, r_name) == 0)
137 1.1 skrll return &r_imm32;
138 1.1 skrll if (strcasecmp (r_jr.name, r_name) == 0)
139 1.1 skrll return &r_jr;
140 1.1 skrll if (strcasecmp (r_off8.name, r_name) == 0)
141 1.1 skrll return &r_off8;
142 1.1 skrll
143 1.1 skrll return NULL;
144 1.1 skrll }
145 1.1 skrll
146 1.1 skrll /* Perform any necessary magic to the addend in a reloc entry. */
147 1.1 skrll
148 1.1 skrll #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
149 1.1 skrll cache_ptr->addend = ext_reloc.r_offset;
150 1.1 skrll
151 1.1 skrll #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
152 1.1 skrll reloc_processing(relent, reloc, symbols, abfd, section)
153 1.1 skrll
154 1.1 skrll static void
155 1.1 skrll reloc_processing (arelent *relent,
156 1.1 skrll struct internal_reloc *reloc,
157 1.1 skrll asymbol **symbols,
158 1.1 skrll bfd *abfd,
159 1.1 skrll asection *section)
160 1.1 skrll {
161 1.1 skrll relent->address = reloc->r_vaddr;
162 1.1 skrll rtype2howto (relent, reloc);
163 1.1 skrll
164 1.1 skrll if (reloc->r_symndx > 0)
165 1.1 skrll relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
166 1.1 skrll else
167 1.1 skrll relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
168 1.1 skrll
169 1.1 skrll relent->addend = reloc->r_offset;
170 1.1 skrll relent->address -= section->vma;
171 1.1 skrll }
172 1.1 skrll
173 1.1 skrll static void
174 1.1 skrll extra_case (bfd *in_abfd,
175 1.1 skrll struct bfd_link_info *link_info,
176 1.1 skrll struct bfd_link_order *link_order,
177 1.1 skrll arelent *reloc,
178 1.1 skrll bfd_byte *data,
179 1.1 skrll unsigned int *src_ptr,
180 1.1 skrll unsigned int *dst_ptr)
181 1.1 skrll {
182 1.1 skrll asection * input_section = link_order->u.indirect.section;
183 1.1 skrll int val;
184 1.1 skrll
185 1.1 skrll switch (reloc->howto->type)
186 1.1 skrll {
187 1.1 skrll case R_OFF8:
188 1.1 skrll val = bfd_coff_reloc16_get_value (reloc, link_info,
189 1.1 skrll input_section);
190 1.1 skrll if (val>127 || val<-128) /* Test for overflow. */
191 1.1.1.4 christos (*link_info->callbacks->reloc_overflow)
192 1.1.1.4 christos (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
193 1.1.1.4 christos reloc->howto->name, reloc->addend, input_section->owner,
194 1.1.1.4 christos input_section, reloc->address);
195 1.1.1.4 christos
196 1.1 skrll bfd_put_8 (in_abfd, val, data + *dst_ptr);
197 1.1 skrll (*dst_ptr) += 1;
198 1.1 skrll (*src_ptr) += 1;
199 1.1 skrll break;
200 1.1 skrll
201 1.1 skrll case R_IMM8:
202 1.1 skrll val = bfd_get_8 ( in_abfd, data+*src_ptr)
203 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
204 1.1 skrll bfd_put_8 (in_abfd, val, data + *dst_ptr);
205 1.1 skrll (*dst_ptr) += 1;
206 1.1 skrll (*src_ptr) += 1;
207 1.1 skrll break;
208 1.1 skrll
209 1.1 skrll case R_IMM16:
210 1.1 skrll val = bfd_get_16 ( in_abfd, data+*src_ptr)
211 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
212 1.1 skrll bfd_put_16 (in_abfd, val, data + *dst_ptr);
213 1.1 skrll (*dst_ptr) += 2;
214 1.1 skrll (*src_ptr) += 2;
215 1.1 skrll break;
216 1.1 skrll
217 1.1 skrll case R_IMM24:
218 1.1 skrll val = bfd_get_16 ( in_abfd, data+*src_ptr)
219 1.1 skrll + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
220 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
221 1.1 skrll bfd_put_16 (in_abfd, val, data + *dst_ptr);
222 1.1 skrll bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
223 1.1 skrll (*dst_ptr) += 3;
224 1.1 skrll (*src_ptr) += 3;
225 1.1 skrll break;
226 1.1 skrll
227 1.1 skrll case R_IMM32:
228 1.1 skrll val = bfd_get_32 ( in_abfd, data+*src_ptr)
229 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
230 1.1 skrll bfd_put_32 (in_abfd, val, data + *dst_ptr);
231 1.1 skrll (*dst_ptr) += 4;
232 1.1 skrll (*src_ptr) += 4;
233 1.1 skrll break;
234 1.1 skrll
235 1.1 skrll case R_JR:
236 1.1 skrll {
237 1.1 skrll bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
238 1.1 skrll input_section);
239 1.1 skrll bfd_vma dot = (*dst_ptr
240 1.1 skrll + input_section->output_offset
241 1.1 skrll + input_section->output_section->vma);
242 1.1 skrll int gap = dst - dot - 1; /* -1, Since the offset is relative
243 1.1 skrll to the value of PC after reading
244 1.1 skrll the offset. */
245 1.1 skrll
246 1.1 skrll if (gap >= 128 || gap < -128)
247 1.1.1.4 christos (*link_info->callbacks->reloc_overflow)
248 1.1.1.4 christos (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
249 1.1.1.4 christos reloc->howto->name, reloc->addend, input_section->owner,
250 1.1.1.4 christos input_section, reloc->address);
251 1.1.1.4 christos
252 1.1 skrll bfd_put_8 (in_abfd, gap, data + *dst_ptr);
253 1.1 skrll (*dst_ptr)++;
254 1.1 skrll (*src_ptr)++;
255 1.1 skrll break;
256 1.1 skrll }
257 1.1 skrll
258 1.1 skrll default:
259 1.1 skrll abort ();
260 1.1 skrll }
261 1.1 skrll }
262 1.1 skrll
263 1.1 skrll #define coff_reloc16_extra_cases extra_case
264 1.1 skrll #define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
265 1.1 skrll #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
266 1.1 skrll
267 1.1 skrll #ifndef bfd_pe_print_pdata
268 1.1 skrll #define bfd_pe_print_pdata NULL
269 1.1 skrll #endif
270 1.1 skrll
271 1.1 skrll #include "coffcode.h"
272 1.1 skrll
273 1.1 skrll #undef coff_bfd_get_relocated_section_contents
274 1.1 skrll #define coff_bfd_get_relocated_section_contents \
275 1.1 skrll bfd_coff_reloc16_get_relocated_section_contents
276 1.1 skrll
277 1.1 skrll #undef coff_bfd_relax_section
278 1.1 skrll #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
279 1.1 skrll
280 1.1.1.3 christos CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
281 1.1.1.3 christos SEC_CODE | SEC_DATA, '\0', NULL,
282 1.1 skrll COFF_SWAP_TABLE)
283 1.1 skrll
284