1 /* BFD support for the ns32k architecture.
2 Copyright (C) 1990, 91, 94, 95, 96, 98, 1999 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
);
80 _bfd_ns32k_put_displacement(value
, buffer
, offset
, size
)
90 if (value
< -64 || value
> 63)
96 if (value
< -8192 || value
> 8191)
100 *buffer
++=(value
>>8);
104 if (value
< -0x1f000000 || value
>= 0x20000000)
107 *buffer
++=(value
>>24);
108 *buffer
++=(value
>>16);
109 *buffer
++=(value
>>8);
119 _bfd_ns32k_get_immediate (buffer
, offset
, size
)
129 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
, offset
, size
)
147 buffer
+= offset
+ size
- 1;
151 *buffer
-- = (value
& 0xff); value
>>= 8;
153 *buffer
-- = (value
& 0xff); value
>>= 8;
155 *buffer
-- = (value
& 0xff); value
>>= 8;
157 *buffer
-- = (value
& 0xff); value
>>= 8;
162 /* This is just like the standard perform_relocation except we
163 * use get_data and put_data which know about the ns32k
165 * This is probably a lot more complicated than it needs to be!
167 static bfd_reloc_status_type
168 do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
169 error_message
, get_data
, put_data
)
171 arelent
*reloc_entry
;
172 struct symbol_cache_entry
*symbol
;
174 asection
*input_section
;
176 char **error_message ATTRIBUTE_UNUSED
;
182 bfd_reloc_status_type flag
= bfd_reloc_ok
;
183 bfd_size_type addr
= reloc_entry
->address
;
184 bfd_vma output_base
= 0;
185 reloc_howto_type
*howto
= reloc_entry
->howto
;
186 asection
*reloc_target_output_section
;
188 if ((symbol
->section
== &bfd_abs_section
)
189 && output_bfd
!= (bfd
*) NULL
)
191 reloc_entry
->address
+= input_section
->output_offset
;
195 /* If we are not producing relocateable output, return an error if
196 the symbol is not defined. An undefined weak symbol is
197 considered to have a value of zero (SVR4 ABI, p. 4-27). */
198 if (symbol
->section
== &bfd_und_section
199 && (symbol
->flags
& BSF_WEAK
) == 0
200 && output_bfd
== (bfd
*) NULL
)
201 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
;
218 reloc_target_output_section
= symbol
->section
->output_section
;
220 /* Convert input-section-relative symbol value to absolute. */
221 if (output_bfd
&& howto
->partial_inplace
== false)
224 output_base
= reloc_target_output_section
->vma
;
226 relocation
+= output_base
+ symbol
->section
->output_offset
;
228 /* Add in supplied addend. */
229 relocation
+= reloc_entry
->addend
;
231 /* Here the variable relocation holds the final address of the
232 symbol we are relocating against, plus any addend. */
234 if (howto
->pc_relative
== true)
236 /* This is a PC relative relocation. We want to set RELOCATION
237 to the distance between the address of the symbol and the
238 location. RELOCATION is already the address of the symbol.
240 We start by subtracting the address of the section containing
243 If pcrel_offset is set, we must further subtract the position
244 of the location within the section. Some targets arrange for
245 the addend to be the negative of the position of the location
246 within the section; for example, i386-aout does this. For
247 i386-aout, pcrel_offset is false. Some other targets do not
248 include the position of the location; for example, m88kbcs,
249 or ELF. For those targets, pcrel_offset is true.
251 If we are producing relocateable output, then we must ensure
252 that this reloc will be correctly computed when the final
253 relocation is done. If pcrel_offset is false we want to wind
254 up with the negative of the location within the section,
255 which means we must adjust the existing addend by the change
256 in the location within the section. If pcrel_offset is true
257 we do not want to adjust the existing addend at all.
259 FIXME: This seems logical to me, but for the case of
260 producing relocateable output it is not what the code
261 actually does. I don't want to change it, because it seems
262 far too likely that something will break. */
265 input_section
->output_section
->vma
+ input_section
->output_offset
;
267 if (howto
->pcrel_offset
== true)
268 relocation
-= reloc_entry
->address
;
271 if (output_bfd
!= (bfd
*) NULL
)
273 if (howto
->partial_inplace
== false)
275 /* This is a partial relocation, and we want to apply the relocation
276 to the reloc entry rather than the raw data. Modify the reloc
277 inplace to reflect what we now know. */
278 reloc_entry
->addend
= relocation
;
279 reloc_entry
->address
+= input_section
->output_offset
;
284 /* This is a partial relocation, but inplace, so modify the
287 If we've relocated with a symbol with a section, change
288 into a ref to the section belonging to the symbol. */
290 reloc_entry
->address
+= input_section
->output_offset
;
293 if (abfd
->xvec
->flavour
== bfd_target_coff_flavour
)
296 /* For m68k-coff, the addend was being subtracted twice during
297 relocation with -r. Removing the line below this comment
298 fixes that problem; see PR 2953.
300 However, Ian wrote the following, regarding removing the line below,
301 which explains why it is still enabled: --djm
303 If you put a patch like that into BFD you need to check all the COFF
304 linkers. I am fairly certain that patch will break coff-i386 (e.g.,
305 SCO); see coff_i386_reloc in coff-i386.c where I worked around the
306 problem in a different way. There may very well be a reason that the
307 code works as it does.
309 Hmmm. The first obvious point is that bfd_perform_relocation should
310 not have any tests that depend upon the flavour. It's seem like
311 entirely the wrong place for such a thing. The second obvious point
312 is that the current code ignores the reloc addend when producing
313 relocateable output for COFF. That's peculiar. In fact, I really
314 have no idea what the point of the line you want to remove is.
316 A typical COFF reloc subtracts the old value of the symbol and adds in
317 the new value to the location in the object file (if it's a pc
318 relative reloc it adds the difference between the symbol value and the
319 location). When relocating we need to preserve that property.
321 BFD handles this by setting the addend to the negative of the old
322 value of the symbol. Unfortunately it handles common symbols in a
323 non-standard way (it doesn't subtract the old value) but that's a
324 different story (we can't change it without losing backward
325 compatibility with old object files) (coff-i386 does subtract the old
326 value, to be compatible with existing coff-i386 targets, like SCO).
328 So everything works fine when not producing relocateable output. When
329 we are producing relocateable output, logically we should do exactly
330 what we do when not producing relocateable output. Therefore, your
331 patch is correct. In fact, it should probably always just set
332 reloc_entry->addend to 0 for all cases, since it is, in fact, going to
333 add the value into the object file. This won't hurt the COFF code,
334 which doesn't use the addend; I'm not sure what it will do to other
335 formats (the thing to check for would be whether any formats both use
336 the addend and set partial_inplace).
338 When I wanted to make coff-i386 produce relocateable output, I ran
339 into the problem that you are running into: I wanted to remove that
340 line. Rather than risk it, I made the coff-i386 relocs use a special
341 function; it's coff_i386_reloc in coff-i386.c. The function
342 specifically adds the addend field into the object file, knowing that
343 bfd_perform_relocation is not going to. If you remove that line, then
344 coff-i386.c will wind up adding the addend field in twice. It's
345 trivial to fix; it just needs to be done.
347 The problem with removing the line is just that it may break some
348 working code. With BFD it's hard to be sure of anything. The right
349 way to deal with this is simply to build and test at least all the
350 supported COFF targets. It should be straightforward if time and disk
351 space consuming. For each target:
353 2) generate some executable, and link it using -r (I would
354 probably use paranoia.o and link against newlib/libc.a, which
355 for all the supported targets would be available in
356 /usr/cygnus/progressive/H-host/target/lib/libc.a).
357 3) make the change to reloc.c
358 4) rebuild the linker
360 6) if the resulting object files are the same, you have at least
362 7) if they are different you have to figure out which version is
365 relocation
-= reloc_entry
->addend
;
367 reloc_entry
->addend
= 0;
371 reloc_entry
->addend
= relocation
;
377 reloc_entry
->addend
= 0;
380 /* FIXME: This overflow checking is incomplete, because the value
381 might have overflowed before we get here. For a correct check we
382 need to compute the value in a size larger than bitsize, but we
383 can't reasonably do that for a reloc the same size as a host
385 FIXME: We should also do overflow checking on the result after
386 adding in the value contained in the object file. */
387 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
391 /* Get the value that will be used for the relocation, but
392 starting at bit position zero. */
393 if (howto
->rightshift
> howto
->bitpos
)
394 check
= relocation
>> (howto
->rightshift
- howto
->bitpos
);
396 check
= relocation
<< (howto
->bitpos
- howto
->rightshift
);
397 switch (howto
->complain_on_overflow
)
399 case complain_overflow_signed
:
401 /* Assumes two's complement. */
402 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
403 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
405 /* The above right shift is incorrect for a signed value.
406 Fix it up by forcing on the upper bits. */
407 if (howto
->rightshift
> howto
->bitpos
408 && (bfd_signed_vma
) relocation
< 0)
409 check
|= ((bfd_vma
) - 1
411 >> (howto
->rightshift
- howto
->bitpos
)));
412 if ((bfd_signed_vma
) check
> reloc_signed_max
413 || (bfd_signed_vma
) check
< reloc_signed_min
)
414 flag
= bfd_reloc_overflow
;
417 case complain_overflow_unsigned
:
419 /* Assumes two's complement. This expression avoids
420 overflow if howto->bitsize is the number of bits in
422 bfd_vma reloc_unsigned_max
=
423 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
425 if ((bfd_vma
) check
> reloc_unsigned_max
)
426 flag
= bfd_reloc_overflow
;
429 case complain_overflow_bitfield
:
431 /* Assumes two's complement. This expression avoids
432 overflow if howto->bitsize is the number of bits in
434 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
436 if (((bfd_vma
) check
& ~reloc_bits
) != 0
437 && ((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
439 /* The above right shift is incorrect for a signed
440 value. See if turning on the upper bits fixes the
442 if (howto
->rightshift
> howto
->bitpos
443 && (bfd_signed_vma
) relocation
< 0)
445 check
|= ((bfd_vma
) - 1
447 >> (howto
->rightshift
- howto
->bitpos
)));
448 if (((bfd_vma
) check
& ~reloc_bits
) != (-1 & ~reloc_bits
))
449 flag
= bfd_reloc_overflow
;
452 flag
= bfd_reloc_overflow
;
462 Either we are relocating all the way, or we don't want to apply
463 the relocation to the reloc entry (probably because there isn't
464 any room in the output format to describe addends to relocs)
467 /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
468 (OSF version 1.3, compiler version 3.11). It miscompiles the
482 x <<= (unsigned long) s.i0;
486 printf ("succeeded (%lx)\n", x);
490 relocation
>>= (bfd_vma
) howto
->rightshift
;
492 /* Shift everything up to where it's going to be used */
494 relocation
<<= (bfd_vma
) howto
->bitpos
;
496 /* Wait for the day when all have the mask in them */
499 i instruction to be left alone
500 o offset within instruction
501 r relocation offset to apply
510 i i i i i o o o o o from bfd_get<size>
511 and S S S S S to get the size offset we want
512 + r r r r r r r r r r to get the final value to place
513 and D D D D D to chop to right size
514 -----------------------
517 ... i i i i i o o o o o from bfd_get<size>
518 and N N N N N get instruction
519 -----------------------
525 -----------------------
526 R R R R R R R R R R put into bfd_put<size>
530 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
536 char x
= get_data (data
, addr
, 1);
538 overflow
= put_data(x
, data
, addr
, 1);
545 short x
= get_data (data
, addr
, 2);
547 overflow
= put_data(x
, (unsigned char *) data
, addr
, 2);
553 long x
= get_data (data
, addr
, 4);
555 overflow
= put_data(x
, data
, addr
, 4);
560 long x
= get_data(data
, addr
, 4);
561 relocation
= -relocation
;
563 overflow
= put_data(x
, data
, addr
, 4);
575 bfd_vma x
= get_data (data
, addr
, 8);
577 overflow
= put_data(x
, data
, addr
, 8);
584 return bfd_reloc_other
;
586 if ((howto
->complain_on_overflow
!= complain_overflow_dont
) && overflow
)
587 return bfd_reloc_overflow
;
592 /* Relocate a given location using a given value and howto. */
594 bfd_reloc_status_type
595 _bfd_do_ns32k_reloc_contents ( howto
, input_bfd
, relocation
, location
,
597 reloc_howto_type
*howto
;
598 bfd
*input_bfd ATTRIBUTE_UNUSED
;
608 /* If the size is negative, negate RELOCATION. This isn't very
611 relocation
= -relocation
;
613 /* Get the value we are going to relocate. */
614 size
= bfd_get_reloc_size (howto
);
626 x
= get_data (location
, 0, size
);
630 /* Check for overflow. FIXME: We may drop bits during the addition
631 which we don't check for. We must either check at every single
632 operation, which would be tedious, or we must do the computations
633 in a type larger than bfd_vma, which would be inefficient. */
635 if (howto
->complain_on_overflow
!= complain_overflow_dont
)
638 bfd_signed_vma signed_check
;
640 bfd_signed_vma signed_add
;
642 if (howto
->rightshift
== 0)
645 signed_check
= (bfd_signed_vma
) relocation
;
649 /* Drop unwanted bits from the value we are relocating to. */
650 check
= relocation
>> howto
->rightshift
;
652 /* If this is a signed value, the rightshift just dropped
653 leading 1 bits (assuming twos complement). */
654 if ((bfd_signed_vma
) relocation
>= 0)
655 signed_check
= check
;
657 signed_check
= (check
659 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
662 /* Get the value from the object file. */
663 add
= x
& howto
->src_mask
;
665 /* Get the value from the object file with an appropriate sign.
666 The expression involving howto->src_mask isolates the upper
667 bit of src_mask. If that bit is set in the value we are
668 adding, it is negative, and we subtract out that number times
669 two. If src_mask includes the highest possible bit, then we
670 can not get the upper bit, but that does not matter since
671 signed_add needs no adjustment to become negative in that
674 if ((add
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
675 signed_add
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
677 /* Add the value from the object file, shifted so that it is a
679 if (howto
->bitpos
== 0)
682 signed_check
+= signed_add
;
686 check
+= add
>> howto
->bitpos
;
688 /* For the signed case we use ADD, rather than SIGNED_ADD,
689 to avoid warnings from SVR4 cc. This is OK since we
690 explictly handle the sign bits. */
692 signed_check
+= add
>> howto
->bitpos
;
694 signed_check
+= ((add
>> howto
->bitpos
)
696 & ~((bfd_vma
) - 1 >> howto
->bitpos
)));
699 switch (howto
->complain_on_overflow
)
701 case complain_overflow_signed
:
703 /* Assumes two's complement. */
704 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
705 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
707 if (signed_check
> reloc_signed_max
708 || signed_check
< reloc_signed_min
)
712 case complain_overflow_unsigned
:
714 /* Assumes two's complement. This expression avoids
715 overflow if howto->bitsize is the number of bits in
717 bfd_vma reloc_unsigned_max
=
718 (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
720 if (check
> reloc_unsigned_max
)
724 case complain_overflow_bitfield
:
726 /* Assumes two's complement. This expression avoids
727 overflow if howto->bitsize is the number of bits in
729 bfd_vma reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
731 if ((check
& ~reloc_bits
) != 0
732 && (((bfd_vma
) signed_check
& ~reloc_bits
)
733 != (-1 & ~reloc_bits
)))
742 /* Put RELOCATION in the right bits. */
743 relocation
>>= (bfd_vma
) howto
->rightshift
;
744 relocation
<<= (bfd_vma
) howto
->bitpos
;
746 /* Add RELOCATION to the right bits of X. */
747 x
= ((x
& ~howto
->dst_mask
)
748 | (((x
& howto
->src_mask
) + relocation
) & howto
->dst_mask
));
750 /* Put the relocated value back in the object file. */
762 put_data(x
, location
, 0, size
);
766 return overflow
? bfd_reloc_overflow
: bfd_reloc_ok
;
769 bfd_reloc_status_type
770 _bfd_ns32k_reloc_disp (abfd
, reloc_entry
, symbol
, data
, input_section
,
771 output_bfd
, error_message
)
773 arelent
*reloc_entry
;
774 struct symbol_cache_entry
*symbol
;
776 asection
*input_section
;
778 char **error_message
;
780 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
781 output_bfd
, error_message
,
782 _bfd_ns32k_get_displacement
,
783 _bfd_ns32k_put_displacement
);
786 bfd_reloc_status_type
787 _bfd_ns32k_reloc_imm (abfd
, reloc_entry
, symbol
, data
, input_section
,
788 output_bfd
, error_message
)
790 arelent
*reloc_entry
;
791 struct symbol_cache_entry
*symbol
;
793 asection
*input_section
;
795 char **error_message
;
797 return do_ns32k_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
798 output_bfd
, error_message
, _bfd_ns32k_get_immediate
,
799 _bfd_ns32k_put_immediate
);
802 bfd_reloc_status_type
803 _bfd_ns32k_final_link_relocate (howto
, input_bfd
, input_section
, contents
,
804 address
, value
, addend
)
805 reloc_howto_type
*howto
;
807 asection
*input_section
;
815 /* Sanity check the address. */
816 if (address
> input_section
->_cooked_size
)
817 return bfd_reloc_outofrange
;
819 /* This function assumes that we are dealing with a basic relocation
820 against a symbol. We want to compute the value of the symbol to
821 relocate to. This is just VALUE, the value of the symbol, plus
822 ADDEND, any addend associated with the reloc. */
823 relocation
= value
+ addend
;
825 /* If the relocation is PC relative, we want to set RELOCATION to
826 the distance between the symbol (currently in RELOCATION) and the
827 location we are relocating. Some targets (e.g., i386-aout)
828 arrange for the contents of the section to be the negative of the
829 offset of the location within the section; for such targets
830 pcrel_offset is false. Other targets (e.g., m88kbcs or ELF)
831 simply leave the contents of the section as zero; for such
832 targets pcrel_offset is true. If pcrel_offset is false we do not
833 need to subtract out the offset of the location within the
834 section (which is just ADDRESS). */
835 if (howto
->pc_relative
)
837 relocation
-= (input_section
->output_section
->vma
838 + input_section
->output_offset
);
839 if (howto
->pcrel_offset
)
840 relocation
-= address
;
843 return _bfd_ns32k_relocate_contents (howto
, input_bfd
, relocation
,