1 /* BFD support for the ns32k architecture.
2 Copyright 1990, 1991, 1994, 1995, 1998, 2000
3 Free Software Foundation, Inc.
4 Almost totally rewritten by Ian Dall from initial work
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 #define N(machine, printable, d, next) \
29 { 32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
31 static const bfd_arch_info_type arch_info_struct
[] =
33 N(32532,"ns32k:32532",true, 0), /* the word ns32k will match this too */
36 const bfd_arch_info_type bfd_ns32k_arch
=
37 N(32032,"ns32k:32032",false, &arch_info_struct
[0]);
40 ns32k_sign_extend(value
, bits
)
44 value
= value
& ((1 << bits
) - 1);
45 return (value
& (1 << (bits
-1))
46 ? value
| (~((1 << bits
) - 1))
51 _bfd_ns32k_get_displacement(buffer
, offset
, size
)
61 value
= ns32k_sign_extend (*buffer
, 7);
64 value
= ns32k_sign_extend(*buffer
++, 6);
65 value
= (value
<< 8) | (0xff & *buffer
);
68 value
= ns32k_sign_extend(*buffer
++, 6);
69 value
= (value
<< 8) | (0xff & *buffer
++);
70 value
= (value
<< 8) | (0xff & *buffer
++);
71 value
= (value
<< 8) | (0xff & *buffer
);
81 _bfd_ns32k_put_displacement(value
, buffer
, offset
, size
)
91 if (value
< -64 || value
> 63)
97 if (value
< -8192 || value
> 8191)
101 *buffer
++=(value
>>8);
105 if (value
< -0x1f000000 || value
>= 0x20000000)
108 *buffer
++=(value
>>24);
109 *buffer
++=(value
>>16);
110 *buffer
++=(value
>>8);
120 _bfd_ns32k_get_immediate (buffer
, offset
, size
)
130 value
= (value
<< 8) | (*buffer
++ & 0xff);
132 value
= (value
<< 8) | (*buffer
++ & 0xff);
134 value
= (value
<< 8) | (*buffer
++ & 0xff);
136 value
= (value
<< 8) | (*buffer
++ & 0xff);
142 _bfd_ns32k_put_immediate (value
, buffer
, offset
, size
)
148 buffer
+= offset
+ size
- 1;
152 *buffer
-- = (value
& 0xff); value
>>= 8;
154 *buffer
-- = (value
& 0xff); value
>>= 8;
156 *buffer
-- = (value
& 0xff); value
>>= 8;
158 *buffer
-- = (value
& 0xff); value
>>= 8;
163 /* This is just like the standard perform_relocation except we
164 * use get_data and put_data which know about the ns32k
166 * This is probably a lot more complicated than it needs to be!
168 static bfd_reloc_status_type
169 do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
170 error_message
, get_data
, put_data
)
172 arelent
*reloc_entry
;
173 struct symbol_cache_entry
*symbol
;
175 asection
*input_section
;
177 char **error_message ATTRIBUTE_UNUSED
;
183 bfd_reloc_status_type flag
= bfd_reloc_ok
;
184 bfd_size_type addr
= reloc_entry
->address
;
185 bfd_vma output_base
= 0;
186 reloc_howto_type
*howto
= reloc_entry
->howto
;
187 asection
*reloc_target_output_section
;
189 if ((symbol
->section
== &bfd_abs_section
)
190 && output_bfd
!= (bfd
*) NULL
)
192 reloc_entry
->address
+= input_section
->output_offset
;
196 /* If we are not producing relocateable output, return an error if
197 the symbol is not defined. An undefined weak symbol is
198 considered to have a value of zero (SVR4 ABI, p. 4-27). */
199 if (symbol
->section
== &bfd_und_section
200 && (symbol
->flags
& BSF_WEAK
) == 0
201 && output_bfd
== (bfd
*) NULL
)
202 flag
= bfd_reloc_undefined
;
204 /* Is the address of the relocation really within the section? */
205 if (reloc_entry
->address
> input_section
->_cooked_size
)
206 return bfd_reloc_outofrange
;
208 /* Work out which section the relocation is targetted at and the
209 initial relocation command value. */
211 /* Get symbol value. (Common symbols are special.) */
212 if (bfd_is_com_section (symbol
->section
))
215 relocation
= symbol
->value
;
217 reloc_target_output_section
= symbol
->section
->output_section
;
219 /* Convert input-section-relative symbol value to absolute. */
220 if (output_bfd
&& howto
->partial_inplace
== false)
223 output_base
= reloc_target_output_section
->vma
;
225 relocation
+= output_base
+ symbol
->section
->output_offset
;
227 /* Add in supplied addend. */
228 relocation
+= reloc_entry
->addend
;
230 /* Here the variable relocation holds the final address of the
231 symbol we are relocating against, plus any addend. */
233 if (howto
->pc_relative
== true)
235 /* This is a PC relative relocation. We want to set RELOCATION
236 to the distance between the address of the symbol and the
237 location. RELOCATION is already the address of the symbol.
239 We start by subtracting the address of the section containing
242 If pcrel_offset is set, we must further subtract the position
243 of the location within the section. Some targets arrange for
244 the addend to be the negative of the position of the location
245 within the section; for example, i386-aout does this. For
246 i386-aout, pcrel_offset is false. Some other targets do not
247 include the position of the location; for example, m88kbcs,
248 or ELF. For those targets, pcrel_offset is true.
250 If we are producing relocateable output, then we must ensure
251 that this reloc will be correctly computed when the final
252 relocation is done. If pcrel_offset is false we want to wind
253 up with the negative of the location within the section,
254 which means we must adjust the existing addend by the change
255 in the location within the section. If pcrel_offset is true
256 we do not want to adjust the existing addend at all.
258 FIXME: This seems logical to me, but for the case of
259 producing relocateable output it is not what the code
260 actually does. I don't want to change it, because it seems
261 far too likely that something will break. */
264 input_section
->output_section
->vma
+ input_section
->output_offset
;
266 if (howto
->pcrel_offset
== true)
267 relocation
-= reloc_entry
->address
;
270 if (output_bfd
!= (bfd
*) NULL
)
272 if (howto
->partial_inplace
== false)
274 /* This is a partial relocation, and we want to apply the relocation
275 to the reloc entry rather than the raw data. Modify the reloc
276 inplace to reflect what we now know. */
277 reloc_entry
->addend
= relocation
;
278 reloc_entry
->address
+= input_section
->output_offset
;
283 /* This is a partial relocation, but inplace, so modify the
286 If we've relocated with a symbol with a section, change
287 into a ref to the section belonging to the symbol. */
289 reloc_entry
->address
+= input_section
->output_offset
;
292 if (abfd
->xvec
->flavour
== bfd_target_coff_flavour
)
295 /* For m68k-coff, the addend was being subtracted twice during
296 relocation with -r. Removing the line below this comment
297 fixes that problem; see PR 2953.
299 However, Ian wrote the following, regarding removing the line below,
300 which explains why it is still enabled: --djm
302 If you put a patch like that into BFD you need to check all the COFF
303 linkers. I am fairly certain that patch will break coff-i386 (e.g.,
304 SCO); see coff_i386_reloc in coff-i386.c where I worked around the
305 problem in a different way. There may very well be a reason that the
306 code works as it does.
308 Hmmm. The first obvious point is that bfd_perform_relocation should
309 not have any tests that depend upon the flavour. It's seem like
310 entirely the wrong place for such a thing. The second obvious point
311 is that the current code ignores the reloc addend when producing
312 relocateable output for COFF. That's peculiar. In fact, I really
313 have no idea what the point of the line you want to remove is.
315 A typical COFF reloc subtracts the old value of the symbol and adds in
316 the new value to the location in the object file (if it's a pc
317 relative reloc it adds the difference between the symbol value and the
318 location). When relocating we need to preserve that property.
320 BFD handles this by setting the addend to the negative of the old
321 value of the symbol. Unfortunately it handles common symbols in a
322 non-standard way (it doesn't subtract the old value) but that's a
323 different story (we can't change it without losing backward
324 compatibility with old object files) (coff-i386 does subtract the old
325 value, to be compatible with existing coff-i386 targets, like SCO).
327 So everything works fine when not producing relocateable output. When
328 we are producing relocateable output, logically we should do exactly
329 what we do when not producing relocateable output. Therefore, your
330 patch is correct. In fact, it should probably always just set
331 reloc_entry->addend to 0 for all cases, since it is, in fact, going to
332 add the value into the object file. This won't hurt the COFF code,
333 which doesn't use the addend; I'm not sure what it will do to other
334 formats (the thing to check for would be whether any formats both use
335 the addend and set partial_inplace).
337 When I wanted to make coff-i386 produce relocateable output, I ran
338 into the problem that you are running into: I wanted to remove that
339 line. Rather than risk it, I made the coff-i386 relocs use a special
340 function; it's coff_i386_reloc in coff-i386.c. The function
341 specifically adds the addend field into the object file, knowing that
342 bfd_perform_relocation is not going to. If you remove that line, then
343 coff-i386.c will wind up adding the addend field in twice. It's
344 trivial to fix; it just needs to be done.
346 The problem with removing the line is just that it may break some
347 working code. With BFD it's hard to be sure of anything. The right
348 way to deal with this is simply to build and test at least all the
349 supported COFF targets. It should be straightforward if time and disk
350 space consuming. For each target:
352 2) generate some executable, and link it using -r (I would
353 probably use paranoia.o and link against newlib/libc.a, which
354 for all the supported targets would be available in
355 /usr/cygnus/progressive/H-host/target/lib/libc.a).
356 3) make the change to reloc.c
357 4) rebuild the linker
359 6) if the resulting object files are the same, you have at least
361 7) if they are different you have to figure out which version is
364 relocation
-= reloc_entry
->addend
;
366 reloc_entry
->addend
= 0;
370 reloc_entry
->addend
= relocation
;
376 reloc_entry
->addend
= 0;
379 /* FIXME: This overflow checking is incomplete, because the value
380 might have overflowed before we get here. For a correct check we
381 need to compute the value in a size larger than bitsize, but we
382 can't reasonably do that for a reloc the same size as a host
384 FIXME: We should also do overflow checking on the result after
385 adding in the value contained in the object file. */
386 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
390 /* Get the value that will be used for the relocation, but
391 starting at bit position zero. */
392 if (howto
->rightshift
> howto
->bitpos
)
393 check
= relocation
>> (howto
->rightshift
- howto
->bitpos
);
395 check
= relocation
<< (howto
->bitpos
- howto
->rightshift
);
396 switch (howto
->complain_on_overflow
)
398 case complain_overflow_signed
:
400 /* Assumes two's complement. */
401 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
402 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
404 /* The above right shift is incorrect for a signed value.
405 Fix it up by forcing on the upper bits. */
406 if (howto
->rightshift
> howto
->bitpos
407 && (bfd_signed_vma
) relocation
< 0)
408 check
|= ((bfd_vma
) - 1
410 >> (howto
->rightshift
- howto
->bitpos
)));
411 if ((bfd_signed_vma
) check
> reloc_signed_max
412 || (bfd_signed_vma
) check
< reloc_signed_min
)
413 flag
= bfd_reloc_overflow
;
416 case complain_overflow_unsigned
:
418 /* Assumes two's complement. This expression avoids
419 overflow if howto->bitsize is the number of bits in
421 bfd_vma reloc_unsigned_max
=
422 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
424 if ((bfd_vma
) check
> reloc_unsigned_max
)
425 flag
= bfd_reloc_overflow
;
428 case complain_overflow_bitfield
:
430 /* Assumes two's complement. This expression avoids
431 overflow if howto->bitsize is the number of bits in
433 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
435 if (((bfd_vma
) check
& ~reloc_bits
) != 0
436 && ((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
438 /* The above right shift is incorrect for a signed
439 value. See if turning on the upper bits fixes the
441 if (howto
->rightshift
> howto
->bitpos
442 && (bfd_signed_vma
) relocation
< 0)
444 check
|= ((bfd_vma
) - 1
446 >> (howto
->rightshift
- howto
->bitpos
)));
447 if (((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
448 flag
= bfd_reloc_overflow
;
451 flag
= bfd_reloc_overflow
;
461 Either we are relocating all the way, or we don't want to apply
462 the relocation to the reloc entry (probably because there isn't
463 any room in the output format to describe addends to relocs)
466 /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
467 (OSF version 1.3, compiler version 3.11). It miscompiles the
481 x <<= (unsigned long) s.i0;
485 printf ("succeeded (%lx)\n", x);
489 relocation
>>= (bfd_vma
) howto
->rightshift
;
491 /* Shift everything up to where it's going to be used */
493 relocation
<<= (bfd_vma
) howto
->bitpos
;
495 /* Wait for the day when all have the mask in them */
498 i instruction to be left alone
499 o offset within instruction
500 r relocation offset to apply
509 i i i i i o o o o o from bfd_get<size>
510 and S S S S S to get the size offset we want
511 + r r r r r r r r r r to get the final value to place
512 and D D D D D to chop to right size
513 -----------------------
516 ... i i i i i o o o o o from bfd_get<size>
517 and N N N N N get instruction
518 -----------------------
524 -----------------------
525 R R R R R R R R R R put into bfd_put<size>
529 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
535 char x
= get_data (data
, addr
, 1);
537 overflow
= put_data(x
, data
, addr
, 1);
544 short x
= get_data (data
, addr
, 2);
546 overflow
= put_data(x
, (unsigned char *) data
, addr
, 2);
552 long x
= get_data (data
, addr
, 4);
554 overflow
= put_data(x
, data
, addr
, 4);
559 long x
= get_data(data
, addr
, 4);
560 relocation
= -relocation
;
562 overflow
= put_data(x
, data
, addr
, 4);
574 bfd_vma x
= get_data (data
, addr
, 8);
576 overflow
= put_data(x
, data
, addr
, 8);
583 return bfd_reloc_other
;
585 if ((howto
->complain_on_overflow
!= complain_overflow_dont
) && overflow
)
586 return bfd_reloc_overflow
;
591 /* Relocate a given location using a given value and howto. */
593 bfd_reloc_status_type
594 _bfd_do_ns32k_reloc_contents ( howto
, input_bfd
, relocation
, location
,
596 reloc_howto_type
*howto
;
597 bfd
*input_bfd ATTRIBUTE_UNUSED
;
607 /* If the size is negative, negate RELOCATION. This isn't very
610 relocation
= -relocation
;
612 /* Get the value we are going to relocate. */
613 size
= bfd_get_reloc_size (howto
);
625 x
= get_data (location
, 0, size
);
629 /* Check for overflow. FIXME: We may drop bits during the addition
630 which we don't check for. We must either check at every single
631 operation, which would be tedious, or we must do the computations
632 in a type larger than bfd_vma, which would be inefficient. */
634 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
637 bfd_signed_vma signed_check
;
639 bfd_signed_vma signed_add
;
641 if (howto
->rightshift
== 0)
644 signed_check
= (bfd_signed_vma
) relocation
;
648 /* Drop unwanted bits from the value we are relocating to. */
649 check
= relocation
>> howto
->rightshift
;
651 /* If this is a signed value, the rightshift just dropped
652 leading 1 bits (assuming twos complement). */
653 if ((bfd_signed_vma
) relocation
>= 0)
654 signed_check
= check
;
656 signed_check
= (check
658 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
661 /* Get the value from the object file. */
662 add
= x
& howto
->src_mask
;
664 /* Get the value from the object file with an appropriate sign.
665 The expression involving howto->src_mask isolates the upper
666 bit of src_mask. If that bit is set in the value we are
667 adding, it is negative, and we subtract out that number times
668 two. If src_mask includes the highest possible bit, then we
669 can not get the upper bit, but that does not matter since
670 signed_add needs no adjustment to become negative in that
673 if ((add
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
674 signed_add
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
676 /* Add the value from the object file, shifted so that it is a
678 if (howto
->bitpos
== 0)
681 signed_check
+= signed_add
;
685 check
+= add
>> howto
->bitpos
;
687 /* For the signed case we use ADD, rather than SIGNED_ADD,
688 to avoid warnings from SVR4 cc. This is OK since we
689 explictly handle the sign bits. */
691 signed_check
+= add
>> howto
->bitpos
;
693 signed_check
+= ((add
>> howto
->bitpos
)
695 & ~((bfd_vma
) - 1 >> howto
->bitpos
)));
698 switch (howto
->complain_on_overflow
)
700 case complain_overflow_signed
:
702 /* Assumes two's complement. */
703 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
704 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
706 if (signed_check
> reloc_signed_max
707 || signed_check
< reloc_signed_min
)
711 case complain_overflow_unsigned
:
713 /* Assumes two's complement. This expression avoids
714 overflow if howto->bitsize is the number of bits in
716 bfd_vma reloc_unsigned_max
=
717 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
719 if (check
> reloc_unsigned_max
)
723 case complain_overflow_bitfield
:
725 /* Assumes two's complement. This expression avoids
726 overflow if howto->bitsize is the number of bits in
728 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
730 if ((check
& ~reloc_bits
) != 0
731 && (((bfd_vma
) signed_check
& ~reloc_bits
)
732 != (-1 & ~reloc_bits
)))
741 /* Put RELOCATION in the right bits. */
742 relocation
>>= (bfd_vma
) howto
->rightshift
;
743 relocation
<<= (bfd_vma
) howto
->bitpos
;
745 /* Add RELOCATION to the right bits of X. */
746 x
= ((x
& ~howto
->dst_mask
)
747 | (((x
& howto
->src_mask
) + relocation
) & howto
->dst_mask
));
749 /* Put the relocated value back in the object file. */
761 put_data(x
, location
, 0, size
);
765 return overflow
? bfd_reloc_overflow
: bfd_reloc_ok
;
768 bfd_reloc_status_type
769 _bfd_ns32k_reloc_disp (abfd
, reloc_entry
, symbol
, data
, input_section
,
770 output_bfd
, error_message
)
772 arelent
*reloc_entry
;
773 struct symbol_cache_entry
*symbol
;
775 asection
*input_section
;
777 char **error_message
;
779 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
780 output_bfd
, error_message
,
781 _bfd_ns32k_get_displacement
,
782 _bfd_ns32k_put_displacement
);
785 bfd_reloc_status_type
786 _bfd_ns32k_reloc_imm (abfd
, reloc_entry
, symbol
, data
, input_section
,
787 output_bfd
, error_message
)
789 arelent
*reloc_entry
;
790 struct symbol_cache_entry
*symbol
;
792 asection
*input_section
;
794 char **error_message
;
796 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
797 output_bfd
, error_message
, _bfd_ns32k_get_immediate
,
798 _bfd_ns32k_put_immediate
);
801 bfd_reloc_status_type
802 _bfd_ns32k_final_link_relocate (howto
, input_bfd
, input_section
, contents
,
803 address
, value
, addend
)
804 reloc_howto_type
*howto
;
806 asection
*input_section
;
814 /* Sanity check the address. */
815 if (address
> input_section
->_cooked_size
)
816 return bfd_reloc_outofrange
;
818 /* This function assumes that we are dealing with a basic relocation
819 against a symbol. We want to compute the value of the symbol to
820 relocate to. This is just VALUE, the value of the symbol, plus
821 ADDEND, any addend associated with the reloc. */
822 relocation
= value
+ addend
;
824 /* If the relocation is PC relative, we want to set RELOCATION to
825 the distance between the symbol (currently in RELOCATION) and the
826 location we are relocating. Some targets (e.g., i386-aout)
827 arrange for the contents of the section to be the negative of the
828 offset of the location within the section; for such targets
829 pcrel_offset is false. Other targets (e.g., m88kbcs or ELF)
830 simply leave the contents of the section as zero; for such
831 targets pcrel_offset is true. If pcrel_offset is false we do not
832 need to subtract out the offset of the location within the
833 section (which is just ADDRESS). */
834 if (howto
->pc_relative
)
836 relocation
-= (input_section
->output_section
->vma
837 + input_section
->output_offset
);
838 if (howto
->pcrel_offset
)
839 relocation
-= address
;
842 return _bfd_ns32k_relocate_contents (howto
, input_bfd
, relocation
,