Home | History | Annotate | Line # | Download | only in bfd
      1       1.1  christos /* BFD support for the ns32k architecture.
      2  1.1.1.10  christos    Copyright (C) 1990-2024 Free Software Foundation, Inc.
      3       1.1  christos    Almost totally rewritten by Ian Dall from initial work
      4       1.1  christos    by Andrew Cagney.
      5       1.1  christos 
      6       1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      7       1.1  christos 
      8       1.1  christos    This program is free software; you can redistribute it and/or modify
      9       1.1  christos    it under the terms of the GNU General Public License as published by
     10       1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11       1.1  christos    (at your option) any later version.
     12       1.1  christos 
     13       1.1  christos    This program is distributed in the hope that it will be useful,
     14       1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15       1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16       1.1  christos    GNU General Public License for more details.
     17       1.1  christos 
     18       1.1  christos    You should have received a copy of the GNU General Public License
     19       1.1  christos    along with this program; if not, write to the Free Software
     20       1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21       1.1  christos    MA 02110-1301, USA.  */
     22       1.1  christos 
     23       1.1  christos #include "sysdep.h"
     24       1.1  christos #include "bfd.h"
     25       1.1  christos #include "libbfd.h"
     26       1.1  christos #include "ns32k.h"
     27       1.1  christos 
     28       1.1  christos #define N(machine, printable, d, next)  \
     29   1.1.1.8  christos  { 32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d, \
     30   1.1.1.8  christos    bfd_default_compatible,bfd_default_scan,bfd_arch_default_fill,next, 0 }
     31       1.1  christos 
     32       1.1  christos static const bfd_arch_info_type arch_info_struct[] =
     33       1.1  christos {
     34   1.1.1.9  christos   N (32532, "ns32k:32532", true, 0), /* The word ns32k will match this too.  */
     35       1.1  christos };
     36       1.1  christos 
     37       1.1  christos const bfd_arch_info_type bfd_ns32k_arch =
     38   1.1.1.9  christos   N (32032, "ns32k:32032", false, &arch_info_struct[0]);
     39       1.1  christos 
     40       1.1  christos bfd_vma
     41   1.1.1.2  christos _bfd_ns32k_get_displacement (bfd_byte *buffer, int size)
     42       1.1  christos {
     43       1.1  christos   bfd_signed_vma value;
     44       1.1  christos 
     45       1.1  christos   switch (size)
     46       1.1  christos     {
     47       1.1  christos     case 1:
     48       1.1  christos       value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
     49       1.1  christos       break;
     50       1.1  christos 
     51       1.1  christos     case 2:
     52       1.1  christos       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
     53       1.1  christos       value = (value << 8) | (0xff & *buffer);
     54       1.1  christos       break;
     55       1.1  christos 
     56       1.1  christos     case 4:
     57       1.1  christos       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
     58       1.1  christos       value = (value << 8) | (0xff & *buffer++);
     59       1.1  christos       value = (value << 8) | (0xff & *buffer++);
     60       1.1  christos       value = (value << 8) | (0xff & *buffer);
     61       1.1  christos       break;
     62       1.1  christos 
     63       1.1  christos     default:
     64       1.1  christos       abort ();
     65       1.1  christos       return 0;
     66       1.1  christos     }
     67       1.1  christos 
     68       1.1  christos   return value;
     69       1.1  christos }
     70       1.1  christos 
     71       1.1  christos void
     72   1.1.1.2  christos _bfd_ns32k_put_displacement (bfd_vma value, bfd_byte *buffer, int size)
     73       1.1  christos {
     74       1.1  christos   switch (size)
     75       1.1  christos     {
     76       1.1  christos     case 1:
     77       1.1  christos       value &= 0x7f;
     78       1.1  christos       *buffer++ = value;
     79       1.1  christos       break;
     80       1.1  christos 
     81       1.1  christos     case 2:
     82       1.1  christos       value &= 0x3fff;
     83       1.1  christos       value |= 0x8000;
     84       1.1  christos       *buffer++ = (value >> 8);
     85       1.1  christos       *buffer++ = value;
     86       1.1  christos       break;
     87       1.1  christos 
     88       1.1  christos     case 4:
     89       1.1  christos       value |= (bfd_vma) 0xc0000000;
     90       1.1  christos       *buffer++ = (value >> 24);
     91       1.1  christos       *buffer++ = (value >> 16);
     92       1.1  christos       *buffer++ = (value >> 8);
     93       1.1  christos       *buffer++ = value;
     94       1.1  christos       break;
     95       1.1  christos   }
     96       1.1  christos   return;
     97       1.1  christos }
     98       1.1  christos 
     99       1.1  christos bfd_vma
    100   1.1.1.2  christos _bfd_ns32k_get_immediate (bfd_byte *buffer, int size)
    101       1.1  christos {
    102       1.1  christos   bfd_vma value = 0;
    103       1.1  christos 
    104       1.1  christos   switch (size)
    105       1.1  christos     {
    106       1.1  christos     case 4:
    107       1.1  christos       value = (value << 8) | (*buffer++ & 0xff);
    108       1.1  christos       value = (value << 8) | (*buffer++ & 0xff);
    109   1.1.1.6  christos       /* Fall through.  */
    110       1.1  christos     case 2:
    111       1.1  christos       value = (value << 8) | (*buffer++ & 0xff);
    112   1.1.1.6  christos       /* Fall through.  */
    113       1.1  christos     case 1:
    114       1.1  christos       value = (value << 8) | (*buffer++ & 0xff);
    115       1.1  christos       break;
    116       1.1  christos     default:
    117       1.1  christos       abort ();
    118       1.1  christos     }
    119       1.1  christos   return value;
    120       1.1  christos }
    121       1.1  christos 
    122       1.1  christos void
    123   1.1.1.2  christos _bfd_ns32k_put_immediate (bfd_vma value, bfd_byte *buffer, int size)
    124       1.1  christos {
    125       1.1  christos   buffer += size - 1;
    126       1.1  christos   switch (size)
    127       1.1  christos     {
    128       1.1  christos     case 4:
    129       1.1  christos       *buffer-- = (value & 0xff); value >>= 8;
    130       1.1  christos       *buffer-- = (value & 0xff); value >>= 8;
    131   1.1.1.6  christos       /* Fall through.  */
    132       1.1  christos     case 2:
    133       1.1  christos       *buffer-- = (value & 0xff); value >>= 8;
    134   1.1.1.6  christos       /* Fall through.  */
    135       1.1  christos     case 1:
    136       1.1  christos       *buffer-- = (value & 0xff); value >>= 8;
    137       1.1  christos     }
    138       1.1  christos }
    139       1.1  christos 
    140       1.1  christos /* This is just like the standard perform_relocation except we
    141       1.1  christos    use get_data and put_data which know about the ns32k storage
    142       1.1  christos    methods.  This is probably a lot more complicated than it
    143       1.1  christos    needs to be!  */
    144       1.1  christos 
    145       1.1  christos static bfd_reloc_status_type
    146   1.1.1.2  christos do_ns32k_reloc (bfd *      abfd,
    147   1.1.1.2  christos 		arelent *  reloc_entry,
    148   1.1.1.2  christos 		struct bfd_symbol * symbol,
    149   1.1.1.2  christos 		void *     data,
    150   1.1.1.2  christos 		asection * input_section,
    151   1.1.1.2  christos 		bfd *      output_bfd,
    152   1.1.1.2  christos 		char **    error_message ATTRIBUTE_UNUSED,
    153   1.1.1.2  christos 		bfd_vma (* get_data) (bfd_byte *, int),
    154   1.1.1.2  christos 		void (*    put_data) (bfd_vma, bfd_byte *, int))
    155       1.1  christos {
    156       1.1  christos   int overflow = 0;
    157       1.1  christos   bfd_vma relocation;
    158       1.1  christos   bfd_reloc_status_type flag = bfd_reloc_ok;
    159       1.1  christos   bfd_size_type addr = reloc_entry->address;
    160       1.1  christos   bfd_vma output_base = 0;
    161       1.1  christos   reloc_howto_type *howto = reloc_entry->howto;
    162       1.1  christos   asection *reloc_target_output_section;
    163       1.1  christos   bfd_byte *location;
    164       1.1  christos 
    165   1.1.1.2  christos   if (bfd_is_abs_section (symbol->section)
    166       1.1  christos       && output_bfd != (bfd *) NULL)
    167       1.1  christos     {
    168       1.1  christos       reloc_entry->address += input_section->output_offset;
    169       1.1  christos       return bfd_reloc_ok;
    170       1.1  christos     }
    171       1.1  christos 
    172       1.1  christos   /* If we are not producing relocatable output, return an error if
    173       1.1  christos      the symbol is not defined.  An undefined weak symbol is
    174       1.1  christos      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
    175   1.1.1.2  christos   if (bfd_is_und_section (symbol->section)
    176       1.1  christos       && (symbol->flags & BSF_WEAK) == 0
    177       1.1  christos       && output_bfd == (bfd *) NULL)
    178       1.1  christos     flag = bfd_reloc_undefined;
    179       1.1  christos 
    180       1.1  christos   /* Is the address of the relocation really within the section?  */
    181       1.1  christos   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
    182       1.1  christos     return bfd_reloc_outofrange;
    183       1.1  christos 
    184       1.1  christos   /* Work out which section the relocation is targeted at and the
    185       1.1  christos      initial relocation command value.  */
    186       1.1  christos 
    187       1.1  christos   /* Get symbol value.  (Common symbols are special.)  */
    188       1.1  christos   if (bfd_is_com_section (symbol->section))
    189       1.1  christos     relocation = 0;
    190       1.1  christos   else
    191       1.1  christos     relocation = symbol->value;
    192       1.1  christos 
    193       1.1  christos   reloc_target_output_section = symbol->section->output_section;
    194       1.1  christos 
    195       1.1  christos   /* Convert input-section-relative symbol value to absolute.  */
    196       1.1  christos   if (output_bfd != NULL && ! howto->partial_inplace)
    197       1.1  christos     output_base = 0;
    198       1.1  christos   else
    199       1.1  christos     output_base = reloc_target_output_section->vma;
    200       1.1  christos 
    201       1.1  christos   relocation += output_base + symbol->section->output_offset;
    202       1.1  christos 
    203       1.1  christos   /* Add in supplied addend.  */
    204       1.1  christos   relocation += reloc_entry->addend;
    205       1.1  christos 
    206       1.1  christos   /* Here the variable relocation holds the final address of the
    207       1.1  christos      symbol we are relocating against, plus any addend.  */
    208       1.1  christos 
    209       1.1  christos   if (howto->pc_relative)
    210       1.1  christos     {
    211       1.1  christos       /* This is a PC relative relocation.  We want to set RELOCATION
    212       1.1  christos 	 to the distance between the address of the symbol and the
    213       1.1  christos 	 location.  RELOCATION is already the address of the symbol.
    214       1.1  christos 
    215       1.1  christos 	 We start by subtracting the address of the section containing
    216       1.1  christos 	 the location.
    217       1.1  christos 
    218       1.1  christos 	 If pcrel_offset is set, we must further subtract the position
    219       1.1  christos 	 of the location within the section.  Some targets arrange for
    220       1.1  christos 	 the addend to be the negative of the position of the location
    221       1.1  christos 	 within the section; for example, i386-aout does this.  For
    222       1.1  christos 	 i386-aout, pcrel_offset is FALSE.  Some other targets do not
    223   1.1.1.7  christos 	 include the position of the location; for example, ELF.
    224   1.1.1.7  christos 	 For those targets, pcrel_offset is TRUE.
    225       1.1  christos 
    226       1.1  christos 	 If we are producing relocatable output, then we must ensure
    227       1.1  christos 	 that this reloc will be correctly computed when the final
    228       1.1  christos 	 relocation is done.  If pcrel_offset is FALSE we want to wind
    229       1.1  christos 	 up with the negative of the location within the section,
    230       1.1  christos 	 which means we must adjust the existing addend by the change
    231       1.1  christos 	 in the location within the section.  If pcrel_offset is TRUE
    232       1.1  christos 	 we do not want to adjust the existing addend at all.
    233       1.1  christos 
    234       1.1  christos 	 FIXME: This seems logical to me, but for the case of
    235       1.1  christos 	 producing relocatable output it is not what the code
    236       1.1  christos 	 actually does.  I don't want to change it, because it seems
    237       1.1  christos 	 far too likely that something will break.  */
    238       1.1  christos       relocation -=
    239       1.1  christos 	input_section->output_section->vma + input_section->output_offset;
    240       1.1  christos 
    241       1.1  christos       if (howto->pcrel_offset)
    242       1.1  christos 	relocation -= reloc_entry->address;
    243       1.1  christos     }
    244       1.1  christos 
    245       1.1  christos   if (output_bfd != (bfd *) NULL)
    246       1.1  christos     {
    247       1.1  christos       if (! howto->partial_inplace)
    248       1.1  christos 	{
    249       1.1  christos 	  /* This is a partial relocation, and we want to apply the relocation
    250       1.1  christos 	     to the reloc entry rather than the raw data. Modify the reloc
    251       1.1  christos 	     inplace to reflect what we now know.  */
    252       1.1  christos 	  reloc_entry->addend = relocation;
    253       1.1  christos 	  reloc_entry->address += input_section->output_offset;
    254       1.1  christos 	  return flag;
    255       1.1  christos 	}
    256       1.1  christos       else
    257       1.1  christos 	{
    258       1.1  christos 	  /* This is a partial relocation, but inplace, so modify the
    259       1.1  christos 	     reloc record a bit.
    260       1.1  christos 
    261       1.1  christos 	     If we've relocated with a symbol with a section, change
    262       1.1  christos 	     into a ref to the section belonging to the symbol.  */
    263       1.1  christos 
    264       1.1  christos 	  reloc_entry->address += input_section->output_offset;
    265       1.1  christos 
    266       1.1  christos 	  /* WTF?? */
    267       1.1  christos 	  if (abfd->xvec->flavour == bfd_target_coff_flavour)
    268       1.1  christos 	    {
    269       1.1  christos 	      /* For m68k-coff, the addend was being subtracted twice during
    270       1.1  christos 		 relocation with -r.  Removing the line below this comment
    271       1.1  christos 		 fixes that problem; see PR 2953.
    272       1.1  christos 
    273       1.1  christos 		 However, Ian wrote the following, regarding removing the line
    274       1.1  christos 		 below, which explains why it is still enabled:  --djm
    275       1.1  christos 
    276       1.1  christos 		 If you put a patch like that into BFD you need to check all
    277       1.1  christos 		 the COFF linkers.  I am fairly certain that patch will break
    278       1.1  christos 		 coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
    279       1.1  christos 		 where I worked around the problem in a different way.  There
    280       1.1  christos 		 may very well be a reason that the code works as it does.
    281       1.1  christos 
    282       1.1  christos 		 Hmmm.  The first obvious point is that bfd_perform_relocation
    283       1.1  christos 		 should not have any tests that depend upon the flavour.  It's
    284       1.1  christos 		 seem like entirely the wrong place for such a thing.  The
    285       1.1  christos 		 second obvious point is that the current code ignores the
    286       1.1  christos 		 reloc addend when producing relocatable output for COFF.
    287       1.1  christos 		 That's peculiar.  In fact, I really have no idea what the
    288       1.1  christos 		 point of the line you want to remove is.
    289       1.1  christos 
    290       1.1  christos 		 A typical COFF reloc subtracts the old value of the symbol
    291       1.1  christos 		 and adds in the new value to the location in the object file
    292       1.1  christos 		 (if it's a pc relative reloc it adds the difference between
    293       1.1  christos 		 the symbol value and the location).  When relocating we need
    294       1.1  christos 		 to preserve that property.
    295       1.1  christos 
    296       1.1  christos 		 BFD handles this by setting the addend to the negative of the
    297       1.1  christos 		 old value of the symbol.  Unfortunately it handles common
    298       1.1  christos 		 symbols in a non-standard way (it doesn't subtract the old
    299       1.1  christos 		 value) but that's a different story (we can't change it
    300       1.1  christos 		 without losing backward compatibility with old object files)
    301       1.1  christos 		 (coff-i386 does subtract the old value, to be compatible with
    302       1.1  christos 		 existing coff-i386 targets, like SCO).
    303       1.1  christos 
    304       1.1  christos 		 So everything works fine when not producing relocatable
    305       1.1  christos 		 output.  When we are producing relocatable output, logically
    306       1.1  christos 		 we should do exactly what we do when not producing
    307       1.1  christos 		 relocatable output.  Therefore, your patch is correct.  In
    308       1.1  christos 		 fact, it should probably always just set reloc_entry->addend
    309       1.1  christos 		 to 0 for all cases, since it is, in fact, going to add the
    310       1.1  christos 		 value into the object file.  This won't hurt the COFF code,
    311       1.1  christos 		 which doesn't use the addend; I'm not sure what it will do
    312       1.1  christos 		 to other formats (the thing to check for would be whether
    313       1.1  christos 		 any formats both use the addend and set partial_inplace).
    314       1.1  christos 
    315       1.1  christos 		 When I wanted to make coff-i386 produce relocatable output,
    316       1.1  christos 		 I ran into the problem that you are running into: I wanted
    317       1.1  christos 		 to remove that line.  Rather than risk it, I made the
    318       1.1  christos 		 coff-i386 relocs use a special function; it's coff_i386_reloc
    319       1.1  christos 		 in coff-i386.c.  The function specifically adds the addend
    320       1.1  christos 		 field into the object file, knowing that bfd_perform_relocation
    321       1.1  christos 		 is not going to.  If you remove that line, then coff-i386.c
    322       1.1  christos 		 will wind up adding the addend field in twice.  It's trivial
    323       1.1  christos 		 to fix; it just needs to be done.
    324       1.1  christos 
    325       1.1  christos 		 The problem with removing the line is just that it may break
    326       1.1  christos 		 some working code.  With BFD it's hard to be sure of anything.
    327       1.1  christos 		 The right way to deal with this is simply to build and test at
    328       1.1  christos 		 least all the supported COFF targets.  It should be
    329       1.1  christos 		 straightforward if time and disk space consuming.  For each
    330       1.1  christos 		 target:
    331       1.1  christos 		   1) build the linker
    332       1.1  christos 		   2) generate some executable, and link it using -r (I would
    333       1.1  christos 		      probably use paranoia.o and link against newlib/libc.a,
    334       1.1  christos 		      which for all the supported targets would be available in
    335       1.1  christos 		      /usr/cygnus/progressive/H-host/target/lib/libc.a).
    336       1.1  christos 		   3) make the change to reloc.c
    337       1.1  christos 		   4) rebuild the linker
    338       1.1  christos 		   5) repeat step 2
    339       1.1  christos 		   6) if the resulting object files are the same, you have at
    340       1.1  christos 		      least made it no worse
    341       1.1  christos 		   7) if they are different you have to figure out which
    342       1.1  christos 		      version is right.  */
    343       1.1  christos 	      relocation -= reloc_entry->addend;
    344       1.1  christos 	      reloc_entry->addend = 0;
    345       1.1  christos 	    }
    346       1.1  christos 	  else
    347       1.1  christos 	    {
    348       1.1  christos 	      reloc_entry->addend = relocation;
    349       1.1  christos 	    }
    350       1.1  christos 	}
    351       1.1  christos     }
    352       1.1  christos   else
    353       1.1  christos     {
    354       1.1  christos       reloc_entry->addend = 0;
    355       1.1  christos     }
    356       1.1  christos 
    357       1.1  christos   /* FIXME: This overflow checking is incomplete, because the value
    358       1.1  christos      might have overflowed before we get here.  For a correct check we
    359       1.1  christos      need to compute the value in a size larger than bitsize, but we
    360       1.1  christos      can't reasonably do that for a reloc the same size as a host
    361       1.1  christos      machine word.
    362       1.1  christos      FIXME: We should also do overflow checking on the result after
    363       1.1  christos      adding in the value contained in the object file.  */
    364       1.1  christos   if (howto->complain_on_overflow != complain_overflow_dont)
    365       1.1  christos     {
    366       1.1  christos       bfd_vma check;
    367       1.1  christos 
    368       1.1  christos       /* Get the value that will be used for the relocation, but
    369       1.1  christos 	 starting at bit position zero.  */
    370       1.1  christos       if (howto->rightshift > howto->bitpos)
    371       1.1  christos 	check = relocation >> (howto->rightshift - howto->bitpos);
    372       1.1  christos       else
    373       1.1  christos 	check = relocation << (howto->bitpos - howto->rightshift);
    374       1.1  christos       switch (howto->complain_on_overflow)
    375       1.1  christos 	{
    376       1.1  christos 	case complain_overflow_signed:
    377       1.1  christos 	  {
    378       1.1  christos 	    /* Assumes two's complement.  */
    379       1.1  christos 	    bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
    380       1.1  christos 	    bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
    381       1.1  christos 
    382       1.1  christos 	    /* The above right shift is incorrect for a signed value.
    383       1.1  christos 	       Fix it up by forcing on the upper bits.  */
    384       1.1  christos 	    if (howto->rightshift > howto->bitpos
    385       1.1  christos 		&& (bfd_signed_vma) relocation < 0)
    386       1.1  christos 	      check |= ((bfd_vma) - 1
    387       1.1  christos 			& ~((bfd_vma) - 1
    388       1.1  christos 			    >> (howto->rightshift - howto->bitpos)));
    389       1.1  christos 	    if ((bfd_signed_vma) check > reloc_signed_max
    390       1.1  christos 		|| (bfd_signed_vma) check < reloc_signed_min)
    391       1.1  christos 	      flag = bfd_reloc_overflow;
    392       1.1  christos 	  }
    393       1.1  christos 	  break;
    394       1.1  christos 	case complain_overflow_unsigned:
    395       1.1  christos 	  {
    396       1.1  christos 	    /* Assumes two's complement.  This expression avoids
    397       1.1  christos 	       overflow if howto->bitsize is the number of bits in
    398       1.1  christos 	       bfd_vma.  */
    399       1.1  christos 	    bfd_vma reloc_unsigned_max =
    400       1.1  christos 	    (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
    401       1.1  christos 
    402       1.1  christos 	    if ((bfd_vma) check > reloc_unsigned_max)
    403       1.1  christos 	      flag = bfd_reloc_overflow;
    404       1.1  christos 	  }
    405       1.1  christos 	  break;
    406       1.1  christos 	case complain_overflow_bitfield:
    407       1.1  christos 	  {
    408       1.1  christos 	    /* Assumes two's complement.  This expression avoids
    409       1.1  christos 	       overflow if howto->bitsize is the number of bits in
    410       1.1  christos 	       bfd_vma.  */
    411       1.1  christos 	    bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
    412       1.1  christos 
    413       1.1  christos 	    if (((bfd_vma) check & ~reloc_bits) != 0
    414       1.1  christos 		&& (((bfd_vma) check & ~reloc_bits)
    415       1.1  christos 		    != (-(bfd_vma) 1 & ~reloc_bits)))
    416       1.1  christos 	      {
    417       1.1  christos 		/* The above right shift is incorrect for a signed
    418       1.1  christos 		   value.  See if turning on the upper bits fixes the
    419       1.1  christos 		   overflow.  */
    420       1.1  christos 		if (howto->rightshift > howto->bitpos
    421       1.1  christos 		    && (bfd_signed_vma) relocation < 0)
    422       1.1  christos 		  {
    423       1.1  christos 		    check |= ((bfd_vma) - 1
    424       1.1  christos 			      & ~((bfd_vma) - 1
    425       1.1  christos 				  >> (howto->rightshift - howto->bitpos)));
    426       1.1  christos 		    if (((bfd_vma) check & ~reloc_bits)
    427       1.1  christos 			!= (-(bfd_vma) 1 & ~reloc_bits))
    428       1.1  christos 		      flag = bfd_reloc_overflow;
    429       1.1  christos 		  }
    430       1.1  christos 		else
    431       1.1  christos 		  flag = bfd_reloc_overflow;
    432       1.1  christos 	      }
    433       1.1  christos 	  }
    434       1.1  christos 	  break;
    435       1.1  christos 	default:
    436       1.1  christos 	  abort ();
    437       1.1  christos 	}
    438       1.1  christos     }
    439       1.1  christos 
    440       1.1  christos   /* Either we are relocating all the way, or we don't want to apply
    441       1.1  christos      the relocation to the reloc entry (probably because there isn't
    442       1.1  christos      any room in the output format to describe addends to relocs).  */
    443       1.1  christos 
    444       1.1  christos   /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
    445       1.1  christos      (OSF version 1.3, compiler version 3.11).  It miscompiles the
    446       1.1  christos      following program:
    447       1.1  christos 
    448       1.1  christos      struct str
    449       1.1  christos      {
    450       1.1  christos        unsigned int i0;
    451       1.1  christos      } s = { 0 };
    452       1.1  christos 
    453       1.1  christos      int
    454       1.1  christos      main ()
    455       1.1  christos      {
    456       1.1  christos        unsigned long x;
    457       1.1  christos 
    458       1.1  christos        x = 0x100000000;
    459       1.1  christos        x <<= (unsigned long) s.i0;
    460       1.1  christos        if (x == 0)
    461       1.1  christos 	 printf ("failed\n");
    462       1.1  christos        else
    463       1.1  christos 	 printf ("succeeded (%lx)\n", x);
    464       1.1  christos      }
    465       1.1  christos      */
    466       1.1  christos 
    467       1.1  christos   relocation >>= (bfd_vma) howto->rightshift;
    468       1.1  christos 
    469       1.1  christos   /* Shift everything up to where it's going to be used.  */
    470       1.1  christos   relocation <<= (bfd_vma) howto->bitpos;
    471       1.1  christos 
    472       1.1  christos   /* Wait for the day when all have the mask in them.  */
    473       1.1  christos 
    474       1.1  christos   /* What we do:
    475       1.1  christos      i instruction to be left alone
    476       1.1  christos      o offset within instruction
    477       1.1  christos      r relocation offset to apply
    478       1.1  christos      S src mask
    479       1.1  christos      D dst mask
    480       1.1  christos      N ~dst mask
    481       1.1  christos      A part 1
    482       1.1  christos      B part 2
    483       1.1  christos      R result
    484       1.1  christos 
    485       1.1  christos      Do this:
    486   1.1.1.7  christos      i i i i i o o o o o	from bfd_get<size>
    487   1.1.1.7  christos      and	   S S S S S	to get the size offset we want
    488   1.1.1.7  christos      +	 r r r r r r r r r r  to get the final value to place
    489   1.1.1.7  christos      and	   D D D D D  to chop to right size
    490       1.1  christos      -----------------------
    491       1.1  christos      A A A A A
    492       1.1  christos      And this:
    493   1.1.1.7  christos      ...   i i i i i o o o o o	from bfd_get<size>
    494   1.1.1.7  christos      and   N N N N N		get instruction
    495       1.1  christos      -----------------------
    496       1.1  christos      ...   B B B B B
    497       1.1  christos 
    498       1.1  christos      And then:
    499       1.1  christos      B B B B B
    500   1.1.1.7  christos      or		     A A A A A
    501       1.1  christos      -----------------------
    502   1.1.1.7  christos      R R R R R R R R R R	put into bfd_put<size>.  */
    503   1.1.1.7  christos 
    504   1.1.1.7  christos   if (howto->negate)
    505   1.1.1.7  christos     relocation = -relocation;
    506       1.1  christos 
    507       1.1  christos #define DOIT(x) \
    508       1.1  christos   x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
    509       1.1  christos 
    510       1.1  christos   location = (bfd_byte *) data + addr;
    511   1.1.1.9  christos   switch (bfd_get_reloc_size (howto))
    512       1.1  christos     {
    513       1.1  christos     case 0:
    514   1.1.1.9  christos       break;
    515   1.1.1.9  christos 
    516   1.1.1.9  christos     case 1:
    517       1.1  christos       {
    518       1.1  christos 	bfd_vma x = get_data (location, 1);
    519       1.1  christos 	DOIT (x);
    520       1.1  christos 	put_data ((bfd_vma) x, location, 1);
    521       1.1  christos       }
    522       1.1  christos       break;
    523       1.1  christos 
    524   1.1.1.9  christos     case 2:
    525       1.1  christos       if (relocation)
    526       1.1  christos 	{
    527       1.1  christos 	  bfd_vma x = get_data (location, 2);
    528       1.1  christos 	  DOIT (x);
    529       1.1  christos 	  put_data ((bfd_vma) x, location, 2);
    530       1.1  christos 	}
    531       1.1  christos       break;
    532   1.1.1.9  christos     case 4:
    533       1.1  christos       if (relocation)
    534       1.1  christos 	{
    535       1.1  christos 	  bfd_vma x = get_data (location, 4);
    536       1.1  christos 	  DOIT (x);
    537       1.1  christos 	  put_data ((bfd_vma) x, location, 4);
    538       1.1  christos 	}
    539       1.1  christos       break;
    540       1.1  christos 
    541   1.1.1.9  christos     case 8:
    542       1.1  christos #ifdef BFD64
    543       1.1  christos       if (relocation)
    544       1.1  christos 	{
    545       1.1  christos 	  bfd_vma x = get_data (location, 8);
    546       1.1  christos 	  DOIT (x);
    547       1.1  christos 	  put_data (x, location, 8);
    548       1.1  christos 	}
    549       1.1  christos #else
    550       1.1  christos       abort ();
    551       1.1  christos #endif
    552       1.1  christos       break;
    553       1.1  christos     default:
    554       1.1  christos       return bfd_reloc_other;
    555       1.1  christos     }
    556       1.1  christos   if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
    557       1.1  christos     return bfd_reloc_overflow;
    558       1.1  christos 
    559       1.1  christos   return flag;
    560       1.1  christos }
    561       1.1  christos 
    562       1.1  christos /* Relocate a given location using a given value and howto.  */
    563       1.1  christos 
    564       1.1  christos bfd_reloc_status_type
    565   1.1.1.2  christos _bfd_do_ns32k_reloc_contents (reloc_howto_type *howto,
    566   1.1.1.2  christos 			      bfd *input_bfd ATTRIBUTE_UNUSED,
    567   1.1.1.2  christos 			      bfd_vma relocation,
    568   1.1.1.2  christos 			      bfd_byte *location,
    569   1.1.1.2  christos 			      bfd_vma (*get_data) (bfd_byte *, int),
    570   1.1.1.2  christos 			      void (*put_data) (bfd_vma, bfd_byte *, int))
    571       1.1  christos {
    572       1.1  christos   int size;
    573       1.1  christos   bfd_vma x;
    574   1.1.1.9  christos   bool overflow;
    575       1.1  christos 
    576   1.1.1.9  christos   if (howto->negate)
    577       1.1  christos     relocation = -relocation;
    578       1.1  christos 
    579       1.1  christos   /* Get the value we are going to relocate.  */
    580       1.1  christos   size = bfd_get_reloc_size (howto);
    581       1.1  christos   switch (size)
    582       1.1  christos     {
    583       1.1  christos     default:
    584       1.1  christos       abort ();
    585   1.1.1.4  christos     case 0:
    586   1.1.1.4  christos       return bfd_reloc_ok;
    587       1.1  christos     case 1:
    588       1.1  christos     case 2:
    589       1.1  christos     case 4:
    590       1.1  christos #ifdef BFD64
    591       1.1  christos     case 8:
    592       1.1  christos #endif
    593       1.1  christos       x = get_data (location, size);
    594       1.1  christos       break;
    595       1.1  christos     }
    596       1.1  christos 
    597       1.1  christos   /* Check for overflow.  FIXME: We may drop bits during the addition
    598       1.1  christos      which we don't check for.  We must either check at every single
    599       1.1  christos      operation, which would be tedious, or we must do the computations
    600       1.1  christos      in a type larger than bfd_vma, which would be inefficient.  */
    601   1.1.1.9  christos   overflow = false;
    602       1.1  christos   if (howto->complain_on_overflow != complain_overflow_dont)
    603       1.1  christos     {
    604       1.1  christos       bfd_vma check;
    605       1.1  christos       bfd_signed_vma signed_check;
    606       1.1  christos       bfd_vma add;
    607       1.1  christos       bfd_signed_vma signed_add;
    608       1.1  christos 
    609       1.1  christos       if (howto->rightshift == 0)
    610       1.1  christos 	{
    611       1.1  christos 	  check = relocation;
    612       1.1  christos 	  signed_check = (bfd_signed_vma) relocation;
    613       1.1  christos 	}
    614       1.1  christos       else
    615       1.1  christos 	{
    616       1.1  christos 	  /* Drop unwanted bits from the value we are relocating to.  */
    617       1.1  christos 	  check = relocation >> howto->rightshift;
    618       1.1  christos 
    619       1.1  christos 	  /* If this is a signed value, the rightshift just dropped
    620       1.1  christos 	     leading 1 bits (assuming twos complement).  */
    621       1.1  christos 	  if ((bfd_signed_vma) relocation >= 0)
    622       1.1  christos 	    signed_check = check;
    623       1.1  christos 	  else
    624       1.1  christos 	    signed_check = (check
    625       1.1  christos 			    | ((bfd_vma) - 1
    626       1.1  christos 			       & ~((bfd_vma) - 1 >> howto->rightshift)));
    627       1.1  christos 	}
    628       1.1  christos 
    629       1.1  christos       /* Get the value from the object file.  */
    630       1.1  christos       add = x & howto->src_mask;
    631       1.1  christos 
    632       1.1  christos       /* Get the value from the object file with an appropriate sign.
    633       1.1  christos 	 The expression involving howto->src_mask isolates the upper
    634       1.1  christos 	 bit of src_mask.  If that bit is set in the value we are
    635       1.1  christos 	 adding, it is negative, and we subtract out that number times
    636       1.1  christos 	 two.  If src_mask includes the highest possible bit, then we
    637       1.1  christos 	 can not get the upper bit, but that does not matter since
    638       1.1  christos 	 signed_add needs no adjustment to become negative in that
    639       1.1  christos 	 case.  */
    640       1.1  christos       signed_add = add;
    641       1.1  christos       if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
    642       1.1  christos 	signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
    643       1.1  christos 
    644       1.1  christos       /* Add the value from the object file, shifted so that it is a
    645       1.1  christos 	 straight number.  */
    646       1.1  christos       if (howto->bitpos == 0)
    647       1.1  christos 	{
    648       1.1  christos 	  check += add;
    649       1.1  christos 	  signed_check += signed_add;
    650       1.1  christos 	}
    651       1.1  christos       else
    652       1.1  christos 	{
    653       1.1  christos 	  check += add >> howto->bitpos;
    654       1.1  christos 
    655       1.1  christos 	  /* For the signed case we use ADD, rather than SIGNED_ADD,
    656       1.1  christos 	     to avoid warnings from SVR4 cc.  This is OK since we
    657       1.1  christos 	     explicitly handle the sign bits.  */
    658       1.1  christos 	  if (signed_add >= 0)
    659       1.1  christos 	    signed_check += add >> howto->bitpos;
    660       1.1  christos 	  else
    661       1.1  christos 	    signed_check += ((add >> howto->bitpos)
    662       1.1  christos 			     | ((bfd_vma) - 1
    663       1.1  christos 				& ~((bfd_vma) - 1 >> howto->bitpos)));
    664       1.1  christos 	}
    665       1.1  christos 
    666       1.1  christos       switch (howto->complain_on_overflow)
    667       1.1  christos 	{
    668       1.1  christos 	case complain_overflow_signed:
    669       1.1  christos 	  {
    670       1.1  christos 	    /* Assumes two's complement.  */
    671       1.1  christos 	    bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
    672       1.1  christos 	    bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
    673       1.1  christos 
    674       1.1  christos 	    if (signed_check > reloc_signed_max
    675       1.1  christos 		|| signed_check < reloc_signed_min)
    676   1.1.1.9  christos 	      overflow = true;
    677       1.1  christos 	  }
    678       1.1  christos 	  break;
    679       1.1  christos 	case complain_overflow_unsigned:
    680       1.1  christos 	  {
    681       1.1  christos 	    /* Assumes two's complement.  This expression avoids
    682       1.1  christos 	       overflow if howto->bitsize is the number of bits in
    683       1.1  christos 	       bfd_vma.  */
    684       1.1  christos 	    bfd_vma reloc_unsigned_max =
    685       1.1  christos 	    (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
    686       1.1  christos 
    687       1.1  christos 	    if (check > reloc_unsigned_max)
    688   1.1.1.9  christos 	      overflow = true;
    689       1.1  christos 	  }
    690       1.1  christos 	  break;
    691       1.1  christos 	case complain_overflow_bitfield:
    692       1.1  christos 	  {
    693       1.1  christos 	    /* Assumes two's complement.  This expression avoids
    694       1.1  christos 	       overflow if howto->bitsize is the number of bits in
    695       1.1  christos 	       bfd_vma.  */
    696       1.1  christos 	    bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
    697       1.1  christos 
    698       1.1  christos 	    if ((check & ~reloc_bits) != 0
    699       1.1  christos 		&& (((bfd_vma) signed_check & ~reloc_bits)
    700       1.1  christos 		    != (-(bfd_vma) 1 & ~reloc_bits)))
    701   1.1.1.9  christos 	      overflow = true;
    702       1.1  christos 	  }
    703       1.1  christos 	  break;
    704       1.1  christos 	default:
    705       1.1  christos 	  abort ();
    706       1.1  christos 	}
    707       1.1  christos     }
    708       1.1  christos 
    709       1.1  christos   /* Put RELOCATION in the right bits.  */
    710       1.1  christos   relocation >>= (bfd_vma) howto->rightshift;
    711       1.1  christos   relocation <<= (bfd_vma) howto->bitpos;
    712       1.1  christos 
    713       1.1  christos   /* Add RELOCATION to the right bits of X.  */
    714       1.1  christos   x = ((x & ~howto->dst_mask)
    715       1.1  christos        | (((x & howto->src_mask) + relocation) & howto->dst_mask));
    716       1.1  christos 
    717       1.1  christos   /* Put the relocated value back in the object file.  */
    718       1.1  christos   switch (size)
    719       1.1  christos     {
    720       1.1  christos     default:
    721       1.1  christos     case 0:
    722       1.1  christos       abort ();
    723       1.1  christos     case 1:
    724       1.1  christos     case 2:
    725       1.1  christos     case 4:
    726       1.1  christos #ifdef BFD64
    727       1.1  christos     case 8:
    728       1.1  christos #endif
    729       1.1  christos       put_data (x, location, size);
    730       1.1  christos       break;
    731       1.1  christos     }
    732       1.1  christos 
    733       1.1  christos   return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
    734       1.1  christos }
    735       1.1  christos 
    736       1.1  christos bfd_reloc_status_type
    737   1.1.1.2  christos _bfd_ns32k_reloc_disp (bfd *abfd,
    738   1.1.1.2  christos 		       arelent *reloc_entry,
    739   1.1.1.2  christos 		       struct bfd_symbol *symbol,
    740   1.1.1.2  christos 		       void * data,
    741   1.1.1.2  christos 		       asection *input_section,
    742   1.1.1.2  christos 		       bfd *output_bfd,
    743   1.1.1.2  christos 		       char **error_message)
    744       1.1  christos {
    745       1.1  christos   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
    746       1.1  christos 			 output_bfd, error_message,
    747       1.1  christos 			 _bfd_ns32k_get_displacement,
    748       1.1  christos 			 _bfd_ns32k_put_displacement);
    749       1.1  christos }
    750       1.1  christos 
    751       1.1  christos bfd_reloc_status_type
    752   1.1.1.2  christos _bfd_ns32k_reloc_imm (bfd *abfd,
    753   1.1.1.2  christos 		      arelent *reloc_entry,
    754   1.1.1.2  christos 		      struct bfd_symbol *symbol,
    755   1.1.1.2  christos 		      void * data,
    756   1.1.1.2  christos 		      asection *input_section,
    757   1.1.1.2  christos 		      bfd *output_bfd,
    758   1.1.1.2  christos 		      char **error_message)
    759       1.1  christos {
    760       1.1  christos   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
    761       1.1  christos 			 output_bfd, error_message, _bfd_ns32k_get_immediate,
    762       1.1  christos 			 _bfd_ns32k_put_immediate);
    763       1.1  christos }
    764       1.1  christos 
    765       1.1  christos bfd_reloc_status_type
    766   1.1.1.2  christos _bfd_ns32k_final_link_relocate (reloc_howto_type *howto,
    767   1.1.1.2  christos 				bfd *input_bfd,
    768   1.1.1.2  christos 				asection *input_section,
    769   1.1.1.2  christos 				bfd_byte *contents,
    770   1.1.1.2  christos 				bfd_vma address,
    771   1.1.1.2  christos 				bfd_vma value,
    772   1.1.1.2  christos 				bfd_vma addend)
    773       1.1  christos {
    774       1.1  christos   bfd_vma relocation;
    775       1.1  christos 
    776       1.1  christos   /* Sanity check the address.  */
    777       1.1  christos   if (address > bfd_get_section_limit (input_bfd, input_section))
    778       1.1  christos     return bfd_reloc_outofrange;
    779       1.1  christos 
    780       1.1  christos   /* This function assumes that we are dealing with a basic relocation
    781       1.1  christos      against a symbol.  We want to compute the value of the symbol to
    782       1.1  christos      relocate to.  This is just VALUE, the value of the symbol, plus
    783       1.1  christos      ADDEND, any addend associated with the reloc.  */
    784       1.1  christos   relocation = value + addend;
    785       1.1  christos 
    786       1.1  christos   /* If the relocation is PC relative, we want to set RELOCATION to
    787       1.1  christos      the distance between the symbol (currently in RELOCATION) and the
    788   1.1.1.7  christos      location we are relocating.  If pcrel_offset is FALSE we do not
    789       1.1  christos      need to subtract out the offset of the location within the
    790       1.1  christos      section (which is just ADDRESS).  */
    791       1.1  christos   if (howto->pc_relative)
    792       1.1  christos     {
    793       1.1  christos       relocation -= (input_section->output_section->vma
    794       1.1  christos 		     + input_section->output_offset);
    795       1.1  christos       if (howto->pcrel_offset)
    796       1.1  christos 	relocation -= address;
    797       1.1  christos     }
    798       1.1  christos 
    799       1.1  christos   return _bfd_ns32k_relocate_contents (howto, input_bfd, relocation,
    800       1.1  christos 				       contents + address);
    801       1.1  christos }
    802