OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [coff-mips.c] - Blame information for rev 1776

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* BFD back-end for MIPS Extended-Coff files.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3
   2000, 2001
4
   Free Software Foundation, Inc.
5
   Original version by Per Bothner.
6
   Full support added by Ian Lance Taylor, ian@cygnus.com.
7
 
8
This file is part of BFD, the Binary File Descriptor library.
9
 
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
14
 
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
GNU General Public License for more details.
19
 
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
 
24
#include "bfd.h"
25
#include "sysdep.h"
26
#include "bfdlink.h"
27
#include "libbfd.h"
28
#include "coff/internal.h"
29
#include "coff/sym.h"
30
#include "coff/symconst.h"
31
#include "coff/ecoff.h"
32
#include "coff/mips.h"
33
#include "libcoff.h"
34
#include "libecoff.h"
35
 
36
/* Prototypes for static functions.  */
37
 
38
static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
39
static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
40
                                              struct internal_reloc *));
41
static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
42
                                               const struct internal_reloc *,
43
                                               PTR));
44
static void mips_adjust_reloc_in PARAMS ((bfd *,
45
                                          const struct internal_reloc *,
46
                                          arelent *));
47
static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
48
                                           struct internal_reloc *));
49
static bfd_reloc_status_type mips_generic_reloc PARAMS ((bfd *abfd,
50
                                                         arelent *reloc,
51
                                                         asymbol *symbol,
52
                                                         PTR data,
53
                                                         asection *section,
54
                                                         bfd *output_bfd,
55
                                                         char **error));
56
static bfd_reloc_status_type mips_refhi_reloc PARAMS ((bfd *abfd,
57
                                                       arelent *reloc,
58
                                                       asymbol *symbol,
59
                                                       PTR data,
60
                                                       asection *section,
61
                                                       bfd *output_bfd,
62
                                                       char **error));
63
static bfd_reloc_status_type mips_reflo_reloc PARAMS ((bfd *abfd,
64
                                                       arelent *reloc,
65
                                                       asymbol *symbol,
66
                                                       PTR data,
67
                                                       asection *section,
68
                                                       bfd *output_bfd,
69
                                                       char **error));
70
static bfd_reloc_status_type mips_gprel_reloc PARAMS ((bfd *abfd,
71
                                                       arelent *reloc,
72
                                                       asymbol *symbol,
73
                                                       PTR data,
74
                                                       asection *section,
75
                                                       bfd *output_bfd,
76
                                                       char **error));
77
static bfd_reloc_status_type mips_relhi_reloc PARAMS ((bfd *abfd,
78
                                                       arelent *reloc,
79
                                                       asymbol *symbol,
80
                                                       PTR data,
81
                                                       asection *section,
82
                                                       bfd *output_bfd,
83
                                                       char **error));
84
static bfd_reloc_status_type mips_rello_reloc PARAMS ((bfd *abfd,
85
                                                       arelent *reloc,
86
                                                       asymbol *symbol,
87
                                                       PTR data,
88
                                                       asection *section,
89
                                                       bfd *output_bfd,
90
                                                       char **error));
91
static bfd_reloc_status_type mips_switch_reloc PARAMS ((bfd *abfd,
92
                                                        arelent *reloc,
93
                                                        asymbol *symbol,
94
                                                        PTR data,
95
                                                        asection *section,
96
                                                        bfd *output_bfd,
97
                                                        char **error));
98
static void mips_relocate_hi PARAMS ((struct internal_reloc *refhi,
99
                                      struct internal_reloc *reflo,
100
                                      bfd *input_bfd,
101
                                      asection *input_section,
102
                                      bfd_byte *contents,
103
                                      size_t adjust,
104
                                      bfd_vma relocation,
105
                                      boolean pcrel));
106
static boolean mips_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
107
                                              bfd *, asection *,
108
                                              bfd_byte *, PTR));
109
static boolean mips_read_relocs PARAMS ((bfd *, asection *));
110
static boolean mips_relax_section PARAMS ((bfd *, asection *,
111
                                           struct bfd_link_info *,
112
                                           boolean *));
113
static boolean mips_relax_pcrel16 PARAMS ((struct bfd_link_info *, bfd *,
114
                                           asection *,
115
                                           struct ecoff_link_hash_entry *,
116
                                           bfd_byte *, bfd_vma));
117
static reloc_howto_type *mips_bfd_reloc_type_lookup
118
  PARAMS ((bfd *, bfd_reloc_code_real_type));
119
 
120
/* ECOFF has COFF sections, but the debugging information is stored in
121
   a completely different format.  ECOFF targets use some of the
122
   swapping routines from coffswap.h, and some of the generic COFF
123
   routines in coffgen.c, but, unlike the real COFF targets, do not
124
   use coffcode.h itself.
125
 
126
   Get the generic COFF swapping routines, except for the reloc,
127
   symbol, and lineno ones.  Give them ECOFF names.  */
128
#define MIPSECOFF
129
#define NO_COFF_RELOCS
130
#define NO_COFF_SYMBOLS
131
#define NO_COFF_LINENOS
132
#define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
133
#define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
134
#define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
135
#define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
136
#define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
137
#define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
138
#include "coffswap.h"
139
 
140
/* Get the ECOFF swapping routines.  */
141
#define ECOFF_32
142
#include "ecoffswap.h"
143
 
144
/* How to process the various relocs types.  */
145
 
146
static reloc_howto_type mips_howto_table[] =
147
{
148
  /* Reloc type 0 is ignored.  The reloc reading code ensures that
149
     this is a reference to the .abs section, which will cause
150
     bfd_perform_relocation to do nothing.  */
151
  HOWTO (MIPS_R_IGNORE, /* type */
152
         0,                      /* rightshift */
153
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
154
         8,                     /* bitsize */
155
         false,                 /* pc_relative */
156
         0,                      /* bitpos */
157
         complain_overflow_dont, /* complain_on_overflow */
158
         0,                      /* special_function */
159
         "IGNORE",              /* name */
160
         false,                 /* partial_inplace */
161
         0,                      /* src_mask */
162
         0,                      /* dst_mask */
163
         false),                /* pcrel_offset */
164
 
165
  /* A 16 bit reference to a symbol, normally from a data section.  */
166
  HOWTO (MIPS_R_REFHALF,        /* type */
167
         0,                      /* rightshift */
168
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
169
         16,                    /* bitsize */
170
         false,                 /* pc_relative */
171
         0,                      /* bitpos */
172
         complain_overflow_bitfield, /* complain_on_overflow */
173
         mips_generic_reloc,    /* special_function */
174
         "REFHALF",             /* name */
175
         true,                  /* partial_inplace */
176
         0xffff,                /* src_mask */
177
         0xffff,                /* dst_mask */
178
         false),                /* pcrel_offset */
179
 
180
  /* A 32 bit reference to a symbol, normally from a data section.  */
181
  HOWTO (MIPS_R_REFWORD,        /* type */
182
         0,                      /* rightshift */
183
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
184
         32,                    /* bitsize */
185
         false,                 /* pc_relative */
186
         0,                      /* bitpos */
187
         complain_overflow_bitfield, /* complain_on_overflow */
188
         mips_generic_reloc,    /* special_function */
189
         "REFWORD",             /* name */
190
         true,                  /* partial_inplace */
191
         0xffffffff,            /* src_mask */
192
         0xffffffff,            /* dst_mask */
193
         false),                /* pcrel_offset */
194
 
195
  /* A 26 bit absolute jump address.  */
196
  HOWTO (MIPS_R_JMPADDR,        /* type */
197
         2,                     /* rightshift */
198
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
199
         26,                    /* bitsize */
200
         false,                 /* pc_relative */
201
         0,                      /* bitpos */
202
         complain_overflow_dont, /* complain_on_overflow */
203
                                /* This needs complex overflow
204
                                   detection, because the upper four
205
                                   bits must match the PC.  */
206
         mips_generic_reloc,    /* special_function */
207
         "JMPADDR",             /* name */
208
         true,                  /* partial_inplace */
209
         0x3ffffff,             /* src_mask */
210
         0x3ffffff,             /* dst_mask */
211
         false),                /* pcrel_offset */
212
 
213
  /* The high 16 bits of a symbol value.  Handled by the function
214
     mips_refhi_reloc.  */
215
  HOWTO (MIPS_R_REFHI,          /* type */
216
         16,                    /* rightshift */
217
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
218
         16,                    /* bitsize */
219
         false,                 /* pc_relative */
220
         0,                      /* bitpos */
221
         complain_overflow_bitfield, /* complain_on_overflow */
222
         mips_refhi_reloc,      /* special_function */
223
         "REFHI",               /* name */
224
         true,                  /* partial_inplace */
225
         0xffff,                /* src_mask */
226
         0xffff,                /* dst_mask */
227
         false),                /* pcrel_offset */
228
 
229
  /* The low 16 bits of a symbol value.  */
230
  HOWTO (MIPS_R_REFLO,          /* type */
231
         0,                      /* rightshift */
232
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
233
         16,                    /* bitsize */
234
         false,                 /* pc_relative */
235
         0,                      /* bitpos */
236
         complain_overflow_dont, /* complain_on_overflow */
237
         mips_reflo_reloc,      /* special_function */
238
         "REFLO",               /* name */
239
         true,                  /* partial_inplace */
240
         0xffff,                /* src_mask */
241
         0xffff,                /* dst_mask */
242
         false),                /* pcrel_offset */
243
 
244
  /* A reference to an offset from the gp register.  Handled by the
245
     function mips_gprel_reloc.  */
246
  HOWTO (MIPS_R_GPREL,          /* type */
247
         0,                      /* rightshift */
248
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
249
         16,                    /* bitsize */
250
         false,                 /* pc_relative */
251
         0,                      /* bitpos */
252
         complain_overflow_signed, /* complain_on_overflow */
253
         mips_gprel_reloc,      /* special_function */
254
         "GPREL",               /* name */
255
         true,                  /* partial_inplace */
256
         0xffff,                /* src_mask */
257
         0xffff,                /* dst_mask */
258
         false),                /* pcrel_offset */
259
 
260
  /* A reference to a literal using an offset from the gp register.
261
     Handled by the function mips_gprel_reloc.  */
262
  HOWTO (MIPS_R_LITERAL,        /* type */
263
         0,                      /* rightshift */
264
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
265
         16,                    /* bitsize */
266
         false,                 /* pc_relative */
267
         0,                      /* bitpos */
268
         complain_overflow_signed, /* complain_on_overflow */
269
         mips_gprel_reloc,      /* special_function */
270
         "LITERAL",             /* name */
271
         true,                  /* partial_inplace */
272
         0xffff,                /* src_mask */
273
         0xffff,                /* dst_mask */
274
         false),                /* pcrel_offset */
275
 
276
  EMPTY_HOWTO (8),
277
  EMPTY_HOWTO (9),
278
  EMPTY_HOWTO (10),
279
  EMPTY_HOWTO (11),
280
 
281
  /* This reloc is a Cygnus extension used when generating position
282
     independent code for embedded systems.  It represents a 16 bit PC
283
     relative reloc rightshifted twice as used in the MIPS branch
284
     instructions.  */
285
  HOWTO (MIPS_R_PCREL16,        /* type */
286
         2,                     /* rightshift */
287
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
288
         16,                    /* bitsize */
289
         true,                  /* pc_relative */
290
         0,                      /* bitpos */
291
         complain_overflow_signed, /* complain_on_overflow */
292
         mips_generic_reloc,    /* special_function */
293
         "PCREL16",             /* name */
294
         true,                  /* partial_inplace */
295
         0xffff,                /* src_mask */
296
         0xffff,                /* dst_mask */
297
         true),                 /* pcrel_offset */
298
 
299
  /* This reloc is a Cygnus extension used when generating position
300
     independent code for embedded systems.  It represents the high 16
301
     bits of a PC relative reloc.  The next reloc must be
302
     MIPS_R_RELLO, and the addend is formed from the addends of the
303
     two instructions, just as in MIPS_R_REFHI and MIPS_R_REFLO.  The
304
     final value is actually PC relative to the location of the
305
     MIPS_R_RELLO reloc, not the MIPS_R_RELHI reloc.  */
306
  HOWTO (MIPS_R_RELHI,          /* type */
307
         16,                    /* rightshift */
308
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
309
         16,                    /* bitsize */
310
         true,                  /* pc_relative */
311
         0,                      /* bitpos */
312
         complain_overflow_bitfield, /* complain_on_overflow */
313
         mips_relhi_reloc,      /* special_function */
314
         "RELHI",               /* name */
315
         true,                  /* partial_inplace */
316
         0xffff,                /* src_mask */
317
         0xffff,                /* dst_mask */
318
         true),                 /* pcrel_offset */
319
 
320
  /* This reloc is a Cygnus extension used when generating position
321
     independent code for embedded systems.  It represents the low 16
322
     bits of a PC relative reloc.  */
323
  HOWTO (MIPS_R_RELLO,          /* type */
324
         0,                      /* rightshift */
325
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
326
         16,                    /* bitsize */
327
         true,                  /* pc_relative */
328
         0,                      /* bitpos */
329
         complain_overflow_dont, /* complain_on_overflow */
330
         mips_rello_reloc,      /* special_function */
331
         "RELLO",               /* name */
332
         true,                  /* partial_inplace */
333
         0xffff,                /* src_mask */
334
         0xffff,                /* dst_mask */
335
         true),                 /* pcrel_offset */
336
 
337
  EMPTY_HOWTO (15),
338
  EMPTY_HOWTO (16),
339
  EMPTY_HOWTO (17),
340
  EMPTY_HOWTO (18),
341
  EMPTY_HOWTO (19),
342
  EMPTY_HOWTO (20),
343
  EMPTY_HOWTO (21),
344
 
345
  /* This reloc is a Cygnus extension used when generating position
346
     independent code for embedded systems.  It represents an entry in
347
     a switch table, which is the difference between two symbols in
348
     the .text section.  The symndx is actually the offset from the
349
     reloc address to the subtrahend.  See include/coff/mips.h for
350
     more details.  */
351
  HOWTO (MIPS_R_SWITCH,         /* type */
352
         0,                      /* rightshift */
353
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
354
         32,                    /* bitsize */
355
         true,                  /* pc_relative */
356
         0,                      /* bitpos */
357
         complain_overflow_dont, /* complain_on_overflow */
358
         mips_switch_reloc,     /* special_function */
359
         "SWITCH",              /* name */
360
         true,                  /* partial_inplace */
361
         0xffffffff,            /* src_mask */
362
         0xffffffff,            /* dst_mask */
363
         true)                  /* pcrel_offset */
364
};
365
 
