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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [pe-mips.c] - Blame information for rev 1767

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

Line No. Rev Author Line
1 578 markom
/* BFD back-end for MIPS PE COFF files.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3
   2000, 2001 Free Software Foundation, Inc.
4
   Modified from coff-i386.c by DJ Delorie, dj@cygnus.com
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
#define COFF_WITH_PE
23
#define COFF_LONG_SECTION_NAMES
24
#define PCRELOFFSET true
25
 
26
#include "bfd.h"
27
#include "sysdep.h"
28
#include "libbfd.h"
29
 
30
#include "coff/mipspe.h"
31
 
32
#include "coff/internal.h"
33
 
34
#include "coff/pe.h"
35
 
36
#include "libcoff.h"
37
 
38
static bfd_reloc_status_type coff_mips_reloc
39
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
40
static reloc_howto_type *coff_mips_rtype_to_howto
41
  PARAMS ((bfd *, asection *, struct internal_reloc *,
42
           struct coff_link_hash_entry *, struct internal_syment *,
43
 
44
           bfd_vma *));
45
#if 0
46
static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
47
                                              struct internal_reloc *));
48
static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
49
                                               const struct internal_reloc *,
50
                                               PTR));
51
static void mips_adjust_reloc_in PARAMS ((bfd *,
52
                                          const struct internal_reloc *,
53
                                          arelent *));
54
static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
55
                                           struct internal_reloc *));
56
#endif
57
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
58
/* The page size is a guess based on ELF.  */
59
 
60
#define COFF_PAGE_SIZE 0x1000
61
 
62
/* For some reason when using mips COFF the value stored in the .text
63
   section for a reference to a common symbol is the value itself plus
64
   any desired offset.  Ian Taylor, Cygnus Support.  */
65
 
66
/* If we are producing relocateable output, we need to do some
67
   adjustments to the object file that are not done by the
68
   bfd_perform_relocation function.  This function is called by every
69
   reloc type to make any required adjustments.  */
70
 
71
static bfd_reloc_status_type
72
coff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
73
                 error_message)
74
     bfd *abfd;
75
     arelent *reloc_entry;
76
     asymbol *symbol;
77
     PTR data;
78
     asection *input_section ATTRIBUTE_UNUSED;
79
     bfd *output_bfd;
80
     char **error_message ATTRIBUTE_UNUSED;
81
{
82
  symvalue diff;
83
 
84
  if (output_bfd == (bfd *) NULL)
85
    return bfd_reloc_continue;
86
 
87
  if (bfd_is_com_section (symbol->section))
88
    {
89
#ifndef COFF_WITH_PE
90
      /* We are relocating a common symbol.  The current value in the
91
         object file is ORIG + OFFSET, where ORIG is the value of the
92
         common symbol as seen by the object file when it was compiled
93
         (this may be zero if the symbol was undefined) and OFFSET is
94
         the offset into the common symbol (normally zero, but may be
95
         non-zero when referring to a field in a common structure).
96
         ORIG is the negative of reloc_entry->addend, which is set by
97
         the CALC_ADDEND macro below.  We want to replace the value in
98
         the object file with NEW + OFFSET, where NEW is the value of
99
         the common symbol which we are going to put in the final
100
         object file.  NEW is symbol->value.  */
101
      diff = symbol->value + reloc_entry->addend;
102
#else
103
      /* In PE mode, we do not offset the common symbol.  */
104
      diff = reloc_entry->addend;
105
#endif
106
    }
107
  else
108
    {
109
      /* For some reason bfd_perform_relocation always effectively
110
         ignores the addend for a COFF target when producing
111
         relocateable output.  This seems to be always wrong for 386
112
         COFF, so we handle the addend here instead.  */
113
      diff = reloc_entry->addend;
114
    }
115
 
116
#ifdef COFF_WITH_PE
117
#if 0
118
  /* dj - handle it like any other reloc? */
119
  /* FIXME: How should this case be handled?  */
120
  if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0)
121
    abort ();
122
#endif
123
#endif
124
 
125
#define DOIT(x) \
126
  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask))
127
 
128
    if (diff != 0)
