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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [bfd/] [elf32-openrisc.c] - Blame information for rev 298

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

Line No. Rev Author Line
1 205 julius
/* OpenRISC-specific support for 32-bit ELF.
2
   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
3
   Free Software Foundation, Inc.
4
   Contributed by Johan Rydberg, jrydberg@opencores.org
5
 
6
   This file is part of BFD, the Binary File Descriptor library.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
#include "bfd.h"
25
#include "libbfd.h"
26
#include "elf-bfd.h"
27
#include "elf/openrisc.h"
28
#include "libiberty.h"
29
 
30
static reloc_howto_type openrisc_elf_howto_table[] =
31
{
32
  /* This reloc does nothing.  */
33
  HOWTO (R_OPENRISC_NONE,       /* type */
34
         0,                      /* rightshift */
35
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
36
         32,                    /* bitsize */
37
         FALSE,                 /* pc_relative */
38
         0,                      /* bitpos */
39
         complain_overflow_bitfield, /* complain_on_overflow */
40
         bfd_elf_generic_reloc, /* special_function */
41
         "R_OPENRISC_NONE",     /* name */
42
         FALSE,                 /* partial_inplace */
43
         0,                      /* src_mask */
44
         0,                      /* dst_mask */
45
         FALSE),                /* pcrel_offset */
46
 
47
  /* A PC relative 26 bit relocation, right shifted by 2.  */
48
  HOWTO (R_OPENRISC_INSN_REL_26, /* type */
49
         2,                     /* rightshift */
50
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
51
         26,                    /* bitsize */
52
         TRUE,                  /* pc_relative */
53
         0,                      /* bitpos */
54
         complain_overflow_signed, /* complain_on_overflow */
55
         bfd_elf_generic_reloc, /* special_function */
56
         "R_OPENRISC_INSN_REL_26", /* name */
57
         FALSE,                 /* partial_inplace */
58
         0x00000000,            /* src_mask */
59
         0x03ffffff,            /* dst_mask */
60
         FALSE),                /* pcrel_offset */
61
 
62
  /* A absolute 26 bit relocation, right shifted by 2.  */
63
  HOWTO (R_OPENRISC_INSN_ABS_26, /* type */
64
         2,                     /* rightshift */
65
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
66
         26,                    /* bitsize */
67
         FALSE,                 /* pc_relative */
68
         0,                      /* bitpos */
69
         complain_overflow_signed, /* complain_on_overflow */
70
         bfd_elf_generic_reloc, /* special_function */
71
         "R_OPENRISC_INSN_ABS_26", /* name */
72
         FALSE,                 /* partial_inplace */
73
         0x00000000,            /* src_mask */
74
         0x03ffffff,            /* dst_mask */
75
         FALSE),                /* pcrel_offset */
76
 
77
  HOWTO (R_OPENRISC_LO_16_IN_INSN, /* type */
78
         0,                      /* rightshift */
79
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
80
         16,                    /* bitsize */
81
         FALSE,                 /* pc_relative */
82
         0,                      /* bitpos */
83
         complain_overflow_dont, /* complain_on_overflow */
84
         bfd_elf_generic_reloc, /* special_function */
85
         "R_OPENRISC_LO_16_IN_INSN", /* name */
86
         FALSE,                 /* partial_inplace */
87
         0,                      /* src_mask */
88
         0x0000ffff,            /* dst_mask */
89
         FALSE),                /* pcrel_offset */
90
 
91
  HOWTO (R_OPENRISC_HI_16_IN_INSN, /* type */
92
         16,                    /* rightshift */
93
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
94
         16,                    /* bitsize */
95
         FALSE,                 /* pc_relative */
96
         0,                      /* bitpos */
97
         complain_overflow_dont,        /* complain_on_overflow */
98
         bfd_elf_generic_reloc, /* special_function */
99
         "R_OPENRISC_HI_16_IN_INSN",    /* name */
100
         FALSE,                 /* partial_inplace */
101
         0,                      /* src_mask */
102
         0x0000ffff,            /* dst_mask */
103
         FALSE),                /* pcrel_offset */
104
 
105
  /* An 8 bit absolute relocation.  */
