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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [bfd/] [elf32-or32.c] - Blame information for rev 856

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

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

powered by: WebSVN 2.1.0

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