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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [coff-mips.c] - Blame information for rev 853

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

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

powered by: WebSVN 2.1.0

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