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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [elf32-fr30.c] - Blame information for rev 1778

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

Line No. Rev Author Line
1 1181 sfurman
/* FR30-specific support for 32-bit ELF.
2
   Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
 
4
This file is part of BFD, the Binary File Descriptor library.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
20
#include "bfd.h"
21
#include "sysdep.h"
22
#include "libbfd.h"
23
#include "elf-bfd.h"
24
#include "elf/fr30.h"
25
 
26
/* Forward declarations.  */
27
static bfd_reloc_status_type fr30_elf_i20_reloc
28
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
29
static bfd_reloc_status_type fr30_elf_i32_reloc
30
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
31
static reloc_howto_type * fr30_reloc_type_lookup
32
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
33
static void fr30_info_to_howto_rela
34
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
35
static boolean fr30_elf_relocate_section
36
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
37
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
38
static bfd_reloc_status_type fr30_final_link_relocate
39
  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
40
           Elf_Internal_Rela *, bfd_vma));
41
static boolean fr30_elf_gc_sweep_hook
42
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
43
           const Elf_Internal_Rela *));
44
static asection * fr30_elf_gc_mark_hook
45
  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
46
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
47
static boolean fr30_elf_check_relocs
48
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
49
           const Elf_Internal_Rela *));
50
 
51
static reloc_howto_type fr30_elf_howto_table [] =
52
{
53
  /* This reloc does nothing.  */
54
  HOWTO (R_FR30_NONE,           /* type */
55
         0,                      /* rightshift */
56
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
57
         32,                    /* bitsize */
58
         false,                 /* pc_relative */
59
         0,                      /* bitpos */
60
         complain_overflow_bitfield, /* complain_on_overflow */
61
         bfd_elf_generic_reloc, /* special_function */
62
         "R_FR30_NONE",         /* name */
63
         false,                 /* partial_inplace */
64
         0,                      /* src_mask */
65
         0,                      /* dst_mask */
66
         false),                /* pcrel_offset */
67
 
68
  /* An 8 bit absolute relocation.  */
69
  HOWTO (R_FR30_8,              /* type */
70
         0,                      /* rightshift */
71
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
72
         8,                     /* bitsize */
73
         false,                 /* pc_relative */
74
         4,                     /* bitpos */
75
         complain_overflow_bitfield, /* complain_on_overflow */
76
         bfd_elf_generic_reloc, /* special_function */
77
         "R_FR30_8",            /* name */
78
         true,                  /* partial_inplace */
79
         0x0000,                /* src_mask */
80
         0x0ff0,                /* dst_mask */
81
         false),                /* pcrel_offset */
82
 
83
  /* A 20 bit absolute relocation.  */
84
  HOWTO (R_FR30_20,             /* type */
85
         0,                      /* rightshift */
86
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
87
         20,                    /* bitsize */
88
         false,                 /* pc_relative */
89
         0,                      /* bitpos */
90
         complain_overflow_bitfield, /* complain_on_overflow */
91
         fr30_elf_i20_reloc,    /* special_function */
92
         "R_FR30_20",           /* name */
93
         true,                  /* partial_inplace */
94
         0x00000000,            /* src_mask */
95
         0x00f0ffff,            /* dst_mask */
96
         false),                /* pcrel_offset */
97
 
98
  /* A 32 bit absolute relocation.  */
99
  HOWTO (R_FR30_32,             /* type */
100
         0,                      /* rightshift */
101
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
102
         32,                    /* bitsize */
103
         false,                 /* pc_relative */
104
         0,                      /* bitpos */
105
         complain_overflow_bitfield, /* complain_on_overflow */
106
         bfd_elf_generic_reloc, /* special_function */
107
         "R_FR30_32",           /* name */
108
         true,                  /* partial_inplace */
109
         0x00000000,            /* src_mask */
110
         0xffffffff,            /* dst_mask */
111
         false),                /* pcrel_offset */
112
 
113
  /* A 32 bit into 48 bits absolute relocation.  */
114
  HOWTO (R_FR30_48,             /* type */
115
         0,                      /* rightshift */
116
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
117
         32,                    /* bitsize */
118
         false,                 /* pc_relative */
119
         0,                      /* bitpos */
120
         complain_overflow_bitfield, /* complain_on_overflow */
121
         fr30_elf_i32_reloc,    /* special_function */
122
         "R_FR30_48",           /* name */
123
         true,                  /* partial_inplace */
124
         0x00000000,            /* src_mask */
125
         0xffffffff,            /* dst_mask */
126
         false),                /* pcrel_offset */
127
 
128
  /* A 6 bit absolute relocation.  */
129
  HOWTO (R_FR30_6_IN_4,         /* type */
130
         2,                     /* rightshift */
131
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
132
         6,                     /* bitsize */
133
         false,                 /* pc_relative */
134
         4,                     /* bitpos */
135
         complain_overflow_unsigned, /* complain_on_overflow */
136
         bfd_elf_generic_reloc, /* special_function */
137
         "R_FR30_6_IN_4",       /* name */
138
         true,                  /* partial_inplace */
139
         0x0000,                /* src_mask */
140
         0x00f0,                /* dst_mask */
141
         false),                /* pcrel_offset */
142
 
143
  /* An 8 bit absolute relocation.  */
144
  HOWTO (R_FR30_8_IN_8,         /* type */
145
         0,                      /* rightshift */
146
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
147
         8,                     /* bitsize */
148
         false,                 /* pc_relative */
149
         4,                     /* bitpos */
150
         complain_overflow_signed, /* complain_on_overflow */
151
         bfd_elf_generic_reloc,/* special_function */
152
         "R_FR30_8_IN_8",       /* name */
153
         true,                  /* partial_inplace */
154
         0x0000,                /* src_mask */
155
         0x0ff0,                /* dst_mask */
156
         false),                /* pcrel_offset */
157
 
158
  /* A 9 bit absolute relocation.  */
159
  HOWTO (R_FR30_9_IN_8,         /* type */
160
         1,                     /* rightshift */
161
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
162
         9,                     /* bitsize */
163
         false,                 /* pc_relative */
164
         4,                     /* bitpos */
165
         complain_overflow_signed, /* complain_on_overflow */
166
         bfd_elf_generic_reloc,/* special_function */
167
         "R_FR30_9_IN_8",       /* name */
168
         true,                  /* partial_inplace */
169
         0x0000,                /* src_mask */
170
         0x0ff0,                /* dst_mask */
171
         false),                /* pcrel_offset */
172
 
173
  /* A 10 bit absolute relocation.  */
174
  HOWTO (R_FR30_10_IN_8,        /* type */
175
         2,                     /* rightshift */
176
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
177
         10,                    /* bitsize */
178
         false,                 /* pc_relative */
179
         4,                     /* bitpos */
180
         complain_overflow_signed, /* complain_on_overflow */
181
         bfd_elf_generic_reloc,/* special_function */
182
         "R_FR30_10_IN_8",      /* name */
183
         true,                  /* partial_inplace */
184
         0x0000,                /* src_mask */
185
         0x0ff0,                /* dst_mask */
186
         false),                /* pcrel_offset */
187
 
188
  /* A PC relative 9 bit relocation, right shifted by 1.  */
189
  HOWTO (R_FR30_9_PCREL,        /* type */
190
         1,                     /* rightshift */
191
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
192
         9,                     /* bitsize */
193
         true,                  /* pc_relative */
194
         0,                      /* bitpos */
195
         complain_overflow_signed, /* complain_on_overflow */
196
         bfd_elf_generic_reloc, /* special_function */
197
         "R_FR30_9_PCREL",      /* name */
198
         false,                 /* partial_inplace */
199
         0x0000,                /* src_mask */
200
         0x00ff,                /* dst_mask */
201
         false),                /* pcrel_offset */
202
 
203
  /* A PC relative 12 bit relocation, right shifted by 1.  */
204
  HOWTO (R_FR30_12_PCREL,       /* type */
205
         1,                     /* rightshift */
206
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
207
         12,                    /* bitsize */
208
         true,                  /* pc_relative */
209
         0,                      /* bitpos */
210
         complain_overflow_signed, /* complain_on_overflow */
211
         bfd_elf_generic_reloc, /* special_function */
212
         "R_FR30_12_PCREL",     /* name */
213
         false,                 /* partial_inplace */
214
         0x0000,                /* src_mask */
215
         0x07ff,                /* dst_mask */
216
         false),                /* pcrel_offset */
217
  /* GNU extension to record C++ vtable hierarchy */
218
  HOWTO (R_FR30_GNU_VTINHERIT, /* type */
219
         0,                     /* rightshift */
220
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
221
         0,                     /* bitsize */
222
         false,                 /* pc_relative */
223
         0,                     /* bitpos */
224
         complain_overflow_dont, /* complain_on_overflow */
225
         NULL,                  /* special_function */
226
         "R_FR30_GNU_VTINHERIT", /* name */
227
         false,                 /* partial_inplace */
228
         0,                     /* src_mask */
229
         0,                     /* dst_mask */
230
         false),                /* pcrel_offset */
231
 
232
  /* GNU extension to record C++ vtable member usage */
233
  HOWTO (R_FR30_GNU_VTENTRY,     /* type */
234
         0,                     /* rightshift */
235
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
236
         0,                     /* bitsize */
237
         false,                 /* pc_relative */
238
         0,                     /* bitpos */
239
         complain_overflow_dont, /* complain_on_overflow */
240
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
241
         "R_FR30_GNU_VTENTRY",   /* name */
242
         false,                 /* partial_inplace */
243
         0,                     /* src_mask */
244
         0,                     /* dst_mask */
245
         false),                /* pcrel_offset */
246
};
247
 
