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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [bfd/] [elf32-or32.c] - Blame information for rev 827

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

Line No. Rev Author Line
1 205 julius
/* OR32-specific support for 32-bit ELF
2
   Copyright 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
3 399 jeremybenn
   Copyright (C) 2010 Embecosm Limited
4 205 julius
   Contributed by Ivan Guzvinec  <ivang@opencores.org>
5
   Modified by Gyorgy Jeney <nog@sdf.lonestar.org> and
6
   Balint Cristian <rezso@rdsor.ro>
7 399 jeremybenn
   Changed from Rel to Rela by Joern Rennecke <joern.rennecke@embecosm.com>.
8 205 julius
 
9
   This file is part of BFD, the Binary File Descriptor library.
10
 
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3 of the License, or
14
   (at your option) any later version.
15
 
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with this program; if not, write to the Free Software
23
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24
   MA 02110-1301, USA.  */
25
 
26
#include "sysdep.h"
27
#include "bfd.h"
28
#include "libbfd.h"
29
#include "elf-bfd.h"
30
#include "elf/or32.h"
31
#include "elf/common.h"
32
#include "libiberty.h"
33
 
34 399 jeremybenn
/* We need RELA in order to handle highpart relocations independent of
35
   the presence and/or location and/or value of a lowpart relocation.  */
36
#if 0
37 205 julius
/* Try to minimize the amount of space occupied by relocation tables
38
   on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
39
#define USE_REL 1
40 399 jeremybenn
#endif
41 205 julius
 
42
/* Set the right machine number for an OR32 ELF file.  */
43
 
44
static bfd_boolean
45
or32_elf_object_p (bfd *abfd)
46
{
47
  (void) bfd_default_set_arch_mach (abfd, bfd_arch_or32, 0);
48
  return TRUE;
49
}
50
 
51
/* The final processing done just before writing out an OR32 ELF object file.
52
   This gets the OR32 architecture right based on the machine number.  */
53
 
54
static void
55
or32_elf_final_write_processing (bfd *abfd,
56
                                 bfd_boolean linker ATTRIBUTE_UNUSED)
57
{
58
        /* Pad the output file so that the aligned reloc section addresses aren't
59
         * outside the file */
60
        unsigned long zero = 0;
61
  if (bfd_seek (abfd, elf_tdata (abfd)->next_file_pos, SEEK_SET) != 0
62
      || bfd_bwrite (&zero, sizeof(zero), abfd) != sizeof(zero))
63
    (*_bfd_error_handler) (_("%B: failed to ensure that reloc sections aren't outside file"), abfd);
64
 
65
  elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
66
}
67
 
68 399 jeremybenn
#if 0 /* Not needed for RELA.  */
69 205 julius
static bfd_reloc_status_type
70
or32_elf_generic_reloc (bfd *abfd,
71
                   arelent *reloc_entry,
72
                   asymbol *symbol,
73
                   void * data,
74
                   asection *input_section,
75
                   bfd *output_bfd,
76
                   char **error_message ATTRIBUTE_UNUSED)
77
{
78
  bfd_signed_vma val;
79
  bfd_reloc_status_type status;
80
  bfd_boolean relocatable;
81
 
82
  if (bfd_is_und_section (symbol->section) /*RGD fix linker undefined miss*/
83
      && output_bfd == (bfd *) NULL)
84
    return bfd_reloc_undefined;
85
 
86
  relocatable = (output_bfd != NULL);
87
 
88
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
89
    return bfd_reloc_outofrange;
90
 
91
  /* Build up the field adjustment in VAL.  */
92
  val = 0;
93
  if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
94
  {
95
    /* Either we're calculating the final field value or we have a
96
       relocation against a section symbol.  Add in the section's
97
       offset or address.  */
98
    val += symbol->section->output_section->vma;
99
    val += symbol->section->output_offset;
100
  }
101
 
102
  if (!relocatable)
103
  {
104
    /* We're calculating the final field value.  Add in the symbol's value
105
             and, if pc-relative, subtract the address of the field itself.  */
106
    val += symbol->value;
107
    if (reloc_entry->howto->pc_relative)
108
      val -= input_section->output_section->vma;
109
  }
110
 
111
  if (reloc_entry->howto->pc_relative)
112
    val -= input_section->output_offset;
113
  /* VAL is now the final adjustment.  If we're keeping this relocation
114
     in the output file, and if the relocation uses a separate addend,
115
     we just need to add VAL to that addend.  Otherwise we need to add
116
     VAL to the relocation field itself.  */
117
  if (relocatable && !reloc_entry->howto->partial_inplace)
118
    reloc_entry->addend += val;
119
  else
120
  {
121
    /* Add in the separate addend, if any.  */
122
    val += reloc_entry->addend;
123
    /* Add VAL to the relocation field.  */
124
    status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
125
                                     (bfd_byte *) data
126
                                     + reloc_entry->address);
127
    if (status != bfd_reloc_ok)
128
      return status;
129
  }
