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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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