248
/* Utility to actually perform an R_FR30_20 reloc.  */
249
 
250
static bfd_reloc_status_type
251
fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
252
                    input_section, output_bfd, error_message)
253
     bfd *      abfd;
254
     arelent *  reloc_entry;
255
     asymbol *  symbol;
256
     PTR        data;
257
     asection * input_section;
258
     bfd *      output_bfd;
259
     char **    error_message ATTRIBUTE_UNUSED;
260
{
261
  bfd_vma       relocation;
262
  unsigned long x;
263
 
264
  /* This part is from bfd_elf_generic_reloc.  */
265
  if (output_bfd != (bfd *) NULL
266
      && (symbol->flags & BSF_SECTION_SYM) == 0
267
      && (! reloc_entry->howto->partial_inplace
268
          || reloc_entry->addend == 0))
269
    {
270
      reloc_entry->address += input_section->output_offset;
271
      return bfd_reloc_ok;
272
    }
273
 
274
  if (output_bfd != NULL)
275
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
276
    return bfd_reloc_ok;
277
 
278
  relocation =
279
    symbol->value
280
    + symbol->section->output_section->vma
281
    + symbol->section->output_offset
282
    + reloc_entry->addend;
283
 
284
  if (relocation > (((bfd_vma) 1 << 20) - 1))
285
    return bfd_reloc_overflow;
286
 
287
  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
288
  x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
289
  bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
290
 
291
  return bfd_reloc_ok;
292
}
293
 
