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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [elf32-fr30.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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