129
      {
130
        reloc_howto_type *howto = reloc_entry->howto;
131
        unsigned char *addr = (unsigned char *) data + reloc_entry->address;
132
 
133
        switch (howto->size)
134
          {
135
          case 0:
136
            {
137
              char x = bfd_get_8 (abfd, addr);
138
              DOIT (x);
139
              bfd_put_8 (abfd, x, addr);
140
            }
141
            break;
142
 
143
          case 1:
144
            {
145
              short x = bfd_get_16 (abfd, addr);
146
              DOIT (x);
147
              bfd_put_16 (abfd, x, addr);
148
            }
149
            break;
150
 
151
          case 2:
152
            {
153
              long x = bfd_get_32 (abfd, addr);
154
              DOIT (x);
155
              bfd_put_32 (abfd, x, addr);
156
            }
157
            break;
158
 
159
          default:
160
            abort ();
161
          }
162
      }
163
 
164
  /* Now let bfd_perform_relocation finish everything up.  */
165
  return bfd_reloc_continue;
166
}
167
 
168
#ifdef COFF_WITH_PE
169
/* Return true if this relocation should
170
   appear in the output .reloc section.  */
171
 
172
static boolean in_reloc_p(abfd, howto)
173
     bfd * abfd ATTRIBUTE_UNUSED;
174
     reloc_howto_type *howto;
175
{
176
  return ! howto->pc_relative && howto->type != MIPS_R_RVA;
177
}
178
#endif
179
 
180
#ifndef PCRELOFFSET
181
#define PCRELOFFSET false
182
#endif
183
 