294
/* Utility to actually perform a R_FR30_48 reloc.  */
295
 
296
static bfd_reloc_status_type
297
fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
298
                    input_section, output_bfd, error_message)
299
     bfd *      abfd;
300
     arelent *  reloc_entry;
301
     asymbol *  symbol;
302
     PTR        data;
303
     asection * input_section;
304
     bfd *      output_bfd;
305
     char **    error_message ATTRIBUTE_UNUSED;
306
{
307
  bfd_vma       relocation;
308
 
309
  /* This part is from bfd_elf_generic_reloc.  */
310
  if (output_bfd != (bfd *) NULL
311
      && (symbol->flags & BSF_SECTION_SYM) == 0
312
      && (! reloc_entry->howto->partial_inplace
313
          || reloc_entry->addend == 0))
314
    {
315
      reloc_entry->address += input_section->output_offset;
316
      return bfd_reloc_ok;
317
    }
318
 
319
  if (output_bfd != NULL)
320
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
321
    return bfd_reloc_ok;
322
 
323
  relocation =
324
    symbol->value
325
    + symbol->section->output_section->vma
326
    + symbol->section->output_offset
327
    + reloc_entry->addend;
328
 
329
  bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
330
 
331
  return bfd_reloc_ok;
332
}
333
 
334
/* Map BFD reloc types to FR30 ELF reloc types.  */
335
 