366
#define MIPS_HOWTO_COUNT \
367
  (sizeof mips_howto_table / sizeof mips_howto_table[0])
368
 
369
/* When the linker is doing relaxing, it may change a external PCREL16
370
   reloc.  This typically represents an instruction like
371
       bal foo
372
   We change it to
373
       .set  noreorder
374
       bal   $L1
375
       lui   $at,%hi(foo - $L1)
376
     $L1:
377
       addiu $at,%lo(foo - $L1)
378
       addu  $at,$at,$31
379
       jalr  $at
380
   PCREL16_EXPANSION_ADJUSTMENT is the number of bytes this changes the
381
   instruction by.  */
382
 
383
#define PCREL16_EXPANSION_ADJUSTMENT (4 * 4)
384
 
385
/* See whether the magic number matches.  */
386
 
387
static boolean
388
mips_ecoff_bad_format_hook (abfd, filehdr)
389
     bfd *abfd;
390
     PTR filehdr;
391
{
392
  struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
393
 
394
  switch (internal_f->f_magic)
395
    {
396
    case MIPS_MAGIC_1:
397
      /* I don't know what endianness this implies.  */
398
      return true;
399
 
400
    case MIPS_MAGIC_BIG:
401
    case MIPS_MAGIC_BIG2:
402
    case MIPS_MAGIC_BIG3:
403
      return bfd_big_endian (abfd);
404
 
405
    case MIPS_MAGIC_LITTLE:
406
    case MIPS_MAGIC_LITTLE2:
407
    case MIPS_MAGIC_LITTLE3:
408
      return bfd_little_endian (abfd);
409
 
410
    default:
411
      return false;
412
    }
413
}
414
 
415
/* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
416
   external form.  They use a bit which indicates whether the symbol
417
   is external.  */
418
 
419
/* Swap a reloc in.  */
420
 
421
static void
422
mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
423
     bfd *abfd;
424
     PTR ext_ptr;
425
     struct internal_reloc *intern;
426
{
427
  const RELOC *ext = (RELOC *) ext_ptr;
428
 
429
  intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);
430
  if (bfd_header_big_endian (abfd))
431
    {
432
      intern->r_symndx = (((int) ext->r_bits[0]
433
                           << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
434
                          | ((int) ext->r_bits[1]
435
                             << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
436
                          | ((int) ext->r_bits[2]
437
                             << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
438
      intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
439
                        >> RELOC_BITS3_TYPE_SH_BIG);
440
      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
441
    }
442
  else
443
    {
444
      intern->r_symndx = (((int) ext->r_bits[0]
445
                           << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
446
                          | ((int) ext->r_bits[1]
447
                             << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
448
                          | ((int) ext->r_bits[2]
449
                             << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
450
      intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
451
                         >> RELOC_BITS3_TYPE_SH_LITTLE)
452
                        | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
453
                           << RELOC_BITS3_TYPEHI_SH_LITTLE));
454
      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
455
    }
456
 
457
  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
458
     MIPS_R_RELLO reloc, r_symndx is actually the offset from the
459
     reloc address to the base of the difference (see
460
     include/coff/mips.h for more details).  We copy symndx into the
461
     r_offset field so as not to confuse ecoff_slurp_reloc_table in
462
     ecoff.c.  In adjust_reloc_in we then copy r_offset into the reloc
463
     addend.  */
464
  if (intern->r_type == MIPS_R_SWITCH
465
      || (! intern->r_extern
466
          && (intern->r_type == MIPS_R_RELLO
467
              || intern->r_type == MIPS_R_RELHI)))
468
    {
469
      BFD_ASSERT (! intern->r_extern);
470
      intern->r_offset = intern->r_symndx;
471
      if (intern->r_offset & 0x800000)
472
        intern->r_offset -= 0x1000000;
473
      intern->r_symndx = RELOC_SECTION_TEXT;
474
    }
475
}
476
 
477
/* Swap a reloc out.  */
478
 
479
static void
480
mips_ecoff_swap_reloc_out (abfd, intern, dst)
481
     bfd *abfd;
482
     const struct internal_reloc *intern;
483
     PTR dst;
484
{
485
  RELOC *ext = (RELOC *) dst;
486
  long r_symndx;
487
 
488
  BFD_ASSERT (intern->r_extern
489
              || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
490
 
491
  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELLO or
492
     MIPS_R_RELHI reloc, we actually want to write the contents of
493
     r_offset out as the symbol index.  This undoes the change made by
494
     mips_ecoff_swap_reloc_in.  */
495
  if (intern->r_type != MIPS_R_SWITCH
496
      && (intern->r_extern
497
          || (intern->r_type != MIPS_R_RELHI
498
              && intern->r_type != MIPS_R_RELLO)))
499
    r_symndx = intern->r_symndx;
500
  else
501
    {
502
      BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);
503
      r_symndx = intern->r_offset & 0xffffff;
504
    }
505
 
506
  bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
507
  if (bfd_header_big_endian (abfd))
508
    {
509
      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
510
      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
511
      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
512
      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
513
                         & RELOC_BITS3_TYPE_BIG)
514
                        | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
515
    }
516
  else
517
    {
518
      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
519
      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
520
      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
521
      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
522
                         & RELOC_BITS3_TYPE_LITTLE)
523
                        | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
524
                            & RELOC_BITS3_TYPEHI_LITTLE))
525
                        | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
526
    }
527
}
528
 
529
/* Finish canonicalizing a reloc.  Part of this is generic to all
530
   ECOFF targets, and that part is in ecoff.c.  The rest is done in
531
   this backend routine.  It must fill in the howto field.  */
532
 
533
static void
534
mips_adjust_reloc_in (abfd, intern, rptr)
535
     bfd *abfd;
536
     const struct internal_reloc *intern;
537
     arelent *rptr;
538
{
539
  if (intern->r_type > MIPS_R_SWITCH)
540
    abort ();
541
 
542
  if (! intern->r_extern
543
      && (intern->r_type == MIPS_R_GPREL
544
          || intern->r_type == MIPS_R_LITERAL))
545
    rptr->addend += ecoff_data (abfd)->gp;
546
 
547
  /* If the type is MIPS_R_IGNORE, make sure this is a reference to
548
     the absolute section so that the reloc is ignored.  */
549
  if (intern->r_type == MIPS_R_IGNORE)
550
    rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
551
 
552
  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
553
     MIPS_R_RELLO reloc, we want the addend field of the BFD relocto
554
     hold the value which was originally in the symndx field of the
555
     internal MIPS ECOFF reloc.  This value was copied into
556
     intern->r_offset by mips_swap_reloc_in, and here we copy it into
557
     the addend field.  */
558
  if (intern->r_type == MIPS_R_SWITCH
559
      || (! intern->r_extern
560
          && (intern->r_type == MIPS_R_RELHI
561
              || intern->r_type == MIPS_R_RELLO)))
562
    rptr->addend = intern->r_offset;
563
 
564
  rptr->howto = &mips_howto_table[intern->r_type];
565
}
566
 
567
/* Make any adjustments needed to a reloc before writing it out.  None
568
   are needed for MIPS.  */
569
 
570
static void
571
mips_adjust_reloc_out (abfd, rel, intern)
572
     bfd *abfd ATTRIBUTE_UNUSED;
573
     const arelent *rel;
574
     struct internal_reloc *intern;
575
{
576
  /* For a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
577
     MIPS_R_RELLO reloc, we must copy rel->addend into
578
     intern->r_offset.  This will then be written out as the symbol
579
     index by mips_ecoff_swap_reloc_out.  This operation parallels the
580
     action of mips_adjust_reloc_in.  */
581
  if (intern->r_type == MIPS_R_SWITCH
582
      || (! intern->r_extern
583
          && (intern->r_type == MIPS_R_RELHI
584
              || intern->r_type == MIPS_R_RELLO)))
585
    intern->r_offset = rel->addend;
586
}
587
 
588
/* ECOFF relocs are either against external symbols, or against
589
   sections.  If we are producing relocateable output, and the reloc
590
   is against an external symbol, and nothing has given us any
591
   additional addend, the resulting reloc will also be against the
592
   same symbol.  In such a case, we don't want to change anything
593
   about the way the reloc is handled, since it will all be done at
594
   final link time.  Rather than put special case code into
595
   bfd_perform_relocation, all the reloc types use this howto
596
   function.  It just short circuits the reloc if producing
597
   relocateable output against an external symbol.  */
598
 
599
static bfd_reloc_status_type
600
mips_generic_reloc (abfd,
601
                    reloc_entry,
602
                    symbol,
603
                    data,
604
                    input_section,
605
                    output_bfd,
606
                    error_message)
607
     bfd *abfd ATTRIBUTE_UNUSED;
608
     arelent *reloc_entry;
609
     asymbol *symbol;
610
     PTR data ATTRIBUTE_UNUSED;
611
     asection *input_section;
612
     bfd *output_bfd;
613
     char **error_message ATTRIBUTE_UNUSED;
614
{
615
  if (output_bfd != (bfd *) NULL
616
      && (symbol->flags & BSF_SECTION_SYM) == 0
617
      && reloc_entry->addend == 0)
618
    {
619
      reloc_entry->address += input_section->output_offset;
620
      return bfd_reloc_ok;
621
    }
622
 
623
  return bfd_reloc_continue;
624
}
625
 
626
/* Do a REFHI relocation.  This has to be done in combination with a
627
   REFLO reloc, because there is a carry from the REFLO to the REFHI.
628
   Here we just save the information we need; we do the actual
629
   relocation when we see the REFLO.  MIPS ECOFF requires that the
630
   REFLO immediately follow the REFHI.  As a GNU extension, we permit
631
   an arbitrary number of HI relocs to be associated with a single LO
632
   reloc.  This extension permits gcc to output the HI and LO relocs
633
   itself.  */
634
 
635
struct mips_hi
636
{
637
  struct mips_hi *next;
638
  bfd_byte *addr;
639
  bfd_vma addend;
640
};
641
 
642
/* FIXME: This should not be a static variable.  */
643
 
644
static struct mips_hi *mips_refhi_list;
645
 
646
static bfd_reloc_status_type
647
mips_refhi_reloc (abfd,
648
                  reloc_entry,
649
                  symbol,
650
                  data,
651
                  input_section,
652
                  output_bfd,
653
                  error_message)
654
     bfd *abfd ATTRIBUTE_UNUSED;
655
     arelent *reloc_entry;
656
     asymbol *symbol;
657
     PTR data;
658
     asection *input_section;
659
     bfd *output_bfd;
660
     char **error_message ATTRIBUTE_UNUSED;
661
{
662
  bfd_reloc_status_type ret;
663
  bfd_vma relocation;
664
  struct mips_hi *n;
665
 
666
  /* If we're relocating, and this an external symbol, we don't want
667
     to change anything.  */
668
  if (output_bfd != (bfd *) NULL
669
      && (symbol->flags & BSF_SECTION_SYM) == 0
670
      && reloc_entry->addend == 0)
671
    {
672
      reloc_entry->address += input_section->output_offset;
673
      return bfd_reloc_ok;
674
    }
675
 
676
  ret = bfd_reloc_ok;
677
  if (bfd_is_und_section (symbol->section)
678
      && output_bfd == (bfd *) NULL)
679
    ret = bfd_reloc_undefined;
680
 
681
  if (bfd_is_com_section (symbol->section))
682
    relocation = 0;
683
  else
684
    relocation = symbol->value;
685
 
686
  relocation += symbol->section->output_section->vma;
687
  relocation += symbol->section->output_offset;
688
  relocation += reloc_entry->addend;
689
 
690
  if (reloc_entry->address > input_section->_cooked_size)
691
    return bfd_reloc_outofrange;
692
 
693
  /* Save the information, and let REFLO do the actual relocation.  */
694
  n = (struct mips_hi *) bfd_malloc (sizeof *n);
695
  if (n == NULL)
696
    return bfd_reloc_outofrange;
697
  n->addr = (bfd_byte *) data + reloc_entry->address;
698
  n->addend = relocation;
699
  n->next = mips_refhi_list;
700
  mips_refhi_list = n;
701
 
702
  if (output_bfd != (bfd *) NULL)
703
    reloc_entry->address += input_section->output_offset;
704
 
705
  return ret;
706
}
707
 
