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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [coff-mips.c] - Blame information for rev 160

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

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

powered by: WebSVN 2.1.0

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