336
struct fr30_reloc_map
337
{
338
  bfd_reloc_code_real_type bfd_reloc_val;
339
  unsigned int fr30_reloc_val;
340
};
341
 
342
static const struct fr30_reloc_map fr30_reloc_map [] =
343
{
344
  { BFD_RELOC_NONE,           R_FR30_NONE },
345
  { BFD_RELOC_8,              R_FR30_8 },
346
  { BFD_RELOC_FR30_20,        R_FR30_20 },
347
  { BFD_RELOC_32,             R_FR30_32 },
348
  { BFD_RELOC_FR30_48,        R_FR30_48 },
349
  { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
350
  { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
351
  { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
352
  { BFD_RELOC_FR30_10_IN_8,   R_FR30_10_IN_8 },
353
  { BFD_RELOC_FR30_9_PCREL,   R_FR30_9_PCREL },
354
  { BFD_RELOC_FR30_12_PCREL,  R_FR30_12_PCREL },
355
  { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
356
  { BFD_RELOC_VTABLE_ENTRY,   R_FR30_GNU_VTENTRY },
357
};
358
 
359
static reloc_howto_type *
360
fr30_reloc_type_lookup (abfd, code)
361
     bfd * abfd ATTRIBUTE_UNUSED;
362
     bfd_reloc_code_real_type code;
363
{
364
  unsigned int i;
365
 
366
  for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
367
       --i;)
368
    if (fr30_reloc_map [i].bfd_reloc_val == code)
369
      return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
370
 
371
  return NULL;
372
}
373
 
374
/* Set the howto pointer for an FR30 ELF reloc.  */
375
 
376
static void
377
fr30_info_to_howto_rela (abfd, cache_ptr, dst)
378
     bfd * abfd ATTRIBUTE_UNUSED;
379
     arelent * cache_ptr;
380
     Elf32_Internal_Rela * dst;
381
{
382
  unsigned int r_type;
383
 
384
  r_type = ELF32_R_TYPE (dst->r_info);
385
  BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
386
  cache_ptr->howto = & fr30_elf_howto_table [r_type];
387
}
388
 
389
/* Perform a single relocation.  By default we use the standard BFD
390
   routines, but a few relocs, we have to do them ourselves.  */
391
 
392
static bfd_reloc_status_type
393
fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
394
     reloc_howto_type *  howto;
395
     bfd *               input_bfd;
396
     asection *          input_section;
397
     bfd_byte *          contents;
398
     Elf_Internal_Rela * rel;
399
     bfd_vma             relocation;
400
{
401
  bfd_reloc_status_type r = bfd_reloc_ok;
402
  bfd_vma               x;
403
  bfd_signed_vma        srel;
404
 
405
  switch (howto->type)
406
    {
407
    case R_FR30_20:
408
      contents   += rel->r_offset;
409
      relocation += rel->r_addend;
410
 
411
      if (relocation > ((1 << 20) - 1))
412
        return bfd_reloc_overflow;
413
 
414
      x = bfd_get_32 (input_bfd, contents);
415
      x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
416
      bfd_put_32 (input_bfd, x, contents);
417
      break;
418
 
419
    case R_FR30_48:
420
      contents   += rel->r_offset + 2;
421
      relocation += rel->r_addend;
422
      bfd_put_32 (input_bfd, relocation, contents);
423
      break;
424
 
425
    case R_FR30_9_PCREL:
426
      contents   += rel->r_offset + 1;
427
      srel = (bfd_signed_vma) relocation;
428
      srel += rel->r_addend;
429
      srel -= rel->r_offset;
430
      srel -= 2;  /* Branch instructions add 2 to the PC...  */
431
      srel -= (input_section->output_section->vma +
432
                     input_section->output_offset);
433
 
434
      if (srel & 1)
435
        return bfd_reloc_outofrange;
436
      if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
437
        return bfd_reloc_overflow;
438
 
439
      bfd_put_8 (input_bfd, srel >> 1, contents);
440
      break;
441
 
442
    case R_FR30_12_PCREL:
443
      contents   += rel->r_offset;
444
      srel = (bfd_signed_vma) relocation;
445
      srel += rel->r_addend;
446
      srel -= rel->r_offset;
447
      srel -= 2; /* Branch instructions add 2 to the PC...  */
448
      srel -= (input_section->output_section->vma +
449
                     input_section->output_offset);
450
 
451
      if (srel & 1)
452
        return bfd_reloc_outofrange;
453
      if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
454
          return bfd_reloc_overflow;
455
 
456
      x = bfd_get_16 (input_bfd, contents);
457
      x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
458
      bfd_put_16 (input_bfd, x, contents);
459
      break;
460
 
461
    default:
462
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
463
                                    contents, rel->r_offset,
464
                                    relocation, rel->r_addend);
465
    }
466
 
467
  return r;
468
}
469
 
470
/* Relocate an FR30 ELF section.
471
 
472
   The RELOCATE_SECTION function is called by the new ELF backend linker
473
   to handle the relocations for a section.
474
 
475
   The relocs are always passed as Rela structures; if the section
476
   actually uses Rel structures, the r_addend field will always be
477
   zero.
478
 
479
   This function is responsible for adjusting the section contents as
480
   necessary, and (if using Rela relocs and generating a relocateable
481
   output file) adjusting the reloc addend as necessary.
482
 
483
   This function does not have to worry about setting the reloc
484
   address or the reloc symbol index.
485
 
486
   LOCAL_SYMS is a pointer to the swapped in local symbols.
487
 
488
   LOCAL_SECTIONS is an array giving the section in the input file
489
   corresponding to the st_shndx field of each local symbol.
490
 
491
   The global hash table entry for the global symbols can be found
492
   via elf_sym_hashes (input_bfd).
493
 
494
   When generating relocateable output, this function must handle
495
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
496
   going to be the section symbol corresponding to the output
497
   section, which means that the addend must be adjusted
498
   accordingly.  */
499
 
500
static boolean
501
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
502
                           contents, relocs, local_syms, local_sections)
503
     bfd *                   output_bfd;
504
     struct bfd_link_info *  info;
505
     bfd *                   input_bfd;
506
     asection *              input_section;
507
     bfd_byte *              contents;
508
     Elf_Internal_Rela *     relocs;
509
     Elf_Internal_Sym *      local_syms;
510
     asection **             local_sections;
511
{
512
  Elf_Internal_Shdr *           symtab_hdr;
513
  struct elf_link_hash_entry ** sym_hashes;
514
  Elf_Internal_Rela *           rel;
515
  Elf_Internal_Rela *           relend;
516
 
517
  if (info->relocateable)
518
    return true;
519
 
520
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
521
  sym_hashes = elf_sym_hashes (input_bfd);
522
  relend     = relocs + input_section->reloc_count;
523
 
524
  for (rel = relocs; rel < relend; rel ++)
525
    {
526
      reloc_howto_type *           howto;
527
      unsigned long                r_symndx;
528
      Elf_Internal_Sym *           sym;
529
      asection *                   sec;
530
      struct elf_link_hash_entry * h;
531
      bfd_vma                      relocation;
532
      bfd_reloc_status_type        r;
533
      const char *                 name = NULL;
534
      int                          r_type;
535
 
536
      r_type = ELF32_R_TYPE (rel->r_info);
537
 
538
      if (   r_type == R_FR30_GNU_VTINHERIT
539
          || r_type == R_FR30_GNU_VTENTRY)
540
        continue;
541
 
542
      r_symndx = ELF32_R_SYM (rel->r_info);
543
 
544
      howto  = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
545
      h      = NULL;
546
      sym    = NULL;
547
      sec    = NULL;
548
 
549
      if (r_symndx < symtab_hdr->sh_info)
550
        {
551
          sym = local_syms + r_symndx;
552
          sec = local_sections [r_symndx];
553
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
554
 
555
          name = bfd_elf_string_from_elf_section
556
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
557
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
558
#if 0
559
          fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
560
                   sec->name, name, sym->st_name,
561
                   sec->output_section->vma, sec->output_offset,
562
                   sym->st_value, rel->r_addend);
563
#endif
564
        }
565
      else
566
        {
567
          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
568
 
569
          while (h->root.type == bfd_link_hash_indirect
570
                 || h->root.type == bfd_link_hash_warning)
571
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
572
 
573
          name = h->root.root.string;
574
 
575
          if (h->root.type == bfd_link_hash_defined
576
              || h->root.type == bfd_link_hash_defweak)
577
            {
578
              sec = h->root.u.def.section;
579
              relocation = (h->root.u.def.value
580
                            + sec->output_section->vma
581
                            + sec->output_offset);
582
#if 0
583
              fprintf (stderr,
584
                       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
585
                       sec->name, name, h->root.u.def.value,
586
                       sec->output_section->vma, sec->output_offset, relocation);
587
#endif
588
            }
589
          else if (h->root.type == bfd_link_hash_undefweak)
590
            {
591
#if 0
592
              fprintf (stderr, "undefined: sec: %s, name: %s\n",
593
                       sec->name, name);
594
#endif
595
              relocation = 0;
596
            }
597
          else
598
            {
599
              if (! ((*info->callbacks->undefined_symbol)
600
                     (info, h->root.root.string, input_bfd,
601
                      input_section, rel->r_offset, true)))
602
                return false;
603
#if 0
604
              fprintf (stderr, "unknown: name: %s\n", name);
605
#endif
606
              relocation = 0;
607
            }
608
        }
609
 
610
      r = fr30_final_link_relocate (howto, input_bfd, input_section,
611
                                     contents, rel, relocation);
612
 
613
      if (r != bfd_reloc_ok)
614
        {
615
          const char * msg = (const char *) NULL;
616
 
617
          switch (r)
618
            {
619
            case bfd_reloc_overflow:
620
              r = info->callbacks->reloc_overflow
621
                (info, name, howto->name, (bfd_vma) 0,
622
                 input_bfd, input_section, rel->r_offset);
623
              break;
624
 
625
            case bfd_reloc_undefined:
626
              r = info->callbacks->undefined_symbol
627
                (info, name, input_bfd, input_section, rel->r_offset,
628
                 true);
629
              break;
630
 
631
            case bfd_reloc_outofrange:
632
              msg = _("internal error: out of range error");
633
              break;
634
 
635
            case bfd_reloc_notsupported:
636
              msg = _("internal error: unsupported relocation error");
637
              break;
638
 
639
            case bfd_reloc_dangerous:
640
              msg = _("internal error: dangerous relocation");
641
              break;
642
 
643
            default:
644
              msg = _("internal error: unknown error");
645
              break;
646
            }
647
 
648
          if (msg)
649
            r = info->callbacks->warning
650
              (info, msg, name, input_bfd, input_section, rel->r_offset);
651
 
652
          if (! r)
653
            return false;
654
        }
655
    }
656
 
657
  return true;
658
}
659
 