184
static reloc_howto_type howto_table[] =
185
{
186
  /* Reloc type 0 is ignored.  The reloc reading code ensures that
187
     this is a reference to the .abs section, which will cause
188
     bfd_perform_relocation to do nothing.  */
189
  HOWTO (MIPS_R_ABSOLUTE,       /* type */
190
         0,                      /* rightshift */
191
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
192
         8,                     /* bitsize */
193
         false,                 /* pc_relative */
194
         0,                      /* bitpos */
195
         complain_overflow_dont, /* complain_on_overflow */
196
         0,                      /* special_function */
197
         "IGNORE",              /* name */
198
         false,                 /* partial_inplace */
199
         0,                      /* src_mask */
200
         0,                      /* dst_mask */
201
         false),                /* pcrel_offset */
202
 
203
  /* A 16 bit reference to a symbol, normally from a data section.  */
204
  HOWTO (MIPS_R_REFHALF,        /* type */
205
         0,                      /* rightshift */
206
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
207
         16,                    /* bitsize */
208
         false,                 /* pc_relative */
209
         0,                      /* bitpos */
210
         complain_overflow_bitfield, /* complain_on_overflow */
211
         coff_mips_reloc,       /* special_function */
212
         "REFHALF",             /* name */
213
         true,                  /* partial_inplace */
214
         0xffff,                /* src_mask */
215
         0xffff,                /* dst_mask */
216
         false),                /* pcrel_offset */
217
 
218
  /* A 32 bit reference to a symbol, normally from a data section.  */
219
  HOWTO (MIPS_R_REFWORD,        /* type */
220
         0,                      /* rightshift */
221
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
222
         32,                    /* bitsize */
223
         false,                 /* pc_relative */
224
         0,                      /* bitpos */
225
         complain_overflow_bitfield, /* complain_on_overflow */
226
         coff_mips_reloc,       /* special_function */
227
         "REFWORD",             /* name */
228
         true,                  /* partial_inplace */
229
         0xffffffff,            /* src_mask */
230
         0xffffffff,            /* dst_mask */
231
         false),                /* pcrel_offset */
232
 
233
  /* A 26 bit absolute jump address.  */
234
  HOWTO (MIPS_R_JMPADDR,        /* type */
235
         2,                     /* rightshift */
236
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
237
         26,                    /* bitsize */
238
         false,                 /* pc_relative */
239
         0,                      /* bitpos */
240
         complain_overflow_dont, /* complain_on_overflow */
241
                                /* This needs complex overflow
242
                                   detection, because the upper four
243
                                   bits must match the PC.  */
244
         coff_mips_reloc,       /* special_function */
245
         "JMPADDR",             /* name */
246
         true,                  /* partial_inplace */
247
         0x3ffffff,             /* src_mask */
248
         0x3ffffff,             /* dst_mask */
249
         false),                /* pcrel_offset */
250
 
251
  /* The high 16 bits of a symbol value.  Handled by the function
252
     mips_refhi_reloc.  */
253
  HOWTO (MIPS_R_REFHI,          /* type */
254
         16,                    /* rightshift */
255
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
256
         16,                    /* bitsize */
257
         false,                 /* pc_relative */
258
         0,                      /* bitpos */
259
         complain_overflow_bitfield, /* complain_on_overflow */
260
         coff_mips_reloc,       /* special_function */
261
         "REFHI",               /* name */
262
         true,                  /* partial_inplace */
263
         0xffff,                /* src_mask */
264
         0xffff,                /* dst_mask */
265
         false),                /* pcrel_offset */
266
 
267
  /* The low 16 bits of a symbol value.  */
268
  HOWTO (MIPS_R_REFLO,          /* type */
269
         0,                      /* rightshift */
270
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
271
         16,                    /* bitsize */
272
         false,                 /* pc_relative */
273
         0,                      /* bitpos */
274
         complain_overflow_dont, /* complain_on_overflow */
275
         coff_mips_reloc,       /* special_function */
276
         "REFLO",               /* name */
277
         true,                  /* partial_inplace */
278
         0xffff,                /* src_mask */
279
         0xffff,                /* dst_mask */
280
         false),                /* pcrel_offset */
281
 
282
  /* A reference to an offset from the gp register.  Handled by the
283
     function mips_gprel_reloc.  */
284
  HOWTO (MIPS_R_GPREL,          /* type */
285
         0,                      /* rightshift */
286
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
287
         16,                    /* bitsize */
288
         false,                 /* pc_relative */
289
         0,                      /* bitpos */
290
         complain_overflow_signed, /* complain_on_overflow */
291
         coff_mips_reloc,       /* special_function */
292
         "GPREL",               /* name */
293
         true,                  /* partial_inplace */
294
         0xffff,                /* src_mask */
295
         0xffff,                /* dst_mask */
296
         false),                /* pcrel_offset */
297
 
298
  /* A reference to a literal using an offset from the gp register.
299
     Handled by the function mips_gprel_reloc.  */
300
  HOWTO (MIPS_R_LITERAL,        /* type */
301
         0,                      /* rightshift */
302
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
303
         16,                    /* bitsize */
304
         false,                 /* pc_relative */
305
         0,                      /* bitpos */
306
         complain_overflow_signed, /* complain_on_overflow */
307
         coff_mips_reloc,       /* special_function */
308
         "LITERAL",             /* name */
309
         true,                  /* partial_inplace */
310
         0xffff,                /* src_mask */
311
         0xffff,                /* dst_mask */
312
         false),                /* pcrel_offset */
313
 
314
  EMPTY_HOWTO (8),
315
  EMPTY_HOWTO (9),
316
  EMPTY_HOWTO (10),
317
  EMPTY_HOWTO (11),
318
  EMPTY_HOWTO (12),
319
  EMPTY_HOWTO (13),
320
  EMPTY_HOWTO (14),
321
  EMPTY_HOWTO (15),
322
  EMPTY_HOWTO (16),
323
  EMPTY_HOWTO (17),
324
  EMPTY_HOWTO (18),
325
  EMPTY_HOWTO (19),
326
  EMPTY_HOWTO (20),
327
  EMPTY_HOWTO (21),
328
  EMPTY_HOWTO (22),
329
  EMPTY_HOWTO (23),
330
  EMPTY_HOWTO (24),
331
  EMPTY_HOWTO (25),
332
  EMPTY_HOWTO (26),
333
  EMPTY_HOWTO (27),
334
  EMPTY_HOWTO (28),
335
  EMPTY_HOWTO (29),
336
  EMPTY_HOWTO (30),
337
  EMPTY_HOWTO (31),
338
  EMPTY_HOWTO (32),
339
  EMPTY_HOWTO (33),
340
  HOWTO (MIPS_R_RVA,            /* type */
341
         0,                      /* rightshift */
342
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
343
         32,                    /* bitsize */
344
         false,                 /* pc_relative */
345
         0,                      /* bitpos */
346
         complain_overflow_bitfield, /* complain_on_overflow */
347
         coff_mips_reloc,       /* special_function */
348
         "rva32",               /* name */
349
         true,                  /* partial_inplace */
350
         0xffffffff,            /* src_mask */
351
         0xffffffff,            /* dst_mask */
352
         false),                /* pcrel_offset */
353
  EMPTY_HOWTO (35),
354
  EMPTY_HOWTO (36),
355
  HOWTO (MIPS_R_PAIR,           /* type */
356
         0,                      /* rightshift */
357
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
358
         32,                    /* bitsize */
359
         false,                 /* pc_relative */
360
         0,                      /* bitpos */
361
         complain_overflow_bitfield, /* complain_on_overflow */
362
         coff_mips_reloc,       /* special_function */
363
         "PAIR",                /* name */
364
         true,                  /* partial_inplace */
365
         0xffffffff,            /* src_mask */
366
         0xffffffff,            /* dst_mask */
367
         false),                /* pcrel_offset */
368
};
369
 
