1 /* BFD support for the ns32k architecture.
2 Copyright (C) 1990, 1991, 1994, 1995 Free Software Foundation, Inc.
3 Almost totally rewritten by Ian Dall from initial work
6 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
11 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #define N(machine, printable, d, next) \
28 { 32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
30 static const bfd_arch_info_type arch_info_struct
[] =
32 N(32532,"ns32k:32532",true, 0), /* the word ns32k will match this too */
35 const bfd_arch_info_type bfd_ns32k_arch
=
36 N(32032,"ns32k:32032",false, &arch_info_struct
[0]);
39 ns32k_sign_extend(value
, bits
)
43 value
= value
& ((1 << bits
) - 1);
44 return (value
& (1 << (bits
-1))
45 ? value
| (~((1 << bits
) - 1))
50 _bfd_ns32k_get_displacement(buffer
, offset
, size
)
60 value
= ns32k_sign_extend (*buffer
, 7);
63 value
= ns32k_sign_extend(*buffer
++, 6);
64 value
= (value
<< 8) | (0xff & *buffer
);
67 value
= ns32k_sign_extend(*buffer
++, 6);
68 value
= (value
<< 8) | (0xff & *buffer
++);
69 value
= (value
<< 8) | (0xff & *buffer
++);
70 value
= (value
<< 8) | (0xff & *buffer
);
77 _bfd_ns32k_put_displacement(value
, buffer
, offset
, size
)
87 if (value
< -64 || value
> 63)
93 if (value
< -8192 || value
> 8191)
101 if (value
< -0x1f000000 || value
>= 0x20000000)
104 *buffer
++=(value
>>24);
105 *buffer
++=(value
>>16);
106 *buffer
++=(value
>>8);
116 _bfd_ns32k_get_immediate (buffer
, offset
, size
)
126 value
= (value
<< 8) | (*buffer
++ & 0xff);
128 value
= (value
<< 8) | (*buffer
++ & 0xff);
130 value
= (value
<< 8) | (*buffer
++ & 0xff);
132 value
= (value
<< 8) | (*buffer
++ & 0xff);
138 _bfd_ns32k_put_immediate (value
, buffer
, offset
, size
)
144 buffer
+= offset
+ size
- 1;
148 *buffer
-- = (value
& 0xff); value
>>= 8;
150 *buffer
-- = (value
& 0xff); value
>>= 8;
152 *buffer
-- = (value
& 0xff); value
>>= 8;
154 *buffer
-- = (value
& 0xff); value
>>= 8;
159 /* This is just like the standard perform_relocation except we
160 * use get_data and put_data which know about the ns32k
162 * This is probably a lot more complicated than it needs to be!
164 static bfd_reloc_status_type
165 do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
166 error_message
, get_data
, put_data
)
168 arelent
*reloc_entry
;
169 struct symbol_cache_entry
*symbol
;
171 asection
*input_section
;
173 char **error_message
;
179 bfd_reloc_status_type flag
= bfd_reloc_ok
;
180 bfd_size_type addr
= reloc_entry
->address
;
181 bfd_vma output_base
= 0;
182 reloc_howto_type
*howto
= reloc_entry
->howto
;
183 asection
*reloc_target_output_section
;
185 if ((symbol
->section
== &bfd_abs_section
)
186 && output_bfd
!= (bfd
*) NULL
)
188 reloc_entry
->address
+= input_section
->output_offset
;
192 /* If we are not producing relocateable output, return an error if
193 the symbol is not defined. An undefined weak symbol is
194 considered to have a value of zero (SVR4 ABI, p. 4-27). */
195 if (symbol
->section
== &bfd_und_section
196 && (symbol
->flags
& BSF_WEAK
) == 0
197 && output_bfd
== (bfd
*) NULL
)
198 flag
= bfd_reloc_undefined
;
201 /* Is the address of the relocation really within the section? */
202 if (reloc_entry
->address
> input_section
->_cooked_size
)
203 return bfd_reloc_outofrange
;
205 /* Work out which section the relocation is targetted at and the
206 initial relocation command value. */
208 /* Get symbol value. (Common symbols are special.) */
209 if (bfd_is_com_section (symbol
->section
))
212 relocation
= symbol
->value
;
215 reloc_target_output_section
= symbol
->section
->output_section
;
217 /* Convert input-section-relative symbol value to absolute. */
218 if (output_bfd
&& howto
->partial_inplace
== false)
221 output_base
= reloc_target_output_section
->vma
;
223 relocation
+= output_base
+ symbol
->section
->output_offset
;
225 /* Add in supplied addend. */
226 relocation
+= reloc_entry
->addend
;
228 /* Here the variable relocation holds the final address of the
229 symbol we are relocating against, plus any addend. */
231 if (howto
->pc_relative
== true)
233 /* This is a PC relative relocation. We want to set RELOCATION
234 to the distance between the address of the symbol and the
235 location. RELOCATION is already the address of the symbol.
237 We start by subtracting the address of the section containing
240 If pcrel_offset is set, we must further subtract the position
241 of the location within the section. Some targets arrange for
242 the addend to be the negative of the position of the location
243 within the section; for example, i386-aout does this. For
244 i386-aout, pcrel_offset is false. Some other targets do not
245 include the position of the location; for example, m88kbcs,
246 or ELF. For those targets, pcrel_offset is true.
248 If we are producing relocateable output, then we must ensure
249 that this reloc will be correctly computed when the final
250 relocation is done. If pcrel_offset is false we want to wind
251 up with the negative of the location within the section,
252 which means we must adjust the existing addend by the change
253 in the location within the section. If pcrel_offset is true
254 we do not want to adjust the existing addend at all.
256 FIXME: This seems logical to me, but for the case of
257 producing relocateable output it is not what the code
258 actually does. I don't want to change it, because it seems
259 far too likely that something will break. */
262 input_section
->output_section
->vma
+ input_section
->output_offset
;
264 if (howto
->pcrel_offset
== true)
265 relocation
-= reloc_entry
->address
;
268 if (output_bfd
!= (bfd
*) NULL
)
270 if (howto
->partial_inplace
== false)
272 /* This is a partial relocation, and we want to apply the relocation
273 to the reloc entry rather than the raw data. Modify the reloc
274 inplace to reflect what we now know. */
275 reloc_entry
->addend
= relocation
;
276 reloc_entry
->address
+= input_section
->output_offset
;
281 /* This is a partial relocation, but inplace, so modify the
284 If we've relocated with a symbol with a section, change
285 into a ref to the section belonging to the symbol. */
287 reloc_entry
->address
+= input_section
->output_offset
;
290 if (abfd
->xvec
->flavour
== bfd_target_coff_flavour
291 && strcmp (abfd
->xvec
->name
, "aixcoff-rs6000") != 0)
294 /* For m68k-coff, the addend was being subtracted twice during
295 relocation with -r. Removing the line below this comment
296 fixes that problem; see PR 2953.
298 However, Ian wrote the following, regarding removing the line below,
299 which explains why it is still enabled: --djm
301 If you put a patch like that into BFD you need to check all the COFF
302 linkers. I am fairly certain that patch will break coff-i386 (e.g.,
303 SCO); see coff_i386_reloc in coff-i386.c where I worked around the
304 problem in a different way. There may very well be a reason that the
305 code works as it does.
307 Hmmm. The first obvious point is that bfd_perform_relocation should
308 not have any tests that depend upon the flavour. It's seem like
309 entirely the wrong place for such a thing. The second obvious point
310 is that the current code ignores the reloc addend when producing
311 relocateable output for COFF. That's peculiar. In fact, I really
312 have no idea what the point of the line you want to remove is.
314 A typical COFF reloc subtracts the old value of the symbol and adds in
315 the new value to the location in the object file (if it's a pc
316 relative reloc it adds the difference between the symbol value and the
317 location). When relocating we need to preserve that property.
319 BFD handles this by setting the addend to the negative of the old
320 value of the symbol. Unfortunately it handles common symbols in a
321 non-standard way (it doesn't subtract the old value) but that's a
322 different story (we can't change it without losing backward
323 compatibility with old object files) (coff-i386 does subtract the old
324 value, to be compatible with existing coff-i386 targets, like SCO).
326 So everything works fine when not producing relocateable output. When
327 we are producing relocateable output, logically we should do exactly
328 what we do when not producing relocateable output. Therefore, your
329 patch is correct. In fact, it should probably always just set
330 reloc_entry->addend to 0 for all cases, since it is, in fact, going to
331 add the value into the object file. This won't hurt the COFF code,
332 which doesn't use the addend; I'm not sure what it will do to other
333 formats (the thing to check for would be whether any formats both use
334 the addend and set partial_inplace).
336 When I wanted to make coff-i386 produce relocateable output, I ran
337 into the problem that you are running into: I wanted to remove that
338 line. Rather than risk it, I made the coff-i386 relocs use a special
339 function; it's coff_i386_reloc in coff-i386.c. The function
340 specifically adds the addend field into the object file, knowing that
341 bfd_perform_relocation is not going to. If you remove that line, then
342 coff-i386.c will wind up adding the addend field in twice. It's
343 trivial to fix; it just needs to be done.
345 The problem with removing the line is just that it may break some
346 working code. With BFD it's hard to be sure of anything. The right
347 way to deal with this is simply to build and test at least all the
348 supported COFF targets. It should be straightforward if time and disk
349 space consuming. For each target:
351 2) generate some executable, and link it using -r (I would
352 probably use paranoia.o and link against newlib/libc.a, which
353 for all the supported targets would be available in
354 /usr/cygnus/progressive/H-host/target/lib/libc.a).
355 3) make the change to reloc.c
356 4) rebuild the linker
358 6) if the resulting object files are the same, you have at least
360 7) if they are different you have to figure out which version is
363 relocation
-= reloc_entry
->addend
;
365 reloc_entry
->addend
= 0;
369 reloc_entry
->addend
= relocation
;
375 reloc_entry
->addend
= 0;
378 /* FIXME: This overflow checking is incomplete, because the value
379 might have overflowed before we get here. For a correct check we
380 need to compute the value in a size larger than bitsize, but we
381 can't reasonably do that for a reloc the same size as a host
383 FIXME: We should also do overflow checking on the result after
384 adding in the value contained in the object file. */
385 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
389 /* Get the value that will be used for the relocation, but
390 starting at bit position zero. */
391 if (howto
->rightshift
> howto
->bitpos
)
392 check
= relocation
>> (howto
->rightshift
- howto
->bitpos
);
394 check
= relocation
<< (howto
->bitpos
- howto
->rightshift
);
395 switch (howto
->complain_on_overflow
)
397 case complain_overflow_signed
:
399 /* Assumes two's complement. */
400 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
401 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
403 /* The above right shift is incorrect for a signed value.
404 Fix it up by forcing on the upper bits. */
405 if (howto
->rightshift
> howto
->bitpos
406 && (bfd_signed_vma
) relocation
< 0)
407 check
|= ((bfd_vma
) - 1
409 >> (howto
->rightshift
- howto
->bitpos
)));
410 if ((bfd_signed_vma
) check
> reloc_signed_max
411 || (bfd_signed_vma
) check
< reloc_signed_min
)
412 flag
= bfd_reloc_overflow
;
415 case complain_overflow_unsigned
:
417 /* Assumes two's complement. This expression avoids
418 overflow if howto->bitsize is the number of bits in
420 bfd_vma reloc_unsigned_max
=
421 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
423 if ((bfd_vma
) check
> reloc_unsigned_max
)
424 flag
= bfd_reloc_overflow
;
427 case complain_overflow_bitfield
:
429 /* Assumes two's complement. This expression avoids
430 overflow if howto->bitsize is the number of bits in
432 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
434 if (((bfd_vma
) check
& ~reloc_bits
) != 0
435 && ((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
437 /* The above right shift is incorrect for a signed
438 value. See if turning on the upper bits fixes the
440 if (howto
->rightshift
> howto
->bitpos
441 && (bfd_signed_vma
) relocation
< 0)
443 check
|= ((bfd_vma
) - 1
445 >> (howto
->rightshift
- howto
->bitpos
)));
446 if (((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
447 flag
= bfd_reloc_overflow
;
450 flag
= bfd_reloc_overflow
;
460 Either we are relocating all the way, or we don't want to apply
461 the relocation to the reloc entry (probably because there isn't
462 any room in the output format to describe addends to relocs)
465 /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
466 (OSF version 1.3, compiler version 3.11). It miscompiles the
480 x <<= (unsigned long) s.i0;
484 printf ("succeeded (%lx)\n", x);
488 relocation
>>= (bfd_vma
) howto
->rightshift
;
490 /* Shift everything up to where it's going to be used */
492 relocation
<<= (bfd_vma
) howto
->bitpos
;
494 /* Wait for the day when all have the mask in them */
497 i instruction to be left alone
498 o offset within instruction
499 r relocation offset to apply
508 i i i i i o o o o o from bfd_get<size>
509 and S S S S S to get the size offset we want
510 + r r r r r r r r r r to get the final value to place
511 and D D D D D to chop to right size
512 -----------------------
515 ... i i i i i o o o o o from bfd_get<size>
516 and N N N N N get instruction
517 -----------------------
523 -----------------------
524 R R R R R R R R R R put into bfd_put<size>
528 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
534 char x
= get_data (data
, addr
, 1);
536 overflow
= put_data(x
, data
, addr
, 1);
543 short x
= get_data (data
, addr
, 2);
545 overflow
= put_data(x
, (unsigned char *) data
, addr
, 2);
551 long x
= get_data (data
, addr
, 4);
553 overflow
= put_data(x
, data
, addr
, 4);
558 long x
= get_data(data
, addr
, 4);
559 relocation
= -relocation
;
561 overflow
= put_data(x
, data
, addr
, 4);
573 bfd_vma x
= get_data (data
, addr
, 8);
575 overflow
= put_data(x
, data
, addr
, 8);
582 return bfd_reloc_other
;
584 if ((howto
->complain_on_overflow
!= complain_overflow_dont
) && overflow
)
585 return bfd_reloc_overflow
;
590 /* Relocate a given location using a given value and howto. */
592 bfd_reloc_status_type
593 _bfd_do_ns32k_reloc_contents ( howto
, input_bfd
, relocation
, location
,
595 reloc_howto_type
*howto
;
606 /* If the size is negative, negate RELOCATION. This isn't very
609 relocation
= -relocation
;
611 /* Get the value we are going to relocate. */
612 size
= bfd_get_reloc_size (howto
);
624 x
= get_data (location
, 0, size
);
628 /* Check for overflow. FIXME: We may drop bits during the addition
629 which we don't check for. We must either check at every single
630 operation, which would be tedious, or we must do the computations
631 in a type larger than bfd_vma, which would be inefficient. */
633 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
636 bfd_signed_vma signed_check
;
638 bfd_signed_vma signed_add
;
640 if (howto
->rightshift
== 0)
643 signed_check
= (bfd_signed_vma
) relocation
;
647 /* Drop unwanted bits from the value we are relocating to. */
648 check
= relocation
>> howto
->rightshift
;
650 /* If this is a signed value, the rightshift just dropped
651 leading 1 bits (assuming twos complement). */
652 if ((bfd_signed_vma
) relocation
>= 0)
653 signed_check
= check
;
655 signed_check
= (check
657 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
660 /* Get the value from the object file. */
661 add
= x
& howto
->src_mask
;
663 /* Get the value from the object file with an appropriate sign.
664 The expression involving howto->src_mask isolates the upper
665 bit of src_mask. If that bit is set in the value we are
666 adding, it is negative, and we subtract out that number times
667 two. If src_mask includes the highest possible bit, then we
668 can not get the upper bit, but that does not matter since
669 signed_add needs no adjustment to become negative in that
672 if ((add
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
673 signed_add
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
675 /* Add the value from the object file, shifted so that it is a
677 if (howto
->bitpos
== 0)
680 signed_check
+= signed_add
;
684 check
+= add
>> howto
->bitpos
;
686 /* For the signed case we use ADD, rather than SIGNED_ADD,
687 to avoid warnings from SVR4 cc. This is OK since we
688 explictly handle the sign bits. */
690 signed_check
+= add
>> howto
->bitpos
;
692 signed_check
+= ((add
>> howto
->bitpos
)
694 & ~((bfd_vma
) - 1 >> howto
->bitpos
)));
697 switch (howto
->complain_on_overflow
)
699 case complain_overflow_signed
:
701 /* Assumes two's complement. */
702 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
703 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
705 if (signed_check
> reloc_signed_max
706 || signed_check
< reloc_signed_min
)
710 case complain_overflow_unsigned
:
712 /* Assumes two's complement. This expression avoids
713 overflow if howto->bitsize is the number of bits in
715 bfd_vma reloc_unsigned_max
=
716 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
718 if (check
> reloc_unsigned_max
)
722 case complain_overflow_bitfield
:
724 /* Assumes two's complement. This expression avoids
725 overflow if howto->bitsize is the number of bits in
727 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
729 if ((check
& ~reloc_bits
) != 0
730 && (((bfd_vma
) signed_check
& ~reloc_bits
)
731 != (-1 & ~reloc_bits
)))
740 /* Put RELOCATION in the right bits. */
741 relocation
>>= (bfd_vma
) howto
->rightshift
;
742 relocation
<<= (bfd_vma
) howto
->bitpos
;
744 /* Add RELOCATION to the right bits of X. */
745 x
= ((x
& ~howto
->dst_mask
)
746 | (((x
& howto
->src_mask
) + relocation
) & howto
->dst_mask
));
748 /* Put the relocated value back in the object file. */
760 put_data(x
, location
, 0, size
);
764 return overflow
? bfd_reloc_overflow
: bfd_reloc_ok
;
767 bfd_reloc_status_type
768 _bfd_ns32k_reloc_disp (abfd
, reloc_entry
, symbol
, data
, input_section
,
769 output_bfd
, error_message
)
771 arelent
*reloc_entry
;
772 struct symbol_cache_entry
*symbol
;
774 asection
*input_section
;
776 char **error_message
;
778 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
779 output_bfd
, error_message
,
780 _bfd_ns32k_get_displacement
,
781 _bfd_ns32k_put_displacement
);
784 bfd_reloc_status_type
785 _bfd_ns32k_reloc_imm (abfd
, reloc_entry
, symbol
, data
, input_section
,
786 output_bfd
, error_message
)
788 arelent
*reloc_entry
;
789 struct symbol_cache_entry
*symbol
;
791 asection
*input_section
;
793 char **error_message
;
795 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
796 output_bfd
, error_message
, _bfd_ns32k_get_immediate
,
797 _bfd_ns32k_put_immediate
);
800 bfd_reloc_status_type
801 _bfd_ns32k_final_link_relocate (howto
, input_bfd
, input_section
, contents
,
802 address
, value
, addend
)
803 reloc_howto_type
*howto
;
805 asection
*input_section
;
813 /* Sanity check the address. */
814 if (address
> input_section
->_cooked_size
)
815 return bfd_reloc_outofrange
;
817 /* This function assumes that we are dealing with a basic relocation
818 against a symbol. We want to compute the value of the symbol to
819 relocate to. This is just VALUE, the value of the symbol, plus
820 ADDEND, any addend associated with the reloc. */
821 relocation
= value
+ addend
;
823 /* If the relocation is PC relative, we want to set RELOCATION to
824 the distance between the symbol (currently in RELOCATION) and the
825 location we are relocating. Some targets (e.g., i386-aout)
826 arrange for the contents of the section to be the negative of the
827 offset of the location within the section; for such targets
828 pcrel_offset is false. Other targets (e.g., m88kbcs or ELF)
829 simply leave the contents of the section as zero; for such
830 targets pcrel_offset is true. If pcrel_offset is false we do not
831 need to subtract out the offset of the location within the
832 section (which is just ADDRESS). */
833 if (howto
->pc_relative
)
835 relocation
-= (input_section
->output_section
->vma
836 + input_section
->output_offset
);
837 if (howto
->pcrel_offset
)
838 relocation
-= address
;
841 return _bfd_ns32k_relocate_contents (howto
, input_bfd
, relocation
,