Test for PR gdb/17511, spurious SIGTRAP after stepping into+in signal handler
[deliverable/binutils-gdb.git] / bfd / coff-w65.c
CommitLineData
252b5132 1/* BFD back-end for WDC 65816 COFF binaries.
4b95cf5c 2 Copyright (C) 1995-2014 Free Software Foundation, Inc.
252b5132
RH
3 Written by Steve Chamberlain, <sac@cygnus.com>.
4
cd123cb7 5 This file is part of BFD, the Binary File Descriptor library.
252b5132 6
cd123cb7
NC
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.
252b5132 11
cd123cb7
NC
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.
252b5132 16
cd123cb7
NC
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. */
252b5132 21
252b5132 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
252b5132
RH
24#include "libbfd.h"
25#include "bfdlink.h"
26#include "coff/w65.h"
27#include "coff/internal.h"
28#include "libcoff.h"
29
30#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
31static reloc_howto_type howto_table[] =
2c3fc389
NC
32{
33 HOWTO (R_W65_ABS8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
b34976b6
AM
34 HOWTO (R_W65_ABS16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
35 HOWTO (R_W65_ABS24, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
36 HOWTO (R_W65_ABS8S8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, ">abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
37 HOWTO (R_W65_ABS8S16, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "^abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
38 HOWTO (R_W65_ABS16S8, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, ">abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
39 HOWTO (R_W65_ABS16S16,1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "^abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
40 HOWTO (R_W65_PCR8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "pcrel8", TRUE, 0x000000ff, 0x000000ff, TRUE),
41 HOWTO (R_W65_PCR16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, TRUE),
42 HOWTO (R_W65_DP, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "dp", TRUE, 0x000000ff, 0x000000ff, FALSE),
f4ffd778
NC
43 };
44
45/* Turn a howto into a reloc number. */
252b5132
RH
46
47#define SELECT_RELOC(x,howto) \
48 { x.r_type = select_reloc(howto); }
49
50#define BADMAG(x) (W65BADMAG(x))
51#define W65 1 /* Customize coffcode.h */
52#define __A_MAGIC_SET__
53
252b5132 54/* Code to swap in the reloc */
dc810e39
AM
55#define SWAP_IN_RELOC_OFFSET H_GET_32
56#define SWAP_OUT_RELOC_OFFSET H_PUT_32
252b5132
RH
57#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
58 dst->r_stuff[0] = 'S'; \
59 dst->r_stuff[1] = 'C';
60
252b5132 61static int
2c3fc389 62select_reloc (reloc_howto_type *howto)
252b5132
RH
63{
64 return howto->type ;
65}
66
f4ffd778 67/* Code to turn a r_type into a howto ptr, uses the above howto table. */
252b5132
RH
68
69static void
2c3fc389
NC
70rtype2howto (arelent *internal,
71 struct internal_reloc *dst)
252b5132 72{
f4ffd778 73 internal->howto = howto_table + dst->r_type - 1;
252b5132
RH
74}
75
76#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
77
f4ffd778 78/* Perform any necessary magic to the addend in a reloc entry. */
252b5132 79
252b5132
RH
80#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
81 cache_ptr->addend = ext_reloc.r_offset;
82
252b5132
RH
83#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
84 reloc_processing(relent, reloc, symbols, abfd, section)
85
86static void
2c3fc389
NC
87reloc_processing (arelent * relent,
88 struct internal_reloc *reloc,
89 asymbol ** symbols,
90 bfd * abfd,
91 asection * section)
252b5132
RH
92{
93 relent->address = reloc->r_vaddr;
94 rtype2howto (relent, reloc);
95
96 if (((int) reloc->r_symndx) > 0)
f4ffd778 97 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 98 else
f592407e 99 relent->sym_ptr_ptr = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
252b5132 100
252b5132
RH
101 relent->addend = reloc->r_offset;
102
103 relent->address -= section->vma;
104 /* relent->section = 0;*/
105}
106
252b5132 107static int
2c3fc389
NC
108w65_reloc16_estimate (bfd *abfd,
109 asection *input_section,
110 arelent *reloc,
111 unsigned int shrink,
112 struct bfd_link_info *link_info)
252b5132 113{
cbfe05c4 114 bfd_vma value;
252b5132
RH
115 bfd_vma dot;
116 bfd_vma gap;
117
cbfe05c4 118 /* The address of the thing to be relocated will have moved back by
2c3fc389
NC
119 the size of the shrink - but we don't change reloc->address here,
120 since we need it to know where the relocation lives in the source
121 uncooked section. */
252b5132
RH
122
123 /* reloc->address -= shrink; conceptual */
124
125 bfd_vma address = reloc->address - shrink;
252b5132
RH
126
127 switch (reloc->howto->type)
cbfe05c4 128 {
252b5132
RH
129 case R_MOV16B2:
130 case R_JMP2:
131 shrink+=2;
132 break;
133
f4ffd778 134 /* Thing is a move one byte. */
252b5132 135 case R_MOV16B1:
f4ffd778 136 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
252b5132
RH
137
138 if (value >= 0xff00)
cbfe05c4 139 {
252b5132 140 /* Change the reloc type from 16bit, possible 8 to 8bit
f4ffd778 141 possible 16. */
cbfe05c4 142 reloc->howto = reloc->howto + 1;
f4ffd778
NC
143 /* The place to relc moves back by one. */
144 /* This will be two bytes smaller in the long run. */
145 shrink += 2;
146 bfd_perform_slip (abfd, 2, input_section, address);
cbfe05c4 147 }
252b5132
RH
148
149 break;
cbfe05c4 150 /* This is the 24 bit branch which could become an 8 bitter,
f4ffd778
NC
151 the relocation points to the first byte of the insn, not the
152 actual data. */
252b5132
RH
153
154 case R_JMPL1:
f4ffd778 155 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
cbfe05c4 156
252b5132
RH
157 dot = input_section->output_section->vma +
158 input_section->output_offset + address;
cbfe05c4 159
252b5132
RH
160 /* See if the address we're looking at within 127 bytes of where
161 we are, if so then we can use a small branch rather than the
f4ffd778
NC
162 jump we were going to. */
163 gap = value - dot;
cbfe05c4 164
f4ffd778 165 if (-120 < (long) gap && (long) gap < 120)
cbfe05c4 166 {
252b5132 167 /* Change the reloc type from 24bit, possible 8 to 8bit
f4ffd778 168 possible 32. */
cbfe05c4 169 reloc->howto = reloc->howto + 1;
f4ffd778
NC
170 /* This will be two bytes smaller in the long run. */
171 shrink += 2;
172 bfd_perform_slip (abfd, 2, input_section, address);
252b5132
RH
173 }
174 break;
175
176 case R_JMP1:
f4ffd778 177 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
cbfe05c4 178
252b5132
RH
179 dot = input_section->output_section->vma +
180 input_section->output_offset + address;
cbfe05c4 181
252b5132
RH
182 /* See if the address we're looking at within 127 bytes of where
183 we are, if so then we can use a small branch rather than the
f4ffd778 184 jump we were going to. */
252b5132 185 gap = value - (dot - shrink);
252b5132 186
f4ffd778 187 if (-120 < (long) gap && (long) gap < 120)
cbfe05c4 188 {
252b5132 189 /* Change the reloc type from 16bit, possible 8 to 8bit
f4ffd778 190 possible 16. */
cbfe05c4 191 reloc->howto = reloc->howto + 1;
f4ffd778 192 /* The place to relc moves back by one. */
252b5132 193
f4ffd778
NC
194 /* This will be two bytes smaller in the long run. */
195 shrink += 2;
196 bfd_perform_slip (abfd, 2, input_section, address);
252b5132
RH
197 }
198 break;
199 }
200
252b5132
RH
201 return shrink;
202}
203
f4ffd778 204/* First phase of a relaxing link. */
252b5132
RH
205
206/* Reloc types
207 large small
208 R_MOV16B1 R_MOV16B2 mov.b with 16bit or 8 bit address
209 R_JMP1 R_JMP2 jmp or pcrel branch
210 R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
f4ffd778 211 R_MOV24B1 R_MOV24B2 24 or 8 bit reloc for mov.b */
252b5132
RH
212
213static void
2c3fc389
NC
214w65_reloc16_extra_cases (bfd *abfd,
215 struct bfd_link_info *link_info,
216 struct bfd_link_order *link_order,
217 arelent *reloc,
218 bfd_byte *data,
219 unsigned int *src_ptr,
220 unsigned int *dst_ptr)
252b5132
RH
221{
222 unsigned int src_address = *src_ptr;
223 unsigned int dst_address = *dst_ptr;
224 asection *input_section = link_order->u.indirect.section;
225
226 switch (reloc->howto->type)
227 {
228 case R_W65_ABS8:
229 case R_W65_DP:
230 {
231 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
232 input_section);
233 bfd_put_8 (abfd, gap, data + dst_address);
234 dst_address += 1;
235 src_address += 1;
236 }
237 break;
238
239 case R_W65_ABS8S8:
240 {
241 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
242 input_section);
243 gap >>= 8;
244 bfd_put_8 (abfd, gap, data + dst_address);
245 dst_address += 1;
246 src_address += 1;
247 }
248 break;
249
250 case R_W65_ABS8S16:
251 {
252 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
253 input_section);
f4ffd778 254 gap >>= 16;
252b5132
RH
255 bfd_put_8 (abfd, gap, data + dst_address);
256 dst_address += 1;
257 src_address += 1;
258 }
259 break;
260
261 case R_W65_ABS16:
262 {
263 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
264 input_section);
265
dc810e39 266 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
267 dst_address += 2;
268 src_address += 2;
269 }
270 break;
271 case R_W65_ABS16S8:
272 {
273 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
274 input_section);
275 gap >>= 8;
dc810e39 276 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
277 dst_address += 2;
278 src_address += 2;
279 }
280 break;
281 case R_W65_ABS16S16:
282 {
283 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
284 input_section);
285 gap >>= 16;
dc810e39 286 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
287 dst_address += 2;
288 src_address += 2;
289 }
290 break;
291
292 case R_W65_ABS24:
293 {
294 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
295 input_section);
dc810e39 296 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
f4ffd778 297 bfd_put_8 (abfd, gap >> 16, data+dst_address + 2);
252b5132
RH
298 dst_address += 3;
299 src_address += 3;
300 }
301 break;
302
303 case R_W65_PCR8:
304 {
305 int gap = bfd_coff_reloc16_get_value (reloc, link_info,
306 input_section);
44da2da1
AM
307 bfd_vma dot = (dst_address
308 + input_section->output_offset
309 + input_section->output_section->vma);
252b5132
RH
310
311 gap -= dot + 1;
f4ffd778
NC
312 if (gap < -128 || gap > 127)
313 {
314 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
315 (link_info, NULL,
316 bfd_asymbol_name (*reloc->sym_ptr_ptr),
f4ffd778
NC
317 reloc->howto->name, reloc->addend, input_section->owner,
318 input_section, reloc->address)))
319 abort ();
320 }
252b5132
RH
321 bfd_put_8 (abfd, gap, data + dst_address);
322 dst_address += 1;
323 src_address += 1;
324 }
325 break;
326
327 case R_W65_PCR16:
328 {
329 bfd_vma gap = bfd_coff_reloc16_get_value (reloc, link_info,
330 input_section);
44da2da1
AM
331 bfd_vma dot = (dst_address
332 + input_section->output_offset
333 + input_section->output_section->vma);
252b5132 334
252b5132 335 /* This wraps within the page, so ignore the relativeness, look at the
f4ffd778
NC
336 high part. */
337 if ((gap & 0xf0000) != (dot & 0xf0000))
338 {
339 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
340 (link_info, NULL,
341 bfd_asymbol_name (*reloc->sym_ptr_ptr),
f4ffd778
NC
342 reloc->howto->name, reloc->addend, input_section->owner,
343 input_section, reloc->address)))
344 abort ();
345 }
252b5132
RH
346
347 gap -= dot + 2;
348 bfd_put_16 (abfd, gap, data + dst_address);
349 dst_address += 2;
350 src_address += 2;
351 }
352 break;
353 default:
6e301b2b 354 printf (_("ignoring reloc %s\n"), reloc->howto->name);
252b5132
RH
355 break;
356
357 }
358 *src_ptr = src_address;
359 *dst_ptr = dst_address;
252b5132
RH
360}
361
f4ffd778
NC
362#define coff_reloc16_extra_cases w65_reloc16_extra_cases
363#define coff_reloc16_estimate w65_reloc16_estimate
252b5132 364
2b5c217d
NC
365#ifndef bfd_pe_print_pdata
366#define bfd_pe_print_pdata NULL
367#endif
368
252b5132
RH
369#include "coffcode.h"
370
252b5132
RH
371#undef coff_bfd_get_relocated_section_contents
372#undef coff_bfd_relax_section
373#define coff_bfd_get_relocated_section_contents \
374 bfd_coff_reloc16_get_relocated_section_contents
375#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
376
6d00b590 377CREATE_LITTLE_COFF_TARGET_VEC (w65_coff_vec, "coff-w65", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)
This page took 0.726429 seconds and 4 git commands to generate.