370
/* Turn a howto into a reloc  nunmber */
371
 
372
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
373
#define BADMAG(x) MIPSBADMAG(x)
374
#define MIPS 1                  /* Customize coffcode.h */
375
 
376
#define RTYPE2HOWTO(cache_ptr, dst) \
377
            (cache_ptr)->howto = howto_table + (dst)->r_type;
378
 
379
/* Compute the addend of a reloc.  If the reloc is to a common symbol,
380
   the object file contains the value of the common symbol.  By the
381
   time this is called, the linker may be using a different symbol
382
   from a different object file with a different value.  Therefore, we
383
   hack wildly to locate the original symbol from this file so that we
384
   can make the correct adjustment.  This macro sets coffsym to the
385
   symbol from the original file, and uses it to set the addend value
386
   correctly.  If this is not a common symbol, the usual addend
387
   calculation is done, except that an additional tweak is needed for
388
   PC relative relocs.
389
   FIXME: This macro refers to symbols and asect; these are from the
390
   calling function, not the macro arguments.  */
391
 
392
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
393
  {                                                             \
394
    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
395
    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
396
      coffsym = (obj_symbols (abfd)                             \
397
                 + (cache_ptr->sym_ptr_ptr - symbols));         \
398
    else if (ptr)                                               \
399
      coffsym = coff_symbol_from (abfd, ptr);                   \
400
    if (coffsym != (coff_symbol_type *) NULL                    \
401
        && coffsym->native->u.syment.n_scnum == 0)               \
402
      cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
403
    else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
404
             && ptr->section != (asection *) NULL)              \
405
      cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
406
    else                                                        \
407
      cache_ptr->addend = 0;                                     \
408
    if (ptr && howto_table[reloc.r_type].pc_relative)           \
409
      cache_ptr->addend += asect->vma;                          \
410
  }
411
 
412
/* Convert an rtype to howto for the COFF backend linker.  */
413
 
414
static reloc_howto_type *
415
coff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
416
     bfd *abfd ATTRIBUTE_UNUSED;
417
     asection *sec;
418
     struct internal_reloc *rel;
419
     struct coff_link_hash_entry *h;
420
     struct internal_syment *sym;
421
     bfd_vma *addendp;
422
{
423
 
424
  reloc_howto_type *howto;
425
 
426
  howto = howto_table + rel->r_type;
427
 
428
#ifdef COFF_WITH_PE
429
  *addendp = 0;
430
#endif
431
 
432
  if (howto->pc_relative)
433
    *addendp += sec->vma;
434
 
435
  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
436
    {
437
      /* This is a common symbol.  The section contents include the
438
         size (sym->n_value) as an addend.  The relocate_section
439
         function will be adding in the final value of the symbol.  We
440
         need to subtract out the current size in order to get the
441
         correct result.  */
442
 
443
      BFD_ASSERT (h != NULL);
444
 
445
#ifndef COFF_WITH_PE
446
      /* I think we *do* want to bypass this.  If we don't, I have
447
         seen some data parameters get the wrong relocation address.
448
         If I link two versions with and without this section bypassed
449
         and then do a binary comparison, the addresses which are
450
         different can be looked up in the map.  The case in which
451
         this section has been bypassed has addresses which correspond
452
         to values I can find in the map.  */
453
      *addendp -= sym->n_value;
454
#endif
455
    }
456
 
457
#ifndef COFF_WITH_PE
458
  /* If the output symbol is common (in which case this must be a
459
     relocateable link), we need to add in the final size of the
460
     common symbol.  */
461
  if (h != NULL && h->root.type == bfd_link_hash_common)
462
    *addendp += h->root.u.c.size;
463
#endif
464
 
465
#ifdef COFF_WITH_PE
466
  if (howto->pc_relative)
467
    {
468
      *addendp -= 4;
469
 
470
      /* If the symbol is defined, then the generic code is going to
471
         add back the symbol value in order to cancel out an
472
         adjustment it made to the addend.  However, we set the addend
473
         to 0 at the start of this function.  We need to adjust here,
474
         to avoid the adjustment the generic code will make.  FIXME:
475
         This is getting a bit hackish.  */
476
      if (sym != NULL && sym->n_scnum != 0)
477
        *addendp -= sym->n_value;
478
    }
479
 
480
  if (rel->r_type == MIPS_R_RVA)
481
    {
482
      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
483
    }
484
#endif
485
 
486
  return howto;
487
}
488
 
