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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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