660
/* Return the section that should be marked against GC for a given
661
   relocation.  */
662
 
663
static asection *
664
fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
665
     asection *                   sec;
666
     struct bfd_link_info *       info ATTRIBUTE_UNUSED;
667
     Elf_Internal_Rela *          rel;
668
     struct elf_link_hash_entry * h;
669
     Elf_Internal_Sym *           sym;
670
{
671
  if (h != NULL)
672
    {
673
      switch (ELF32_R_TYPE (rel->r_info))
674
        {
675
        case R_FR30_GNU_VTINHERIT:
676
        case R_FR30_GNU_VTENTRY:
677
          break;
678
 
679
        default:
680
          switch (h->root.type)
681
            {
682
            case bfd_link_hash_defined:
683
            case bfd_link_hash_defweak:
684
              return h->root.u.def.section;
685
 
686
            case bfd_link_hash_common:
687
              return h->root.u.c.p->section;
688
 
689
            default:
690
              break;
691
            }
692
        }
693
    }
694
  else
695
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
696
 
697
  return NULL;
698
}
699
 
700
/* Update the got entry reference counts for the section being removed.  */
701
 
702
static boolean
703
fr30_elf_gc_sweep_hook (abfd, info, sec, relocs)
704
     bfd *                     abfd ATTRIBUTE_UNUSED;