489
#define coff_rtype_to_howto coff_mips_rtype_to_howto
490
 
491
#define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup
492
 
493
/* Get the howto structure for a generic reloc type.  */
494
 
495
static reloc_howto_type *
496
coff_mips_reloc_type_lookup (abfd, code)
497
     bfd *abfd ATTRIBUTE_UNUSED;
498
     bfd_reloc_code_real_type code;
499
{
500
  int mips_type;
501
 
502
  switch (code)
503
    {
504
    case BFD_RELOC_16:
505
      mips_type = MIPS_R_REFHALF;
506
      break;
507
    case BFD_RELOC_32:
508
    case BFD_RELOC_CTOR:
509
      mips_type = MIPS_R_REFWORD;
510
      break;
511
    case BFD_RELOC_MIPS_JMP:
512
      mips_type = MIPS_R_JMPADDR;
513
      break;
514
    case BFD_RELOC_HI16_S:
515
      mips_type = MIPS_R_REFHI;
516
      break;
517
    case BFD_RELOC_LO16:
518
      mips_type = MIPS_R_REFLO;
519
      break;
520
    case BFD_RELOC_MIPS_GPREL:
521
      mips_type = MIPS_R_GPREL;
522
      break;
523
    case BFD_RELOC_MIPS_LITERAL:
524
      mips_type = MIPS_R_LITERAL;
525
      break;
526
/* FIXME?
527
    case BFD_RELOC_16_PCREL_S2:
528
      mips_type = MIPS_R_PCREL16;
529
      break;
530
    case BFD_RELOC_PCREL_HI16_S:
531
      mips_type = MIPS_R_RELHI;
532
      break;
533
    case BFD_RELOC_PCREL_LO16:
534
      mips_type = MIPS_R_RELLO;
535
      break;
536
    case BFD_RELOC_GPREL32:
537
      mips_type = MIPS_R_SWITCH;
538
      break;
539
*/
540
    case BFD_RELOC_RVA:
541
      mips_type = MIPS_R_RVA;
542
      break;
543
    default:
544
      return (reloc_howto_type *) NULL;
545
    }
546
 
547
  return &howto_table[mips_type];
548
}
549
 
550
static void
551
mips_swap_reloc_in (abfd, src, dst)
552
     bfd *abfd;
553
     PTR src;
554
     PTR dst;
555
{
556
  static struct internal_reloc pair_prev;
557
  RELOC *reloc_src = (RELOC *) src;
558
  struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
559
 
560
  reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr);
561
  reloc_dst->r_symndx =
562
    bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx);
563
  reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type);
564
  reloc_dst->r_size = 0;
565
  reloc_dst->r_extern = 0;
566
  reloc_dst->r_offset = 0;
567
 
568
  switch (reloc_dst->r_type)
569
  {
570
  case MIPS_R_REFHI:
571
    pair_prev = *reloc_dst;
572
    break;
573
  case MIPS_R_PAIR:
574
    reloc_dst->r_offset = reloc_dst->r_symndx;
575
    if (reloc_dst->r_offset & 0x8000)
576
      reloc_dst->r_offset -= 0x10000;
577
    /*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/
578
    reloc_dst->r_symndx = pair_prev.r_symndx;
579
    break;
580
  }
581
}
582
 
583
static unsigned int
584
mips_swap_reloc_out (abfd, src, dst)
585
     bfd       *abfd;
586
     PTR        src;
587
     PTR        dst;
588
{
589
  static int prev_offset = 1;
590
  static bfd_vma prev_addr = 0;
591
  struct internal_reloc *reloc_src = (struct internal_reloc *)src;
592
  struct external_reloc *reloc_dst = (struct external_reloc *)dst;
593
 
594
  switch (reloc_src->r_type)
595
    {
596
    case MIPS_R_REFHI:
597
      prev_addr = reloc_src->r_vaddr;
598
      prev_offset = reloc_src->r_offset;
599
      break;
600
    case MIPS_R_REFLO:
601
      if (reloc_src->r_vaddr == prev_addr)
602
        {
603
          /* FIXME: only slightly hackish.  If we see a REFLO pointing to
604
             the same address as a REFHI, we assume this is the matching
605
             PAIR reloc and output it accordingly.  The symndx is really
606
             the low 16 bits of the addend */
607
          bfd_h_put_32 (abfd, reloc_src->r_vaddr,
608
                        (bfd_byte *) reloc_dst->r_vaddr);
609
          bfd_h_put_32 (abfd, reloc_src->r_symndx,
610
                        (bfd_byte *) reloc_dst->r_symndx);
611
 
612
          bfd_h_put_16(abfd, MIPS_R_PAIR, (bfd_byte *)
613
                       reloc_dst->r_type);
614
          return RELSZ;
615
        }