708
/* Do a REFLO relocation.  This is a straightforward 16 bit inplace
709
   relocation; this function exists in order to do the REFHI
710
   relocation described above.  */
711
 
712
static bfd_reloc_status_type
713
mips_reflo_reloc (abfd,
714
                  reloc_entry,
715
                  symbol,
716
                  data,
717
                  input_section,
718
                  output_bfd,
719
                  error_message)
720
     bfd *abfd;
721
     arelent *reloc_entry;
722
     asymbol *symbol;
723
     PTR data;
724
     asection *input_section;
725
     bfd *output_bfd;
726
     char **error_message;
727
{
728
  if (mips_refhi_list != NULL)
729
    {
730
      struct mips_hi *l;
731
 
732
      l = mips_refhi_list;
733
      while (l != NULL)
734
        {
735
          unsigned long insn;
736
          unsigned long val;
737
          unsigned long vallo;
738
          struct mips_hi *next;
739
 
740
          /* Do the REFHI relocation.  Note that we actually don't
741
             need to know anything about the REFLO itself, except
742
             where to find the low 16 bits of the addend needed by the
743
             REFHI.  */
744
          insn = bfd_get_32 (abfd, l->addr);
745
          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
746
                   & 0xffff);
747
          val = ((insn & 0xffff) << 16) + vallo;
748
          val += l->addend;
749
 
750
          /* The low order 16 bits are always treated as a signed
751
             value.  Therefore, a negative value in the low order bits
752
             requires an adjustment in the high order bits.  We need
753
             to make this adjustment in two ways: once for the bits we
754
             took from the data, and once for the bits we are putting
755
             back in to the data.  */
756
          if ((vallo & 0x8000) != 0)
757
            val -= 0x10000;
758
          if ((val & 0x8000) != 0)
759
            val += 0x10000;
760
 
761
          insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
762
          bfd_put_32 (abfd, insn, l->addr);
763
 
764
          next = l->next;
765
          free (l);
766
          l = next;
767
        }
768
 
769
      mips_refhi_list = NULL;
770
    }
771
 
772
  /* Now do the REFLO reloc in the usual way.  */
773
  return mips_generic_reloc (abfd, reloc_entry, symbol, data,
774
                              input_section, output_bfd, error_message);
775
}
776
 
777
/* Do a GPREL relocation.  This is a 16 bit value which must become
778
   the offset from the gp register.  */
779
 
780
static bfd_reloc_status_type
781
mips_gprel_reloc (abfd,
782
                  reloc_entry,
783
                  symbol,
784
                  data,
785
                  input_section,
786
                  output_bfd,
787
                  error_message)
788
     bfd *abfd;
789
     arelent *reloc_entry;
790
     asymbol *symbol;
791
     PTR data;
792
     asection *input_section;
793
     bfd *output_bfd;
794
     char **error_message;
795
{
796
  boolean relocateable;
797
  bfd_vma gp;
798
  bfd_vma relocation;
799
  unsigned long val;
800
  unsigned long insn;
801
 
802
  /* If we're relocating, and this is an external symbol with no
803
     addend, we don't want to change anything.  We will only have an
804
     addend if this is a newly created reloc, not read from an ECOFF
805
     file.  */
806
  if (output_bfd != (bfd *) NULL
807
      && (symbol->flags & BSF_SECTION_SYM) == 0
808
      && reloc_entry->addend == 0)
809
    {
810
      reloc_entry->address += input_section->output_offset;
811
      return bfd_reloc_ok;
812
    }
813
 
814
  if (output_bfd != (bfd *) NULL)
815
    relocateable = true;
816
  else
817
    {
818
      relocateable = false;
819
      output_bfd = symbol->section->output_section->owner;
820
    }
821
 
822
  if (bfd_is_und_section (symbol->section)
823
      && relocateable == false)
824
    return bfd_reloc_undefined;
825
 
826
  /* We have to figure out the gp value, so that we can adjust the
827
     symbol value correctly.  We look up the symbol _gp in the output
828
     BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
829
     target data.  We don't need to adjust the symbol value for an
830
     external symbol if we are producing relocateable output.  */
831
  gp = _bfd_get_gp_value (output_bfd);
832
  if (gp == 0
833
      && (relocateable == false
834
          || (symbol->flags & BSF_SECTION_SYM) != 0))
835
    {
836
      if (relocateable != false)
837
        {
838
          /* Make up a value.  */
839
          gp = symbol->section->output_section->vma + 0x4000;
840
          _bfd_set_gp_value (output_bfd, gp);
841
        }
842
      else
843
        {
844
          unsigned int count;
845
          asymbol **sym;
846
          unsigned int i;
847
 
848
          count = bfd_get_symcount (output_bfd);
849
          sym = bfd_get_outsymbols (output_bfd);
850
 
851
          if (sym == (asymbol **) NULL)
852
            i = count;
853
          else
854
            {
855
              for (i = 0; i < count; i++, sym++)
856
                {
857
                  register CONST char *name;
858
 
859
                  name = bfd_asymbol_name (*sym);
860
                  if (*name == '_' && strcmp (name, "_gp") == 0)
861
                    {
862
                      gp = bfd_asymbol_value (*sym);
863
                      _bfd_set_gp_value (output_bfd, gp);
864
                      break;
865
                    }
866
                }
867
            }
868
 
869
          if (i >= count)
870
            {
871
              /* Only get the error once.  */
872
              gp = 4;
873
              _bfd_set_gp_value (output_bfd, gp);
874
              *error_message =
875
                (char *) _("GP relative relocation when _gp not defined");
876
              return bfd_reloc_dangerous;
877
            }
878
        }
879
    }
880
 
881
  if (bfd_is_com_section (symbol->section))
882
    relocation = 0;
883
  else
884
    relocation = symbol->value;
885
 
886
  relocation += symbol->section->output_section->vma;
887
  relocation += symbol->section->output_offset;
888
 
889
  if (reloc_entry->address > input_section->_cooked_size)
890
    return bfd_reloc_outofrange;
891
 
892
  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
893
 
894
  /* Set val to the offset into the section or symbol.  */
895
  val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
896
  if (val & 0x8000)
897
    val -= 0x10000;
898
 
899
  /* Adjust val for the final section location and GP value.  If we
900
     are producing relocateable output, we don't want to do this for
901
     an external symbol.  */
902
  if (relocateable == false
903
      || (symbol->flags & BSF_SECTION_SYM) != 0)
904
    val += relocation - gp;
905
 
906
  insn = (insn &~ 0xffff) | (val & 0xffff);
907
  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
908
 
909
  if (relocateable != false)
910
    reloc_entry->address += input_section->output_offset;
911
 
912
  /* Make sure it fit in 16 bits.  */
913
  if ((long) val >= 0x8000 || (long) val < -0x8000)
914
    return bfd_reloc_overflow;
915
 
916
  return bfd_reloc_ok;
917
}
918
 
919
/* Do a RELHI relocation.  We do this in conjunction with a RELLO
920
   reloc, just as REFHI and REFLO are done together.  RELHI and RELLO
921
   are Cygnus extensions used when generating position independent
922
   code for embedded systems.  */
923
 
924
/* FIXME: This should not be a static variable.  */
925
 
926
static struct mips_hi *mips_relhi_list;
927
 
928
static bfd_reloc_status_type
929
mips_relhi_reloc (abfd,
930
                  reloc_entry,
931
                  symbol,
932
                  data,
933
                  input_section,
934
                  output_bfd,
935
                  error_message)
936
     bfd *abfd ATTRIBUTE_UNUSED;
937
     arelent *reloc_entry;
938
     asymbol *symbol;
939
     PTR data;
940
     asection *input_section;
941
     bfd *output_bfd;
942
     char **error_message ATTRIBUTE_UNUSED;
943
{
944
  bfd_reloc_status_type ret;
945
  bfd_vma relocation;
946
  struct mips_hi *n;
947
 
948
  /* If this is a reloc against a section symbol, then it is correct
949
     in the object file.  The only time we want to change this case is
950
     when we are relaxing, and that is handled entirely by
951
     mips_relocate_section and never calls this function.  */
952
  if ((symbol->flags & BSF_SECTION_SYM) != 0)
953
    {
954
      if (output_bfd != (bfd *) NULL)
955
        reloc_entry->address += input_section->output_offset;
956
      return bfd_reloc_ok;
957
    }
958
 
959
  /* This is an external symbol.  If we're relocating, we don't want
960
     to change anything.  */
961
  if (output_bfd != (bfd *) NULL)
962
    {
963
      reloc_entry->address += input_section->output_offset;
964
      return bfd_reloc_ok;
965
    }
966
 
967
  ret = bfd_reloc_ok;
968
  if (bfd_is_und_section (symbol->section)
969
      && output_bfd == (bfd *) NULL)
970
    ret = bfd_reloc_undefined;
971
 
972
  if (bfd_is_com_section (symbol->section))
973
    relocation = 0;
974
  else
975
    relocation = symbol->value;
976
 
977
  relocation += symbol->section->output_section->vma;
978
  relocation += symbol->section->output_offset;
979
  relocation += reloc_entry->addend;
980
 
981
  if (reloc_entry->address > input_section->_cooked_size)
982
    return bfd_reloc_outofrange;
983
 
984
  /* Save the information, and let RELLO do the actual relocation.  */
985
  n = (struct mips_hi *) bfd_malloc (sizeof *n);
986
  if (n == NULL)
987
    return bfd_reloc_outofrange;
988
  n->addr = (bfd_byte *) data + reloc_entry->address;
989
  n->addend = relocation;
990
  n->next = mips_relhi_list;
991
  mips_relhi_list = n;
992
 
993
  if (output_bfd != (bfd *) NULL)
994
    reloc_entry->address += input_section->output_offset;
995
 
996
  return ret;
997
}
998
 
999
/* Do a RELLO relocation.  This is a straightforward 16 bit PC
1000
   relative relocation; this function exists in order to do the RELHI
1001
   relocation described above.  */
1002
 
1003
static bfd_reloc_status_type
1004
mips_rello_reloc (abfd,
1005
                  reloc_entry,
1006
                  symbol,
1007
                  data,
1008
                  input_section,
1009
                  output_bfd,
1010
                  error_message)
1011
     bfd *abfd;
1012
     arelent *reloc_entry;
1013
     asymbol *symbol;
1014
     PTR data;
1015
     asection *input_section;
1016
     bfd *output_bfd;
1017
     char **error_message;
1018
{
1019
  if (mips_relhi_list != NULL)
1020
    {
1021
      struct mips_hi *l;
1022
 
1023
      l = mips_relhi_list;
1024
      while (l != NULL)
1025
        {
1026
          unsigned long insn;
1027
          unsigned long val;
1028
          unsigned long vallo;
1029
          struct mips_hi *next;
1030
 
1031
          /* Do the RELHI relocation.  Note that we actually don't
1032
             need to know anything about the RELLO itself, except
1033
             where to find the low 16 bits of the addend needed by the
1034
             RELHI.  */
1035
          insn = bfd_get_32 (abfd, l->addr);
1036
          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
1037
                   & 0xffff);
1038
          val = ((insn & 0xffff) << 16) + vallo;
1039
          val += l->addend;
1040
 
1041
          /* If the symbol is defined, make val PC relative.  If the
1042
             symbol is not defined we don't want to do this, because
1043
             we don't want the value in the object file to incorporate
1044
             the address of the reloc.  */
1045
          if (! bfd_is_und_section (bfd_get_section (symbol))
1046
              && ! bfd_is_com_section (bfd_get_section (symbol)))
1047
            val -= (input_section->output_section->vma
1048
                    + input_section->output_offset
1049
                    + reloc_entry->address);
1050
 
1051
          /* The low order 16 bits are always treated as a signed
1052
             value.  Therefore, a negative value in the low order bits
1053
             requires an adjustment in the high order bits.  We need
1054
             to make this adjustment in two ways: once for the bits we
1055
             took from the data, and once for the bits we are putting
1056
             back in to the data.  */
1057
          if ((vallo & 0x8000) != 0)
1058
            val -= 0x10000;
1059
          if ((val & 0x8000) != 0)
1060
            val += 0x10000;
1061
 
1062
          insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
1063
          bfd_put_32 (abfd, insn, l->addr);
1064
 
1065
          next = l->next;
1066
          free (l);
1067
          l = next;
1068
        }
1069
 
1070
      mips_relhi_list = NULL;
1071
    }
1072
 
1073
  /* If this is a reloc against a section symbol, then it is correct
1074
     in the object file.  The only time we want to change this case is
1075
     when we are relaxing, and that is handled entirely by
1076
     mips_relocate_section and never calls this function.  */
1077
  if ((symbol->flags & BSF_SECTION_SYM) != 0)
