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