[BACK]Return to cpu-ns32k.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / bfd

Annotation of src/external/gpl3/binutils.old/dist/bfd/cpu-ns32k.c, Revision 1.6

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

CVSweb <webmaster@jp.NetBSD.org>