130
  if (relocatable)
131
    reloc_entry->address += input_section->output_offset;
132
 
133
  return bfd_reloc_ok;
134
}
135
 
136
/* Do a R_OR32_CONSTH relocation.  This has to be done in combination
137
   with a R_OR32_CONST reloc, because there is a carry from the LO16 to
138
   the HI16.  Here we just save the information we need; we do the
139
   actual relocation when we see the LO16.  OR32 ELF requires that the
140
   LO16 immediately follow the HI16.  As a GNU extension, we permit an
141
   arbitrary number of HI16 relocs to be associated with a single LO16
142
   reloc.  This extension permits gcc to output the HI and LO relocs
143
   itself. This code is copied from the elf32-mips.c.  */
144
 
145
struct or32_consth
146
{
147
  struct or32_consth *next;
148
  bfd_byte *data;
149
  asection *input_section;
150
  arelent rel;
151
};
152
 
153
/* FIXME: This should not be a static variable.  */
154
 
155
static struct or32_consth *or32_consth_list;
156
 
157
static bfd_reloc_status_type
158
or32_elf_consth_reloc (bfd *abfd ATTRIBUTE_UNUSED,
159
                       arelent *reloc_entry,
160
                       asymbol *symbol ATTRIBUTE_UNUSED,
161
                       void * data,
162
                       asection *input_section,
163
                       bfd *output_bfd,
164
                       char **error_message ATTRIBUTE_UNUSED)
165
{
166
  struct or32_consth *n;
167
 
168
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
169
    return bfd_reloc_outofrange;
170
 
171
  /* Save the information, and let LO16 do the actual relocation.  */
172
  n = bfd_malloc (sizeof *n);
173
  if (n == NULL)
174
    return bfd_reloc_outofrange;
175
 
176
  /* Push this reloc on the list of pending relocations */
177
  n->next = or32_consth_list;
178
  n->data = data;
179
  n->input_section = input_section;
180
  n->rel = *reloc_entry;
181
  or32_consth_list = n;
182
 
183
  if (output_bfd != NULL)
184
    reloc_entry->address += input_section->output_offset;
185
 
186
  return bfd_reloc_ok;
187
}
188
 
189
/* Do a R_OR32_CONST relocation.  This is a straightforward 16 bit
190
   inplace relocation; this function exists in order to do the
191
   R_OR32_CONSTH relocation described above.  */
192
 
193
static bfd_reloc_status_type
194
or32_elf_const_reloc (bfd *abfd,
195
                      arelent *reloc_entry,
196
                      asymbol *symbol,
197
                      void * data,
198
                      asection *input_section,
199
                      bfd *output_bfd,
200
                      char **error_message)
201
{
202
  bfd_vma vallo;
203
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
204
    return bfd_reloc_outofrange;
205
  vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address) & 0xffff;
206
  while (or32_consth_list != NULL)
207
  {
208
    bfd_reloc_status_type ret;
209
    struct or32_consth *hi;
210
 
211
    hi = or32_consth_list;
212
 
213
    /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
214
       carry or borrow will induce a change of +1 or -1 in the high part.  */
215
    hi->rel.addend += vallo;
216
 
217
    ret = or32_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
218
                                   hi->input_section, output_bfd,
219
                                   error_message);
220
    if (ret != bfd_reloc_ok)
221
      return ret;
222
 
223
    or32_consth_list = hi->next;
224
    free (hi);
225
  }
226
  return or32_elf_generic_reloc (abfd, reloc_entry, symbol, data,
227
                                  input_section, output_bfd,
228
                                  error_message);
229
}
230 399 jeremybenn
#endif
231 205 julius
 
232
 