106
  HOWTO (R_OPENRISC_8,          /* type */
107
         0,                      /* rightshift */
108
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
109
         8,                     /* bitsize */
110
         FALSE,                 /* pc_relative */
111
         0,                      /* bitpos */
112
         complain_overflow_bitfield, /* complain_on_overflow */
113
         bfd_elf_generic_reloc, /* special_function */
114
         "R_OPENRISC_8",        /* name */
115
         TRUE,                  /* partial_inplace */
116
         0x0000,                /* src_mask */
117
         0x00ff,                /* dst_mask */
118
         FALSE),                /* pcrel_offset */
119
 
120
  /* A 16 bit absolute relocation.  */
121
  HOWTO (R_OPENRISC_16,         /* type */
122
         0,                      /* rightshift */
123
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
124
         16,                    /* bitsize */
125
         FALSE,                 /* pc_relative */
126
         0,                      /* bitpos */
127
         complain_overflow_bitfield, /* complain_on_overflow */
128
         bfd_elf_generic_reloc, /* special_function */
129
         "R_OPENRISC_16",       /* name */
130
         TRUE,                  /* partial_inplace */
131
         0x00000000,            /* src_mask */
132
         0x0000ffff,            /* dst_mask */
133
         FALSE),                /* pcrel_offset */
134
 
135
  /* A 32 bit absolute relocation.  */
136
  HOWTO (R_OPENRISC_32,         /* type */
137
         0,                      /* rightshift */
138
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
139
         32,                    /* bitsize */
140
         FALSE,                 /* pc_relative */
141
         0,                      /* bitpos */
142
         complain_overflow_bitfield, /* complain_on_overflow */
143
         bfd_elf_generic_reloc, /* special_function */
144
         "R_OPENRISC_32",       /* name */
145
         TRUE,                  /* partial_inplace */
146
         0x00000000,            /* src_mask */
147
         0xffffffff,            /* dst_mask */
148
         FALSE),                /* pcrel_offset */
149
 
150
  /* GNU extension to record C++ vtable hierarchy.  */
151
  HOWTO (R_OPENRISC_GNU_VTINHERIT, /* type */
152
         0,                      /* rightshift */
153
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
154
         0,                      /* bitsize */
155
         FALSE,                 /* pc_relative */
156
         0,                      /* bitpos */
157
         complain_overflow_dont, /* complain_on_overflow */
158
         NULL,                  /* special_function */
159
         "R_OPENRISC_GNU_VTINHERIT", /* name */
160
         FALSE,                 /* partial_inplace */
161
         0,                      /* src_mask */
162
         0,                      /* dst_mask */
163
         FALSE),                /* pcrel_offset */
164
 
165
  /* GNU extension to record C++ vtable member usage.  */
166
  HOWTO (R_OPENRISC_GNU_VTENTRY, /* type */
167
         0,                      /* rightshift */
168
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
169
         0,                      /* bitsize */
170
         FALSE,                 /* pc_relative */
171
         0,                      /* bitpos */
172
         complain_overflow_dont, /* complain_on_overflow */
173
         _bfd_elf_rel_vtable_reloc_fn, /* special_function */
174
         "R_OPENRISC_GNU_VTENTRY", /* name */
175
         FALSE,                 /* partial_inplace */
176
         0,                      /* src_mask */
177
         0,                      /* dst_mask */
178
         FALSE),                /* pcrel_offset */
179
};
180
 
181
/* Map BFD reloc types to OpenRISC ELF reloc types.  */
182
 
183
struct openrisc_reloc_map
184
{
185
  bfd_reloc_code_real_type bfd_reloc_val;
186
  unsigned int openrisc_reloc_val;
187
};
188
 
189
static const struct openrisc_reloc_map openrisc_reloc_map[] =
190
{
191
  { BFD_RELOC_NONE,             R_OPENRISC_NONE },
192
  { BFD_RELOC_32,               R_OPENRISC_32 },
193
  { BFD_RELOC_16,               R_OPENRISC_16 },
194
  { BFD_RELOC_8,                R_OPENRISC_8 },
195
  { BFD_RELOC_OPENRISC_REL_26,  R_OPENRISC_INSN_REL_26 },
196
  { BFD_RELOC_OPENRISC_ABS_26,  R_OPENRISC_INSN_ABS_26 },
197
  { BFD_RELOC_HI16,             R_OPENRISC_HI_16_IN_INSN },
198
  { BFD_RELOC_LO16,             R_OPENRISC_LO_16_IN_INSN },
199
  { BFD_RELOC_VTABLE_INHERIT,   R_OPENRISC_GNU_VTINHERIT },
200
  { BFD_RELOC_VTABLE_ENTRY,     R_OPENRISC_GNU_VTENTRY }
201
};
202
 