1078
    {
1079
      if (output_bfd != (bfd *) NULL)
1080
        reloc_entry->address += input_section->output_offset;
1081
      return bfd_reloc_ok;
1082
    }
1083
 
1084
  /* bfd_perform_relocation does not handle pcrel_offset relocations
1085
     correctly when generating a relocateable file, so handle them
1086
     directly here.  */
1087
  if (output_bfd != (bfd *) NULL)
1088
    {
1089
      reloc_entry->address += input_section->output_offset;
1090
      return bfd_reloc_ok;
1091
    }
1092
 
1093
  /* Now do the RELLO reloc in the usual way.  */
1094
  return mips_generic_reloc (abfd, reloc_entry, symbol, data,
1095
                              input_section, output_bfd, error_message);
1096
}
1097
 
1098
/* This is the special function for the MIPS_R_SWITCH reloc.  This
1099
   special reloc is normally correct in the object file, and only
1100
   requires special handling when relaxing.  We don't want
1101
   bfd_perform_relocation to tamper with it at all.  */
1102
 
1103
static bfd_reloc_status_type
1104
mips_switch_reloc (abfd,
1105
                   reloc_entry,
1106
                   symbol,
1107
                   data,
1108
                   input_section,
1109
                   output_bfd,
1110
                   error_message)
1111
     bfd *abfd ATTRIBUTE_UNUSED;
1112
     arelent *reloc_entry ATTRIBUTE_UNUSED;
1113
     asymbol *symbol ATTRIBUTE_UNUSED;
1114
     PTR data ATTRIBUTE_UNUSED;
1115
     asection *input_section ATTRIBUTE_UNUSED;
1116
     bfd *output_bfd ATTRIBUTE_UNUSED;
1117
     char **error_message ATTRIBUTE_UNUSED;
1118
{
1119
  return bfd_reloc_ok;
1120
}
1121
 
1122
/* Get the howto structure for a generic reloc type.  */
1123
 
1124
static reloc_howto_type *
1125
mips_bfd_reloc_type_lookup (abfd, code)
1126
     bfd *abfd ATTRIBUTE_UNUSED;
1127
     bfd_reloc_code_real_type code;
1128
{
1129
  int mips_type;
1130
 
1131
  switch (code)
1132
    {
1133
    case BFD_RELOC_16:
1134
      mips_type = MIPS_R_REFHALF;
1135
      break;
1136
    case BFD_RELOC_32:
1137
    case BFD_RELOC_CTOR:
1138
      mips_type = MIPS_R_REFWORD;
1139
      break;
1140
    case BFD_RELOC_MIPS_JMP:
1141
      mips_type = MIPS_R_JMPADDR;
1142
      break;
1143
    case BFD_RELOC_HI16_S:
1144
      mips_type = MIPS_R_REFHI;
1145
      break;
1146
    case BFD_RELOC_LO16:
1147
      mips_type = MIPS_R_REFLO;
1148
      break;
1149
    case BFD_RELOC_MIPS_GPREL:
1150
      mips_type = MIPS_R_GPREL;
1151
      break;
1152
    case BFD_RELOC_MIPS_LITERAL:
1153
      mips_type = MIPS_R_LITERAL;
1154
      break;
1155
    case BFD_RELOC_16_PCREL_S2:
1156
      mips_type = MIPS_R_PCREL16;
1157
      break;
1158
    case BFD_RELOC_PCREL_HI16_S:
1159
      mips_type = MIPS_R_RELHI;
1160
      break;
1161
    case BFD_RELOC_PCREL_LO16:
1162
      mips_type = MIPS_R_RELLO;
1163
      break;
1164
    case BFD_RELOC_GPREL32:
1165
      mips_type = MIPS_R_SWITCH;
1166
      break;
1167
    default:
1168
      return (reloc_howto_type *) NULL;
1169
    }
1170
 
1171
  return &mips_howto_table[mips_type];
1172
}
1173
 
1174
/* A helper routine for mips_relocate_section which handles the REFHI
1175
   and RELHI relocations.  The REFHI relocation must be followed by a
1176
   REFLO relocation (and RELHI by a RELLO), and the addend used is
1177
   formed from the addends of both instructions.  */
1178
 
1179
static void
1180
mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents, adjust,
1181
                  relocation, pcrel)
1182
     struct internal_reloc *refhi;
1183
     struct internal_reloc *reflo;
1184
     bfd *input_bfd;
1185
     asection *input_section;
1186
     bfd_byte *contents;
1187
     size_t adjust;
1188
     bfd_vma relocation;
1189
     boolean pcrel;
1190
{
1191
  unsigned long insn;
1192
  unsigned long val;
1193
  unsigned long vallo;
1194
 
1195
  if (refhi == NULL)
1196
    return;
1197
 
1198
  insn = bfd_get_32 (input_bfd,
1199
                     contents + adjust + refhi->r_vaddr - input_section->vma);
1200
  if (reflo == NULL)
1201
    vallo = 0;
1202
  else
1203
    vallo = (bfd_get_32 (input_bfd,
1204
                         contents + adjust + reflo->r_vaddr - input_section->vma)
1205
             & 0xffff);
1206
 
1207
  val = ((insn & 0xffff) << 16) + vallo;
1208
  val += relocation;
1209
 
1210
  /* The low order 16 bits are always treated as a signed value.
1211
     Therefore, a negative value in the low order bits requires an
1212
     adjustment in the high order bits.  We need to make this
1213
     adjustment in two ways: once for the bits we took from the data,
1214
     and once for the bits we are putting back in to the data.  */
1215
  if ((vallo & 0x8000) != 0)
1216
    val -= 0x10000;
1217
 
1218
  if (pcrel)
1219
    val -= (input_section->output_section->vma
1220
            + input_section->output_offset
1221
            + (reflo->r_vaddr - input_section->vma + adjust));
1222
 
1223
  if ((val & 0x8000) != 0)
1224
    val += 0x10000;
1225
 
1226
  insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
1227
  bfd_put_32 (input_bfd, (bfd_vma) insn,
1228
              contents + adjust + refhi->r_vaddr - input_section->vma);
1229
}
1230
 
1231
/* Relocate a section while linking a MIPS ECOFF file.  */
1232
 
1233
static boolean
1234
mips_relocate_section (output_bfd, info, input_bfd, input_section,
1235
                       contents, external_relocs)
1236
     bfd *output_bfd;
1237
     struct bfd_link_info *info;
1238
     bfd *input_bfd;
1239
     asection *input_section;
1240
     bfd_byte *contents;
1241
     PTR external_relocs;