233
static reloc_howto_type elf_or32_howto_table[] =
234
{
235
  /* This reloc does nothing.  */
236
  HOWTO (R_OR32_NONE,           /* type */
237
         0,                      /* rightshift */
238
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
239
         32,                    /* bitsize */
240
         FALSE,                 /* pc_relative */
241
         0,                      /* bitpos */
242
         complain_overflow_bitfield, /* complain_on_overflow */
243
         bfd_elf_generic_reloc, /* special_function */
244
         "R_OR32_NONE",         /* name */
245
         FALSE,                 /* partial_inplace */
246
         0,                      /* src_mask */
247
         0,                      /* dst_mask */
248
         FALSE),                /* pcrel_offset */
249
 
250
  /* A standard 32 bit relocation.  */
251
  HOWTO (R_OR32_32,             /* type */
252
         0,                      /* rightshift */
253
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
254
         32,                    /* bitsize */
255
         FALSE,                 /* pc_relative */
256
         0,                      /* bitpos */
257
         complain_overflow_bitfield, /* complain_on_overflow */
258 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
259 205 julius
         "R_OR32_32",           /* name */
260 399 jeremybenn
         FALSE,                 /* partial_inplace */
261
         0,                      /* src_mask */
262 205 julius
         0xffffffff,            /* dst_mask */
263
         FALSE),                /* pcrel_offset */
264
 
265
  /* A standard 16 bit relocation.  */
266
  HOWTO (R_OR32_16,             /* type */
267
         0,                      /* rightshift */
268
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
269
         16,                    /* bitsize */
270
         FALSE,                 /* pc_relative */
271
         0,                      /* bitpos */
272
         complain_overflow_bitfield, /* complain_on_overflow */
273 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
274 205 julius
         "R_OR32_16",           /* name */
275 399 jeremybenn
         FALSE,                 /* partial_inplace */
276
         0,                      /* src_mask */
277 205 julius
         0x0000ffff,            /* dst_mask */
278
         FALSE),                /* pcrel_offset */
279
 
280
  /* A standard 8 bit relocation.  */
281
  HOWTO (R_OR32_8,              /* type */
282
         0,                      /* rightshift */
283
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
284
         8,                     /* bitsize */
285
         FALSE,                 /* pc_relative */
286
         0,                      /* bitpos */
287
         complain_overflow_bitfield, /* complain_on_overflow */
288 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
289 205 julius
         "R_OR32_8",            /* name */
290 399 jeremybenn
         FALSE,                 /* partial_inplace */
291
         0,                      /* src_mask */
292 205 julius
         0x000000ff,            /* dst_mask */
293
         FALSE),                /* pcrel_offset */
294
 
295
  /* A standard low 16 bit relocation.  */
296
  HOWTO (R_OR32_CONST,          /* type */
297
         0,                      /* rightshift */
298
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
299
         16,                    /* bitsize */
300
         FALSE,                 /* pc_relative */
301
         0,                      /* bitpos */
302
         complain_overflow_dont, /* complain_on_overflow */
303 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
304 205 julius
         "R_OR32_CONST",        /* name */
305 399 jeremybenn
         FALSE,                 /* partial_inplace */
306
         0,                      /* src_mask */
307 205 julius
         0x0000ffff,            /* dst_mask */
308
         FALSE),                /* pcrel_offset */
309
 
310
  /* A standard high 16 bit relocation.  */
311
  HOWTO (R_OR32_CONSTH,         /* type */
312
         16,                    /* rightshift */
313
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
314
         16,                    /* bitsize */
315
         FALSE,                 /* pc_relative */
316
         0,                      /* bitpos */
317
         complain_overflow_dont, /* complain_on_overflow */
318 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
319 205 julius
         "R_OR32_CONSTH",       /* name */
320 399 jeremybenn
         FALSE,                 /* partial_inplace */
321
         0,                      /* src_mask */
322 205 julius
         0x0000ffff,            /* dst_mask */
323
         FALSE),                /* pcrel_offset */
324
 
325
  /* A standard branch relocation.  */
326
  HOWTO (R_OR32_JUMPTARG,       /* type */
327
         2,                     /* rightshift */
328
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
329
         28,                    /* bitsize */
330
         TRUE,                  /* pc_relative */
331
         0,                      /* bitpos */
332
         complain_overflow_dont, /* complain_on_overflow */
333 399 jeremybenn
         bfd_elf_generic_reloc, /* special_function */
334 205 julius
         "R_OR32_JUMPTARG",     /* name */
335 399 jeremybenn
         FALSE,                 /* partial_inplace */
336
         0,                      /* src_mask */
337 205 julius
         0x03ffffff,            /* dst_mask */
338 413 jeremybenn
         TRUE),                 /* pcrel_offset */
339 205 julius
 
340
  /* GNU extension to record C++ vtable hierarchy.  */
341
  HOWTO (R_OR32_GNU_VTINHERIT, /* type */
342
         0,                     /* rightshift */
343
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
344
         0,                     /* bitsize */
345
         FALSE,                 /* pc_relative */
346
         0,                     /* bitpos */
347
         complain_overflow_dont, /* complain_on_overflow */
348
         NULL,                  /* special_function */
349
         "R_OR32_GNU_VTINHERIT", /* name */
350
         FALSE,                 /* partial_inplace */
351
         0,                     /* src_mask */
352
         0,                     /* dst_mask */
353
         FALSE),                /* pcrel_offset */
354
 
355
  /* GNU extension to record C++ vtable member usage.  */
356
  HOWTO (R_OR32_GNU_VTENTRY,     /* type */
357
         0,                     /* rightshift */
358
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
359
         0,                     /* bitsize */
360
         FALSE,                 /* pc_relative */
361
         0,                     /* bitpos */
362
         complain_overflow_dont, /* complain_on_overflow */
363
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
364
         "R_OR32_GNU_VTENTRY",   /* name */
365
         FALSE,                 /* partial_inplace */
366
         0,                     /* src_mask */
367
         0,                     /* dst_mask */
368
         FALSE),                /* pcrel_offset */
369
};
370
 
