[BACK]Return to coff-mips.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/coff-mips.c, Revision 1.4.8.1

1.1       christos    1: /* BFD back-end for MIPS Extended-Coff files.
1.4.8.1 ! pgoyette    2:    Copyright (C) 1990-2016 Free Software Foundation, Inc.
1.1       christos    3:    Original version by Per Bothner.
                      4:    Full support added by Ian Lance Taylor, ian@cygnus.com.
                      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 "bfdlink.h"
                     26: #include "libbfd.h"
                     27: #include "coff/internal.h"
                     28: #include "coff/sym.h"
                     29: #include "coff/symconst.h"
                     30: #include "coff/ecoff.h"
                     31: #include "coff/mips.h"
                     32: #include "libcoff.h"
                     33: #include "libecoff.h"
                     34: 
                     35: /* Prototypes for static functions.  */
                     36: static bfd_reloc_status_type
                     37: mips_generic_reloc
                     38:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
                     39: static bfd_reloc_status_type
                     40: mips_refhi_reloc
                     41:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
                     42: static bfd_reloc_status_type
                     43: mips_reflo_reloc
                     44:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
                     45: static bfd_reloc_status_type
1.3       christos   46: mips_gprel_reloc
1.1       christos   47:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
                     48:
                     49: 
                     50: /* ECOFF has COFF sections, but the debugging information is stored in
                     51:    a completely different format.  ECOFF targets use some of the
                     52:    swapping routines from coffswap.h, and some of the generic COFF
                     53:    routines in coffgen.c, but, unlike the real COFF targets, do not
                     54:    use coffcode.h itself.
                     55:
                     56:    Get the generic COFF swapping routines, except for the reloc,
                     57:    symbol, and lineno ones.  Give them ECOFF names.  */
                     58: #define MIPSECOFF
                     59: #define NO_COFF_RELOCS
                     60: #define NO_COFF_SYMBOLS
                     61: #define NO_COFF_LINENOS
                     62: #define coff_swap_filehdr_in  mips_ecoff_swap_filehdr_in
                     63: #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
                     64: #define coff_swap_aouthdr_in  mips_ecoff_swap_aouthdr_in
                     65: #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
                     66: #define coff_swap_scnhdr_in   mips_ecoff_swap_scnhdr_in
                     67: #define coff_swap_scnhdr_out  mips_ecoff_swap_scnhdr_out
                     68:
                     69: #include "coffswap.h"
                     70:
                     71: /* Get the ECOFF swapping routines.  */
                     72: #define ECOFF_32
                     73: #include "ecoffswap.h"
                     74: 
                     75: /* How to process the various relocs types.  */
                     76:
                     77: static reloc_howto_type mips_howto_table[] =
                     78: {
                     79:   /* Reloc type 0 is ignored.  The reloc reading code ensures that
                     80:      this is a reference to the .abs section, which will cause
                     81:      bfd_perform_relocation to do nothing.  */
                     82:   HOWTO (MIPS_R_IGNORE,        /* type */
                     83:         0,                     /* rightshift */
                     84:         0,                     /* size (0 = byte, 1 = short, 2 = long) */
                     85:         8,                     /* bitsize */
                     86:         FALSE,                 /* pc_relative */
                     87:         0,                     /* bitpos */
                     88:         complain_overflow_dont, /* complain_on_overflow */
                     89:         0,                     /* special_function */
                     90:         "IGNORE",              /* name */
                     91:         FALSE,                 /* partial_inplace */
                     92:         0,                     /* src_mask */
                     93:         0,                     /* dst_mask */
                     94:         FALSE),                /* pcrel_offset */
                     95:
                     96:   /* A 16 bit reference to a symbol, normally from a data section.  */
                     97:   HOWTO (MIPS_R_REFHALF,       /* type */
                     98:         0,                     /* rightshift */
                     99:         1,                     /* size (0 = byte, 1 = short, 2 = long) */
                    100:         16,                    /* bitsize */
                    101:         FALSE,                 /* pc_relative */
                    102:         0,                     /* bitpos */
                    103:         complain_overflow_bitfield, /* complain_on_overflow */
                    104:         mips_generic_reloc,    /* special_function */
                    105:         "REFHALF",             /* name */
                    106:         TRUE,                  /* partial_inplace */
                    107:         0xffff,                /* src_mask */
                    108:         0xffff,                /* dst_mask */
                    109:         FALSE),                /* pcrel_offset */
                    110:
                    111:   /* A 32 bit reference to a symbol, normally from a data section.  */
                    112:   HOWTO (MIPS_R_REFWORD,       /* type */
                    113:         0,                     /* rightshift */
                    114:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    115:         32,                    /* bitsize */
                    116:         FALSE,                 /* pc_relative */
                    117:         0,                     /* bitpos */
                    118:         complain_overflow_bitfield, /* complain_on_overflow */
                    119:         mips_generic_reloc,    /* special_function */
                    120:         "REFWORD",             /* name */
                    121:         TRUE,                  /* partial_inplace */
                    122:         0xffffffff,            /* src_mask */
                    123:         0xffffffff,            /* dst_mask */
                    124:         FALSE),                /* pcrel_offset */
                    125:
                    126:   /* A 26 bit absolute jump address.  */
                    127:   HOWTO (MIPS_R_JMPADDR,       /* type */
                    128:         2,                     /* rightshift */
                    129:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    130:         26,                    /* bitsize */
                    131:         FALSE,                 /* pc_relative */
                    132:         0,                     /* bitpos */
                    133:         complain_overflow_dont, /* complain_on_overflow */
                    134:                                /* This needs complex overflow
                    135:                                   detection, because the upper four
                    136:                                   bits must match the PC.  */
                    137:         mips_generic_reloc,    /* special_function */
                    138:         "JMPADDR",             /* name */
                    139:         TRUE,                  /* partial_inplace */
                    140:         0x3ffffff,             /* src_mask */
                    141:         0x3ffffff,             /* dst_mask */
                    142:         FALSE),                /* pcrel_offset */
                    143:
                    144:   /* The high 16 bits of a symbol value.  Handled by the function
                    145:      mips_refhi_reloc.  */
                    146:   HOWTO (MIPS_R_REFHI,         /* type */
                    147:         16,                    /* rightshift */
                    148:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    149:         16,                    /* bitsize */
                    150:         FALSE,                 /* pc_relative */
                    151:         0,                     /* bitpos */
                    152:         complain_overflow_bitfield, /* complain_on_overflow */
                    153:         mips_refhi_reloc,      /* special_function */
                    154:         "REFHI",               /* name */
                    155:         TRUE,                  /* partial_inplace */
                    156:         0xffff,                /* src_mask */
                    157:         0xffff,                /* dst_mask */
                    158:         FALSE),                /* pcrel_offset */
                    159:
                    160:   /* The low 16 bits of a symbol value.  */
                    161:   HOWTO (MIPS_R_REFLO,         /* type */
                    162:         0,                     /* rightshift */
                    163:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    164:         16,                    /* bitsize */
                    165:         FALSE,                 /* pc_relative */
                    166:         0,                     /* bitpos */
                    167:         complain_overflow_dont, /* complain_on_overflow */
                    168:         mips_reflo_reloc,      /* special_function */
                    169:         "REFLO",               /* name */
                    170:         TRUE,                  /* partial_inplace */
                    171:         0xffff,                /* src_mask */
                    172:         0xffff,                /* dst_mask */
                    173:         FALSE),                /* pcrel_offset */
                    174:
                    175:   /* A reference to an offset from the gp register.  Handled by the
                    176:      function mips_gprel_reloc.  */
                    177:   HOWTO (MIPS_R_GPREL,         /* type */
                    178:         0,                     /* rightshift */
                    179:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    180:         16,                    /* bitsize */
                    181:         FALSE,                 /* pc_relative */
                    182:         0,                     /* bitpos */
                    183:         complain_overflow_signed, /* complain_on_overflow */
                    184:         mips_gprel_reloc,      /* special_function */
                    185:         "GPREL",               /* name */
                    186:         TRUE,                  /* partial_inplace */
                    187:         0xffff,                /* src_mask */
                    188:         0xffff,                /* dst_mask */
                    189:         FALSE),                /* pcrel_offset */
                    190:
                    191:   /* A reference to a literal using an offset from the gp register.
                    192:      Handled by the function mips_gprel_reloc.  */
                    193:   HOWTO (MIPS_R_LITERAL,       /* type */
                    194:         0,                     /* rightshift */
                    195:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    196:         16,                    /* bitsize */
                    197:         FALSE,                 /* pc_relative */
                    198:         0,                     /* bitpos */
                    199:         complain_overflow_signed, /* complain_on_overflow */
                    200:         mips_gprel_reloc,      /* special_function */
                    201:         "LITERAL",             /* name */
                    202:         TRUE,                  /* partial_inplace */
                    203:         0xffff,                /* src_mask */
                    204:         0xffff,                /* dst_mask */
                    205:         FALSE),                /* pcrel_offset */
                    206:
                    207:   EMPTY_HOWTO (8),
                    208:   EMPTY_HOWTO (9),
                    209:   EMPTY_HOWTO (10),
                    210:   EMPTY_HOWTO (11),
                    211:
                    212:   /* FIXME: This relocation is used (internally only) to represent branches
                    213:      when assembling.  It should never appear in output files, and
                    214:      be removed.  (It used to be used for embedded-PIC support.)  */
                    215:   HOWTO (MIPS_R_PCREL16,       /* type */
                    216:         2,                     /* rightshift */
                    217:         2,                     /* size (0 = byte, 1 = short, 2 = long) */
                    218:         16,                    /* bitsize */
                    219:         TRUE,                  /* pc_relative */
                    220:         0,                     /* bitpos */
                    221:         complain_overflow_signed, /* complain_on_overflow */
                    222:         mips_generic_reloc,    /* special_function */
                    223:         "PCREL16",             /* name */
                    224:         TRUE,                  /* partial_inplace */
                    225:         0xffff,                /* src_mask */
                    226:         0xffff,                /* dst_mask */
                    227:         TRUE),                 /* pcrel_offset */
                    228: };
                    229:
                    230: #define MIPS_HOWTO_COUNT \
                    231:   (sizeof mips_howto_table / sizeof mips_howto_table[0])
                    232: 
                    233: /* See whether the magic number matches.  */
                    234:
                    235: static bfd_boolean
                    236: mips_ecoff_bad_format_hook (bfd * abfd, void * filehdr)
                    237: {
                    238:   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
                    239:
                    240:   switch (internal_f->f_magic)
                    241:     {
                    242:     case MIPS_MAGIC_1:
                    243:       /* I don't know what endianness this implies.  */
                    244:       return TRUE;
                    245:
                    246:     case MIPS_MAGIC_BIG:
                    247:     case MIPS_MAGIC_BIG2:
                    248:     case MIPS_MAGIC_BIG3:
                    249:       return bfd_big_endian (abfd);
                    250:
                    251:     case MIPS_MAGIC_LITTLE:
                    252:     case MIPS_MAGIC_LITTLE2:
                    253:     case MIPS_MAGIC_LITTLE3:
                    254:       return bfd_little_endian (abfd);
                    255:
                    256:     default:
                    257:       return FALSE;
                    258:     }
                    259: }
                    260: 
                    261: /* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
                    262:    external form.  They use a bit which indicates whether the symbol
                    263:    is external.  */
                    264:
                    265: /* Swap a reloc in.  */
                    266:
                    267: static void
                    268: mips_ecoff_swap_reloc_in (bfd *  abfd,
                    269:                          void * ext_ptr,
                    270:                          struct internal_reloc *intern)
                    271: {
                    272:   const RELOC *ext = (RELOC *) ext_ptr;
                    273:
                    274:   intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
                    275:   if (bfd_header_big_endian (abfd))
                    276:     {
                    277:       intern->r_symndx = (((int) ext->r_bits[0]
                    278:                           << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
                    279:                          | ((int) ext->r_bits[1]
                    280:                             << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
                    281:                          | ((int) ext->r_bits[2]
                    282:                             << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
                    283:       intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
                    284:                        >> RELOC_BITS3_TYPE_SH_BIG);
                    285:       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
                    286:     }
                    287:   else
                    288:     {
                    289:       intern->r_symndx = (((int) ext->r_bits[0]
                    290:                           << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
                    291:                          | ((int) ext->r_bits[1]
                    292:                             << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
                    293:                          | ((int) ext->r_bits[2]
                    294:                             << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
                    295:       intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
                    296:                         >> RELOC_BITS3_TYPE_SH_LITTLE)
                    297:                        | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
                    298:                           << RELOC_BITS3_TYPEHI_SH_LITTLE));
                    299:       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
                    300:     }
                    301: }
                    302:
                    303: /* Swap a reloc out.  */
                    304:
                    305: static void
                    306: mips_ecoff_swap_reloc_out (bfd * abfd,
                    307:                           const struct internal_reloc * intern,
                    308:                           void * dst)
                    309: {
                    310:   RELOC *ext = (RELOC *) dst;
                    311:   long r_symndx;
                    312:
                    313:   BFD_ASSERT (intern->r_extern
                    314:              || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
                    315:
                    316:   r_symndx = intern->r_symndx;
                    317:
                    318:   H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
                    319:   if (bfd_header_big_endian (abfd))
                    320:     {
                    321:       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
                    322:       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
                    323:       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
                    324:       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
                    325:                         & RELOC_BITS3_TYPE_BIG)
                    326:                        | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
                    327:     }
                    328:   else
                    329:     {
                    330:       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
                    331:       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
                    332:       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
                    333:       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
                    334:                         & RELOC_BITS3_TYPE_LITTLE)
                    335:                        | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
                    336:                            & RELOC_BITS3_TYPEHI_LITTLE))
                    337:                        | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
                    338:     }
                    339: }
                    340:
                    341: /* Finish canonicalizing a reloc.  Part of this is generic to all
                    342:    ECOFF targets, and that part is in ecoff.c.  The rest is done in
                    343:    this backend routine.  It must fill in the howto field.  */
                    344:
                    345: static void
                    346: mips_adjust_reloc_in (bfd *abfd,
                    347:                      const struct internal_reloc *intern,
                    348:                      arelent *rptr)
                    349: {
                    350:   if (intern->r_type > MIPS_R_PCREL16)
                    351:     abort ();
                    352:
                    353:   if (! intern->r_extern
                    354:       && (intern->r_type == MIPS_R_GPREL
                    355:          || intern->r_type == MIPS_R_LITERAL))
                    356:     rptr->addend += ecoff_data (abfd)->gp;
                    357:
                    358:   /* If the type is MIPS_R_IGNORE, make sure this is a reference to
                    359:      the absolute section so that the reloc is ignored.  */
                    360:   if (intern->r_type == MIPS_R_IGNORE)
                    361:     rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
                    362:
                    363:   rptr->howto = &mips_howto_table[intern->r_type];
                    364: }
                    365:
                    366: /* Make any adjustments needed to a reloc before writing it out.  None
                    367:    are needed for MIPS.  */
                    368:
                    369: static void
                    370: mips_adjust_reloc_out (bfd *abfd ATTRIBUTE_UNUSED,
                    371:                       const arelent *rel ATTRIBUTE_UNUSED,
                    372:                       struct internal_reloc *intern ATTRIBUTE_UNUSED)
                    373: {
                    374: }
                    375:
                    376: /* ECOFF relocs are either against external symbols, or against
                    377:    sections.  If we are producing relocatable output, and the reloc
                    378:    is against an external symbol, and nothing has given us any
                    379:    additional addend, the resulting reloc will also be against the
                    380:    same symbol.  In such a case, we don't want to change anything
                    381:    about the way the reloc is handled, since it will all be done at
                    382:    final link time.  Rather than put special case code into
                    383:    bfd_perform_relocation, all the reloc types use this howto
                    384:    function.  It just short circuits the reloc if producing
                    385:    relocatable output against an external symbol.  */
                    386:
                    387: static bfd_reloc_status_type
                    388: mips_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                    389:                    arelent *reloc_entry,
                    390:                    asymbol *symbol,
                    391:                    void * data ATTRIBUTE_UNUSED,
                    392:                    asection *input_section,
                    393:                    bfd *output_bfd,
                    394:                    char **error_message ATTRIBUTE_UNUSED)
                    395: {
                    396:   if (output_bfd != (bfd *) NULL
                    397:       && (symbol->flags & BSF_SECTION_SYM) == 0
                    398:       && reloc_entry->addend == 0)
                    399:     {
                    400:       reloc_entry->address += input_section->output_offset;
                    401:       return bfd_reloc_ok;
                    402:     }
                    403:
                    404:   return bfd_reloc_continue;
                    405: }
                    406:
                    407: /* Do a REFHI relocation.  This has to be done in combination with a
                    408:    REFLO reloc, because there is a carry from the REFLO to the REFHI.
                    409:    Here we just save the information we need; we do the actual
                    410:    relocation when we see the REFLO.  MIPS ECOFF requires that the
                    411:    REFLO immediately follow the REFHI.  As a GNU extension, we permit
                    412:    an arbitrary number of HI relocs to be associated with a single LO
                    413:    reloc.  This extension permits gcc to output the HI and LO relocs
                    414:    itself.  */
                    415:
                    416: struct mips_hi
                    417: {
                    418:   struct mips_hi *next;
                    419:   bfd_byte *addr;
                    420:   bfd_vma addend;
                    421: };
                    422:
                    423: /* FIXME: This should not be a static variable.  */
                    424:
                    425: static struct mips_hi *mips_refhi_list;
                    426:
                    427: static bfd_reloc_status_type
                    428: mips_refhi_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                    429:                  arelent *reloc_entry,
                    430:                  asymbol *symbol,
                    431:                  void * data,
                    432:                  asection *input_section,
                    433:                  bfd *output_bfd,
                    434:                  char **error_message ATTRIBUTE_UNUSED)
                    435: {
                    436:   bfd_reloc_status_type ret;
                    437:   bfd_vma relocation;
                    438:   struct mips_hi *n;
                    439:
                    440:   /* If we're relocating, and this an external symbol, we don't want
                    441:      to change anything.  */
                    442:   if (output_bfd != (bfd *) NULL
                    443:       && (symbol->flags & BSF_SECTION_SYM) == 0
                    444:       && reloc_entry->addend == 0)
                    445:     {
                    446:       reloc_entry->address += input_section->output_offset;
                    447:       return bfd_reloc_ok;
                    448:     }
                    449:
                    450:   ret = bfd_reloc_ok;
                    451:   if (bfd_is_und_section (symbol->section)
                    452:       && output_bfd == (bfd *) NULL)
                    453:     ret = bfd_reloc_undefined;
                    454:
                    455:   if (bfd_is_com_section (symbol->section))
                    456:     relocation = 0;
                    457:   else
                    458:     relocation = symbol->value;
                    459:
                    460:   relocation += symbol->section->output_section->vma;
                    461:   relocation += symbol->section->output_offset;
                    462:   relocation += reloc_entry->addend;
                    463:
                    464:   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
                    465:     return bfd_reloc_outofrange;
                    466:
                    467:   /* Save the information, and let REFLO do the actual relocation.  */
                    468:   n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
                    469:   if (n == NULL)
                    470:     return bfd_reloc_outofrange;
                    471:   n->addr = (bfd_byte *) data + reloc_entry->address;
                    472:   n->addend = relocation;
                    473:   n->next = mips_refhi_list;
                    474:   mips_refhi_list = n;
                    475:
                    476:   if (output_bfd != (bfd *) NULL)
                    477:     reloc_entry->address += input_section->output_offset;
                    478:
                    479:   return ret;
                    480: }
                    481:
                    482: /* Do a REFLO relocation.  This is a straightforward 16 bit inplace
                    483:    relocation; this function exists in order to do the REFHI
                    484:    relocation described above.  */
                    485:
                    486: static bfd_reloc_status_type
                    487: mips_reflo_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                    488:                  arelent *reloc_entry,
                    489:                  asymbol *symbol,
                    490:                  void * data,
                    491:                  asection *input_section,
                    492:                  bfd *output_bfd,
                    493:                  char **error_message ATTRIBUTE_UNUSED)
                    494: {
                    495:   if (mips_refhi_list != NULL)
                    496:     {
                    497:       struct mips_hi *l;
                    498:
                    499:       l = mips_refhi_list;
                    500:       while (l != NULL)
                    501:        {
                    502:          unsigned long insn;
                    503:          unsigned long val;
                    504:          unsigned long vallo;
                    505:          struct mips_hi *next;
                    506:
                    507:          /* Do the REFHI relocation.  Note that we actually don't
                    508:             need to know anything about the REFLO itself, except
                    509:             where to find the low 16 bits of the addend needed by the
                    510:             REFHI.  */
                    511:          insn = bfd_get_32 (abfd, l->addr);
                    512:          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
                    513:                   & 0xffff);
                    514:          val = ((insn & 0xffff) << 16) + vallo;
                    515:          val += l->addend;
                    516:
                    517:          /* The low order 16 bits are always treated as a signed
                    518:             value.  Therefore, a negative value in the low order bits
                    519:             requires an adjustment in the high order bits.  We need
                    520:             to make this adjustment in two ways: once for the bits we
                    521:             took from the data, and once for the bits we are putting
                    522:             back in to the data.  */
                    523:          if ((vallo & 0x8000) != 0)
                    524:            val -= 0x10000;
                    525:          if ((val & 0x8000) != 0)
                    526:            val += 0x10000;
                    527:
                    528:          insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
                    529:          bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
                    530:
                    531:          next = l->next;
                    532:          free (l);
                    533:          l = next;
                    534:        }
                    535:
                    536:       mips_refhi_list = NULL;
                    537:     }
                    538:
                    539:   /* Now do the REFLO reloc in the usual way.  */
                    540:   return mips_generic_reloc (abfd, reloc_entry, symbol, data,
                    541:                              input_section, output_bfd, error_message);
                    542: }
                    543:
                    544: /* Do a GPREL relocation.  This is a 16 bit value which must become
                    545:    the offset from the gp register.  */
                    546:
                    547: static bfd_reloc_status_type
                    548: mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                    549:                  arelent *reloc_entry,
                    550:                  asymbol *symbol,
                    551:                  void * data,
                    552:                  asection *input_section,
                    553:                  bfd *output_bfd,
                    554:                  char **error_message ATTRIBUTE_UNUSED)
                    555: {
                    556:   bfd_boolean relocatable;
                    557:   bfd_vma gp;
                    558:   bfd_vma relocation;
                    559:   unsigned long val;
                    560:   unsigned long insn;
                    561:
                    562:   /* If we're relocating, and this is an external symbol with no
                    563:      addend, we don't want to change anything.  We will only have an
                    564:      addend if this is a newly created reloc, not read from an ECOFF
                    565:      file.  */
                    566:   if (output_bfd != (bfd *) NULL
                    567:       && (symbol->flags & BSF_SECTION_SYM) == 0
                    568:       && reloc_entry->addend == 0)
                    569:     {
                    570:       reloc_entry->address += input_section->output_offset;
                    571:       return bfd_reloc_ok;
                    572:     }
                    573:
                    574:   if (output_bfd != (bfd *) NULL)
                    575:     relocatable = TRUE;
                    576:   else
                    577:     {
                    578:       relocatable = FALSE;
                    579:       output_bfd = symbol->section->output_section->owner;
                    580:     }
                    581:
                    582:   if (bfd_is_und_section (symbol->section) && ! relocatable)
                    583:     return bfd_reloc_undefined;
                    584:
                    585:   /* We have to figure out the gp value, so that we can adjust the
                    586:      symbol value correctly.  We look up the symbol _gp in the output
                    587:      BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
                    588:      target data.  We don't need to adjust the symbol value for an
                    589:      external symbol if we are producing relocatable output.  */
                    590:   gp = _bfd_get_gp_value (output_bfd);
                    591:   if (gp == 0
                    592:       && (! relocatable
                    593:          || (symbol->flags & BSF_SECTION_SYM) != 0))
                    594:     {
                    595:       if (relocatable)
                    596:        {
                    597:          /* Make up a value.  */
                    598:          gp = symbol->section->output_section->vma + 0x4000;
                    599:          _bfd_set_gp_value (output_bfd, gp);
                    600:        }
                    601:       else
                    602:        {
                    603:          unsigned int count;
                    604:          asymbol **sym;
                    605:          unsigned int i;
                    606:
                    607:          count = bfd_get_symcount (output_bfd);
                    608:          sym = bfd_get_outsymbols (output_bfd);
                    609:
                    610:          if (sym == (asymbol **) NULL)
                    611:            i = count;
                    612:          else
                    613:            {
                    614:              for (i = 0; i < count; i++, sym++)
                    615:                {
                    616:                  register const char *name;
                    617:
                    618:                  name = bfd_asymbol_name (*sym);
                    619:                  if (*name == '_' && strcmp (name, "_gp") == 0)
                    620:                    {
                    621:                      gp = bfd_asymbol_value (*sym);
                    622:                      _bfd_set_gp_value (output_bfd, gp);
                    623:                      break;
                    624:                    }
                    625:                }
                    626:            }
                    627:
                    628:          if (i >= count)
                    629:            {
                    630:              /* Only get the error once.  */
                    631:              gp = 4;
                    632:              _bfd_set_gp_value (output_bfd, gp);
                    633:              *error_message =
                    634:                (char *) _("GP relative relocation when _gp not defined");
                    635:              return bfd_reloc_dangerous;
                    636:            }
                    637:        }
                    638:     }
                    639:
                    640:   if (bfd_is_com_section (symbol->section))
                    641:     relocation = 0;
                    642:   else
                    643:     relocation = symbol->value;
                    644:
                    645:   relocation += symbol->section->output_section->vma;
                    646:   relocation += symbol->section->output_offset;
                    647:
                    648:   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
                    649:     return bfd_reloc_outofrange;
                    650:
                    651:   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
                    652:
                    653:   /* Set val to the offset into the section or symbol.  */
                    654:   val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
                    655:   if (val & 0x8000)
                    656:     val -= 0x10000;
                    657:
                    658:   /* Adjust val for the final section location and GP value.  If we
                    659:      are producing relocatable output, we don't want to do this for
                    660:      an external symbol.  */
                    661:   if (! relocatable
                    662:       || (symbol->flags & BSF_SECTION_SYM) != 0)
                    663:     val += relocation - gp;
                    664:
                    665:   insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
                    666:   bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
                    667:
                    668:   if (relocatable)
                    669:     reloc_entry->address += input_section->output_offset;
                    670:
                    671:   /* Make sure it fit in 16 bits.  */
                    672:   if ((long) val >= 0x8000 || (long) val < -0x8000)
                    673:     return bfd_reloc_overflow;
                    674:
                    675:   return bfd_reloc_ok;
                    676: }
                    677:
                    678: /* Get the howto structure for a generic reloc type.  */
                    679:
                    680: static reloc_howto_type *
                    681: mips_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
                    682:                            bfd_reloc_code_real_type code)
                    683: {
                    684:   int mips_type;
                    685:
                    686:   switch (code)
                    687:     {
                    688:     case BFD_RELOC_16:
                    689:       mips_type = MIPS_R_REFHALF;
                    690:       break;
                    691:     case BFD_RELOC_32:
                    692:     case BFD_RELOC_CTOR:
                    693:       mips_type = MIPS_R_REFWORD;
                    694:       break;
                    695:     case BFD_RELOC_MIPS_JMP:
                    696:       mips_type = MIPS_R_JMPADDR;
                    697:       break;
                    698:     case BFD_RELOC_HI16_S:
                    699:       mips_type = MIPS_R_REFHI;
                    700:       break;
                    701:     case BFD_RELOC_LO16:
                    702:       mips_type = MIPS_R_REFLO;
                    703:       break;
                    704:     case BFD_RELOC_GPREL16:
                    705:       mips_type = MIPS_R_GPREL;
                    706:       break;
                    707:     case BFD_RELOC_MIPS_LITERAL:
                    708:       mips_type = MIPS_R_LITERAL;
                    709:       break;
                    710:     case BFD_RELOC_16_PCREL_S2:
                    711:       mips_type = MIPS_R_PCREL16;
                    712:       break;
                    713:     default:
                    714:       return (reloc_howto_type *) NULL;
                    715:     }
                    716:
                    717:   return &mips_howto_table[mips_type];
                    718: }
                    719:
                    720: static reloc_howto_type *
                    721: mips_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
                    722:                            const char *r_name)
                    723: {
                    724:   unsigned int i;
                    725:
                    726:   for (i = 0;
                    727:        i < sizeof (mips_howto_table) / sizeof (mips_howto_table[0]);
                    728:        i++)
                    729:     if (mips_howto_table[i].name != NULL
                    730:        && strcasecmp (mips_howto_table[i].name, r_name) == 0)
                    731:       return &mips_howto_table[i];
                    732:
                    733:   return NULL;
                    734: }
                    735: 
                    736: /* A helper routine for mips_relocate_section which handles the REFHI
                    737:    relocations.  The REFHI relocation must be followed by a REFLO
                    738:    relocation, and the addend used is formed from the addends of both
                    739:    instructions.  */
                    740:
                    741: static void
                    742: mips_relocate_hi (struct internal_reloc *refhi,
                    743:                  struct internal_reloc *reflo,
                    744:                  bfd *input_bfd,
                    745:                  asection *input_section,
                    746:                  bfd_byte *contents,
                    747:                  bfd_vma relocation)
                    748: {
                    749:   unsigned long insn;
                    750:   unsigned long val;
                    751:   unsigned long vallo;
                    752:
                    753:   if (refhi == NULL)
                    754:     return;
                    755:
                    756:   insn = bfd_get_32 (input_bfd,
                    757:                     contents + refhi->r_vaddr - input_section->vma);
                    758:   if (reflo == NULL)
                    759:     vallo = 0;
                    760:   else
                    761:     vallo = (bfd_get_32 (input_bfd,
                    762:                         contents + reflo->r_vaddr - input_section->vma)
                    763:             & 0xffff);
                    764:
                    765:   val = ((insn & 0xffff) << 16) + vallo;
                    766:   val += relocation;
                    767:
                    768:   /* The low order 16 bits are always treated as a signed value.
                    769:      Therefore, a negative value in the low order bits requires an
                    770:      adjustment in the high order bits.  We need to make this
                    771:      adjustment in two ways: once for the bits we took from the data,
                    772:      and once for the bits we are putting back in to the data.  */
                    773:   if ((vallo & 0x8000) != 0)
                    774:     val -= 0x10000;
                    775:
                    776:   if ((val & 0x8000) != 0)
                    777:     val += 0x10000;
                    778:
                    779:   insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
                    780:   bfd_put_32 (input_bfd, (bfd_vma) insn,
                    781:              contents + refhi->r_vaddr - input_section->vma);
                    782: }
                    783:
                    784: /* Relocate a section while linking a MIPS ECOFF file.  */
                    785:
                    786: static bfd_boolean
                    787: mips_relocate_section (bfd *output_bfd,
                    788:                       struct bfd_link_info *info,
                    789:                       bfd *input_bfd,
                    790:                       asection *input_section,
                    791:                       bfd_byte *contents,
                    792:                       void * external_relocs)
                    793: {
                    794:   asection **symndx_to_section;
                    795:   struct ecoff_link_hash_entry **sym_hashes;
                    796:   bfd_vma gp;
                    797:   bfd_boolean gp_undefined;
                    798:   struct external_reloc *ext_rel;
                    799:   struct external_reloc *ext_rel_end;
                    800:   unsigned int i;
                    801:   bfd_boolean got_lo;
                    802:   struct internal_reloc lo_int_rel;
                    803:   bfd_size_type amt;
                    804:
                    805:   BFD_ASSERT (input_bfd->xvec->byteorder
                    806:              == output_bfd->xvec->byteorder);
                    807:
                    808:   /* We keep a table mapping the symndx found in an internal reloc to
                    809:      the appropriate section.  This is faster than looking up the
                    810:      section by name each time.  */
                    811:   symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
                    812:   if (symndx_to_section == (asection **) NULL)
                    813:     {
                    814:       amt = NUM_RELOC_SECTIONS * sizeof (asection *);
                    815:       symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
                    816:       if (!symndx_to_section)
                    817:        return FALSE;
                    818:
                    819:       symndx_to_section[RELOC_SECTION_NONE] = NULL;
                    820:       symndx_to_section[RELOC_SECTION_TEXT] =
                    821:        bfd_get_section_by_name (input_bfd, ".text");
                    822:       symndx_to_section[RELOC_SECTION_RDATA] =
                    823:        bfd_get_section_by_name (input_bfd, ".rdata");
                    824:       symndx_to_section[RELOC_SECTION_DATA] =
                    825:        bfd_get_section_by_name (input_bfd, ".data");
                    826:       symndx_to_section[RELOC_SECTION_SDATA] =
                    827:        bfd_get_section_by_name (input_bfd, ".sdata");
                    828:       symndx_to_section[RELOC_SECTION_SBSS] =
                    829:        bfd_get_section_by_name (input_bfd, ".sbss");
                    830:       symndx_to_section[RELOC_SECTION_BSS] =
                    831:        bfd_get_section_by_name (input_bfd, ".bss");
                    832:       symndx_to_section[RELOC_SECTION_INIT] =
                    833:        bfd_get_section_by_name (input_bfd, ".init");
                    834:       symndx_to_section[RELOC_SECTION_LIT8] =
                    835:        bfd_get_section_by_name (input_bfd, ".lit8");
                    836:       symndx_to_section[RELOC_SECTION_LIT4] =
                    837:        bfd_get_section_by_name (input_bfd, ".lit4");
                    838:       symndx_to_section[RELOC_SECTION_XDATA] = NULL;
                    839:       symndx_to_section[RELOC_SECTION_PDATA] = NULL;
                    840:       symndx_to_section[RELOC_SECTION_FINI] =
                    841:        bfd_get_section_by_name (input_bfd, ".fini");
                    842:       symndx_to_section[RELOC_SECTION_LITA] = NULL;
                    843:       symndx_to_section[RELOC_SECTION_ABS] = NULL;
                    844:
                    845:       ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
                    846:     }
                    847:
                    848:   sym_hashes = ecoff_data (input_bfd)->sym_hashes;
                    849:
                    850:   gp = _bfd_get_gp_value (output_bfd);
                    851:   if (gp == 0)
                    852:     gp_undefined = TRUE;
                    853:   else
                    854:     gp_undefined = FALSE;
                    855:
                    856:   got_lo = FALSE;
                    857:
                    858:   ext_rel = (struct external_reloc *) external_relocs;
                    859:   ext_rel_end = ext_rel + input_section->reloc_count;
                    860:   for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
                    861:     {
                    862:       struct internal_reloc int_rel;
                    863:       bfd_boolean use_lo = FALSE;
                    864:       bfd_vma addend;
                    865:       reloc_howto_type *howto;
                    866:       struct ecoff_link_hash_entry *h = NULL;
                    867:       asection *s = NULL;
                    868:       bfd_vma relocation;
                    869:       bfd_reloc_status_type r;
                    870:
                    871:       if (! got_lo)
                    872:        mips_ecoff_swap_reloc_in (input_bfd, ext_rel, &int_rel);
                    873:       else
                    874:        {
                    875:          int_rel = lo_int_rel;
                    876:          got_lo = FALSE;
                    877:        }
                    878:
                    879:       BFD_ASSERT (int_rel.r_type
                    880:                  < sizeof mips_howto_table / sizeof mips_howto_table[0]);
                    881:
                    882:       /* The REFHI reloc requires special handling.  It must be followed
                    883:         by a REFLO reloc, and the addend is formed from both relocs.  */
                    884:       if (int_rel.r_type == MIPS_R_REFHI)
                    885:        {
                    886:          struct external_reloc *lo_ext_rel;
                    887:
                    888:          /* As a GNU extension, permit an arbitrary number of REFHI
                    889:              relocs before the REFLO reloc.  This permits gcc to emit
                    890:             the HI and LO relocs itself.  */
                    891:          for (lo_ext_rel = ext_rel + 1;
                    892:               lo_ext_rel < ext_rel_end;
                    893:               lo_ext_rel++)
                    894:            {
                    895:              mips_ecoff_swap_reloc_in (input_bfd, lo_ext_rel,
                    896:                                        &lo_int_rel);
                    897:              if (lo_int_rel.r_type != int_rel.r_type)
                    898:                break;
                    899:            }
                    900:
                    901:          if (lo_ext_rel < ext_rel_end
                    902:              && lo_int_rel.r_type == MIPS_R_REFLO
                    903:              && int_rel.r_extern == lo_int_rel.r_extern
                    904:              && int_rel.r_symndx == lo_int_rel.r_symndx)
                    905:            {
                    906:              use_lo = TRUE;
                    907:              if (lo_ext_rel == ext_rel + 1)
                    908:                got_lo = TRUE;
                    909:            }
                    910:        }
                    911:
                    912:       howto = &mips_howto_table[int_rel.r_type];
                    913:
                    914:       if (int_rel.r_extern)
                    915:        {
                    916:          h = sym_hashes[int_rel.r_symndx];
                    917:          /* If h is NULL, that means that there is a reloc against an
                    918:             external symbol which we thought was just a debugging
                    919:             symbol.  This should not happen.  */
                    920:          if (h == (struct ecoff_link_hash_entry *) NULL)
                    921:            abort ();
                    922:        }
                    923:       else
                    924:        {
                    925:          if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
                    926:            s = NULL;
                    927:          else
                    928:            s = symndx_to_section[int_rel.r_symndx];
                    929:
                    930:          if (s == (asection *) NULL)
                    931:            abort ();
                    932:        }
                    933:
                    934:       /* The GPREL reloc uses an addend: the difference in the GP
                    935:         values.  */
                    936:       if (int_rel.r_type != MIPS_R_GPREL
                    937:          && int_rel.r_type != MIPS_R_LITERAL)
                    938:        addend = 0;
                    939:       else
                    940:        {
                    941:          if (gp_undefined)
                    942:            {
1.4.8.1 ! pgoyette  943:              (*info->callbacks->reloc_dangerous)
        !           944:                (info, _("GP relative relocation used when GP not defined"),
        !           945:                 input_bfd, input_section,
        !           946:                 int_rel.r_vaddr - input_section->vma);
1.1       christos  947:              /* Only give the error once per link.  */
                    948:              gp = 4;
                    949:              _bfd_set_gp_value (output_bfd, gp);
                    950:              gp_undefined = FALSE;
                    951:            }
                    952:          if (! int_rel.r_extern)
                    953:            {
                    954:              /* This is a relocation against a section.  The current
                    955:                 addend in the instruction is the difference between
                    956:                 INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
                    957:                 must change this to be the difference between the
                    958:                 final definition (which will end up in RELOCATION)
                    959:                 and the GP value of OUTPUT_BFD (which is in GP).  */
                    960:              addend = ecoff_data (input_bfd)->gp - gp;
                    961:            }
1.3       christos  962:          else if (! bfd_link_relocatable (info)
1.1       christos  963:                   || h->root.type == bfd_link_hash_defined
                    964:                   || h->root.type == bfd_link_hash_defweak)
                    965:            {
                    966:              /* This is a relocation against a defined symbol.  The
                    967:                 current addend in the instruction is simply the
                    968:                 desired offset into the symbol (normally zero).  We
                    969:                 are going to change this into a relocation against a
                    970:                 defined symbol, so we want the instruction to hold
                    971:                 the difference between the final definition of the
                    972:                 symbol (which will end up in RELOCATION) and the GP
                    973:                 value of OUTPUT_BFD (which is in GP).  */
                    974:              addend = - gp;
                    975:            }
                    976:          else
                    977:            {
                    978:              /* This is a relocation against an undefined or common
                    979:                 symbol.  The current addend in the instruction is
                    980:                 simply the desired offset into the symbol (normally
                    981:                 zero).  We are generating relocatable output, and we
                    982:                 aren't going to define this symbol, so we just leave
                    983:                 the instruction alone.  */
                    984:              addend = 0;
                    985:            }
                    986:        }
                    987:
1.3       christos  988:       if (bfd_link_relocatable (info))
1.1       christos  989:        {
                    990:          /* We are generating relocatable output, and must convert
                    991:             the existing reloc.  */
                    992:          if (int_rel.r_extern)
                    993:            {
                    994:              if ((h->root.type == bfd_link_hash_defined
                    995:                   || h->root.type == bfd_link_hash_defweak)
                    996:                  && ! bfd_is_abs_section (h->root.u.def.section))
                    997:                {
                    998:                  const char *name;
                    999:
                   1000:                  /* This symbol is defined in the output.  Convert
                   1001:                     the reloc from being against the symbol to being
                   1002:                     against the section.  */
                   1003:
                   1004:                  /* Clear the r_extern bit.  */
                   1005:                  int_rel.r_extern = 0;
                   1006:
                   1007:                  /* Compute a new r_symndx value.  */
                   1008:                  s = h->root.u.def.section;
                   1009:                  name = bfd_get_section_name (output_bfd,
                   1010:                                               s->output_section);
                   1011:
                   1012:                  int_rel.r_symndx = -1;
                   1013:                  switch (name[1])
                   1014:                    {
                   1015:                    case 'b':
                   1016:                      if (strcmp (name, ".bss") == 0)
                   1017:                        int_rel.r_symndx = RELOC_SECTION_BSS;
                   1018:                      break;
                   1019:                    case 'd':
                   1020:                      if (strcmp (name, ".data") == 0)
                   1021:                        int_rel.r_symndx = RELOC_SECTION_DATA;
                   1022:                      break;
                   1023:                    case 'f':
                   1024:                      if (strcmp (name, ".fini") == 0)
                   1025:                        int_rel.r_symndx = RELOC_SECTION_FINI;
                   1026:                      break;
                   1027:                    case 'i':
                   1028:                      if (strcmp (name, ".init") == 0)
                   1029:                        int_rel.r_symndx = RELOC_SECTION_INIT;
                   1030:                      break;
                   1031:                    case 'l':
                   1032:                      if (strcmp (name, ".lit8") == 0)
                   1033:                        int_rel.r_symndx = RELOC_SECTION_LIT8;
                   1034:                      else if (strcmp (name, ".lit4") == 0)
                   1035:                        int_rel.r_symndx = RELOC_SECTION_LIT4;
                   1036:                      break;
                   1037:                    case 'r':
                   1038:                      if (strcmp (name, ".rdata") == 0)
                   1039:                        int_rel.r_symndx = RELOC_SECTION_RDATA;
                   1040:                      break;
                   1041:                    case 's':
                   1042:                      if (strcmp (name, ".sdata") == 0)
                   1043:                        int_rel.r_symndx = RELOC_SECTION_SDATA;
                   1044:                      else if (strcmp (name, ".sbss") == 0)
                   1045:                        int_rel.r_symndx = RELOC_SECTION_SBSS;
                   1046:                      break;
                   1047:                    case 't':
                   1048:                      if (strcmp (name, ".text") == 0)
                   1049:                        int_rel.r_symndx = RELOC_SECTION_TEXT;
                   1050:                      break;
                   1051:                    }
                   1052:
                   1053:                  if (int_rel.r_symndx == -1)
                   1054:                    abort ();
                   1055:
                   1056:                  /* Add the section VMA and the symbol value.  */
                   1057:                  relocation = (h->root.u.def.value
                   1058:                                + s->output_section->vma
                   1059:                                + s->output_offset);
                   1060:
                   1061:                  /* For a PC relative relocation, the object file
                   1062:                     currently holds just the addend.  We must adjust
                   1063:                     by the address to get the right value.  */
                   1064:                  if (howto->pc_relative)
                   1065:                    relocation -= int_rel.r_vaddr - input_section->vma;
                   1066:
                   1067:                  h = NULL;
                   1068:                }
                   1069:              else
                   1070:                {
                   1071:                  /* Change the symndx value to the right one for the
                   1072:                     output BFD.  */
                   1073:                  int_rel.r_symndx = h->indx;
                   1074:                  if (int_rel.r_symndx == -1)
                   1075:                    {
                   1076:                      /* This symbol is not being written out.  */
1.4.8.1 ! pgoyette 1077:                      (*info->callbacks->unattached_reloc)
        !          1078:                        (info, h->root.root.string, input_bfd, input_section,
        !          1079:                         int_rel.r_vaddr - input_section->vma);
1.1       christos 1080:                      int_rel.r_symndx = 0;
                   1081:                    }
                   1082:                  relocation = 0;
                   1083:                }
                   1084:            }
                   1085:          else
                   1086:            {
                   1087:              /* This is a relocation against a section.  Adjust the
                   1088:                 value by the amount the section moved.  */
                   1089:              relocation = (s->output_section->vma
                   1090:                            + s->output_offset
                   1091:                            - s->vma);
                   1092:            }
                   1093:
                   1094:          relocation += addend;
                   1095:          addend = 0;
                   1096:
                   1097:          /* Adjust a PC relative relocation by removing the reference
                   1098:             to the original address in the section and including the
                   1099:             reference to the new address.  */
                   1100:          if (howto->pc_relative)
                   1101:            relocation -= (input_section->output_section->vma
                   1102:                           + input_section->output_offset
                   1103:                           - input_section->vma);
                   1104:
                   1105:          /* Adjust the contents.  */
                   1106:          if (relocation == 0)
                   1107:            r = bfd_reloc_ok;
                   1108:          else
                   1109:            {
                   1110:              if (int_rel.r_type != MIPS_R_REFHI)
                   1111:                r = _bfd_relocate_contents (howto, input_bfd, relocation,
                   1112:                                            (contents
                   1113:                                             + int_rel.r_vaddr
                   1114:                                             - input_section->vma));
                   1115:              else
                   1116:                {
                   1117:                  mips_relocate_hi (&int_rel,
                   1118:                                    use_lo ? &lo_int_rel : NULL,
                   1119:                                    input_bfd, input_section, contents,
                   1120:                                    relocation);
                   1121:                  r = bfd_reloc_ok;
                   1122:                }
                   1123:            }
                   1124:
                   1125:          /* Adjust the reloc address.  */
                   1126:          int_rel.r_vaddr += (input_section->output_section->vma
                   1127:                              + input_section->output_offset
                   1128:                              - input_section->vma);
                   1129:
                   1130:          /* Save the changed reloc information.  */
                   1131:          mips_ecoff_swap_reloc_out (input_bfd, &int_rel, ext_rel);
                   1132:        }
                   1133:       else
                   1134:        {
                   1135:          /* We are producing a final executable.  */
                   1136:          if (int_rel.r_extern)
                   1137:            {
                   1138:              /* This is a reloc against a symbol.  */
                   1139:              if (h->root.type == bfd_link_hash_defined
                   1140:                  || h->root.type == bfd_link_hash_defweak)
                   1141:                {
                   1142:                  asection *hsec;
                   1143:
                   1144:                  hsec = h->root.u.def.section;
                   1145:                  relocation = (h->root.u.def.value
                   1146:                                + hsec->output_section->vma
                   1147:                                + hsec->output_offset);
                   1148:                }
                   1149:              else
                   1150:                {
1.4.8.1 ! pgoyette 1151:                  (*info->callbacks->undefined_symbol)
        !          1152:                    (info, h->root.root.string, input_bfd, input_section,
        !          1153:                     int_rel.r_vaddr - input_section->vma, TRUE);
1.1       christos 1154:                  relocation = 0;
                   1155:                }
                   1156:            }
                   1157:          else
                   1158:            {
                   1159:              /* This is a reloc against a section.  */
                   1160:              relocation = (s->output_section->vma
                   1161:                            + s->output_offset
                   1162:                            - s->vma);
                   1163:
                   1164:              /* A PC relative reloc is already correct in the object
                   1165:                 file.  Make it look like a pcrel_offset relocation by
                   1166:                 adding in the start address.  */
                   1167:              if (howto->pc_relative)
                   1168:                relocation += int_rel.r_vaddr;
                   1169:            }
                   1170:
                   1171:          if (int_rel.r_type != MIPS_R_REFHI)
                   1172:            r = _bfd_final_link_relocate (howto,
                   1173:                                          input_bfd,
                   1174:                                          input_section,
                   1175:                                          contents,
                   1176:                                          (int_rel.r_vaddr
                   1177:                                           - input_section->vma),
                   1178:                                          relocation,
                   1179:                                          addend);
                   1180:          else
                   1181:            {
                   1182:              mips_relocate_hi (&int_rel,
                   1183:                                use_lo ? &lo_int_rel : NULL,
                   1184:                                input_bfd, input_section, contents,
                   1185:                                relocation);
                   1186:              r = bfd_reloc_ok;
                   1187:            }
                   1188:        }
                   1189:
                   1190:       /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
                   1191:         instruction provides a 28 bit address (the two lower bits are
                   1192:         implicit zeroes) which is combined with the upper four bits
                   1193:         of the instruction address.  */
                   1194:       if (r == bfd_reloc_ok
                   1195:          && int_rel.r_type == MIPS_R_JMPADDR
                   1196:          && (((relocation
                   1197:                + addend
                   1198:                + (int_rel.r_extern ? 0 : s->vma))
                   1199:               & 0xf0000000)
                   1200:              != ((input_section->output_section->vma
                   1201:                   + input_section->output_offset
                   1202:                   + (int_rel.r_vaddr - input_section->vma))
                   1203:                  & 0xf0000000)))
                   1204:        r = bfd_reloc_overflow;
                   1205:
                   1206:       if (r != bfd_reloc_ok)
                   1207:        {
                   1208:          switch (r)
                   1209:            {
                   1210:            default:
                   1211:            case bfd_reloc_outofrange:
                   1212:              abort ();
                   1213:            case bfd_reloc_overflow:
                   1214:              {
                   1215:                const char *name;
                   1216:
                   1217:                if (int_rel.r_extern)
                   1218:                  name = NULL;
                   1219:                else
                   1220:                  name = bfd_section_name (input_bfd, s);
1.4.8.1 ! pgoyette 1221:                (*info->callbacks->reloc_overflow)
        !          1222:                  (info, (h ? &h->root : NULL), name, howto->name,
        !          1223:                   (bfd_vma) 0, input_bfd, input_section,
        !          1224:                   int_rel.r_vaddr - input_section->vma);
1.1       christos 1225:              }
                   1226:              break;
                   1227:            }
                   1228:        }
                   1229:     }
                   1230:
                   1231:   return TRUE;
                   1232: }
                   1233: 
                   1234: /* This is the ECOFF backend structure.  The backend field of the
                   1235:    target vector points to this.  */
                   1236:
                   1237: static const struct ecoff_backend_data mips_ecoff_backend_data =
                   1238: {
                   1239:   /* COFF backend structure.  */
                   1240:   {
                   1241:     (void (*) (bfd *,void *,int,int,int,int,void *)) bfd_void, /* aux_in */
                   1242:     (void (*) (bfd *,void *,void *)) bfd_void, /* sym_in */
                   1243:     (void (*) (bfd *,void *,void *)) bfd_void, /* lineno_in */
                   1244:     (unsigned (*) (bfd *,void *,int,int,int,int,void *)) bfd_void,/*aux_out*/
                   1245:     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* sym_out */
                   1246:     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* lineno_out */
                   1247:     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* reloc_out */
                   1248:     mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
                   1249:     mips_ecoff_swap_scnhdr_out,
1.3       christos 1250:     FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE,
                   1251:     ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768,
1.1       christos 1252:     mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
                   1253:     mips_ecoff_swap_scnhdr_in, NULL,
                   1254:     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
                   1255:     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
                   1256:     _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
                   1257:     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                   1258:     NULL, NULL, NULL
                   1259:   },
                   1260:   /* Supported architecture.  */
                   1261:   bfd_arch_mips,
                   1262:   /* Initial portion of armap string.  */
                   1263:   "__________",
                   1264:   /* The page boundary used to align sections in a demand-paged
                   1265:      executable file.  E.g., 0x1000.  */
                   1266:   0x1000,
                   1267:   /* TRUE if the .rdata section is part of the text segment, as on the
                   1268:      Alpha.  FALSE if .rdata is part of the data segment, as on the
                   1269:      MIPS.  */
                   1270:   FALSE,
                   1271:   /* Bitsize of constructor entries.  */
                   1272:   32,
                   1273:   /* Reloc to use for constructor entries.  */
                   1274:   &mips_howto_table[MIPS_R_REFWORD],
                   1275:   {
                   1276:     /* Symbol table magic number.  */
                   1277:     magicSym,
                   1278:     /* Alignment of debugging information.  E.g., 4.  */
                   1279:     4,
                   1280:     /* Sizes of external symbolic information.  */
                   1281:     sizeof (struct hdr_ext),
                   1282:     sizeof (struct dnr_ext),
                   1283:     sizeof (struct pdr_ext),
                   1284:     sizeof (struct sym_ext),
                   1285:     sizeof (struct opt_ext),
                   1286:     sizeof (struct fdr_ext),
                   1287:     sizeof (struct rfd_ext),
                   1288:     sizeof (struct ext_ext),
                   1289:     /* Functions to swap in external symbolic data.  */
                   1290:     ecoff_swap_hdr_in,
                   1291:     ecoff_swap_dnr_in,
                   1292:     ecoff_swap_pdr_in,
                   1293:     ecoff_swap_sym_in,
                   1294:     ecoff_swap_opt_in,
                   1295:     ecoff_swap_fdr_in,
                   1296:     ecoff_swap_rfd_in,
                   1297:     ecoff_swap_ext_in,
                   1298:     _bfd_ecoff_swap_tir_in,
                   1299:     _bfd_ecoff_swap_rndx_in,
                   1300:     /* Functions to swap out external symbolic data.  */
                   1301:     ecoff_swap_hdr_out,
                   1302:     ecoff_swap_dnr_out,
                   1303:     ecoff_swap_pdr_out,
                   1304:     ecoff_swap_sym_out,
                   1305:     ecoff_swap_opt_out,
                   1306:     ecoff_swap_fdr_out,
                   1307:     ecoff_swap_rfd_out,
                   1308:     ecoff_swap_ext_out,
                   1309:     _bfd_ecoff_swap_tir_out,
                   1310:     _bfd_ecoff_swap_rndx_out,
                   1311:     /* Function to read in symbolic data.  */
                   1312:     _bfd_ecoff_slurp_symbolic_info
                   1313:   },
                   1314:   /* External reloc size.  */
                   1315:   RELSZ,
                   1316:   /* Reloc swapping functions.  */
                   1317:   mips_ecoff_swap_reloc_in,
                   1318:   mips_ecoff_swap_reloc_out,
                   1319:   /* Backend reloc tweaking.  */
                   1320:   mips_adjust_reloc_in,
                   1321:   mips_adjust_reloc_out,
                   1322:   /* Relocate section contents while linking.  */
                   1323:   mips_relocate_section,
                   1324:   /* Do final adjustments to filehdr and aouthdr.  */
                   1325:   NULL,
                   1326:   /* Read an element from an archive at a given file position.  */
                   1327:   _bfd_get_elt_at_filepos
                   1328: };
                   1329:
                   1330: /* Looking up a reloc type is MIPS specific.  */
                   1331: #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
                   1332: #define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup
                   1333:
                   1334: /* Getting relocated section contents is generic.  */
                   1335: #define _bfd_ecoff_bfd_get_relocated_section_contents \
                   1336:   bfd_generic_get_relocated_section_contents
                   1337:
                   1338: /* Handling file windows is generic.  */
                   1339: #define _bfd_ecoff_get_section_contents_in_window \
                   1340:   _bfd_generic_get_section_contents_in_window
                   1341:
                   1342: /* Relaxing sections is MIPS specific.  */
                   1343: #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
                   1344:
                   1345: /* GC of sections is not done.  */
                   1346: #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
                   1347:
                   1348: /* Input section flags is not implemented.  */
                   1349: #define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags
                   1350:
                   1351: /* Merging of sections is not done.  */
                   1352: #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
                   1353:
                   1354: #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
                   1355: #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
                   1356: #define _bfd_ecoff_section_already_linked \
                   1357:   _bfd_coff_section_already_linked
                   1358: #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
                   1359:
1.3       christos 1360: extern const bfd_target mips_ecoff_be_vec;
1.1       christos 1361:
1.3       christos 1362: const bfd_target mips_ecoff_le_vec =
1.1       christos 1363: {
                   1364:   "ecoff-littlemips",          /* name */
                   1365:   bfd_target_ecoff_flavour,
                   1366:   BFD_ENDIAN_LITTLE,           /* data byte order is little */
                   1367:   BFD_ENDIAN_LITTLE,           /* header byte order is little */
                   1368:
                   1369:   (HAS_RELOC | EXEC_P |                /* object flags */
                   1370:    HAS_LINENO | HAS_DEBUG |
                   1371:    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
                   1372:
                   1373:   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
                   1374:   0,                           /* leading underscore */
                   1375:   ' ',                         /* ar_pad_char */
                   1376:   15,                          /* ar_max_namelen */
                   1377:   0,                           /* match priority.  */
                   1378:   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
                   1379:      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
                   1380:      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
                   1381:   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
                   1382:      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
                   1383:      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
                   1384:
                   1385:   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
                   1386:      bfd_generic_archive_p, _bfd_dummy_target},
                   1387:   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
                   1388:      _bfd_generic_mkarchive, bfd_false},
                   1389:   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
                   1390:      _bfd_write_archive_contents, bfd_false},
                   1391:
                   1392:      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
                   1393:      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
                   1394:      BFD_JUMP_TABLE_CORE (_bfd_nocore),
                   1395:      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
                   1396:      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
                   1397:      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
                   1398:      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
                   1399:      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
                   1400:      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
                   1401:
1.3       christos 1402:   & mips_ecoff_be_vec,
1.1       christos 1403:
                   1404:   & mips_ecoff_backend_data
                   1405: };
                   1406:
1.3       christos 1407: const bfd_target mips_ecoff_be_vec =
1.1       christos 1408: {
                   1409:   "ecoff-bigmips",             /* name */
                   1410:   bfd_target_ecoff_flavour,
                   1411:   BFD_ENDIAN_BIG,              /* data byte order is big */
                   1412:   BFD_ENDIAN_BIG,              /* header byte order is big */
                   1413:
                   1414:   (HAS_RELOC | EXEC_P |                /* object flags */
                   1415:    HAS_LINENO | HAS_DEBUG |
                   1416:    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
                   1417:
                   1418:   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
                   1419:   0,                           /* leading underscore */
                   1420:   ' ',                         /* ar_pad_char */
                   1421:   15,                          /* ar_max_namelen */
                   1422:   0,                           /* match priority.  */
                   1423:   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
                   1424:      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
                   1425:      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
                   1426:   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
                   1427:      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
                   1428:      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
                   1429:  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
                   1430:     bfd_generic_archive_p, _bfd_dummy_target},
                   1431:  {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
                   1432:     _bfd_generic_mkarchive, bfd_false},
                   1433:  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
                   1434:     _bfd_write_archive_contents, bfd_false},
                   1435:
                   1436:      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
                   1437:      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
                   1438:      BFD_JUMP_TABLE_CORE (_bfd_nocore),
                   1439:      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
                   1440:      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
                   1441:      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
                   1442:      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
                   1443:      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
                   1444:      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
                   1445:
1.3       christos 1446:   & mips_ecoff_le_vec,
1.1       christos 1447:
                   1448:   & mips_ecoff_backend_data
                   1449: };
                   1450:
1.3       christos 1451: const bfd_target mips_ecoff_bele_vec =
1.1       christos 1452: {
                   1453:   "ecoff-biglittlemips",               /* name */
                   1454:   bfd_target_ecoff_flavour,
                   1455:   BFD_ENDIAN_LITTLE,           /* data byte order is little */
                   1456:   BFD_ENDIAN_BIG,              /* header byte order is big */
                   1457:
                   1458:   (HAS_RELOC | EXEC_P |                /* object flags */
                   1459:    HAS_LINENO | HAS_DEBUG |
                   1460:    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
                   1461:
                   1462:   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
                   1463:   0,                           /* leading underscore */
                   1464:   ' ',                         /* ar_pad_char */
                   1465:   15,                          /* ar_max_namelen */
                   1466:   0,                           /* match priority.  */
                   1467:   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
                   1468:      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
                   1469:      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
                   1470:   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
                   1471:      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
                   1472:      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
                   1473:
                   1474:   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
                   1475:      bfd_generic_archive_p, _bfd_dummy_target},
                   1476:   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
                   1477:      _bfd_generic_mkarchive, bfd_false},
                   1478:   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
                   1479:      _bfd_write_archive_contents, bfd_false},
                   1480:
                   1481:      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
                   1482:      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
                   1483:      BFD_JUMP_TABLE_CORE (_bfd_nocore),
                   1484:      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
                   1485:      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
                   1486:      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
                   1487:      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
                   1488:      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
                   1489:      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
                   1490:
                   1491:   NULL,
                   1492:
                   1493:   & mips_ecoff_backend_data
                   1494: };

CVSweb <webmaster@jp.NetBSD.org>