203
static reloc_howto_type *
204
openrisc_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
205
                            bfd_reloc_code_real_type code)
206
{
207
  unsigned int i;
208
 
209
  for (i = ARRAY_SIZE (openrisc_reloc_map); --i;)
210
    if (openrisc_reloc_map[i].bfd_reloc_val == code)
211
      return & openrisc_elf_howto_table[openrisc_reloc_map[i].
212
                                       openrisc_reloc_val];
213
 
214
  return NULL;
215
}
216
 
217
static reloc_howto_type *
218
openrisc_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
219
                            const char *r_name)
220
{
221
  unsigned int i;
222
 
223
  for (i = 0;
224
       i < (sizeof (openrisc_elf_howto_table)
225
            / sizeof (openrisc_elf_howto_table[0]));
226
       i++)
227
    if (openrisc_elf_howto_table[i].name != NULL
228
        && strcasecmp (openrisc_elf_howto_table[i].name, r_name) == 0)
229
      return &openrisc_elf_howto_table[i];
230
 
231
  return NULL;
232
}
233
 
234
/* Set the howto pointer for an OpenRISC ELF reloc.  */
235
 
236
static void
237
openrisc_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
238
                             arelent * cache_ptr,
239
                             Elf_Internal_Rela * dst)
240
{
241
  unsigned int r_type;
242
 
243
  r_type = ELF32_R_TYPE (dst->r_info);
244
  BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
245
  cache_ptr->howto = & openrisc_elf_howto_table[r_type];
246
}
247
 
248
/* Perform a single relocation.  By default we use the standard BFD
249
   routines, but a few relocs, we have to do them ourselves.  */
250
 
251
static bfd_reloc_status_type
252
openrisc_final_link_relocate (reloc_howto_type *howto,
253
                              bfd *input_bfd,
254
                              asection *input_section,
255
                              bfd_byte *contents,
256
                              Elf_Internal_Rela *rel,
257
                              bfd_vma relocation)
258
{
259
  bfd_reloc_status_type r = bfd_reloc_ok;
260
 
261
  switch (howto->type)
262
    {
263
    case R_OPENRISC_LO_16_IN_INSN:
264
      relocation &= 0xffff;
265
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
266
                                    contents, rel->r_offset,
267
                                    relocation, rel->r_addend);
268
      break;
269
 
270
    default:
271
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
272
                                    contents, rel->r_offset,
273
                                    relocation, rel->r_addend);
274
    }
275
 
276
  return r;
277
}
278
 
279
/* Relocate an OpenRISC ELF section.
280
 
281
   The RELOCATE_SECTION function is called by the new ELF backend linker
282
   to handle the relocations for a section.
283
 
284
   The relocs are always passed as Rela structures; if the section
285
   actually uses Rel structures, the r_addend field will always be
286
   zero.
287
 
288
   This function is responsible for adjusting the section contents as
289
   necessary, and (if using Rela relocs and generating a relocatable
290
   output file) adjusting the reloc addend as necessary.
291
 
292
   This function does not have to worry about setting the reloc
293
   address or the reloc symbol index.
294
 
295
   LOCAL_SYMS is a pointer to the swapped in local symbols.
296
 
297
   LOCAL_SECTIONS is an array giving the section in the input file
298
   corresponding to the st_shndx field of each local symbol.
299
 
300
   The global hash table entry for the global symbols can be found
301
   via elf_sym_hashes (input_bfd).
302
 
303
   When generating relocatable output, this function must handle
304
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
305
   going to be the section symbol corresponding to the output
306
   section, which means that the addend must be adjusted
307
   accordingly.  */
308
 
309
static bfd_boolean
310
openrisc_elf_relocate_section (bfd *output_bfd,
311
                               struct bfd_link_info *info,
312
                               bfd *input_bfd,
313
                               asection *input_section,
314
                               bfd_byte *contents,
315
                               Elf_Internal_Rela *relocs,
316
                               Elf_Internal_Sym *local_syms,
317
                               asection **local_sections)