1242
{
1243
  asection **symndx_to_section;
1244
  struct ecoff_link_hash_entry **sym_hashes;
1245
  bfd_vma gp;
1246
  boolean gp_undefined;
1247
  size_t adjust;
1248
  long *offsets;
1249
  struct external_reloc *ext_rel;
1250
  struct external_reloc *ext_rel_end;
1251
  unsigned int i;
1252
  boolean got_lo;
1253
  struct internal_reloc lo_int_rel;
1254
 
1255
  BFD_ASSERT (input_bfd->xvec->byteorder
1256
              == output_bfd->xvec->byteorder);
1257
 
1258
  /* We keep a table mapping the symndx found in an internal reloc to
1259
     the appropriate section.  This is faster than looking up the
1260
     section by name each time.  */
1261
  symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
1262
  if (symndx_to_section == (asection **) NULL)
1263
    {
1264
      symndx_to_section = ((asection **)
1265
                           bfd_alloc (input_bfd,
1266
                                      (NUM_RELOC_SECTIONS
1267
                                       * sizeof (asection *))));
1268
      if (!symndx_to_section)
1269
        return false;
1270
 
1271
      symndx_to_section[RELOC_SECTION_NONE] = NULL;
1272
      symndx_to_section[RELOC_SECTION_TEXT] =
1273
        bfd_get_section_by_name (input_bfd, ".text");
1274
      symndx_to_section[RELOC_SECTION_RDATA] =
1275
        bfd_get_section_by_name (input_bfd, ".rdata");
1276
      symndx_to_section[RELOC_SECTION_DATA] =
1277
        bfd_get_section_by_name (input_bfd, ".data");
1278
      symndx_to_section[RELOC_SECTION_SDATA] =
1279
        bfd_get_section_by_name (input_bfd, ".sdata");
1280
      symndx_to_section[RELOC_SECTION_SBSS] =
1281
        bfd_get_section_by_name (input_bfd, ".sbss");
1282
      symndx_to_section[RELOC_SECTION_BSS] =
1283
        bfd_get_section_by_name (input_bfd, ".bss");
1284
      symndx_to_section[RELOC_SECTION_INIT] =
1285
        bfd_get_section_by_name (input_bfd, ".init");
1286
      symndx_to_section[RELOC_SECTION_LIT8] =
1287
        bfd_get_section_by_name (input_bfd, ".lit8");
1288
      symndx_to_section[RELOC_SECTION_LIT4] =
1289
        bfd_get_section_by_name (input_bfd, ".lit4");
1290
      symndx_to_section[RELOC_SECTION_XDATA] = NULL;
1291
      symndx_to_section[RELOC_SECTION_PDATA] = NULL;
1292
      symndx_to_section[RELOC_SECTION_FINI] =
1293
        bfd_get_section_by_name (input_bfd, ".fini");
1294
      symndx_to_section[RELOC_SECTION_LITA] = NULL;
1295
      symndx_to_section[RELOC_SECTION_ABS] = NULL;
1296
 
1297
      ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
1298
    }
1299
 
1300
  sym_hashes = ecoff_data (input_bfd)->sym_hashes;
1301
 
1302
  gp = _bfd_get_gp_value (output_bfd);
1303
  if (gp == 0)
1304
    gp_undefined = true;
1305
  else
1306
    gp_undefined = false;
1307
 
1308
  got_lo = false;
1309
 
1310
  adjust = 0;
1311
 
1312
  if (ecoff_section_data (input_bfd, input_section) == NULL)
1313
    offsets = NULL;
1314
  else
1315
    offsets = ecoff_section_data (input_bfd, input_section)->offsets;
1316
 
1317
  ext_rel = (struct external_reloc *) external_relocs;
1318
  ext_rel_end = ext_rel + input_section->reloc_count;
1319
  for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
1320
    {
1321
      struct internal_reloc int_rel;
1322
      boolean use_lo = false;
1323
      bfd_vma addend;
1324
      reloc_howto_type *howto;
1325
      struct ecoff_link_hash_entry *h = NULL;
1326
      asection *s = NULL;
1327
      bfd_vma relocation;
1328
      bfd_reloc_status_type r;
1329
 
1330
      if (! got_lo)
1331
        mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
1332
      else
1333
        {
1334
          int_rel = lo_int_rel;
1335
          got_lo = false;
1336
        }
1337
 
1338
      BFD_ASSERT (int_rel.r_type
1339
                  < sizeof mips_howto_table / sizeof mips_howto_table[0]);
1340
 
1341
      /* The REFHI and RELHI relocs requires special handling.  they
1342
         must be followed by a REFLO or RELLO reloc, respectively, and
1343
         the addend is formed from both relocs.  */
1344
      if (int_rel.r_type == MIPS_R_REFHI
1345
          || int_rel.r_type == MIPS_R_RELHI)
1346
        {
1347
          struct external_reloc *lo_ext_rel;
1348
 
1349
          /* As a GNU extension, permit an arbitrary number of REFHI
1350
             or RELHI relocs before the REFLO or RELLO reloc.  This
1351
             permits gcc to emit the HI and LO relocs itself.  */
1352
          for (lo_ext_rel = ext_rel + 1;
1353
               lo_ext_rel < ext_rel_end;
1354
               lo_ext_rel++)
1355
            {
1356
              mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
1357
                                        &lo_int_rel);
1358
              if (lo_int_rel.r_type != int_rel.r_type)
1359
                break;
1360
            }
1361
 
1362
          if (lo_ext_rel < ext_rel_end
1363
              && (lo_int_rel.r_type
1364
                  == (int_rel.r_type == MIPS_R_REFHI
1365
                      ? MIPS_R_REFLO
1366
                      : MIPS_R_RELLO))
1367
              && int_rel.r_extern == lo_int_rel.r_extern
1368
              && int_rel.r_symndx == lo_int_rel.r_symndx)
1369
            {
1370
              use_lo = true;
1371
              if (lo_ext_rel == ext_rel + 1)
1372
                got_lo = true;
1373
            }
1374
        }
1375
 
1376
      howto = &mips_howto_table[int_rel.r_type];
1377
 
1378
      /* The SWITCH reloc must be handled specially.  This reloc is
1379
         marks the location of a difference between two portions of an
1380
         object file.  The symbol index does not reference a symbol,
1381
         but is actually the offset from the reloc to the subtrahend
1382
         of the difference.  This reloc is correct in the object file,
1383
         and needs no further adjustment, unless we are relaxing.  If
1384
         we are relaxing, we may have to add in an offset.  Since no
1385
         symbols are involved in this reloc, we handle it completely
1386
         here.  */
1387
      if (int_rel.r_type == MIPS_R_SWITCH)
1388
        {
1389
          if (offsets != NULL
1390
              && offsets[i] != 0)
1391
            {
1392
              r = _bfd_relocate_contents (howto, input_bfd,
1393
                                          (bfd_vma) offsets[i],
1394
                                          (contents
1395
                                           + adjust
1396
                                           + int_rel.r_vaddr
1397
                                           - input_section->vma));
1398
              BFD_ASSERT (r == bfd_reloc_ok);
1399
            }
1400
 
1401
          continue;
1402
        }
1403
 
1404
      if (int_rel.r_extern)
1405
        {
1406
          h = sym_hashes[int_rel.r_symndx];
1407
          /* If h is NULL, that means that there is a reloc against an
1408
             external symbol which we thought was just a debugging
1409
             symbol.  This should not happen.  */
1410
          if (h == (struct ecoff_link_hash_entry *) NULL)
1411
            abort ();
1412
        }
1413
      else
1414
        {
1415
          if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
1416
            s = NULL;
1417
          else
1418
            s = symndx_to_section[int_rel.r_symndx];
1419
 
1420
          if (s == (asection *) NULL)
1421
            abort ();
1422
        }
1423
 
1424
      /* The GPREL reloc uses an addend: the difference in the GP
1425
         values.  */
1426
      if (int_rel.r_type != MIPS_R_GPREL
1427
          && int_rel.r_type != MIPS_R_LITERAL)
1428
        addend = 0;
1429
      else
1430
        {
1431
          if (gp_undefined)
1432
            {
1433
              if (! ((*info->callbacks->reloc_dangerous)
1434
                     (info, _("GP relative relocation when GP not defined"),
1435
                      input_bfd, input_section,
1436
                      int_rel.r_vaddr - input_section->vma)))
1437
                return false;
1438
              /* Only give the error once per link.  */
1439
              gp = 4;
1440
              _bfd_set_gp_value (output_bfd, gp);
1441
              gp_undefined = false;
1442
            }
1443
          if (! int_rel.r_extern)
1444
            {
1445
              /* This is a relocation against a section.  The current
1446
                 addend in the instruction is the difference between
1447
                 INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
1448
                 must change this to be the difference between the
1449
                 final definition (which will end up in RELOCATION)
1450
                 and the GP value of OUTPUT_BFD (which is in GP).  */
1451
              addend = ecoff_data (input_bfd)->gp - gp;
1452
            }
1453
          else if (! info->relocateable
1454
                   || h->root.type == bfd_link_hash_defined
1455
                   || h->root.type == bfd_link_hash_defweak)
1456
            {
1457
              /* This is a relocation against a defined symbol.  The
1458
                 current addend in the instruction is simply the
1459
                 desired offset into the symbol (normally zero).  We
1460
                 are going to change this into a relocation against a
1461
                 defined symbol, so we want the instruction to hold
1462
                 the difference between the final definition of the
1463
                 symbol (which will end up in RELOCATION) and the GP
1464
                 value of OUTPUT_BFD (which is in GP).  */
1465
              addend = - gp;
1466
            }
1467
          else
1468
            {
1469
              /* This is a relocation against an undefined or common
1470
                 symbol.  The current addend in the instruction is
1471
                 simply the desired offset into the symbol (normally
1472
                 zero).  We are generating relocateable output, and we
1473
                 aren't going to define this symbol, so we just leave
1474
                 the instruction alone.  */
1475
              addend = 0;
1476
            }
1477
        }
1478
 
1479
      /* If we are relaxing, mips_relax_section may have set
1480
         offsets[i] to some value.  A value of 1 means we must expand
1481
         a PC relative branch into a multi-instruction of sequence,
1482
         and any other value is an addend.  */
1483
      if (offsets != NULL
1484
          && offsets[i] != 0)
1485
        {
1486
          BFD_ASSERT (! info->relocateable);
1487
          BFD_ASSERT (int_rel.r_type == MIPS_R_PCREL16
1488
                      || int_rel.r_type == MIPS_R_RELHI
1489
                      || int_rel.r_type == MIPS_R_RELLO);
1490
          if (offsets[i] != 1)
1491
            addend += offsets[i];
1492
          else
1493
            {
1494
              bfd_byte *here;
1495
 
1496
              BFD_ASSERT (int_rel.r_extern
1497
                          && int_rel.r_type == MIPS_R_PCREL16);
1498
 
1499
              /* Move the rest of the instructions up.  */
1500
              here = (contents
1501
                      + adjust
1502
                      + int_rel.r_vaddr
1503
                      - input_section->vma);
1504
              memmove (here + PCREL16_EXPANSION_ADJUSTMENT, here,
1505
                       (size_t) (input_section->_raw_size
1506
                                 - (int_rel.r_vaddr - input_section->vma)));
1507
 
1508
              /* Generate the new instructions.  */
1509
              if (! mips_relax_pcrel16 (info, input_bfd, input_section,
1510
                                        h, here,
1511
                                        (input_section->output_section->vma
1512
                                         + input_section->output_offset
1513
                                         + (int_rel.r_vaddr
1514
                                            - input_section->vma)
1515
                                         + adjust)))
1516
                return false;
1517
 
1518
              /* We must adjust everything else up a notch.  */
1519
              adjust += PCREL16_EXPANSION_ADJUSTMENT;
1520
 
1521
              /* mips_relax_pcrel16 handles all the details of this
1522
                 relocation.  */
1523
              continue;
1524
            }
1525
        }
1526
 
1527
      /* If we are relaxing, and this is a reloc against the .text
1528
         segment, we may need to adjust it if some branches have been
1529
         expanded.  The reloc types which are likely to occur in the
1530
         .text section are handled efficiently by mips_relax_section,
1531
         and thus do not need to be handled here.  */
1532
      if (ecoff_data (input_bfd)->debug_info.adjust != NULL
1533
          && ! int_rel.r_extern
1534
          && int_rel.r_symndx == RELOC_SECTION_TEXT
1535
          && (strcmp (bfd_get_section_name (input_bfd, input_section),
1536
                      ".text") != 0
1537
              || (int_rel.r_type != MIPS_R_PCREL16
1538
                  && int_rel.r_type != MIPS_R_SWITCH
1539
                  && int_rel.r_type != MIPS_R_RELHI
1540
                  && int_rel.r_type != MIPS_R_RELLO)))
1541
        {
1542
          bfd_vma adr;
1543
          struct ecoff_value_adjust *a;
1544
 
1545
          /* We need to get the addend so that we know whether we need
1546
             to adjust the address.  */
1547
          BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
1548
 
1549
          adr = bfd_get_32 (input_bfd,
1550
                            (contents
1551
                             + adjust
1552
                             + int_rel.r_vaddr
1553
                             - input_section->vma));
1554
 
1555
          for (a = ecoff_data (input_bfd)->debug_info.adjust;
1556
               a != (struct ecoff_value_adjust *) NULL;
1557
               a = a->next)
1558
            {
1559
              if (adr >= a->start && adr < a->end)
1560
                addend += a->adjust;
1561
            }
1562
        }
1563
 
1564
      if (info->relocateable)
1565
        {
1566
          /* We are generating relocateable output, and must convert
1567
             the existing reloc.  */
1568
          if (int_rel.r_extern)
1569
            {
1570
              if ((h->root.type == bfd_link_hash_defined
1571
                   || h->root.type == bfd_link_hash_defweak)
1572
                  && ! bfd_is_abs_section (h->root.u.def.section))
1573
                {
1574
                  const char *name;
1575
 
1576
                  /* This symbol is defined in the output.  Convert
1577
                     the reloc from being against the symbol to being
1578
                     against the section.  */
1579
 
1580
                  /* Clear the r_extern bit.  */
1581
                  int_rel.r_extern = 0;
1582
 
1583
                  /* Compute a new r_symndx value.  */
1584
                  s = h->root.u.def.section;
1585
                  name = bfd_get_section_name (output_bfd,
1586
                                               s->output_section);
1587
 
1588
                  int_rel.r_symndx = -1;
1589
                  switch (name[1])
1590
                    {
1591
                    case 'b':
1592
                      if (strcmp (name, ".bss") == 0)
1593
                        int_rel.r_symndx = RELOC_SECTION_BSS;
1594
                      break;
1595
                    case 'd':
1596
                      if (strcmp (name, ".data") == 0)
1597
                        int_rel.r_symndx = RELOC_SECTION_DATA;
1598
                      break;
1599
                    case 'f':
1600
                      if (strcmp (name, ".fini") == 0)
1601
                        int_rel.r_symndx = RELOC_SECTION_FINI;
1602
                      break;
1603
                    case 'i':
1604
                      if (strcmp (name, ".init") == 0)
1605
                        int_rel.r_symndx = RELOC_SECTION_INIT;
1606
                      break;
1607
                    case 'l':
1608
                      if (strcmp (name, ".lit8") == 0)
1609
                        int_rel.r_symndx = RELOC_SECTION_LIT8;
1610
                      else if (strcmp (name, ".lit4") == 0)
1611
                        int_rel.r_symndx = RELOC_SECTION_LIT4;
1612
                      break;
1613
                    case 'r':
1614
                      if (strcmp (name, ".rdata") == 0)
1615
                        int_rel.r_symndx = RELOC_SECTION_RDATA;
1616
                      break;
1617
                    case 's':
1618
                      if (strcmp (name, ".sdata") == 0)
1619
                        int_rel.r_symndx = RELOC_SECTION_SDATA;
1620
                      else if (strcmp (name, ".sbss") == 0)
1621
                        int_rel.r_symndx = RELOC_SECTION_SBSS;
1622
                      break;
1623
                    case 't':
1624
                      if (strcmp (name, ".text") == 0)
1625
                        int_rel.r_symndx = RELOC_SECTION_TEXT;
1626
                      break;
1627
                    }
1628
 
1629
                  if (int_rel.r_symndx == -1)
1630
                    abort ();
1631
 
1632
                  /* Add the section VMA and the symbol value.  */
1633
                  relocation = (h->root.u.def.value
1634
                                + s->output_section->vma
1635
                                + s->output_offset);
1636
 
1637
                  /* For a PC relative relocation, the object file
1638
                     currently holds just the addend.  We must adjust
1639
                     by the address to get the right value.  */
1640
                  if (howto->pc_relative)
1641
                    {
1642
                      relocation -= int_rel.r_vaddr - input_section->vma;
1643
 
1644
                      /* If we are converting a RELHI or RELLO reloc
1645
                         from being against an external symbol to
1646
                         being against a section, we must put a
1647
                         special value into the r_offset field.  This
1648
                         value is the old addend.  The r_offset for
1649
                         both the RELHI and RELLO relocs are the same,
1650
                         and we set both when we see RELHI.  */
1651
                      if (int_rel.r_type == MIPS_R_RELHI)
1652
                        {
1653
                          long addhi, addlo;
1654
 
1655
                          addhi = bfd_get_32 (input_bfd,
1656
                                              (contents
1657
                                               + adjust
1658
                                               + int_rel.r_vaddr
1659
                                               - input_section->vma));
1660
                          addhi &= 0xffff;
1661
                          if (addhi & 0x8000)
1662
                            addhi -= 0x10000;
1663
                          addhi <<= 16;
1664
 
1665
                          if (! use_lo)
1666
                            addlo = 0;
1667
                          else
1668
                            {
1669
                              addlo = bfd_get_32 (input_bfd,
1670
                                                  (contents
1671
                                                   + adjust
1672
                                                   + lo_int_rel.r_vaddr
1673
                                                   - input_section->vma));
1674
                              addlo &= 0xffff;
1675
                              if (addlo & 0x8000)
1676
                                addlo -= 0x10000;
1677
 
1678
                              lo_int_rel.r_offset = addhi + addlo;
1679
                            }
1680
 
1681
                          int_rel.r_offset = addhi + addlo;
1682
                        }
1683
                    }
1684
 
1685
                  h = NULL;
1686
                }
1687
              else
1688
                {
1689
                  /* Change the symndx value to the right one for the
1690
                     output BFD.  */
1691
                  int_rel.r_symndx = h->indx;
1692
                  if (int_rel.r_symndx == -1)
1693
                    {
1694
                      /* This symbol is not being written out.  */
1695
                      if (! ((*info->callbacks->unattached_reloc)
1696
                             (info, h->root.root.string, input_bfd,
1697
                              input_section,
1698
                              int_rel.r_vaddr - input_section->vma)))
1699
                        return false;
1700
                      int_rel.r_symndx = 0;
1701
                    }
1702
                  relocation = 0;
1703
                }
1704
            }
1705
          else
1706
            {
1707
              /* This is a relocation against a section.  Adjust the
1708
                 value by the amount the section moved.  */
1709
              relocation = (s->output_section->vma
1710
                            + s->output_offset
1711
                            - s->vma);
1712
            }
1713
 
1714
          relocation += addend;
1715
          addend = 0;
1716
 
1717
          /* Adjust a PC relative relocation by removing the reference
1718
             to the original address in the section and including the
1719
             reference to the new address.  However, external RELHI
1720
             and RELLO relocs are PC relative, but don't include any
1721
             reference to the address.  The addend is merely an
1722
             addend.  */
1723
          if (howto->pc_relative
1724
              && (! int_rel.r_extern
1725
                  || (int_rel.r_type != MIPS_R_RELHI
1726
                      && int_rel.r_type != MIPS_R_RELLO)))
1727
            relocation -= (input_section->output_section->vma
1728
                           + input_section->output_offset
1729
                           - input_section->vma);
1730
 
1731
          /* Adjust the contents.  */
1732
          if (relocation == 0)
1733
            r = bfd_reloc_ok;
1734
          else
1735
            {
1736
              if (int_rel.r_type != MIPS_R_REFHI
1737
                  && int_rel.r_type != MIPS_R_RELHI)
1738
                r = _bfd_relocate_contents (howto, input_bfd, relocation,
1739
                                            (contents
1740
                                             + adjust
1741
                                             + int_rel.r_vaddr
1742
                                             - input_section->vma));
1743
              else
1744
                {
1745
                  mips_relocate_hi (&int_rel,
1746
                                    use_lo ? &lo_int_rel : NULL,
1747
                                    input_bfd, input_section, contents,
1748
                                    adjust, relocation,
1749
                                    int_rel.r_type == MIPS_R_RELHI);
1750
                  r = bfd_reloc_ok;
1751
                }
1752
            }
1753
 
1754
          /* Adjust the reloc address.  */
1755
          int_rel.r_vaddr += (input_section->output_section->vma
1756
                              + input_section->output_offset
1757
                              - input_section->vma);
1758
 
1759
          /* Save the changed reloc information.  */
1760
          mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
1761
        }
1762
      else
1763
        {
1764
          /* We are producing a final executable.  */
1765
          if (int_rel.r_extern)
1766
            {
1767
              /* This is a reloc against a symbol.  */
1768
              if (h->root.type == bfd_link_hash_defined
1769
                  || h->root.type == bfd_link_hash_defweak)
1770
                {
1771
                  asection *hsec;
1772
 
1773
                  hsec = h->root.u.def.section;
1774
                  relocation = (h->root.u.def.value
1775
                                + hsec->output_section->vma
1776
                                + hsec->output_offset);
1777
                }
1778
              else
1779
                {
1780
                  if (! ((*info->callbacks->undefined_symbol)
1781
                         (info, h->root.root.string, input_bfd,
1782
                          input_section,
1783
                          int_rel.r_vaddr - input_section->vma, true)))
1784
                    return false;
1785
                  relocation = 0;
1786
                }
1787
            }
1788
          else
1789
            {
1790
              /* This is a reloc against a section.  */
1791
              relocation = (s->output_section->vma
1792
                            + s->output_offset
1793
                            - s->vma);
1794
 
1795
              /* A PC relative reloc is already correct in the object
1796
                 file.  Make it look like a pcrel_offset relocation by
1797
                 adding in the start address.  */
1798
              if (howto->pc_relative)
1799
                {
1800
                  if (int_rel.r_type != MIPS_R_RELHI || ! use_lo)
1801
                    relocation += int_rel.r_vaddr + adjust;
1802
                  else
1803
                    relocation += lo_int_rel.r_vaddr + adjust;
1804
                }
1805
            }
1806
 
1807
          if (int_rel.r_type != MIPS_R_REFHI
1808
              && int_rel.r_type != MIPS_R_RELHI)
1809
            r = _bfd_final_link_relocate (howto,
1810
                                          input_bfd,
1811
                                          input_section,
1812
                                          contents,
1813
                                          (int_rel.r_vaddr
1814
                                           - input_section->vma
1815
                                           + adjust),
1816
                                          relocation,
1817
                                          addend);
1818
          else
1819
            {
1820
              mips_relocate_hi (&int_rel,
1821
                                use_lo ? &lo_int_rel : NULL,
1822
                                input_bfd, input_section, contents, adjust,
1823
                                relocation,
1824
                                int_rel.r_type == MIPS_R_RELHI);
1825
              r = bfd_reloc_ok;
1826
            }
1827
        }
1828
 
1829
      /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
1830
         instruction provides a 28 bit address (the two lower bits are
1831
         implicit zeroes) which is combined with the upper four bits
1832
         of the instruction address.  */
1833
      if (r == bfd_reloc_ok
1834
          && int_rel.r_type == MIPS_R_JMPADDR
1835
          && (((relocation
1836
                + addend
1837
                + (int_rel.r_extern ? 0 : s->vma))
1838
               & 0xf0000000)
1839
              != ((input_section->output_section->vma
1840
                   + input_section->output_offset
1841
                   + (int_rel.r_vaddr - input_section->vma)
1842
                   + adjust)
1843
                  & 0xf0000000)))
1844
        r = bfd_reloc_overflow;
1845
 
1846
      if (r != bfd_reloc_ok)
1847
        {
1848
          switch (r)
1849
            {
1850
            default:
1851
            case bfd_reloc_outofrange:
1852
              abort ();
1853
            case bfd_reloc_overflow:
1854
              {
1855
                const char *name;
1856
 
1857
                if (int_rel.r_extern)
1858
                  name = h->root.root.string;
1859
                else
1860
                  name = bfd_section_name (input_bfd, s);
1861
                if (! ((*info->callbacks->reloc_overflow)
1862
                       (info, name, howto->name, (bfd_vma) 0,
1863
                        input_bfd, input_section,
1864
                        int_rel.r_vaddr - input_section->vma)))
1865
                  return false;
1866
              }
1867
              break;
1868
            }
1869
        }
1870
    }
