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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [bfd/] [pe-mips.c] - Blame information for rev 252

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

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

powered by: WebSVN 2.1.0

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