318
{
319
  Elf_Internal_Shdr *symtab_hdr;
320
  struct elf_link_hash_entry **sym_hashes;
321
  Elf_Internal_Rela *rel;
322
  Elf_Internal_Rela *relend;
323
 
324
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
325
  sym_hashes = elf_sym_hashes (input_bfd);
326
  relend = relocs + input_section->reloc_count;
327
 
328
  for (rel = relocs; rel < relend; rel++)
329
    {
330
      reloc_howto_type *howto;
331
      unsigned long r_symndx;
332
      Elf_Internal_Sym *sym;
333
      asection *sec;
334
      struct elf_link_hash_entry *h;
335
      bfd_vma relocation;
336
      bfd_reloc_status_type r;
337
      const char *name = NULL;
338
      int r_type;
339
 
340
      r_type = ELF32_R_TYPE (rel->r_info);
341
      r_symndx = ELF32_R_SYM (rel->r_info);
342
 
343
      if (r_type == R_OPENRISC_GNU_VTINHERIT
344
          || r_type == R_OPENRISC_GNU_VTENTRY)
345
        continue;
346
 
347
      if ((unsigned int) r_type >
348
          (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
349
        abort ();
350
 
351
      howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
352
      h = NULL;
353
      sym = NULL;
354
      sec = NULL;
355
 
356
      if (r_symndx < symtab_hdr->sh_info)
357
        {
358
          sym = local_syms + r_symndx;
359
          sec = local_sections[r_symndx];
360
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
361
 
362
          name = bfd_elf_string_from_elf_section
363
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
364
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
365
        }
366
      else
367
        {
368
          bfd_boolean unresolved_reloc, warned;
369
 
370
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
371
                                   r_symndx, symtab_hdr, sym_hashes,
372
                                   h, sec, relocation,
373
                                   unresolved_reloc, warned);
374
        }
375
 
376
      if (sec != NULL && elf_discarded_section (sec))
377
        {
378
          /* For relocs against symbols from removed linkonce sections,
379
             or sections discarded by a linker script, we just want the
380
             section contents zeroed.  Avoid any special processing.  */
381
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
382
          rel->r_info = 0;
383
          rel->r_addend = 0;
384
          continue;
385
        }
386
 
387
      if (info->relocatable)
388
        continue;
389
 
390
      r = openrisc_final_link_relocate (howto, input_bfd, input_section,
391
                                        contents, rel, relocation);
392
 
393
      if (r != bfd_reloc_ok)
394
        {
395
          const char *msg = NULL;
396
 
397
          switch (r)
398
            {
399
            case bfd_reloc_overflow:
400
              r = info->callbacks->reloc_overflow
401
                (info, (h ? &h->root : NULL), name, howto->name,
402
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
403
              break;
404
 
405
            case bfd_reloc_undefined:
406
              r = info->callbacks->undefined_symbol
407
                (info, name, input_bfd, input_section, rel->r_offset, TRUE);
408
              break;
409
 
410
            case bfd_reloc_outofrange:
411
              msg = _("internal error: out of range error");
412
              break;
413
 
414
            case bfd_reloc_notsupported:
415
              msg = _("internal error: unsupported relocation error");
416
              break;
417
 
418
            case bfd_reloc_dangerous:
419
              msg = _("internal error: dangerous relocation");
420
              break;
421
 
422
            default:
423
              msg = _("internal error: unknown error");
424
              break;
425
            }
426
 
427
          if (msg)
428
            r = info->callbacks->warning
429
              (info, msg, name, input_bfd, input_section, rel->r_offset);
430
 
431
          if (!r)
432
            return FALSE;
433
        }
434
    }
435
 
436
  return TRUE;
437
}
438
 
439
/* Return the section that should be marked against GC for a given
440
   relocation.  */
441
 
442
static asection *
443
openrisc_elf_gc_mark_hook (asection *sec,
444
                           struct bfd_link_info *info,
445
                           Elf_Internal_Rela *rel,
446
                           struct elf_link_hash_entry *h,
447
                           Elf_Internal_Sym *sym)
448
{
449
  if (h != NULL)
450
    switch (ELF32_R_TYPE (rel->r_info))
451
      {
452
      case R_OPENRISC_GNU_VTINHERIT:
453
      case R_OPENRISC_GNU_VTENTRY:
454
        return NULL;
455
      }
456
 
457
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
458
}
459
 
460
/* Look through the relocs for a section during the first phase.
461
   Since we don't do .gots or .plts, we just need to consider the
462
   virtual table relocs for gc.  */
463
 
464
static bfd_boolean
465
openrisc_elf_check_relocs (bfd *abfd,
466
                           struct bfd_link_info *info,
467
                           asection *sec,
468
                           const Elf_Internal_Rela *relocs)
469
{
470
  Elf_Internal_Shdr *symtab_hdr;
471
  struct elf_link_hash_entry **sym_hashes;
472
  const Elf_Internal_Rela *rel;
473
  const Elf_Internal_Rela *rel_end;
474
 
475
  if (info->relocatable)
476
    return TRUE;
477
 
478
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
479
  sym_hashes = elf_sym_hashes (abfd);
480
 
481
  rel_end = relocs + sec->reloc_count;
482
  for (rel = relocs; rel < rel_end; rel++)
483
    {
484
      struct elf_link_hash_entry *h;
485
      unsigned long r_symndx;
486
 
487
      r_symndx = ELF32_R_SYM (rel->r_info);
488
      if (r_symndx < symtab_hdr->sh_info)
489
        h = NULL;
490
      else
491
        {
492
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
493
          while (h->root.type == bfd_link_hash_indirect
494
                 || h->root.type == bfd_link_hash_warning)
495
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
496
        }
497
 
498
      switch (ELF32_R_TYPE (rel->r_info))
499
        {
500
          /* This relocation describes the C++ object vtable hierarchy.
501
             Reconstruct it for later use during GC.  */
502
        case R_OPENRISC_GNU_VTINHERIT:
503
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
504
            return FALSE;
505
          break;
506
 
507
          /* This relocation describes which C++ vtable entries are actually
508
             used.  Record for later use during GC.  */
509
        case R_OPENRISC_GNU_VTENTRY:
510
          BFD_ASSERT (h != NULL);
511
          if (h != NULL
512
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
513
            return FALSE;
514
          break;
515
        }
516
    }
517
 
518
  return TRUE;
519
}
520
 
521
/* Set the right machine number.  */
522
 
523
static bfd_boolean
524
openrisc_elf_object_p (bfd *abfd)
525
{
526
  bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
527
  return TRUE;
528
}
529
 
530
/* Store the machine number in the flags field.  */
531
 
532
static void
533
openrisc_elf_final_write_processing (bfd *abfd,
534
                                     bfd_boolean linker ATTRIBUTE_UNUSED)
535
{
536
  unsigned long val;
537
 
538
  switch (bfd_get_mach (abfd))
539
    {
540
    default:
541
      val = 0;
542
      break;
543
    }
544
 
545
  elf_elfheader (abfd)->e_flags &= ~0xf;
546
  elf_elfheader (abfd)->e_flags |= val;
547
}
548
 
549
 
550
#define ELF_ARCH                        bfd_arch_openrisc
551
#define ELF_MACHINE_CODE                EM_OPENRISC
552
#define ELF_MACHINE_ALT1                EM_OPENRISC_OLD
553
#define ELF_MAXPAGESIZE                 0x1000
554
 
555
#define TARGET_BIG_SYM                  bfd_elf32_openrisc_vec
556
#define TARGET_BIG_NAME                 "elf32-openrisc"
557
 
558
#define elf_info_to_howto_rel           NULL
559
#define elf_info_to_howto               openrisc_info_to_howto_rela
560
#define elf_backend_relocate_section    openrisc_elf_relocate_section
561
#define elf_backend_gc_mark_hook        openrisc_elf_gc_mark_hook
562
#define elf_backend_check_relocs        openrisc_elf_check_relocs
563
 
564
#define elf_backend_can_gc_sections     1
565
#define elf_backend_rela_normal         1
566
 
567
#define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
568
#define bfd_elf32_bfd_reloc_name_lookup openrisc_reloc_name_lookup
569
 
570
#define elf_backend_object_p                openrisc_elf_object_p
571
#define elf_backend_final_write_processing  openrisc_elf_final_write_processing
572
 
573
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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