616
      break;
617
    }
618
 
619
  bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr);
620
  bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx);
621
 
622
  bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *)
623
               reloc_dst->r_type);
624
  return RELSZ;
625
}
626
 
627
#define coff_swap_reloc_in mips_swap_reloc_in
628
#define coff_swap_reloc_out mips_swap_reloc_out
629
#define NO_COFF_RELOCS
630
 
631
static boolean
632
coff_pe_mips_relocate_section (output_bfd, info, input_bfd,
633
                               input_section, contents, relocs, syms,
634
                               sections)
635
     bfd *output_bfd;
636
     struct bfd_link_info *info;
637
     bfd *input_bfd;
638
     asection *input_section;
639
     bfd_byte *contents;
640
     struct internal_reloc *relocs;
641
     struct internal_syment *syms;
642
     asection **sections;
643
{
644
  bfd_vma gp;
645
  boolean gp_undefined;
646
  size_t adjust;
647
  struct internal_reloc *rel;
648
  struct internal_reloc *rel_end;
649
  unsigned int i;
650
  boolean got_lo;
651
 
652
  if (info->relocateable)
653
  {
654
    (*_bfd_error_handler) (_("\
655
%s: `ld -r' not supported with PE MIPS objects\n"),
656
                          bfd_get_filename (input_bfd));
657
    bfd_set_error (bfd_error_bad_value);
658
    return false;
659
  }
660
 
661
  BFD_ASSERT (input_bfd->xvec->byteorder
662
              == output_bfd->xvec->byteorder);
663
 
664
#if 0
665
  printf ("dj: relocate %s(%s) %08x\n",
666
         input_bfd->filename, input_section->name,
667
         input_section->output_section->vma + input_section->output_offset);
668
#endif
669
 
670
  gp = _bfd_get_gp_value (output_bfd);
671
  if (gp == 0)
672
    gp_undefined = true;
673
  else
674
    gp_undefined = false;
675
 
676
  got_lo = false;
677
 
678
  adjust = 0;
679
 
680
  rel = relocs;
681
  rel_end = rel + input_section->reloc_count;
682
  for (i = 0; rel < rel_end; rel++, i++)
683
    {
684
      long symndx;
685
      struct coff_link_hash_entry *h;
686
      struct internal_syment *sym;
687
      bfd_vma addend = 0;
688
      bfd_vma val, tmp, targ, src, low;
689
      reloc_howto_type *howto;
690
      unsigned char *mem = contents + rel->r_vaddr;
691
 
692
      symndx = rel->r_symndx;
693
 
694
      if (symndx == -1)
695
        {
696
          h = NULL;
697
          sym = NULL;
698
        }
699
      else
700
        {
701
          h = obj_coff_sym_hashes (input_bfd)[symndx];
702
          sym = syms + symndx;
703
        }
704
 
705
      /* COFF treats common symbols in one of two ways.  Either the
706
         size of the symbol is included in the section contents, or it
707
         is not.  We assume that the size is not included, and force
708
         the rtype_to_howto function to adjust the addend as needed.  */
709
 
710
      if (sym != NULL && sym->n_scnum != 0)
711
        addend = - sym->n_value;
712
      else
713
        addend = 0;
714
 
715
      howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
716
                                       sym, &addend);
717
      if (howto == NULL)
718
        return false;
719
 
720
      /* If we are doing a relocateable link, then we can just ignore
721
         a PC relative reloc that is pcrel_offset.  It will already
722
         have the correct value.  If this is not a relocateable link,
723
         then we should ignore the symbol value.  */
724
      if (howto->pc_relative && howto->pcrel_offset)
725
        {
726
          if (info->relocateable)
727
            continue;
728
          if (sym != NULL && sym->n_scnum != 0)
729
            addend += sym->n_value;
730
        }
731
 
732
      val = 0;
733
 
734
      if (h == NULL)
735
        {
736
          asection *sec;
737
 
738
          if (symndx == -1)
739
            {
740
              sec = bfd_abs_section_ptr;
741
              val = 0;
742
            }
743
          else
744
            {
745
              sec = sections[symndx];
746
              val = (sec->output_section->vma
747
                     + sec->output_offset
748
                     + sym->n_value);
749
              if (! obj_pe (input_bfd))
750
                val -= sec->vma;
751
            }
752
        }
753
      else
754
        {
755
          if (h->root.type == bfd_link_hash_defined
756
              || h->root.type == bfd_link_hash_defweak)
757
            {
758
              asection *sec;
759
 
760
              sec = h->root.u.def.section;
761
              val = (h->root.u.def.value
762
                     + sec->output_section->vma
763
                     + sec->output_offset);
764
              }
765
 
766
          else if (! info->relocateable)
767
            {
768
              if (! ((*info->callbacks->undefined_symbol)
769
                     (info, h->root.root.string, input_bfd, input_section,
770
                      rel->r_vaddr - input_section->vma, true)))
771
                return false;
772
            }
773
        }
774
 
775
      src = rel->r_vaddr + input_section->output_section->vma
776
        + input_section->output_offset;
777
#if 0
778
      printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n",
779
             rel->r_type, howto_table[rel->r_type].name,
780
             src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset,
781
             h?h->root.root.string:"(none)");
782
#endif
783
 
784
      /* OK, at this point the following variables are set up:
785
           src = VMA of the memory we're fixing up
786
           mem = pointer to memory we're fixing up
787
           val = VMA of what we need to refer to
788
      */
789
 
790
#define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \
791
                                    bfd_get_filename (input_bfd), x); \
792
              bfd_set_error (bfd_error_bad_value);
793
 
794
      switch (rel->r_type)
795
        {
796
        case MIPS_R_ABSOLUTE:
797
          /* ignore these */
798
          break;
799
 
800
        case MIPS_R_REFHALF:
801
          UI("refhalf");
802
          break;
803
 
804
        case MIPS_R_REFWORD:
805
          tmp = bfd_get_32(input_bfd, mem);
806
          /* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */
807
          tmp += val;
808
          bfd_put_32(input_bfd, tmp, mem);
809
          break;
810
 
811
        case MIPS_R_JMPADDR:
812
          tmp = bfd_get_32(input_bfd, mem);
813
          targ = val + (tmp&0x03ffffff)*4;
814
          if ((src & 0xf0000000) != (targ & 0xf0000000))
815
            {
816
              (*_bfd_error_handler) (_("%s: jump too far away\n"),
817
                                    bfd_get_filename (input_bfd));
818
              bfd_set_error (bfd_error_bad_value);
819
              return false;
820
            }
821
          tmp &= 0xfc000000;
822
          tmp |= (targ/4) & 0x3ffffff;
823
          bfd_put_32(input_bfd, tmp, mem);
824
          break;
825
 
826
        case MIPS_R_REFHI:
827
          tmp = bfd_get_32(input_bfd, mem);
828
          switch (rel[1].r_type)
829
            {
830
            case MIPS_R_PAIR:
831
              /* MS PE object */
832
              targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16);
833
              break;
834
            case MIPS_R_REFLO:
835
              /* GNU COFF object */
836
              low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr);
837
              low &= 0xffff;
838
              if (low & 0x8000)
839
                low -= 0x10000;
840
              targ = val + low + ((tmp & 0xffff) << 16);
841
              break;
842
            default:
843
              (*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"),
844
                                    bfd_get_filename (input_bfd));
845
              bfd_set_error (bfd_error_bad_value);
846
              return false;
847
            }
848
          tmp &= 0xffff0000;
849
          tmp |= (targ >> 16) & 0xffff;
850
          bfd_put_32(input_bfd, tmp, mem);
851
          break;
852
 
853
        case MIPS_R_REFLO:
854
          tmp = bfd_get_32(input_bfd, mem);
855
          targ = val + (tmp & 0xffff);
856
          /* printf ("refword: src=%08x targ=%08x\n", src, targ); */
857
          tmp &= 0xffff0000;
858
          tmp |= targ & 0xffff;
859
          bfd_put_32(input_bfd, tmp, mem);
860
          break;
861
 
862
        case MIPS_R_GPREL:
863
        case MIPS_R_LITERAL:
864
          UI("gprel");
865
          break;
866
 
867
        case MIPS_R_SECTION:
868
          UI("section");
869
          break;
870
 
871
        case MIPS_R_SECREL:
872
          UI("secrel");
873
          break;
874
 
875
        case MIPS_R_SECRELLO:
876
          UI("secrello");
877
          break;
878
 
879
        case MIPS_R_SECRELHI:
880
          UI("secrelhi");
881
          break;
882
 
883
        case MIPS_R_RVA:
884
          tmp = bfd_get_32 (input_bfd, mem);
885
          /* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */
886
          tmp += val
887
            - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
888
          bfd_put_32 (input_bfd, tmp, mem);
889
          break;
890
 
891
        case MIPS_R_PAIR:
892
          /* ignore these */
893
          break;
894
        }
895
    }
896
 
897
  return true;
898
}
899
 
900
#define coff_relocate_section coff_pe_mips_relocate_section
901
 
902
#ifdef TARGET_UNDERSCORE
903
 
904
/* If mips gcc uses underscores for symbol names, then it does not use
905
   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
906
   we treat all symbols starting with L as local.  */
907
 
908
static boolean coff_mips_is_local_label_name PARAMS ((bfd *, const char *));
909
 
910
static boolean
911
coff_mips_is_local_label_name (abfd, name)
912
     bfd *abfd;
913
     const char *name;
914
{
915
  if (name[0] == 'L')
916
    return true;
917
 
918
  return _bfd_coff_is_local_label_name (abfd, name);
919
}
920
 
921
#define coff_bfd_is_local_label_name coff_mips_is_local_label_name
922
 
923
#endif /* TARGET_UNDERSCORE */
924
 
925
#define COFF_NO_HACK_SCNHDR_SIZE
926
 
927
#include "coffcode.h"
928
 
929
const bfd_target
930
#ifdef TARGET_SYM
931
  TARGET_SYM =
932
#else
933
  mipslpe_vec =
934
#endif
935
{
936
#ifdef TARGET_NAME
937
  TARGET_NAME,
938
#else
939
  "pe-mips",                    /* name */
940
#endif
941
  bfd_target_coff_flavour,
942
  BFD_ENDIAN_LITTLE,            /* data byte order is little */
943
  BFD_ENDIAN_LITTLE,            /* header byte order is little */
944
 
945
  (HAS_RELOC | EXEC_P |         /* object flags */
946
   HAS_LINENO | HAS_DEBUG |
947
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
948
 
949
#ifndef COFF_WITH_PE
950
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
951
   | SEC_CODE | SEC_DATA),
952
#else
953
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
954
   | SEC_CODE | SEC_DATA
955
   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
956
#endif
957
 
958
#ifdef TARGET_UNDERSCORE
959
  TARGET_UNDERSCORE,            /* leading underscore */
960
#else
961
  0,                             /* leading underscore */
962
#endif
963
  '/',                          /* ar_pad_char */
964
  15,                           /* ar_max_namelen */
965
 
966
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
967
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
968
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
969
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
970
     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
971
     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
972
 
973
/* Note that we allow an object file to be treated as a core file as well.  */
974
    {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
975
       bfd_generic_archive_p, coff_object_p},
976
    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
977
       bfd_false},
978
    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
979
       _bfd_write_archive_contents, bfd_false},
980
 
981
     BFD_JUMP_TABLE_GENERIC (coff),
982
     BFD_JUMP_TABLE_COPY (coff),
983
     BFD_JUMP_TABLE_CORE (_bfd_nocore),
984
     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
985
     BFD_JUMP_TABLE_SYMBOLS (coff),
986
     BFD_JUMP_TABLE_RELOCS (coff),
987
     BFD_JUMP_TABLE_WRITE (coff),
988
     BFD_JUMP_TABLE_LINK (coff),
989
     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
990
 
991
  NULL,
992
 
993
  COFF_SWAP_TABLE
994
};

powered by: WebSVN 2.1.0

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