1871
 
1872
  return true;
1873
}
1874
 
1875
/* Read in the relocs for a section.  */
1876
 
1877
static boolean
1878
mips_read_relocs (abfd, sec)
1879
     bfd *abfd;
1880
     asection *sec;
1881
{
1882
  struct ecoff_section_tdata *section_tdata;
1883
 
1884
  section_tdata = ecoff_section_data (abfd, sec);
1885
  if (section_tdata == (struct ecoff_section_tdata *) NULL)
1886
    {
1887
      sec->used_by_bfd =
1888
        (PTR) bfd_alloc (abfd, sizeof (struct ecoff_section_tdata));
1889
      if (sec->used_by_bfd == NULL)
1890
        return false;
1891
 
1892
      section_tdata = ecoff_section_data (abfd, sec);
1893
      section_tdata->external_relocs = NULL;
1894
      section_tdata->contents = NULL;
1895
      section_tdata->offsets = NULL;
1896
    }
1897
 
1898
  if (section_tdata->external_relocs == NULL)
1899
    {
1900
      bfd_size_type external_relocs_size;
1901
 
1902
      external_relocs_size = (ecoff_backend (abfd)->external_reloc_size
1903
                              * sec->reloc_count);
1904
 
1905
      section_tdata->external_relocs =
1906
        (PTR) bfd_alloc (abfd, external_relocs_size);
1907
      if (section_tdata->external_relocs == NULL && external_relocs_size != 0)
1908
        return false;
1909
 
1910
      if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
1911
          || (bfd_read (section_tdata->external_relocs, 1,
1912
                        external_relocs_size, abfd)
1913
              != external_relocs_size))
1914
        return false;
1915
    }
1916
 
1917
  return true;
1918
}
1919
 
1920
/* Relax a section when linking a MIPS ECOFF file.  This is used for
1921
   embedded PIC code, which always uses PC relative branches which
1922
   only have an 18 bit range on MIPS.  If a branch is not in range, we
1923
   generate a long instruction sequence to compensate.  Each time we
1924
   find a branch to expand, we have to check all the others again to
1925
   make sure they are still in range.  This is slow, but it only has
1926
   to be done when -relax is passed to the linker.
1927
 
1928
   This routine figures out which branches need to expand; the actual
1929
   expansion is done in mips_relocate_section when the section
1930
   contents are relocated.  The information is stored in the offsets
1931
   field of the ecoff_section_tdata structure.  An offset of 1 means
1932
   that the branch must be expanded into a multi-instruction PC
1933
   relative branch (such an offset will only occur for a PC relative
1934
   branch to an external symbol).  Any other offset must be a multiple
1935
   of four, and is the amount to change the branch by (such an offset
1936
   will only occur for a PC relative branch within the same section).
1937
 
1938
   We do not modify the section relocs or contents themselves so that
1939
   if memory usage becomes an issue we can discard them and read them
1940
   again.  The only information we must save in memory between this
1941
   routine and the mips_relocate_section routine is the table of
1942
   offsets.  */
1943
 
1944
static boolean
1945
mips_relax_section (abfd, sec, info, again)
1946
     bfd *abfd;
1947
     asection *sec;
1948
     struct bfd_link_info *info;
1949
     boolean *again;
1950
{
1951
  struct ecoff_section_tdata *section_tdata;
1952
  bfd_byte *contents = NULL;
1953
  long *offsets;
1954
  struct external_reloc *ext_rel;
1955
  struct external_reloc *ext_rel_end;
1956
  unsigned int i;
1957
 
1958
  /* Assume we are not going to need another pass.  */
1959
  *again = false;
1960
 
1961
  /* If we are not generating an ECOFF file, this is much too
1962
     confusing to deal with.  */
1963
  if (info->hash->creator->flavour != bfd_get_flavour (abfd))
1964
    return true;
1965
 
1966
  /* If there are no relocs, there is nothing to do.  */
1967
  if (sec->reloc_count == 0)
1968
    return true;
1969
 
1970
  /* We are only interested in PC relative relocs, and why would there
1971
     ever be one from anything but the .text section?  */
1972
  if (strcmp (bfd_get_section_name (abfd, sec), ".text") != 0)
1973
    return true;
1974
 
1975
  /* Read in the relocs, if we haven't already got them.  */
1976
  section_tdata = ecoff_section_data (abfd, sec);
1977
  if (section_tdata == (struct ecoff_section_tdata *) NULL
1978
      || section_tdata->external_relocs == NULL)
1979
    {
1980
      if (! mips_read_relocs (abfd, sec))
1981
        goto error_return;
1982
      section_tdata = ecoff_section_data (abfd, sec);
1983
    }
1984
 
1985
  if (sec->_cooked_size == 0)
1986
    {
1987
      /* We must initialize _cooked_size only the first time we are
1988
         called.  */
1989
      sec->_cooked_size = sec->_raw_size;
1990
    }
1991
 
1992
  contents = section_tdata->contents;
1993
  offsets = section_tdata->offsets;
1994
 
1995
  /* Look for any external PC relative relocs.  Internal PC relative
1996
     relocs are already correct in the object file, so they certainly
1997
     can not overflow.  */
1998
  ext_rel = (struct external_reloc *) section_tdata->external_relocs;
1999
  ext_rel_end = ext_rel + sec->reloc_count;
2000
  for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
2001
    {
2002
      struct internal_reloc int_rel;
2003
      struct ecoff_link_hash_entry *h;
2004
      asection *hsec;
2005
      bfd_signed_vma relocation;
2006
      struct external_reloc *adj_ext_rel;
2007
      unsigned int adj_i;
2008
      unsigned long ext_count;
2009
      struct ecoff_link_hash_entry **adj_h_ptr;
2010
      struct ecoff_link_hash_entry **adj_h_ptr_end;
2011
      struct ecoff_value_adjust *adjust;
2012
 
2013
      /* If we have already expanded this reloc, we certainly don't
2014
         need to do it again.  */
2015
      if (offsets != (long *) NULL && offsets[i] == 1)
2016
        continue;
2017
 
2018
      /* Quickly check that this reloc is external PCREL16.  */
2019
      if (bfd_header_big_endian (abfd))
2020
        {
2021
          if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0
2022
              || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
2023
                   >> RELOC_BITS3_TYPE_SH_BIG)
2024
                  != MIPS_R_PCREL16))
2025
            continue;
2026
        }
2027
      else
2028
        {
2029
          if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) == 0
2030
              || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
2031
                   >> RELOC_BITS3_TYPE_SH_LITTLE)
2032
                  != MIPS_R_PCREL16))
2033
            continue;
2034
        }
2035
 
2036
      mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
2037
 
2038
      h = ecoff_data (abfd)->sym_hashes[int_rel.r_symndx];
2039
      if (h == (struct ecoff_link_hash_entry *) NULL)
2040
        abort ();
2041
 
2042
      if (h->root.type != bfd_link_hash_defined
2043
          && h->root.type != bfd_link_hash_defweak)
2044
        {
2045
          /* Just ignore undefined symbols.  These will presumably
2046
             generate an error later in the link.  */
2047
          continue;
2048
        }
2049
 
2050
      /* Get the value of the symbol.  */
2051
      hsec = h->root.u.def.section;
2052
      relocation = (h->root.u.def.value
2053
                    + hsec->output_section->vma
2054
                    + hsec->output_offset);
2055
 
2056
      /* Subtract out the current address.  */
2057
      relocation -= (sec->output_section->vma
2058
                     + sec->output_offset
2059
                     + (int_rel.r_vaddr - sec->vma));
2060
 
2061
      /* The addend is stored in the object file.  In the normal case
2062
         of ``bal symbol'', the addend will be -4.  It will only be
2063
         different in the case of ``bal symbol+constant''.  To avoid
2064
         always reading in the section contents, we don't check the
2065
         addend in the object file (we could easily check the contents
2066
         if we happen to have already read them in, but I fear that
2067
         this could be confusing).  This means we will screw up if
2068
         there is a branch to a symbol that is in range, but added to
2069
         a constant which puts it out of range; in such a case the
2070
         link will fail with a reloc overflow error.  Since the
2071
         compiler will never generate such code, it should be easy
2072
         enough to work around it by changing the assembly code in the
2073
         source file.  */
