Ignore:
Timestamp:
Aug 16, 2003, 6:59:22 PM (22 years ago)
Author:
bird
Message:

binutils v2.14 - offical sources.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GNU/src/binutils/bfd/cpu-ns32k.c

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r608 r609  
    11/* BFD support for the ns32k architecture.
    2    Copyright 1990, 1991, 1994, 1995, 1998, 2000
     2   Copyright 1990, 1991, 1994, 1995, 1998, 2000, 2001, 2002
    33   Free Software Foundation, Inc.
    44   Almost totally rewritten by Ian Dall from initial work
    55   by Andrew Cagney.
    66
    7 This file is part of BFD, the Binary File Descriptor library.
    8 
    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.
    13 
    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.
    18 
    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.  */
     7   This file is part of BFD, the Binary File Descriptor library.
     8
     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.
     13
     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.
     18
     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.  */
    2222
    2323#include "bfd.h"
     
    3131static const bfd_arch_info_type arch_info_struct[] =
    3232{
    33   N(32532,"ns32k:32532",true, 0), /* the word ns32k will match this too */
     33  N(32532,"ns32k:32532",TRUE, 0), /* The word ns32k will match this too. */
    3434};
    3535
    3636const bfd_arch_info_type bfd_ns32k_arch =
    37   N(32032,"ns32k:32032",false, &arch_info_struct[0]);
    38 
    39 static long
    40 ns32k_sign_extend(value, bits)
    41      int value;
    42      int bits;
    43 {
    44   value = value & ((1 << bits) - 1);
    45   return (value & (1 << (bits-1))
    46           ? value | (~((1 << bits) - 1))
    47           : value);
    48 }
    49 
    50 long
    51 _bfd_ns32k_get_displacement(buffer, offset, size)
     37  N(32032,"ns32k:32032",FALSE, &arch_info_struct[0]);
     38
     39static bfd_reloc_status_type do_ns32k_reloc
     40  PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
     41           bfd *, char **,
     42           bfd_vma (*) (bfd_byte *, int),
     43           void (*) (bfd_vma, bfd_byte *, int)));
     44
     45bfd_vma
     46_bfd_ns32k_get_displacement (buffer, size)
    5247     bfd_byte *buffer;
    53      long offset;
    54      long size;
    55 {
    56   long value;
    57   buffer += offset;
     48     int size;
     49{
     50  bfd_signed_vma value;
     51
    5852  switch (size)
    5953    {
    6054    case 1:
    61       value = ns32k_sign_extend (*buffer, 7);
    62       break;
     55      value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
     56      break;
     57
    6358    case 2:
    64       value = ns32k_sign_extend(*buffer++, 6);
     59      value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
    6560      value = (value << 8) | (0xff & *buffer);
    6661      break;
     62
    6763    case 4:
    68       value = ns32k_sign_extend(*buffer++, 6);
     64      value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
    6965      value = (value << 8) | (0xff & *buffer++);
    7066      value = (value << 8) | (0xff & *buffer++);
    7167      value = (value << 8) | (0xff & *buffer);
    7268      break;
     69
    7370    default:
    7471      abort ();
    7572      return 0;
    7673    }
     74
    7775  return value;
    7876}
    7977
    80 int
    81 _bfd_ns32k_put_displacement(value, buffer, offset, size)
    82      long value;
     78void
     79_bfd_ns32k_put_displacement (value, buffer, size)
     80     bfd_vma value;
    8381     bfd_byte *buffer;
    84      long offset;
    85      long size;
    86 {
    87   buffer += offset;
     82     int size;
     83{
    8884  switch (size)
    8985    {
    9086    case 1:
    91       if (value < -64 || value > 63)
    92         return -1;
    93       value&=0x7f;
    94       *buffer++=value;
    95       break;
     87      value &= 0x7f;
     88      *buffer++ = value;
     89      break;
     90
    9691    case 2:
    97       if (value < -8192 || value > 8191)
    98         return -1;
    99       value&=0x3fff;
    100       value|=0x8000;
    101       *buffer++=(value>>8);
    102       *buffer++=value;
    103       break;
     92      value &= 0x3fff;
     93      value |= 0x8000;
     94      *buffer++ = (value >> 8);
     95      *buffer++ = value;
     96      break;
     97
    10498    case 4:
    105       if (value < -0x1f000000 || value >= 0x20000000)
    106         return -1;
    107       value|=0xc0000000;
    108       *buffer++=(value>>24);
    109       *buffer++=(value>>16);
    110       *buffer++=(value>>8);
    111       *buffer++=value;
    112       break;
    113     default:
    114       return -1;
     99      value |= (bfd_vma) 0xc0000000;
     100      *buffer++ = (value >> 24);
     101      *buffer++ = (value >> 16);
     102      *buffer++ = (value >> 8);
     103      *buffer++ = value;
     104      break;
    115105  }
    116   return 0;
     106  return;
    117107}
    118108
    119 long
    120 _bfd_ns32k_get_immediate (buffer, offset, size)
     109bfd_vma
     110_bfd_ns32k_get_immediate (buffer, size)
    121111     bfd_byte *buffer;
    122      long offset;
    123      long size;
    124 {
    125   long value = 0;
    126   buffer += offset;
     112     int size;
     113{
     114  bfd_vma value = 0;
     115
    127116  switch (size)
    128117    {
    129118    case 4:
    130119      value = (value << 8) | (*buffer++ & 0xff);
    131     case 3:
    132120      value = (value << 8) | (*buffer++ & 0xff);
    133121    case 2:
     
    135123    case 1:
    136124      value = (value << 8) | (*buffer++ & 0xff);
     125      break;
     126    default:
     127      abort ();
    137128    }
    138129  return value;
    139130}
    140131
    141 int
    142 _bfd_ns32k_put_immediate (value, buffer, offset, size)
    143      long value;
     132void
     133_bfd_ns32k_put_immediate (value, buffer, size)
     134     bfd_vma value;
    144135     bfd_byte *buffer;
    145      long offset;
    146      long size;
    147 {
    148   buffer += offset + size - 1;
     136     int size;
     137{
     138  buffer += size - 1;
    149139  switch (size)
    150140    {
    151141    case 4:
    152142      *buffer-- = (value & 0xff); value >>= 8;
    153     case 3:
    154143      *buffer-- = (value & 0xff); value >>= 8;
    155144    case 2:
     
    158147      *buffer-- = (value & 0xff); value >>= 8;
    159148    }
    160   return 0;
    161149}
    162150
    163151/* This is just like the standard perform_relocation except we
    164  * use get_data and put_data which know about the ns32k
    165  * storage methods.
    166  * This is probably a lot more complicated than it needs to be!
    167  */
     152   use get_data and put_data which know about the ns32k storage
     153   methods.  This is probably a lot more complicated than it
     154   needs to be!  */
     155
    168156static bfd_reloc_status_type
    169157do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
     
    176164     bfd *output_bfd;
    177165     char **error_message ATTRIBUTE_UNUSED;
    178      long (*get_data) ();
    179      int (*put_data) ();
     166     bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
     167     void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
    180168{
    181169  int overflow = 0;
     
    186174  reloc_howto_type *howto = reloc_entry->howto;
    187175  asection *reloc_target_output_section;
     176  bfd_byte *location;
    188177
    189178  if ((symbol->section == &bfd_abs_section)
     
    218207
    219208  /* Convert input-section-relative symbol value to absolute.  */
    220   if (output_bfd && howto->partial_inplace == false)
     209  if (output_bfd != NULL && ! howto->partial_inplace)
    221210    output_base = 0;
    222211  else
     
    231220     symbol we are relocating against, plus any addend.  */
    232221
    233   if (howto->pc_relative == true)
     222  if (howto->pc_relative)
    234223    {
    235224      /* This is a PC relative relocation.  We want to set RELOCATION
     
    244233         the addend to be the negative of the position of the location
    245234         within the section; for example, i386-aout does this.  For
    246          i386-aout, pcrel_offset is false.  Some other targets do not
     235         i386-aout, pcrel_offset is FALSE.  Some other targets do not
    247236         include the position of the location; for example, m88kbcs,
    248          or ELF.  For those targets, pcrel_offset is true.
     237         or ELF.  For those targets, pcrel_offset is TRUE.
    249238
    250239         If we are producing relocateable output, then we must ensure
    251240         that this reloc will be correctly computed when the final
    252          relocation is done.  If pcrel_offset is false we want to wind
     241         relocation is done.  If pcrel_offset is FALSE we want to wind
    253242         up with the negative of the location within the section,
    254243         which means we must adjust the existing addend by the change
    255          in the location within the section.  If pcrel_offset is true
     244         in the location within the section.  If pcrel_offset is TRUE
    256245         we do not want to adjust the existing addend at all.
    257246
     
    260249         actually does.  I don't want to change it, because it seems
    261250         far too likely that something will break.  */
    262 
    263251      relocation -=
    264252        input_section->output_section->vma + input_section->output_offset;
    265253
    266       if (howto->pcrel_offset == true)
     254      if (howto->pcrel_offset)
    267255        relocation -= reloc_entry->address;
    268256    }
     
    270258  if (output_bfd != (bfd *) NULL)
    271259    {
    272       if (howto->partial_inplace == false)
     260      if (! howto->partial_inplace)
    273261        {
    274262          /* This is a partial relocation, and we want to apply the relocation
     
    297285                 fixes that problem; see PR 2953.
    298286
    299 However, Ian wrote the following, regarding removing the line below,
    300 which explains why it is still enabled:  --djm
    301 
    302 If you put a patch like that into BFD you need to check all the COFF
    303 linkers.  I am fairly certain that patch will break coff-i386 (e.g.,
    304 SCO); see coff_i386_reloc in coff-i386.c where I worked around the
    305 problem in a different way.  There may very well be a reason that the
    306 code works as it does.
    307 
    308 Hmmm.  The first obvious point is that bfd_perform_relocation should
    309 not have any tests that depend upon the flavour.  It's seem like
    310 entirely the wrong place for such a thing.  The second obvious point
    311 is that the current code ignores the reloc addend when producing
    312 relocateable output for COFF.  That's peculiar.  In fact, I really
    313 have no idea what the point of the line you want to remove is.
    314 
    315 A typical COFF reloc subtracts the old value of the symbol and adds in
    316 the new value to the location in the object file (if it's a pc
    317 relative reloc it adds the difference between the symbol value and the
    318 location).  When relocating we need to preserve that property.
    319 
    320 BFD handles this by setting the addend to the negative of the old
    321 value of the symbol.  Unfortunately it handles common symbols in a
    322 non-standard way (it doesn't subtract the old value) but that's a
    323 different story (we can't change it without losing backward
    324 compatibility with old object files) (coff-i386 does subtract the old
    325 value, to be compatible with existing coff-i386 targets, like SCO).
    326 
    327 So everything works fine when not producing relocateable output.  When
    328 we are producing relocateable output, logically we should do exactly
    329 what we do when not producing relocateable output.  Therefore, your
    330 patch is correct.  In fact, it should probably always just set
    331 reloc_entry->addend to 0 for all cases, since it is, in fact, going to
    332 add the value into the object file.  This won't hurt the COFF code,
    333 which doesn't use the addend; I'm not sure what it will do to other
    334 formats (the thing to check for would be whether any formats both use
    335 the addend and set partial_inplace).
    336 
    337 When I wanted to make coff-i386 produce relocateable output, I ran
    338 into the problem that you are running into: I wanted to remove that
    339 line.  Rather than risk it, I made the coff-i386 relocs use a special
    340 function; it's coff_i386_reloc in coff-i386.c.  The function
    341 specifically adds the addend field into the object file, knowing that
    342 bfd_perform_relocation is not going to.  If you remove that line, then
    343 coff-i386.c will wind up adding the addend field in twice.  It's
    344 trivial to fix; it just needs to be done.
    345 
    346 The problem with removing the line is just that it may break some
    347 working code.  With BFD it's hard to be sure of anything.  The right
    348 way to deal with this is simply to build and test at least all the
    349 supported COFF targets.  It should be straightforward if time and disk
    350 space consuming.  For each target:
    351     1) build the linker
    352     2) generate some executable, and link it using -r (I would
    353        probably use paranoia.o and link against newlib/libc.a, which
    354        for all the supported targets would be available in
    355        /usr/cygnus/progressive/H-host/target/lib/libc.a).
    356     3) make the change to reloc.c
    357     4) rebuild the linker
    358     5) repeat step 2
    359     6) if the resulting object files are the same, you have at least
    360        made it no worse
    361     7) if they are different you have to figure out which version is
    362        right
    363 */
     287                 However, Ian wrote the following, regarding removing the line
     288                 below, which explains why it is still enabled:  --djm
     289
     290                 If you put a patch like that into BFD you need to check all
     291                 the COFF linkers.  I am fairly certain that patch will break
     292                 coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
     293                 where I worked around the problem in a different way.  There
     294                 may very well be a reason that the code works as it does.
     295
     296                 Hmmm.  The first obvious point is that bfd_perform_relocation
     297                 should not have any tests that depend upon the flavour.  It's
     298                 seem like entirely the wrong place for such a thing.  The
     299                 second obvious point is that the current code ignores the
     300                 reloc addend when producing relocateable output for COFF.
     301                 That's peculiar.  In fact, I really have no idea what the
     302                 point of the line you want to remove is.
     303
     304                 A typical COFF reloc subtracts the old value of the symbol
     305                 and adds in the new value to the location in the object file
     306                 (if it's a pc relative reloc it adds the difference between
     307                 the symbol value and the location).  When relocating we need
     308                 to preserve that property.
     309
     310                 BFD handles this by setting the addend to the negative of the
     311                 old value of the symbol.  Unfortunately it handles common
     312                 symbols in a non-standard way (it doesn't subtract the old
     313                 value) but that's a different story (we can't change it
     314                 without losing backward compatibility with old object files)
     315                 (coff-i386 does subtract the old value, to be compatible with
     316                 existing coff-i386 targets, like SCO).
     317
     318                 So everything works fine when not producing relocateable
     319                 output.  When we are producing relocateable output, logically
     320                 we should do exactly what we do when not producing
     321                 relocateable output.  Therefore, your patch is correct.  In
     322                 fact, it should probably always just set reloc_entry->addend
     323                 to 0 for all cases, since it is, in fact, going to add the
     324                 value into the object file.  This won't hurt the COFF code,
     325                 which doesn't use the addend; I'm not sure what it will do
     326                 to other formats (the thing to check for would be whether
     327                 any formats both use the addend and set partial_inplace).
     328
     329                 When I wanted to make coff-i386 produce relocateable output,
     330                 I ran into the problem that you are running into: I wanted
     331                 to remove that line.  Rather than risk it, I made the
     332                 coff-i386 relocs use a special function; it's coff_i386_reloc
     333                 in coff-i386.c.  The function specifically adds the addend
     334                 field into the object file, knowing that bfd_perform_relocation
     335                 is not going to.  If you remove that line, then coff-i386.c
     336                 will wind up adding the addend field in twice.  It's trivial
     337                 to fix; it just needs to be done.
     338
     339                 The problem with removing the line is just that it may break
     340                 some working code.  With BFD it's hard to be sure of anything.
     341                 The right way to deal with this is simply to build and test at
     342                 least all the supported COFF targets.  It should be
     343                 straightforward if time and disk space consuming.  For each
     344                 target:
     345                   1) build the linker
     346                   2) generate some executable, and link it using -r (I would
     347                      probably use paranoia.o and link against newlib/libc.a,
     348                      which for all the supported targets would be available in
     349                      /usr/cygnus/progressive/H-host/target/lib/libc.a).
     350                   3) make the change to reloc.c
     351                   4) rebuild the linker
     352                   5) repeat step 2
     353                   6) if the resulting object files are the same, you have at
     354                      least made it no worse
     355                   7) if they are different you have to figure out which
     356                      version is right.  */
    364357              relocation -= reloc_entry->addend;
    365358#endif
     
    434427
    435428            if (((bfd_vma) check & ~reloc_bits) != 0
    436                 && ((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
     429                && (((bfd_vma) check & ~reloc_bits)
     430                    != (-(bfd_vma) 1 & ~reloc_bits)))
    437431              {
    438432                /* The above right shift is incorrect for a signed
     
    445439                              & ~((bfd_vma) - 1
    446440                                  >> (howto->rightshift - howto->bitpos)));
    447                     if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
     441                    if (((bfd_vma) check & ~reloc_bits)
     442                        != (-(bfd_vma) 1 & ~reloc_bits))
    448443                      flag = bfd_reloc_overflow;
    449444                  }
     
    458453    }
    459454
    460   /*
    461     Either we are relocating all the way, or we don't want to apply
    462     the relocation to the reloc entry (probably because there isn't
    463     any room in the output format to describe addends to relocs)
    464     */
     455  /* Either we are relocating all the way, or we don't want to apply
     456     the relocation to the reloc entry (probably because there isn't
     457     any room in the output format to describe addends to relocs).  */
    465458
    466459  /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
     
    489482  relocation >>= (bfd_vma) howto->rightshift;
    490483
    491   /* Shift everything up to where it's going to be used */
    492 
     484  /* Shift everything up to where it's going to be used.  */
    493485  relocation <<= (bfd_vma) howto->bitpos;
    494486
    495   /* Wait for the day when all have the mask in them */
     487  /* Wait for the day when all have the mask in them. */
    496488
    497489  /* What we do:
     
    523515     or              A A A A A
    524516     -----------------------
    525      R R R R R R R R R R        put into bfd_put<size>
    526      */
     517     R R R R R R R R R R        put into bfd_put<size>.  */
    527518
    528519#define DOIT(x) \
    529520  x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
    530521
     522  location = (bfd_byte *) data + addr;
    531523  switch (howto->size)
    532524    {
    533525    case 0:
    534526      {
    535         char x = get_data (data, addr, 1);
     527        bfd_vma x = get_data (location, 1);
    536528        DOIT (x);
    537         overflow = put_data(x, data, addr, 1);
     529        put_data ((bfd_vma) x, location, 1);
    538530      }
    539531      break;
     
    542534      if (relocation)
    543535        {
    544           short x = get_data (data, addr, 2);
     536          bfd_vma x = get_data (location, 2);
    545537          DOIT (x);
    546           overflow = put_data(x, (unsigned char *) data, addr, 2);
     538          put_data ((bfd_vma) x, location, 2);
    547539        }
    548540      break;
     
    550542      if (relocation)
    551543        {
    552           long x = get_data (data, addr, 4);
     544          bfd_vma x = get_data (location, 4);
    553545          DOIT (x);
    554           overflow = put_data(x, data, addr, 4);
     546          put_data ((bfd_vma) x, location, 4);
    555547        }
    556548      break;
    557549    case -2:
    558550      {
    559         long  x = get_data(data, addr, 4);
     551        bfd_vma x = get_data (location, 4);
    560552        relocation = -relocation;
    561553        DOIT(x);
    562         overflow = put_data(x, data , addr, 4);
     554        put_data ((bfd_vma) x, location, 4);
    563555      }
    564556      break;
    565557
    566558    case 3:
    567       /* Do nothing */
     559      /* Do nothing. */
    568560      break;
    569561
     
    572564      if (relocation)
    573565        {
    574           bfd_vma x = get_data (data, addr, 8);
     566          bfd_vma x = get_data (location, 8);
    575567          DOIT (x);
    576           overflow = put_data(x, data, addr, 8);
     568          put_data (x, location, 8);
    577569        }
    578570#else
     
    592584
    593585bfd_reloc_status_type
    594 _bfd_do_ns32k_reloc_contents ( howto, input_bfd, relocation, location,
     586_bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation, location,
    595587                              get_data, put_data)
    596588     reloc_howto_type *howto;
     
    598590     bfd_vma relocation;
    599591     bfd_byte *location;
    600      long (*get_data) ();
    601      int (*put_data) ();
     592     bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
     593     void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
    602594{
    603595  int size;
    604596  bfd_vma x;
    605   boolean overflow;
     597  bfd_boolean overflow;
    606598
    607599  /* If the size is negative, negate RELOCATION.  This isn't very
     
    623615    case 8:
    624616#endif
    625       x = get_data (location, 0, size);
     617      x = get_data (location, size);
    626618      break;
    627619    }
     
    631623     operation, which would be tedious, or we must do the computations
    632624     in a type larger than bfd_vma, which would be inefficient.  */
    633   overflow = false;
     625  overflow = FALSE;
    634626  if (howto->complain_on_overflow != complain_overflow_dont)
    635627    {
     
    706698            if (signed_check > reloc_signed_max
    707699                || signed_check < reloc_signed_min)
    708               overflow = true;
     700              overflow = TRUE;
    709701          }
    710702          break;
     
    718710
    719711            if (check > reloc_unsigned_max)
    720               overflow = true;
     712              overflow = TRUE;
    721713          }
    722714          break;
     
    730722            if ((check & ~reloc_bits) != 0
    731723                && (((bfd_vma) signed_check & ~reloc_bits)
    732                     != (-1 & ~reloc_bits)))
    733               overflow = true;
     724                    != (-(bfd_vma) 1 & ~reloc_bits)))
     725              overflow = TRUE;
    734726          }
    735727          break;
     
    759751    case 8:
    760752#endif
    761       put_data(x, location, 0, size);
     753      put_data (x, location, size);
    762754      break;
    763755    }
     
    827819     arrange for the contents of the section to be the negative of the
    828820     offset of the location within the section; for such targets
    829      pcrel_offset is false.  Other targets (e.g., m88kbcs or ELF)
     821     pcrel_offset is FALSE.  Other targets (e.g., m88kbcs or ELF)
    830822     simply leave the contents of the section as zero; for such
    831      targets pcrel_offset is true.  If pcrel_offset is false we do not
     823     targets pcrel_offset is TRUE.  If pcrel_offset is FALSE we do not
    832824     need to subtract out the offset of the location within the
    833825     section (which is just ADDRESS).  */
Note: See TracChangeset for help on using the changeset viewer.