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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elf32-openrisc.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* 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
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
378
                                         rel, relend, howto, contents);
379
 
380
      if (info->relocatable)
381
        continue;
382
 
383
      r = openrisc_final_link_relocate (howto, input_bfd, input_section,
384
                                        contents, rel, relocation);
385
 
386
      if (r != bfd_reloc_ok)
387
        {
388
          const char *msg = NULL;
389
 
390
          switch (r)
391
            {
392
            case bfd_reloc_overflow:
393
              r = info->callbacks->reloc_overflow
394
                (info, (h ? &h->root : NULL), name, howto->name,
395
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
396
              break;
397
 
398
            case bfd_reloc_undefined:
399
              r = info->callbacks->undefined_symbol
400
                (info, name, input_bfd, input_section, rel->r_offset, TRUE);
401
              break;
402
 
403
            case bfd_reloc_outofrange:
404
              msg = _("internal error: out of range error");
405
              break;
406
 
407
            case bfd_reloc_notsupported:
408
              msg = _("internal error: unsupported relocation error");
409
              break;
410
 
411
            case bfd_reloc_dangerous:
412
              msg = _("internal error: dangerous relocation");
413
              break;
414
 
415
            default:
416
              msg = _("internal error: unknown error");
417
              break;
418
            }
419
 
420
          if (msg)
421
            r = info->callbacks->warning
422
              (info, msg, name, input_bfd, input_section, rel->r_offset);
423
 
424
          if (!r)
425
            return FALSE;
426
        }
427
    }
428
 
429
  return TRUE;
430
}
431
 
432
/* Return the section that should be marked against GC for a given
433
   relocation.  */
434
 
435
static asection *
436
openrisc_elf_gc_mark_hook (asection *sec,
437
                           struct bfd_link_info *info,
438
                           Elf_Internal_Rela *rel,
439
                           struct elf_link_hash_entry *h,
440
                           Elf_Internal_Sym *sym)
441
{
442
  if (h != NULL)
443
    switch (ELF32_R_TYPE (rel->r_info))
444
      {
445
      case R_OPENRISC_GNU_VTINHERIT:
446
      case R_OPENRISC_GNU_VTENTRY:
447
        return NULL;
448
      }
449
 
450
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
451
}
452
 
453
/* Look through the relocs for a section during the first phase.
454
   Since we don't do .gots or .plts, we just need to consider the
455
   virtual table relocs for gc.  */
456
 
457
static bfd_boolean
458
openrisc_elf_check_relocs (bfd *abfd,
459
                           struct bfd_link_info *info,
460
                           asection *sec,
461
                           const Elf_Internal_Rela *relocs)
462
{
463
  Elf_Internal_Shdr *symtab_hdr;
464
  struct elf_link_hash_entry **sym_hashes;
465
  const Elf_Internal_Rela *rel;
466
  const Elf_Internal_Rela *rel_end;
467
 
468
  if (info->relocatable)
469
    return TRUE;
470
 
471
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
472
  sym_hashes = elf_sym_hashes (abfd);
473
 
474
  rel_end = relocs + sec->reloc_count;
475
  for (rel = relocs; rel < rel_end; rel++)
476
    {
477
      struct elf_link_hash_entry *h;
478
      unsigned long r_symndx;
479
 
480
      r_symndx = ELF32_R_SYM (rel->r_info);
481
      if (r_symndx < symtab_hdr->sh_info)
482
        h = NULL;
483
      else
484
        {
485
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
486
          while (h->root.type == bfd_link_hash_indirect
487
                 || h->root.type == bfd_link_hash_warning)
488
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
489
        }
490
 
491
      switch (ELF32_R_TYPE (rel->r_info))
492
        {
493
          /* This relocation describes the C++ object vtable hierarchy.
494
             Reconstruct it for later use during GC.  */
495
        case R_OPENRISC_GNU_VTINHERIT:
496
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
497
            return FALSE;
498
          break;
499
 
500
          /* This relocation describes which C++ vtable entries are actually
501
             used.  Record for later use during GC.  */
502
        case R_OPENRISC_GNU_VTENTRY:
503
          BFD_ASSERT (h != NULL);
504
          if (h != NULL
505
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
506
            return FALSE;
507
          break;
508
        }
509
    }
510
 
511
  return TRUE;
512
}
513
 
514
/* Set the right machine number.  */
515
 
516
static bfd_boolean
517
openrisc_elf_object_p (bfd *abfd)
518
{
519
  bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
520
  return TRUE;
521
}
522
 
523
/* Store the machine number in the flags field.  */
524
 
525
static void
526
openrisc_elf_final_write_processing (bfd *abfd,
527
                                     bfd_boolean linker ATTRIBUTE_UNUSED)
528
{
529
  unsigned long val;
530
 
531
  switch (bfd_get_mach (abfd))
532
    {
533
    default:
534
      val = 0;
535
      break;
536
    }
537
 
538
  elf_elfheader (abfd)->e_flags &= ~0xf;
539
  elf_elfheader (abfd)->e_flags |= val;
540
}
541
 
542
 
543
#define ELF_ARCH                        bfd_arch_openrisc
544
#define ELF_MACHINE_CODE                EM_OPENRISC
545
#define ELF_MACHINE_ALT1                EM_OPENRISC_OLD
546
#define ELF_MAXPAGESIZE                 0x1000
547
 
548
#define TARGET_BIG_SYM                  bfd_elf32_openrisc_vec
549
#define TARGET_BIG_NAME                 "elf32-openrisc"
550
 
551
#define elf_info_to_howto_rel           NULL
552
#define elf_info_to_howto               openrisc_info_to_howto_rela
553
#define elf_backend_relocate_section    openrisc_elf_relocate_section
554
#define elf_backend_gc_mark_hook        openrisc_elf_gc_mark_hook
555
#define elf_backend_check_relocs        openrisc_elf_check_relocs
556
 
557
#define elf_backend_can_gc_sections     1
558
#define elf_backend_rela_normal         1
559
 
560
#define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
561
#define bfd_elf32_bfd_reloc_name_lookup openrisc_reloc_name_lookup
562
 
563
#define elf_backend_object_p                openrisc_elf_object_p
564
#define elf_backend_final_write_processing  openrisc_elf_final_write_processing
565
 
566
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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