coff-z80.c revision 1.1 1 1.1 skrll /* BFD back-end for Zilog Z80 COFF binaries.
2 1.1 skrll Copyright 2005, 2007, 2008 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 skrll 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 skrll HOWTO (R_IMM32, 0, 1, 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 skrll 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 skrll 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 skrll abort ();
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 skrll {
192 1.1 skrll if (! ((*link_info->callbacks->reloc_overflow)
193 1.1 skrll (link_info, NULL,
194 1.1 skrll bfd_asymbol_name (*reloc->sym_ptr_ptr),
195 1.1 skrll reloc->howto->name, reloc->addend, input_section->owner,
196 1.1 skrll input_section, reloc->address)))
197 1.1 skrll abort ();
198 1.1 skrll }
199 1.1 skrll bfd_put_8 (in_abfd, val, data + *dst_ptr);
200 1.1 skrll (*dst_ptr) += 1;
201 1.1 skrll (*src_ptr) += 1;
202 1.1 skrll break;
203 1.1 skrll
204 1.1 skrll case R_IMM8:
205 1.1 skrll val = bfd_get_8 ( in_abfd, data+*src_ptr)
206 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
207 1.1 skrll bfd_put_8 (in_abfd, val, data + *dst_ptr);
208 1.1 skrll (*dst_ptr) += 1;
209 1.1 skrll (*src_ptr) += 1;
210 1.1 skrll break;
211 1.1 skrll
212 1.1 skrll case R_IMM16:
213 1.1 skrll val = bfd_get_16 ( in_abfd, data+*src_ptr)
214 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
215 1.1 skrll bfd_put_16 (in_abfd, val, data + *dst_ptr);
216 1.1 skrll (*dst_ptr) += 2;
217 1.1 skrll (*src_ptr) += 2;
218 1.1 skrll break;
219 1.1 skrll
220 1.1 skrll case R_IMM24:
221 1.1 skrll val = bfd_get_16 ( in_abfd, data+*src_ptr)
222 1.1 skrll + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
223 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
224 1.1 skrll bfd_put_16 (in_abfd, val, data + *dst_ptr);
225 1.1 skrll bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
226 1.1 skrll (*dst_ptr) += 3;
227 1.1 skrll (*src_ptr) += 3;
228 1.1 skrll break;
229 1.1 skrll
230 1.1 skrll case R_IMM32:
231 1.1 skrll val = bfd_get_32 ( in_abfd, data+*src_ptr)
232 1.1 skrll + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
233 1.1 skrll bfd_put_32 (in_abfd, val, data + *dst_ptr);
234 1.1 skrll (*dst_ptr) += 4;
235 1.1 skrll (*src_ptr) += 4;
236 1.1 skrll break;
237 1.1 skrll
238 1.1 skrll case R_JR:
239 1.1 skrll {
240 1.1 skrll bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
241 1.1 skrll input_section);
242 1.1 skrll bfd_vma dot = (*dst_ptr
243 1.1 skrll + input_section->output_offset
244 1.1 skrll + input_section->output_section->vma);
245 1.1 skrll int gap = dst - dot - 1; /* -1, Since the offset is relative
246 1.1 skrll to the value of PC after reading
247 1.1 skrll the offset. */
248 1.1 skrll
249 1.1 skrll if (gap >= 128 || gap < -128)
250 1.1 skrll {
251 1.1 skrll if (! ((*link_info->callbacks->reloc_overflow)
252 1.1 skrll (link_info, NULL,
253 1.1 skrll bfd_asymbol_name (*reloc->sym_ptr_ptr),
254 1.1 skrll reloc->howto->name, reloc->addend, input_section->owner,
255 1.1 skrll input_section, reloc->address)))
256 1.1 skrll abort ();
257 1.1 skrll }
258 1.1 skrll bfd_put_8 (in_abfd, gap, data + *dst_ptr);
259 1.1 skrll (*dst_ptr)++;
260 1.1 skrll (*src_ptr)++;
261 1.1 skrll break;
262 1.1 skrll }
263 1.1 skrll
264 1.1 skrll default:
265 1.1 skrll abort ();
266 1.1 skrll }
267 1.1 skrll }
268 1.1 skrll
269 1.1 skrll #define coff_reloc16_extra_cases extra_case
270 1.1 skrll #define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
271 1.1 skrll #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
272 1.1 skrll
273 1.1 skrll #ifndef bfd_pe_print_pdata
274 1.1 skrll #define bfd_pe_print_pdata NULL
275 1.1 skrll #endif
276 1.1 skrll
277 1.1 skrll #include "coffcode.h"
278 1.1 skrll
279 1.1 skrll #undef coff_bfd_get_relocated_section_contents
280 1.1 skrll #define coff_bfd_get_relocated_section_contents \
281 1.1 skrll bfd_coff_reloc16_get_relocated_section_contents
282 1.1 skrll
283 1.1 skrll #undef coff_bfd_relax_section
284 1.1 skrll #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
285 1.1 skrll
286 1.1 skrll CREATE_LITTLE_COFF_TARGET_VEC (z80coff_vec, "coff-z80", 0, 0, '\0', NULL,
287 1.1 skrll COFF_SWAP_TABLE)
288 1.1 skrll
289