1 /* BFD support for the ns32k architecture.
2 Copyright 1990, 1991, 1994, 1995, 1998, 2000, 2001, 2002
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]);
39 static bfd_reloc_status_type do_ns32k_reloc
40 PARAMS ((bfd
*, arelent
*, struct symbol_cache_entry
*, PTR
, asection
*,
42 bfd_vma (*) (bfd_byte
*, int),
43 int (*) (bfd_vma
, bfd_byte
*, int)));
46 _bfd_ns32k_get_displacement (buffer
, size
)
54 value
= ((*buffer
& 0x7f) ^ 0x40) - 0x40;
58 value
= ((*buffer
++ & 0x3f) ^ 0x20) - 0x20;
59 value
= (value
<< 8) | (0xff & *buffer
);
63 value
= ((*buffer
++ & 0x3f) ^ 0x20) - 0x20;
64 value
= (value
<< 8) | (0xff & *buffer
++);
65 value
= (value
<< 8) | (0xff & *buffer
++);
66 value
= (value
<< 8) | (0xff & *buffer
);
77 _bfd_ns32k_put_displacement (value
, buffer
, size
)
85 if (value
+ 0x40 > 0x7f)
92 if (value
+ 0x2000 > 0x3fff)
96 *buffer
++ = (value
>> 8);
101 /* FIXME: is this correct? -0x1f000000 <= value < 0x2000000 */
102 if (value
+ 0x1f000000 > 0x3effffff)
104 value
|= (bfd_vma
) 0xc0000000;
105 *buffer
++ = (value
>> 24);
106 *buffer
++ = (value
>> 16);
107 *buffer
++ = (value
>> 8);
117 _bfd_ns32k_get_immediate (buffer
, size
)
125 value
= (value
<< 8) | (*buffer
++ & 0xff);
126 value
= (value
<< 8) | (*buffer
++ & 0xff);
127 value
= (value
<< 8) | (*buffer
++ & 0xff);
128 value
= (value
<< 8) | (*buffer
++ & 0xff);
130 value
= (value
<< 8) | (*buffer
++ & 0xff);
131 value
= (value
<< 8) | (*buffer
++ & 0xff);
133 value
= (value
<< 8) | (*buffer
++ & 0xff);
135 value
= (value
<< 8) | (*buffer
++ & 0xff);
141 _bfd_ns32k_put_immediate (value
, buffer
, size
)
150 *buffer
-- = (value
& 0xff); value
>>= 8;
151 *buffer
-- = (value
& 0xff); value
>>= 8;
152 *buffer
-- = (value
& 0xff); value
>>= 8;
153 *buffer
-- = (value
& 0xff); value
>>= 8;
155 *buffer
-- = (value
& 0xff); value
>>= 8;
156 *buffer
-- = (value
& 0xff); value
>>= 8;
158 *buffer
-- = (value
& 0xff); value
>>= 8;
160 *buffer
-- = (value
& 0xff); value
>>= 8;
165 /* This is just like the standard perform_relocation except we
166 * use get_data and put_data which know about the ns32k
168 * This is probably a lot more complicated than it needs to be!
170 static bfd_reloc_status_type
171 do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
172 error_message
, get_data
, put_data
)
174 arelent
*reloc_entry
;
175 struct symbol_cache_entry
*symbol
;
177 asection
*input_section
;
179 char **error_message ATTRIBUTE_UNUSED
;
180 bfd_vma (*get_data
) PARAMS ((bfd_byte
*, int));
181 int (*put_data
) PARAMS ((bfd_vma
, bfd_byte
*, int));
185 bfd_reloc_status_type flag
= bfd_reloc_ok
;
186 bfd_size_type addr
= reloc_entry
->address
;
187 bfd_vma output_base
= 0;
188 reloc_howto_type
*howto
= reloc_entry
->howto
;
189 asection
*reloc_target_output_section
;
192 if ((symbol
->section
== &bfd_abs_section
)
193 && output_bfd
!= (bfd
*) NULL
)
195 reloc_entry
->address
+= input_section
->output_offset
;
199 /* If we are not producing relocateable output, return an error if
200 the symbol is not defined. An undefined weak symbol is
201 considered to have a value of zero (SVR4 ABI, p. 4-27). */
202 if (symbol
->section
== &bfd_und_section
203 && (symbol
->flags
& BSF_WEAK
) == 0
204 && output_bfd
== (bfd
*) NULL
)
205 flag
= bfd_reloc_undefined
;
207 /* Is the address of the relocation really within the section? */
208 if (reloc_entry
->address
> input_section
->_cooked_size
)
209 return bfd_reloc_outofrange
;
211 /* Work out which section the relocation is targetted at and the
212 initial relocation command value. */
214 /* Get symbol value. (Common symbols are special.) */
215 if (bfd_is_com_section (symbol
->section
))
218 relocation
= symbol
->value
;
220 reloc_target_output_section
= symbol
->section
->output_section
;
222 /* Convert input-section-relative symbol value to absolute. */
223 if (output_bfd
!= NULL
&& ! howto
->partial_inplace
)
226 output_base
= reloc_target_output_section
->vma
;
228 relocation
+= output_base
+ symbol
->section
->output_offset
;
230 /* Add in supplied addend. */
231 relocation
+= reloc_entry
->addend
;
233 /* Here the variable relocation holds the final address of the
234 symbol we are relocating against, plus any addend. */
236 if (howto
->pc_relative
)
238 /* This is a PC relative relocation. We want to set RELOCATION
239 to the distance between the address of the symbol and the
240 location. RELOCATION is already the address of the symbol.
242 We start by subtracting the address of the section containing
245 If pcrel_offset is set, we must further subtract the position
246 of the location within the section. Some targets arrange for
247 the addend to be the negative of the position of the location
248 within the section; for example, i386-aout does this. For
249 i386-aout, pcrel_offset is false. Some other targets do not
250 include the position of the location; for example, m88kbcs,
251 or ELF. For those targets, pcrel_offset is true.
253 If we are producing relocateable output, then we must ensure
254 that this reloc will be correctly computed when the final
255 relocation is done. If pcrel_offset is false we want to wind
256 up with the negative of the location within the section,
257 which means we must adjust the existing addend by the change
258 in the location within the section. If pcrel_offset is true
259 we do not want to adjust the existing addend at all.
261 FIXME: This seems logical to me, but for the case of
262 producing relocateable output it is not what the code
263 actually does. I don't want to change it, because it seems
264 far too likely that something will break. */
267 input_section
->output_section
->vma
+ input_section
->output_offset
;
269 if (howto
->pcrel_offset
)
270 relocation
-= reloc_entry
->address
;
273 if (output_bfd
!= (bfd
*) NULL
)
275 if (! howto
->partial_inplace
)
277 /* This is a partial relocation, and we want to apply the relocation
278 to the reloc entry rather than the raw data. Modify the reloc
279 inplace to reflect what we now know. */
280 reloc_entry
->addend
= relocation
;
281 reloc_entry
->address
+= input_section
->output_offset
;
286 /* This is a partial relocation, but inplace, so modify the
289 If we've relocated with a symbol with a section, change
290 into a ref to the section belonging to the symbol. */
292 reloc_entry
->address
+= input_section
->output_offset
;
295 if (abfd
->xvec
->flavour
== bfd_target_coff_flavour
)
298 /* For m68k-coff, the addend was being subtracted twice during
299 relocation with -r. Removing the line below this comment
300 fixes that problem; see PR 2953.
302 However, Ian wrote the following, regarding removing the line below,
303 which explains why it is still enabled: --djm
305 If you put a patch like that into BFD you need to check all the COFF
306 linkers. I am fairly certain that patch will break coff-i386 (e.g.,
307 SCO); see coff_i386_reloc in coff-i386.c where I worked around the
308 problem in a different way. There may very well be a reason that the
309 code works as it does.
311 Hmmm. The first obvious point is that bfd_perform_relocation should
312 not have any tests that depend upon the flavour. It's seem like
313 entirely the wrong place for such a thing. The second obvious point
314 is that the current code ignores the reloc addend when producing
315 relocateable output for COFF. That's peculiar. In fact, I really
316 have no idea what the point of the line you want to remove is.
318 A typical COFF reloc subtracts the old value of the symbol and adds in
319 the new value to the location in the object file (if it's a pc
320 relative reloc it adds the difference between the symbol value and the
321 location). When relocating we need to preserve that property.
323 BFD handles this by setting the addend to the negative of the old
324 value of the symbol. Unfortunately it handles common symbols in a
325 non-standard way (it doesn't subtract the old value) but that's a
326 different story (we can't change it without losing backward
327 compatibility with old object files) (coff-i386 does subtract the old
328 value, to be compatible with existing coff-i386 targets, like SCO).
330 So everything works fine when not producing relocateable output. When
331 we are producing relocateable output, logically we should do exactly
332 what we do when not producing relocateable output. Therefore, your
333 patch is correct. In fact, it should probably always just set
334 reloc_entry->addend to 0 for all cases, since it is, in fact, going to
335 add the value into the object file. This won't hurt the COFF code,
336 which doesn't use the addend; I'm not sure what it will do to other
337 formats (the thing to check for would be whether any formats both use
338 the addend and set partial_inplace).
340 When I wanted to make coff-i386 produce relocateable output, I ran
341 into the problem that you are running into: I wanted to remove that
342 line. Rather than risk it, I made the coff-i386 relocs use a special
343 function; it's coff_i386_reloc in coff-i386.c. The function
344 specifically adds the addend field into the object file, knowing that
345 bfd_perform_relocation is not going to. If you remove that line, then
346 coff-i386.c will wind up adding the addend field in twice. It's
347 trivial to fix; it just needs to be done.
349 The problem with removing the line is just that it may break some
350 working code. With BFD it's hard to be sure of anything. The right
351 way to deal with this is simply to build and test at least all the
352 supported COFF targets. It should be straightforward if time and disk
353 space consuming. For each target:
355 2) generate some executable, and link it using -r (I would
356 probably use paranoia.o and link against newlib/libc.a, which
357 for all the supported targets would be available in
358 /usr/cygnus/progressive/H-host/target/lib/libc.a).
359 3) make the change to reloc.c
360 4) rebuild the linker
362 6) if the resulting object files are the same, you have at least
364 7) if they are different you have to figure out which version is
367 relocation
-= reloc_entry
->addend
;
369 reloc_entry
->addend
= 0;
373 reloc_entry
->addend
= relocation
;
379 reloc_entry
->addend
= 0;
382 /* FIXME: This overflow checking is incomplete, because the value
383 might have overflowed before we get here. For a correct check we
384 need to compute the value in a size larger than bitsize, but we
385 can't reasonably do that for a reloc the same size as a host
387 FIXME: We should also do overflow checking on the result after
388 adding in the value contained in the object file. */
389 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
393 /* Get the value that will be used for the relocation, but
394 starting at bit position zero. */
395 if (howto
->rightshift
> howto
->bitpos
)
396 check
= relocation
>> (howto
->rightshift
- howto
->bitpos
);
398 check
= relocation
<< (howto
->bitpos
- howto
->rightshift
);
399 switch (howto
->complain_on_overflow
)
401 case complain_overflow_signed
:
403 /* Assumes two's complement. */
404 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
405 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
407 /* The above right shift is incorrect for a signed value.
408 Fix it up by forcing on the upper bits. */
409 if (howto
->rightshift
> howto
->bitpos
410 && (bfd_signed_vma
) relocation
< 0)
411 check
|= ((bfd_vma
) - 1
413 >> (howto
->rightshift
- howto
->bitpos
)));
414 if ((bfd_signed_vma
) check
> reloc_signed_max
415 || (bfd_signed_vma
) check
< reloc_signed_min
)
416 flag
= bfd_reloc_overflow
;
419 case complain_overflow_unsigned
:
421 /* Assumes two's complement. This expression avoids
422 overflow if howto->bitsize is the number of bits in
424 bfd_vma reloc_unsigned_max
=
425 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
427 if ((bfd_vma
) check
> reloc_unsigned_max
)
428 flag
= bfd_reloc_overflow
;
431 case complain_overflow_bitfield
:
433 /* Assumes two's complement. This expression avoids
434 overflow if howto->bitsize is the number of bits in
436 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
438 if (((bfd_vma
) check
& ~reloc_bits
) != 0
439 && (((bfd_vma
) check
& ~reloc_bits
)
440 != (-(bfd_vma
) 1 & ~reloc_bits
)))
442 /* The above right shift is incorrect for a signed
443 value. See if turning on the upper bits fixes the
445 if (howto
->rightshift
> howto
->bitpos
446 && (bfd_signed_vma
) relocation
< 0)
448 check
|= ((bfd_vma
) - 1
450 >> (howto
->rightshift
- howto
->bitpos
)));
451 if (((bfd_vma
) check
& ~reloc_bits
)
452 != (-(bfd_vma
) 1 & ~reloc_bits
))
453 flag
= bfd_reloc_overflow
;
456 flag
= bfd_reloc_overflow
;
466 Either we are relocating all the way, or we don't want to apply
467 the relocation to the reloc entry (probably because there isn't
468 any room in the output format to describe addends to relocs)
471 /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
472 (OSF version 1.3, compiler version 3.11). It miscompiles the
486 x <<= (unsigned long) s.i0;
490 printf ("succeeded (%lx)\n", x);
494 relocation
>>= (bfd_vma
) howto
->rightshift
;
496 /* Shift everything up to where it's going to be used */
498 relocation
<<= (bfd_vma
) howto
->bitpos
;
500 /* Wait for the day when all have the mask in them */
503 i instruction to be left alone
504 o offset within instruction
505 r relocation offset to apply
514 i i i i i o o o o o from bfd_get<size>
515 and S S S S S to get the size offset we want
516 + r r r r r r r r r r to get the final value to place
517 and D D D D D to chop to right size
518 -----------------------
521 ... i i i i i o o o o o from bfd_get<size>
522 and N N N N N get instruction
523 -----------------------
529 -----------------------
530 R R R R R R R R R R put into bfd_put<size>
534 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
536 location
= (bfd_byte
*) data
+ addr
;
541 char x
= get_data (location
, 1);
543 overflow
= put_data ((bfd_vma
) x
, location
, 1);
550 short x
= get_data (location
, 2);
552 overflow
= put_data ((bfd_vma
) x
, location
, 2);
558 long x
= get_data (location
, 4);
560 overflow
= put_data ((bfd_vma
) x
, location
, 4);
565 long x
= get_data (location
, 4);
566 relocation
= -relocation
;
568 overflow
= put_data ((bfd_vma
) x
, location
, 4);
580 bfd_vma x
= get_data (location
, 8);
582 overflow
= put_data (x
, location
, 8);
589 return bfd_reloc_other
;
591 if ((howto
->complain_on_overflow
!= complain_overflow_dont
) && overflow
)
592 return bfd_reloc_overflow
;
597 /* Relocate a given location using a given value and howto. */
599 bfd_reloc_status_type
600 _bfd_do_ns32k_reloc_contents (howto
, input_bfd
, relocation
, location
,
602 reloc_howto_type
*howto
;
603 bfd
*input_bfd ATTRIBUTE_UNUSED
;
606 bfd_vma (*get_data
) PARAMS ((bfd_byte
*, int));
607 int (*put_data
) PARAMS ((bfd_vma
, bfd_byte
*, int));
613 /* If the size is negative, negate RELOCATION. This isn't very
616 relocation
= -relocation
;
618 /* Get the value we are going to relocate. */
619 size
= bfd_get_reloc_size (howto
);
631 x
= get_data (location
, size
);
635 /* Check for overflow. FIXME: We may drop bits during the addition
636 which we don't check for. We must either check at every single
637 operation, which would be tedious, or we must do the computations
638 in a type larger than bfd_vma, which would be inefficient. */
640 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
643 bfd_signed_vma signed_check
;
645 bfd_signed_vma signed_add
;
647 if (howto
->rightshift
== 0)
650 signed_check
= (bfd_signed_vma
) relocation
;
654 /* Drop unwanted bits from the value we are relocating to. */
655 check
= relocation
>> howto
->rightshift
;
657 /* If this is a signed value, the rightshift just dropped
658 leading 1 bits (assuming twos complement). */
659 if ((bfd_signed_vma
) relocation
>= 0)
660 signed_check
= check
;
662 signed_check
= (check
664 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
667 /* Get the value from the object file. */
668 add
= x
& howto
->src_mask
;
670 /* Get the value from the object file with an appropriate sign.
671 The expression involving howto->src_mask isolates the upper
672 bit of src_mask. If that bit is set in the value we are
673 adding, it is negative, and we subtract out that number times
674 two. If src_mask includes the highest possible bit, then we
675 can not get the upper bit, but that does not matter since
676 signed_add needs no adjustment to become negative in that
679 if ((add
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
680 signed_add
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
682 /* Add the value from the object file, shifted so that it is a
684 if (howto
->bitpos
== 0)
687 signed_check
+= signed_add
;
691 check
+= add
>> howto
->bitpos
;
693 /* For the signed case we use ADD, rather than SIGNED_ADD,
694 to avoid warnings from SVR4 cc. This is OK since we
695 explictly handle the sign bits. */
697 signed_check
+= add
>> howto
->bitpos
;
699 signed_check
+= ((add
>> howto
->bitpos
)
701 & ~((bfd_vma
) - 1 >> howto
->bitpos
)));
704 switch (howto
->complain_on_overflow
)
706 case complain_overflow_signed
:
708 /* Assumes two's complement. */
709 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
710 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
712 if (signed_check
> reloc_signed_max
713 || signed_check
< reloc_signed_min
)
717 case complain_overflow_unsigned
:
719 /* Assumes two's complement. This expression avoids
720 overflow if howto->bitsize is the number of bits in
722 bfd_vma reloc_unsigned_max
=
723 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
725 if (check
> reloc_unsigned_max
)
729 case complain_overflow_bitfield
:
731 /* Assumes two's complement. This expression avoids
732 overflow if howto->bitsize is the number of bits in
734 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
736 if ((check
& ~reloc_bits
) != 0
737 && (((bfd_vma
) signed_check
& ~reloc_bits
)
738 != (-(bfd_vma
) 1 & ~reloc_bits
)))
747 /* Put RELOCATION in the right bits. */
748 relocation
>>= (bfd_vma
) howto
->rightshift
;
749 relocation
<<= (bfd_vma
) howto
->bitpos
;
751 /* Add RELOCATION to the right bits of X. */
752 x
= ((x
& ~howto
->dst_mask
)
753 | (((x
& howto
->src_mask
) + relocation
) & howto
->dst_mask
));
755 /* Put the relocated value back in the object file. */
767 put_data (x
, location
, size
);
771 return overflow
? bfd_reloc_overflow
: bfd_reloc_ok
;
774 bfd_reloc_status_type
775 _bfd_ns32k_reloc_disp (abfd
, reloc_entry
, symbol
, data
, input_section
,
776 output_bfd
, error_message
)
778 arelent
*reloc_entry
;
779 struct symbol_cache_entry
*symbol
;
781 asection
*input_section
;
783 char **error_message
;
785 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
786 output_bfd
, error_message
,
787 _bfd_ns32k_get_displacement
,
788 _bfd_ns32k_put_displacement
);
791 bfd_reloc_status_type
792 _bfd_ns32k_reloc_imm (abfd
, reloc_entry
, symbol
, data
, input_section
,
793 output_bfd
, error_message
)
795 arelent
*reloc_entry
;
796 struct symbol_cache_entry
*symbol
;
798 asection
*input_section
;
800 char **error_message
;
802 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
803 output_bfd
, error_message
, _bfd_ns32k_get_immediate
,
804 _bfd_ns32k_put_immediate
);
807 bfd_reloc_status_type
808 _bfd_ns32k_final_link_relocate (howto
, input_bfd
, input_section
, contents
,
809 address
, value
, addend
)
810 reloc_howto_type
*howto
;
812 asection
*input_section
;
820 /* Sanity check the address. */
821 if (address
> input_section
->_cooked_size
)
822 return bfd_reloc_outofrange
;
824 /* This function assumes that we are dealing with a basic relocation
825 against a symbol. We want to compute the value of the symbol to
826 relocate to. This is just VALUE, the value of the symbol, plus
827 ADDEND, any addend associated with the reloc. */
828 relocation
= value
+ addend
;
830 /* If the relocation is PC relative, we want to set RELOCATION to
831 the distance between the symbol (currently in RELOCATION) and the
832 location we are relocating. Some targets (e.g., i386-aout)
833 arrange for the contents of the section to be the negative of the
834 offset of the location within the section; for such targets
835 pcrel_offset is false. Other targets (e.g., m88kbcs or ELF)
836 simply leave the contents of the section as zero; for such
837 targets pcrel_offset is true. If pcrel_offset is false we do not
838 need to subtract out the offset of the location within the
839 section (which is just ADDRESS). */
840 if (howto
->pc_relative
)
842 relocation
-= (input_section
->output_section
->vma
843 + input_section
->output_offset
);
844 if (howto
->pcrel_offset
)
845 relocation
-= address
;
848 return _bfd_ns32k_relocate_contents (howto
, input_bfd
, relocation
,