371 399 jeremybenn
static bfd_boolean
372
or32_relocate_section (bfd * output_bfd,
373
                       struct bfd_link_info *info,
374
                       bfd * input_bfd,
375
                       asection * input_section,
376
                       bfd_byte * contents,
377
                       Elf_Internal_Rela * relocs,
378
                       Elf_Internal_Sym * local_syms,
379
                       asection ** local_sections)
380
{
381
  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
382
  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
383
  Elf_Internal_Rela *rel= rel = relocs;
384
  Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
385
 
386
  for (; rel < relend; rel++)
387
    {
388
      int r_type = ELF32_R_TYPE (rel->r_info);
389
      reloc_howto_type *howto;
390
      unsigned long r_symndx;
391
      struct elf_link_hash_entry *h = NULL;
392
      Elf_Internal_Sym *sym = NULL;
393
      asection *sec = NULL;
394
      bfd_vma relocation = 0;
395
      bfd_reloc_status_type r;
396
      const char *name = NULL;
397
 
398
      if ((unsigned) r_type >= ARRAY_SIZE (elf_or32_howto_table))
399
        {
400
          bfd_set_error (bfd_error_bad_value);
401
          return FALSE;
402
        }
403
 
404
      if (r_type == R_OR32_GNU_VTENTRY
405
          || r_type == R_OR32_GNU_VTINHERIT)
406
        continue;
407
 
408
      howto = &elf_or32_howto_table[r_type];
409
      r_symndx = ELF32_R_SYM (rel->r_info);
410
 
411
      if (r_symndx < symtab_hdr->sh_info)
412
        {
413
          sym = local_syms + r_symndx;
414
          sec = local_sections[r_symndx];
415
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
416
 
417
          name = bfd_elf_string_from_elf_section
418
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
419
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
420
        }
421
      else
422
        {
423
          bfd_boolean unresolved_reloc, warned;
424
 
425
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
426
                                   r_symndx, symtab_hdr, sym_hashes,
427
                                   h, sec, relocation,
428
                                   unresolved_reloc, warned);
429
        }
430
 
431
      if (sec != NULL && elf_discarded_section (sec))
432
        {
433
          /* For relocs against symbols from removed linkonce sections,
434
             or sections discarded by a linker script, we just want the
435
             section contents zeroed.  Avoid any special processing.  */
436
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
437
          rel->r_info = 0;
438
          rel->r_addend = 0;
439
          continue;
440
        }
441
 
442
      if (info->relocatable)
443
        continue;
444
 
445
      r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
446
                                    rel->r_offset, relocation, rel->r_addend);