705
     struct bfd_link_info *    info ATTRIBUTE_UNUSED;
706
     asection *                sec ATTRIBUTE_UNUSED;
707
     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
708
{
709
  return true;
710
}
711
 
712
/* Look through the relocs for a section during the first phase.
713
   Since we don't do .gots or .plts, we just need to consider the
714
   virtual table relocs for gc.  */
715
 
716
static boolean
717
fr30_elf_check_relocs (abfd, info, sec, relocs)
718
     bfd *abfd;
719
     struct bfd_link_info *info;
720
     asection *sec;
721
     const Elf_Internal_Rela *relocs;
722
{
723
  Elf_Internal_Shdr *symtab_hdr;
724
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
725
  const Elf_Internal_Rela *rel;
726
  const Elf_Internal_Rela *rel_end;
727
 
728
  if (info->relocateable)
729
    return true;
730
 
731
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
732
  sym_hashes = elf_sym_hashes (abfd);
733
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
734
  if (!elf_bad_symtab (abfd))
735
    sym_hashes_end -= symtab_hdr->sh_info;
736
 
737
  rel_end = relocs + sec->reloc_count;
738
  for (rel = relocs; rel < rel_end; rel++)
739
    {
740
      struct elf_link_hash_entry *h;
741
      unsigned long r_symndx;
742
 
743
      r_symndx = ELF32_R_SYM (rel->r_info);
744
      if (r_symndx < symtab_hdr->sh_info)
745
        h = NULL;
746
      else
747
        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
748
 
749
      switch (ELF32_R_TYPE (rel->r_info))
750
        {
751
        /* This relocation describes the C++ object vtable hierarchy.
752
           Reconstruct it for later use during GC.  */
753
        case R_FR30_GNU_VTINHERIT:
754
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
755
            return false;
756
          break;
757
 
758
        /* This relocation describes which C++ vtable entries are actually
759
           used.  Record for later use during GC.  */
760
        case R_FR30_GNU_VTENTRY:
761
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
762
            return false;
763
          break;
764
        }
765
    }
766
 
767
  return true;
768
}
769
 
770
#define ELF_ARCH                bfd_arch_fr30
771
#define ELF_MACHINE_CODE        EM_FR30
772
#define ELF_MACHINE_ALT1        EM_CYGNUS_FR30
773
#define ELF_MAXPAGESIZE         0x1000
774
 
775
#define TARGET_BIG_SYM          bfd_elf32_fr30_vec
776
#define TARGET_BIG_NAME         "elf32-fr30"
777
 
778
#define elf_info_to_howto_rel                   NULL
779
#define elf_info_to_howto                       fr30_info_to_howto_rela
780
#define elf_backend_relocate_section            fr30_elf_relocate_section
781
#define elf_backend_gc_mark_hook                fr30_elf_gc_mark_hook
782
#define elf_backend_gc_sweep_hook               fr30_elf_gc_sweep_hook
783
#define elf_backend_check_relocs                fr30_elf_check_relocs
784
 
785
#define elf_backend_can_gc_sections             1
786
#define elf_backend_rela_normal                 1
787
 
788
#define bfd_elf32_bfd_reloc_type_lookup         fr30_reloc_type_lookup
789
 
790
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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