Coverage Report

Created: 2026-07-25 10:20

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