2074
      relocation -= 4;
2075
 
2076
      /* Now RELOCATION is the number we want to put in the object
2077
         file.  See whether it fits.  */
2078
      if (relocation >= -0x20000 && relocation < 0x20000)
2079
        continue;
2080
 
2081
      /* Now that we know this reloc needs work, which will rarely
2082
         happen, go ahead and grab the section contents.  */
2083
      if (contents == (bfd_byte *) NULL)
2084
        {
2085
          if (info->keep_memory)
2086
            contents = (bfd_byte *) bfd_alloc (abfd, sec->_raw_size);
2087
          else
2088
            contents = (bfd_byte *) bfd_malloc ((size_t) sec->_raw_size);
2089
          if (contents == (bfd_byte *) NULL)
2090
            goto error_return;
2091
          if (! bfd_get_section_contents (abfd, sec, (PTR) contents,
2092
                                          (file_ptr) 0, sec->_raw_size))
2093
            goto error_return;
2094
          if (info->keep_memory)
2095
            section_tdata->contents = contents;
2096
        }
2097
 
2098
      /* We only support changing the bal instruction.  It would be
2099
         possible to handle other PC relative branches, but some of
2100
         them (the conditional branches) would require a different
2101
         length instruction sequence which would complicate both this
2102
         routine and mips_relax_pcrel16.  It could be written if
2103
         somebody felt it were important.  Ignoring this reloc will
2104
         presumably cause a reloc overflow error later on.  */
2105
      if (bfd_get_32 (abfd, contents + int_rel.r_vaddr - sec->vma)
2106
          != 0x0411ffff) /* bgezal $0,. == bal .  */
2107
        continue;
2108
 
2109
      /* Bother.  We need to expand this reloc, and we will need to
2110
         make another relaxation pass since this change may put other
2111
         relocs out of range.  We need to examine the local branches
2112
         and we need to allocate memory to hold the offsets we must
2113
         add to them.  We also need to adjust the values of all
2114
         symbols in the object file following this location.  */
2115
 
2116
      sec->_cooked_size += PCREL16_EXPANSION_ADJUSTMENT;
2117
      *again = true;
2118
 
2119
      if (offsets == (long *) NULL)
2120
        {
2121
          size_t size;
2122
 
2123
          size = sec->reloc_count * sizeof (long);
2124
          offsets = (long *) bfd_alloc (abfd, size);
2125
          if (offsets == (long *) NULL)
2126
            goto error_return;
2127
          memset (offsets, 0, size);
2128
          section_tdata->offsets = offsets;
2129
        }
2130
 
2131
      offsets[i] = 1;
2132
 
2133
      /* Now look for all PC relative references that cross this reloc
2134
         and adjust their offsets.  */
2135
      adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
2136
      for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
2137
        {
2138
          struct internal_reloc adj_int_rel;
2139
          bfd_vma start, stop;
2140
          int change;
2141
 
2142
          mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
2143
 
2144
          if (adj_int_rel.r_type == MIPS_R_PCREL16)
2145
            {
2146
              unsigned long insn;
2147
 
2148
              /* We only care about local references.  External ones
2149
                 will be relocated correctly anyhow.  */
2150
              if (adj_int_rel.r_extern)
2151
                continue;
2152
 
2153
              /* We are only interested in a PC relative reloc within
2154
                 this section.  FIXME: Cross section PC relative
2155
                 relocs may not be handled correctly; does anybody
2156
                 care?  */
2157
              if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
2158
                continue;
2159
 
2160
              start = adj_int_rel.r_vaddr;
2161
 
2162
              insn = bfd_get_32 (abfd,
2163
                                 contents + adj_int_rel.r_vaddr - sec->vma);
2164
 
2165
              stop = (insn & 0xffff) << 2;
2166
              if ((stop & 0x20000) != 0)
2167
                stop -= 0x40000;
2168
              stop += adj_int_rel.r_vaddr + 4;
2169
            }
2170
          else if (adj_int_rel.r_type == MIPS_R_RELHI)
2171
            {
2172
              struct internal_reloc rello;
2173
              long addhi, addlo;
2174
 
2175
              /* The next reloc must be MIPS_R_RELLO, and we handle
2176
                 them together.  */
2177
              BFD_ASSERT (adj_ext_rel + 1 < ext_rel_end);
2178
 
2179
              mips_ecoff_swap_reloc_in (abfd, (PTR) (adj_ext_rel + 1), &rello);
2180
 
2181
              BFD_ASSERT (rello.r_type == MIPS_R_RELLO);
2182
 
2183
              addhi = bfd_get_32 (abfd,
2184
                                   contents + adj_int_rel.r_vaddr - sec->vma);
2185
              addhi &= 0xffff;
2186
              if (addhi & 0x8000)
2187
                addhi -= 0x10000;
2188
              addhi <<= 16;
2189
 
2190
              addlo = bfd_get_32 (abfd, contents + rello.r_vaddr - sec->vma);
2191
              addlo &= 0xffff;
2192
              if (addlo & 0x8000)
2193
                addlo -= 0x10000;
2194
 
2195
              if (adj_int_rel.r_extern)
2196
                {
2197
                  /* The value we want here is
2198
                       sym - RELLOaddr + addend
2199
                     which we can express as
2200
                       sym - (RELLOaddr - addend)
2201
                     Therefore if we are expanding the area between
2202
                     RELLOaddr and RELLOaddr - addend we must adjust
2203
                     the addend.  This is admittedly ambiguous, since
2204
                     we might mean (sym + addend) - RELLOaddr, but in
2205
                     practice we don't, and there is no way to handle
2206
                     that case correctly since at this point we have
2207
                     no idea whether any reloc is being expanded
2208
                     between sym and sym + addend.  */
2209
                  start = rello.r_vaddr - (addhi + addlo);
2210
                  stop = rello.r_vaddr;
2211
                }
2212
              else
2213
                {
2214
                  /* An internal RELHI/RELLO pair represents the
2215
                     difference between two addresses, $LC0 - foo.
2216
                     The symndx value is actually the difference
2217
                     between the reloc address and $LC0.  This lets us
2218
                     compute $LC0, and, by considering the addend,
2219
                     foo.  If the reloc we are expanding falls between
2220
                     those two relocs, we must adjust the addend.  At
2221
                     this point, the symndx value is actually in the
2222
                     r_offset field, where it was put by
2223
                     mips_ecoff_swap_reloc_in.  */
2224
                  start = rello.r_vaddr - adj_int_rel.r_offset;
2225
                  stop = start + addhi + addlo;
2226
                }
2227
            }
2228
          else if (adj_int_rel.r_type == MIPS_R_SWITCH)
2229
            {
2230
              /* A MIPS_R_SWITCH reloc represents a word of the form
2231
                   .word $L3-$LS12
2232
                 The value in the object file is correct, assuming the
2233
                 original value of $L3.  The symndx value is actually
2234
                 the difference between the reloc address and $LS12.
2235
                 This lets us compute the original value of $LS12 as
2236
                   vaddr - symndx
2237
                 and the original value of $L3 as
2238
                   vaddr - symndx + addend
2239
                 where addend is the value from the object file.  At
2240
                 this point, the symndx value is actually found in the
2241
                 r_offset field, since it was moved by
2242
                 mips_ecoff_swap_reloc_in.  */
2243
              start = adj_int_rel.r_vaddr - adj_int_rel.r_offset;
2244
              stop = start + bfd_get_32 (abfd,
2245
                                         (contents
2246
                                          + adj_int_rel.r_vaddr
2247
                                          - sec->vma));
2248
            }
2249
          else
2250
            continue;
2251
 
2252
          /* If the range expressed by this reloc, which is the
2253
             distance between START and STOP crosses the reloc we are
2254
             expanding, we must adjust the offset.  The sign of the
2255
             adjustment depends upon the direction in which the range
2256
             crosses the reloc being expanded.  */
2257
          if (start <= int_rel.r_vaddr && stop > int_rel.r_vaddr)
2258
            change = PCREL16_EXPANSION_ADJUSTMENT;
2259
          else if (start > int_rel.r_vaddr && stop <= int_rel.r_vaddr)
2260
            change = - PCREL16_EXPANSION_ADJUSTMENT;
2261
          else
2262
            change = 0;
2263
 
2264
          offsets[adj_i] += change;
2265
 
2266
          if (adj_int_rel.r_type == MIPS_R_RELHI)
2267
            {
2268
              adj_ext_rel++;
2269
              adj_i++;
2270
              offsets[adj_i] += change;
2271
            }
2272
        }
2273
 
2274
      /* Find all symbols in this section defined by this object file
2275
         and adjust their values.  Note that we decide whether to
2276
         adjust the value based on the value stored in the ECOFF EXTR
2277
         structure, because the value stored in the hash table may
2278
         have been changed by an earlier expanded reloc and thus may
2279
         no longer correctly indicate whether the symbol is before or
2280
         after the expanded reloc.  */
2281
      ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
2282
      adj_h_ptr = ecoff_data (abfd)->sym_hashes;
2283
      adj_h_ptr_end = adj_h_ptr + ext_count;
2284
      for (; adj_h_ptr < adj_h_ptr_end; adj_h_ptr++)
2285
        {
2286
          struct ecoff_link_hash_entry *adj_h;
2287
 
2288
          adj_h = *adj_h_ptr;
2289
          if (adj_h != (struct ecoff_link_hash_entry *) NULL
2290
              && (adj_h->root.type == bfd_link_hash_defined
2291
                  || adj_h->root.type == bfd_link_hash_defweak)
2292
              && adj_h->root.u.def.section == sec
2293
              && adj_h->esym.asym.value > int_rel.r_vaddr)
2294
            adj_h->root.u.def.value += PCREL16_EXPANSION_ADJUSTMENT;
2295
        }
2296
 
2297
      /* Add an entry to the symbol value adjust list.  This is used
2298
         by bfd_ecoff_debug_accumulate to adjust the values of
2299
         internal symbols and FDR's.  */
2300
      adjust = ((struct ecoff_value_adjust *)
2301
                bfd_alloc (abfd, sizeof (struct ecoff_value_adjust)));
2302
      if (adjust == (struct ecoff_value_adjust *) NULL)
2303
        goto error_return;
2304
 
2305
      adjust->start = int_rel.r_vaddr;
2306
      adjust->end = sec->vma + sec->_raw_size;
2307
      adjust->adjust = PCREL16_EXPANSION_ADJUSTMENT;
2308
 
2309
      adjust->next = ecoff_data (abfd)->debug_info.adjust;
2310
      ecoff_data (abfd)->debug_info.adjust = adjust;
2311
    }
2312
 
2313
  if (contents != (bfd_byte *) NULL && ! info->keep_memory)
2314
    free (contents);
2315
 
2316
  return true;
2317
 
2318
 error_return:
2319
  if (contents != (bfd_byte *) NULL && ! info->keep_memory)
2320
    free (contents);
2321
  return false;
2322
}
2323
 
2324
/* This routine is called from mips_relocate_section when a PC
2325
   relative reloc must be expanded into the five instruction sequence.
2326
   It handles all the details of the expansion, including resolving
2327
   the reloc.  */
2328
 
2329
static boolean
2330
mips_relax_pcrel16 (info, input_bfd, input_section, h, location, address)
2331
     struct bfd_link_info *info ATTRIBUTE_UNUSED;
2332
     bfd *input_bfd;
2333
     asection *input_section ATTRIBUTE_UNUSED;
2334
     struct ecoff_link_hash_entry *h;
2335
     bfd_byte *location;
2336
     bfd_vma address;
2337
{
2338
  bfd_vma relocation;
2339
 
2340
  /* 0x0411ffff is bgezal $0,. == bal .  */
2341
  BFD_ASSERT (bfd_get_32 (input_bfd, location) == 0x0411ffff);
2342
 
2343
  /* We need to compute the distance between the symbol and the
2344
     current address plus eight.  */
2345
  relocation = (h->root.u.def.value
2346
                + h->root.u.def.section->output_section->vma
2347
                + h->root.u.def.section->output_offset);
2348
  relocation -= address + 8;
2349
 
2350
  /* If the lower half is negative, increment the upper 16 half.  */
2351
  if ((relocation & 0x8000) != 0)
2352
    relocation += 0x10000;
2353
 
2354
  bfd_put_32 (input_bfd, 0x04110001, location); /* bal .+8 */
2355
  bfd_put_32 (input_bfd,
2356
              0x3c010000 | ((relocation >> 16) & 0xffff), /* lui $at,XX */
2357
              location + 4);
2358
  bfd_put_32 (input_bfd,
2359
              0x24210000 | (relocation & 0xffff), /* addiu $at,$at,XX */
2360
              location + 8);
2361
  bfd_put_32 (input_bfd, 0x003f0821, location + 12); /* addu $at,$at,$ra */
2362
  bfd_put_32 (input_bfd, 0x0020f809, location + 16); /* jalr $at */
2363
 
2364
  return true;
2365
}
2366
 