447
      if (r != bfd_reloc_ok)
448
        {
449
          const char *msg = NULL;
450
 
451
          switch (r)
452
            {
453
            /* FIXME: give useful messages for possible errors.  */
454
            default:
455
              msg = _("internal error: unknown error");
456
              break;
457
            }
458
          if (msg)
459
            r = info->callbacks->warning
460
              (info, msg, name, input_bfd, input_section, rel->r_offset);
461
 
462
          if (!r)
463
            return FALSE;
464
        }
465
    }
466
  return TRUE;
467
}
468
 
469 205 julius
/* Map BFD reloc types to OR32 ELF reloc types.  */
470
 
471
struct or32_reloc_map
472
{
473
  bfd_reloc_code_real_type  bfd_reloc_val;
474
  unsigned char             elf_reloc_val;
475
};
476
 
477
static const struct or32_reloc_map or32_reloc_map[] =
478
{
479
  { BFD_RELOC_NONE, R_OR32_NONE },
480
  { BFD_RELOC_32, R_OR32_32 },
481
  { BFD_RELOC_16, R_OR32_16 },
482
  { BFD_RELOC_8, R_OR32_8 },
483
  { BFD_RELOC_LO16, R_OR32_CONST },
484
  { BFD_RELOC_HI16, R_OR32_CONSTH },
485
  { BFD_RELOC_28_PCREL_S2, R_OR32_JUMPTARG },
486
  { BFD_RELOC_VTABLE_INHERIT, R_OR32_GNU_VTINHERIT },
487
  { BFD_RELOC_VTABLE_ENTRY, R_OR32_GNU_VTENTRY },
488
};
489
 
490
static reloc_howto_type *
491
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
492
                                 bfd_reloc_code_real_type code)
493
{
494
  unsigned int i;
495
 
496
  for (i = ARRAY_SIZE (or32_reloc_map); i--;)
497
    if (or32_reloc_map[i].bfd_reloc_val == code)
498
      return &elf_or32_howto_table[or32_reloc_map[i].elf_reloc_val];
499
 
500
  return NULL;
501
}
502
 
503
static reloc_howto_type *
504
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
505
                                 const char *r_name)
506
{
507
  unsigned int i;
508
 
509
  for (i = 0;
510
       i < sizeof (elf_or32_howto_table) / sizeof (elf_or32_howto_table[0]);
511
       i++)
512
    if (elf_or32_howto_table[i].name != NULL
513
        && strcasecmp (elf_or32_howto_table[i].name, r_name) == 0)
514
      return &elf_or32_howto_table[i];
515
 
516
  return NULL;
517
}
518
 
519
/* Set the howto pointer for an OR32 ELF reloc.  */
520
 
521
static void
522
or32_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
523
                        arelent *cache_ptr,
524
                        Elf_Internal_Rela *dst)
525
{
526
  unsigned int r_type;
527
 
528
  r_type = ELF32_R_TYPE (dst->r_info);
529
  BFD_ASSERT (r_type < (unsigned int) R_OR32_max);
530
  cache_ptr->howto = &elf_or32_howto_table[r_type];
531
 
532
  asymbol *s = *(cache_ptr->sym_ptr_ptr);
533
  if (ELF32_R_SYM(dst->r_info) && (s->flags & BSF_SECTION_SYM))
534
    cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
535
}
536
 
537
#define TARGET_LITTLE_SYM       bfd_elf32_or32_little_vec
538
#define TARGET_LITTLE_NAME      "elf32-littleor32"
539
#define TARGET_BIG_SYM          bfd_elf32_or32_big_vec
540
#define TARGET_BIG_NAME         "elf32-or32"
541
#define ELF_ARCH                bfd_arch_or32
542
#define ELF_MACHINE_CODE        EM_OPENRISC
543
#define ELF_MACHINE_ALT1        EM_OR32
544
#define ELF_MAXPAGESIZE         0x2000
545
 
546
#define elf_info_to_howto       0
547
#define elf_info_to_howto_rel   or32_info_to_howto_rel
548
#define elf_backend_object_p    or32_elf_object_p
549
#define elf_backend_final_write_processing \
550
                                or32_elf_final_write_processing
551 399 jeremybenn
#define elf_backend_rela_normal 1
552
#define elf_backend_relocate_section or32_relocate_section
553 205 julius
 
554
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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