2367
/* Given a .sdata section and a .rel.sdata in-memory section, store
2368
   relocation information into the .rel.sdata section which can be
2369
   used at runtime to relocate the section.  This is called by the
2370
   linker when the --embedded-relocs switch is used.  This is called
2371
   after the add_symbols entry point has been called for all the
2372
   objects, and before the final_link entry point is called.  This
2373
   function presumes that the object was compiled using
2374
   -membedded-pic.  */
2375
 
2376
boolean
2377
bfd_mips_ecoff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
2378
     bfd *abfd;
2379
     struct bfd_link_info *info;
2380
     asection *datasec;
2381
     asection *relsec;
2382
     char **errmsg;
2383
{
2384
  struct ecoff_link_hash_entry **sym_hashes;
2385
  struct ecoff_section_tdata *section_tdata;
2386
  struct external_reloc *ext_rel;
2387
  struct external_reloc *ext_rel_end;
2388
  bfd_byte *p;
2389
 
2390
  BFD_ASSERT (! info->relocateable);
2391
 
2392
  *errmsg = NULL;
2393
 
2394
  if (datasec->reloc_count == 0)
2395
    return true;
2396
 
2397
  sym_hashes = ecoff_data (abfd)->sym_hashes;
2398
 
2399
  if (! mips_read_relocs (abfd, datasec))
2400
    return false;
2401
 
2402
  relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 4);
2403
  if (relsec->contents == NULL)
2404
    return false;
2405
 
2406
  p = relsec->contents;
2407
 
2408
  section_tdata = ecoff_section_data (abfd, datasec);
2409
  ext_rel = (struct external_reloc *) section_tdata->external_relocs;
2410
  ext_rel_end = ext_rel + datasec->reloc_count;
2411
  for (; ext_rel < ext_rel_end; ext_rel++, p += 4)
2412
    {
2413
      struct internal_reloc int_rel;
2414
      boolean text_relative;
2415
 
2416
      mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
2417
 
2418
      /* We are going to write a four byte word into the runtime reloc
2419
         section.  The word will be the address in the data section
2420
         which must be relocated.  This must be on a word boundary,
2421
         which means the lower two bits must be zero.  We use the
2422
         least significant bit to indicate how the value in the data
2423
         section must be relocated.  A 0 means that the value is
2424
         relative to the text section, while a 1 indicates that the
2425
         value is relative to the data section.  Given that we are
2426
         assuming the code was compiled using -membedded-pic, there
2427
         should not be any other possibilities.  */
2428
 
2429
      /* We can only relocate REFWORD relocs at run time.  */
2430
      if (int_rel.r_type != MIPS_R_REFWORD)
2431
        {
2432
          *errmsg = _("unsupported reloc type");
2433
          bfd_set_error (bfd_error_bad_value);
2434
          return false;
2435
        }
2436
 
2437
      if (int_rel.r_extern)
2438
        {
2439
          struct ecoff_link_hash_entry *h;
2440
 
2441
          h = sym_hashes[int_rel.r_symndx];
2442
          /* If h is NULL, that means that there is a reloc against an
2443
             external symbol which we thought was just a debugging
2444
             symbol.  This should not happen.  */
2445
          if (h == (struct ecoff_link_hash_entry *) NULL)
2446
            abort ();
2447
          if ((h->root.type == bfd_link_hash_defined
2448
               || h->root.type == bfd_link_hash_defweak)
2449
              && (h->root.u.def.section->flags & SEC_CODE) != 0)
2450
            text_relative = true;
2451
          else
2452
            text_relative = false;
2453
        }
2454
      else
2455
        {
2456
          switch (int_rel.r_symndx)
2457
            {
2458
            case RELOC_SECTION_TEXT:
2459
              text_relative = true;
2460
              break;
2461
            case RELOC_SECTION_SDATA:
2462
            case RELOC_SECTION_SBSS:
2463
            case RELOC_SECTION_LIT8:
2464
              text_relative = false;
2465
              break;
2466
            default:
2467
              /* No other sections should appear in -membedded-pic
2468
                 code.  */
2469
              *errmsg = _("reloc against unsupported section");
2470
              bfd_set_error (bfd_error_bad_value);
2471
              return false;
2472
            }
2473
        }
2474
 
2475
      if ((int_rel.r_offset & 3) != 0)
2476
        {
2477
          *errmsg = _("reloc not properly aligned");
2478
          bfd_set_error (bfd_error_bad_value);
2479
          return false;
2480
        }
2481
 
2482
      bfd_put_32 (abfd,
2483
                  (int_rel.r_vaddr - datasec->vma + datasec->output_offset
2484
                   + (text_relative ? 0 : 1)),
2485
                  p);
2486
    }
2487
 
2488
  return true;
2489
}
2490
 
2491
/* This is the ECOFF backend structure.  The backend field of the
2492
   target vector points to this.  */
2493
 
2494
static const struct ecoff_backend_data mips_ecoff_backend_data =
2495
{
2496
  /* COFF backend structure.  */
2497
  {
2498
    (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
2499
    (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
2500
    (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
2501
    (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
2502
    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
2503
    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
2504
    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
2505
    mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
2506
    mips_ecoff_swap_scnhdr_out,
2507
    FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, true, false, 4, false, 2,
2508
    mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
2509
    mips_ecoff_swap_scnhdr_in, NULL,
2510
    mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
2511
    _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
2512
    _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
2513
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2514
    NULL, NULL
2515
  },
2516
  /* Supported architecture.  */
2517
  bfd_arch_mips,
2518
  /* Initial portion of armap string.  */
2519
  "__________",
2520
  /* The page boundary used to align sections in a demand-paged
2521
     executable file.  E.g., 0x1000.  */
2522
  0x1000,
2523
  /* True if the .rdata section is part of the text segment, as on the
2524
     Alpha.  False if .rdata is part of the data segment, as on the
2525
     MIPS.  */
2526
  false,
2527
  /* Bitsize of constructor entries.  */
2528
  32,
2529
  /* Reloc to use for constructor entries.  */
2530
  &mips_howto_table[MIPS_R_REFWORD],
2531
  {
2532
    /* Symbol table magic number.  */
2533
    magicSym,
2534
    /* Alignment of debugging information.  E.g., 4.  */
2535
    4,
2536
    /* Sizes of external symbolic information.  */
2537
    sizeof (struct hdr_ext),
2538
    sizeof (struct dnr_ext),
2539
    sizeof (struct pdr_ext),
2540
    sizeof (struct sym_ext),
2541
    sizeof (struct opt_ext),
2542
    sizeof (struct fdr_ext),
2543
    sizeof (struct rfd_ext),
2544
    sizeof (struct ext_ext),
2545
    /* Functions to swap in external symbolic data.  */
2546
    ecoff_swap_hdr_in,
2547
    ecoff_swap_dnr_in,
2548
    ecoff_swap_pdr_in,
2549
    ecoff_swap_sym_in,
2550
    ecoff_swap_opt_in,
2551
    ecoff_swap_fdr_in,
2552
    ecoff_swap_rfd_in,
2553
    ecoff_swap_ext_in,
2554
    _bfd_ecoff_swap_tir_in,
2555
    _bfd_ecoff_swap_rndx_in,
2556
    /* Functions to swap out external symbolic data.  */
2557
    ecoff_swap_hdr_out,
2558
    ecoff_swap_dnr_out,
2559
    ecoff_swap_pdr_out,
2560
    ecoff_swap_sym_out,
2561
    ecoff_swap_opt_out,
2562
    ecoff_swap_fdr_out,
2563
    ecoff_swap_rfd_out,
2564
    ecoff_swap_ext_out,
2565
    _bfd_ecoff_swap_tir_out,
2566
    _bfd_ecoff_swap_rndx_out,
2567
    /* Function to read in symbolic data.  */
2568
    _bfd_ecoff_slurp_symbolic_info
2569
  },
2570
  /* External reloc size.  */
2571
  RELSZ,
2572
  /* Reloc swapping functions.  */
2573
  mips_ecoff_swap_reloc_in,
2574
  mips_ecoff_swap_reloc_out,
2575
  /* Backend reloc tweaking.  */
2576
  mips_adjust_reloc_in,
2577
  mips_adjust_reloc_out,
2578
  /* Relocate section contents while linking.  */
2579
  mips_relocate_section,
2580
  /* Do final adjustments to filehdr and aouthdr.  */
2581
  NULL,
2582
  /* Read an element from an archive at a given file position.  */
2583
  _bfd_get_elt_at_filepos
2584
};
2585
 
2586
/* Looking up a reloc type is MIPS specific.  */
2587
#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
2588
 
2589
/* Getting relocated section contents is generic.  */
2590
#define _bfd_ecoff_bfd_get_relocated_section_contents \
2591
  bfd_generic_get_relocated_section_contents
2592
 
2593
/* Handling file windows is generic.  */
2594
#define _bfd_ecoff_get_section_contents_in_window \
2595
  _bfd_generic_get_section_contents_in_window
2596
 
2597
/* Relaxing sections is MIPS specific.  */
2598
#define _bfd_ecoff_bfd_relax_section mips_relax_section
2599
 
2600
/* GC of sections is not done.  */
2601
#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
2602
 
2603
/* Merging of sections is not done.  */
2604
#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
2605
 
2606
extern const bfd_target ecoff_big_vec;
2607
 
2608
const bfd_target ecoff_little_vec =
2609
{
2610
  "ecoff-littlemips",           /* name */
2611
  bfd_target_ecoff_flavour,
2612
  BFD_ENDIAN_LITTLE,            /* data byte order is little */
2613
  BFD_ENDIAN_LITTLE,            /* header byte order is little */
2614
 
2615
  (HAS_RELOC | EXEC_P |         /* object flags */
2616
   HAS_LINENO | HAS_DEBUG |
2617
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2618
 
2619
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
2620
  0,                             /* leading underscore */
2621
  ' ',                          /* ar_pad_char */
2622
  15,                           /* ar_max_namelen */
2623
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2624
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2625
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
2626
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2627
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2628
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
2629
 
2630
  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2631
     _bfd_ecoff_archive_p, _bfd_dummy_target},
2632
  {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
2633
     _bfd_generic_mkarchive, bfd_false},
2634
  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
2635
     _bfd_write_archive_contents, bfd_false},
2636
 
2637
     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
2638
     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
2639
     BFD_JUMP_TABLE_CORE (_bfd_nocore),
2640
     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
2641
     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
2642
     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
2643
     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
2644
     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
2645
     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2646
 
2647
  & ecoff_big_vec,
2648
 
2649
  (PTR) &mips_ecoff_backend_data
2650
};
2651
 
2652
const bfd_target ecoff_big_vec =
2653
{
2654
  "ecoff-bigmips",              /* name */
2655
  bfd_target_ecoff_flavour,
2656
  BFD_ENDIAN_BIG,               /* data byte order is big */
2657
  BFD_ENDIAN_BIG,               /* header byte order is big */
2658
 
2659
  (HAS_RELOC | EXEC_P |         /* object flags */
2660
   HAS_LINENO | HAS_DEBUG |
2661
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2662
 
2663
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
2664
  0,                             /* leading underscore */
2665
  ' ',                          /* ar_pad_char */
2666
  15,                           /* ar_max_namelen */
2667
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2668
     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2669
     bfd_getb16, bfd_getb_signed_16, bfd_putb16,
2670
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2671
     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2672
     bfd_getb16, bfd_getb_signed_16, bfd_putb16,
2673
 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2674
    _bfd_ecoff_archive_p, _bfd_dummy_target},
2675
 {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
2676
    _bfd_generic_mkarchive, bfd_false},
2677
 {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
2678
    _bfd_write_archive_contents, bfd_false},
2679
 
2680
     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
2681
     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
2682
     BFD_JUMP_TABLE_CORE (_bfd_nocore),
2683
     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
2684
     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
2685
     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
2686
     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
2687
     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
2688
     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2689
 
2690
  & ecoff_little_vec,
2691
 
2692
  (PTR) &mips_ecoff_backend_data
2693
};
2694
 
2695
const bfd_target ecoff_biglittle_vec =
2696
{
2697
  "ecoff-biglittlemips",                /* name */
2698
  bfd_target_ecoff_flavour,
2699
  BFD_ENDIAN_LITTLE,            /* data byte order is little */
2700
  BFD_ENDIAN_BIG,               /* header byte order is big */
2701
 
2702
  (HAS_RELOC | EXEC_P |         /* object flags */
2703
   HAS_LINENO | HAS_DEBUG |
2704
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2705
 
2706
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
2707
  0,                             /* leading underscore */
2708
  ' ',                          /* ar_pad_char */
2709
  15,                           /* ar_max_namelen */
2710
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2711
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2712
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
2713
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2714
     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2715
     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
2716
 
2717
  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2718
     _bfd_ecoff_archive_p, _bfd_dummy_target},
2719
  {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
2720
     _bfd_generic_mkarchive, bfd_false},
2721
  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
2722
     _bfd_write_archive_contents, bfd_false},
2723
 
2724
     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
2725
     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
2726
     BFD_JUMP_TABLE_CORE (_bfd_nocore),
2727
     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
2728
     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
2729
     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
2730
     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
2731
     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
2732
     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2733
 
2734
  NULL,
2735
 
2736
  (PTR) &mips_ecoff_backend_data
2737
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.