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

Subversion Repositories open8_urisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* 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
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "libbfd.h"
25
#include "elf-bfd.h"
26
#include "elf/or32.h"
27
#include "libiberty.h"
28
 
29
/* Try to minimize the amount of space occupied by relocation tables
30
   on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
31
#define USE_REL 1
32
 
33
/* Set the right machine number for an OR32 ELF file.  */
34
 
35
static bfd_boolean
36
or32_elf_object_p (bfd *abfd)
37
{
38
  (void) bfd_default_set_arch_mach (abfd, bfd_arch_or32, 0);
39
  return TRUE;
40
}
41
 
42
/* The final processing done just before writing out an OR32 ELF object file.
43
   This gets the OR32 architecture right based on the machine number.  */
44
 
45
static void
46
or32_elf_final_write_processing (bfd *abfd,
47
                                 bfd_boolean linker ATTRIBUTE_UNUSED)
48
{
49
  elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
50
}
51
 
52
static bfd_reloc_status_type
53
or32_elf_32_reloc (bfd *abfd,
54
                   arelent *reloc_entry,
55
                   asymbol *symbol,
56
                   void * data,
57
                   asection *input_section,
58
                   bfd *output_bfd,
59
                   char **error_message ATTRIBUTE_UNUSED)
60
{
61
  if (output_bfd != NULL)
62
    {
63
      unsigned long insn;
64
      bfd_size_type addr = reloc_entry->address;
65
 
66
      reloc_entry->address += input_section->output_offset;
67
 
68
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
69
      insn += symbol->section->output_section->vma;
70
      insn += symbol->section->output_offset;
71
      insn += symbol->value;
72
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
73
 
74
      return bfd_reloc_ok;
75
    }
76
 
77
  return bfd_reloc_continue;
78
}
79
 
80
static bfd_reloc_status_type
81
or32_elf_16_reloc (bfd *abfd,
82
                   arelent *reloc_entry,
83
                   asymbol *symbol,
84
                   void * data,
85
                   asection *input_section,
86
                   bfd *output_bfd,
87
                   char **error_message ATTRIBUTE_UNUSED)
88
{
89
  if (output_bfd != NULL)
90
    {
91
      unsigned short insn;
92
      bfd_size_type addr = reloc_entry->address;
93
 
94
      reloc_entry->address += input_section->output_offset;
95
 
96
      insn = bfd_get_16 (abfd, (bfd_byte *) data + addr);
97
      insn += symbol->section->output_section->vma;
98
      insn += symbol->section->output_offset;
99
      insn += symbol->value;
100
      bfd_put_16 (abfd, insn, (bfd_byte *) data + addr);
101
 
102
      return bfd_reloc_ok;
103
    }
104
 
105
  return bfd_reloc_continue;
106
}
107
 
108
static bfd_reloc_status_type
109
or32_elf_8_reloc (bfd *abfd ATTRIBUTE_UNUSED,
110
                  arelent *reloc_entry,
111
                  asymbol *symbol,
112
                  void * data,
113
                  asection *input_section,
114
                  bfd *output_bfd,
115
                  char **error_message ATTRIBUTE_UNUSED)
116
{
117
  if (output_bfd != NULL)
118
    {
119
      unsigned char insn;
120
      bfd_size_type addr = reloc_entry->address;
121
 
122
      reloc_entry->address += input_section->output_offset;
123
 
124
      insn = bfd_get_8 (abfd, (bfd_byte *) data + addr);
125
      insn += symbol->section->output_section->vma;
126
      insn += symbol->section->output_offset;
127
      insn += symbol->value;
128
      bfd_put_8 (abfd, insn, (bfd_byte *) data + addr);
129
 
130
      return bfd_reloc_ok;
131
    }
132
 
133
  return bfd_reloc_continue;
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 *addr;
149
  bfd_vma addend;
150
};
151
 
152
/* FIXME: This should not be a static variable.  */
153
 
154
static struct or32_consth *or32_consth_list;
155
 
156
static bfd_reloc_status_type
157
or32_elf_consth_reloc (bfd *abfd ATTRIBUTE_UNUSED,
158
                       arelent *reloc_entry,
159
                       asymbol *symbol,
160
                       void * data,
161
                       asection *input_section,
162
                       bfd *output_bfd,
163
                       char **error_message ATTRIBUTE_UNUSED)
164
{
165
  bfd_reloc_status_type ret;
166
  bfd_vma relocation;
167
  struct or32_consth *n;
168
 
169
  ret = bfd_reloc_ok;
170
 
171
  if (bfd_is_und_section (symbol->section)
172
      && output_bfd == NULL)
173
    ret = bfd_reloc_undefined;
174
 
175
  if (bfd_is_com_section (symbol->section))
176
    relocation = 0;
177
  else
178
    relocation = symbol->value;
179
 
180
  relocation += symbol->section->output_section->vma;
181
  relocation += symbol->section->output_offset;
182
  relocation += reloc_entry->addend;
183
 
184
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
185
    return bfd_reloc_outofrange;
186
 
187
  /* Save the information, and let LO16 do the actual relocation.  */
188
  n = bfd_malloc (sizeof *n);
189
  if (n == NULL)
190
    return bfd_reloc_outofrange;
191
  n->addr = (bfd_byte *) data + reloc_entry->address;
192
  n->addend = relocation;
193
  n->next = or32_consth_list;
194
  or32_consth_list = n;
195
 
196
  if (output_bfd != NULL)
197
    reloc_entry->address += input_section->output_offset;
198
 
199
  return ret;
200
}
201
 
202
/* Do a R_OR32_CONST relocation.  This is a straightforward 16 bit
203
   inplace relocation; this function exists in order to do the
204
   R_OR32_CONSTH relocation described above.  */
205
 
206
static bfd_reloc_status_type
207
or32_elf_const_reloc (bfd *abfd,
208
                      arelent *reloc_entry,
209
                      asymbol *symbol,
210
                      void * data,
211
                      asection *input_section,
212
                      bfd *output_bfd,
213
                      char **error_message)
214
{
215
  if (or32_consth_list != NULL)
216
    {
217
      struct or32_consth *l;
218
 
219
      l = or32_consth_list;
220
      while (l != NULL)
221
        {
222
          unsigned long insn;
223
          unsigned long val;
224
          unsigned long vallo;
225
          struct or32_consth *next;
226
 
227
          /* Do the HI16 relocation.  Note that we actually don't need
228
             to know anything about the LO16 itself, except where to
229
             find the low 16 bits of the addend needed by the LO16.  */
230
          insn = bfd_get_32 (abfd, l->addr);
231
          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
232
                   & 0xffff);
233
          val = ((insn & 0xffff) << 16) + vallo;
234
          val += l->addend;
235
 
236
          insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
237
          bfd_put_32 (abfd, insn, l->addr);
238
 
239
          next = l->next;
240
          free (l);
241
          l = next;
242
        }
243
 
244
      or32_consth_list = NULL;
245
    }
246
 
247
  if (output_bfd != NULL)
248
    {
249
      unsigned long insn, tmp;
250
      bfd_size_type addr = reloc_entry->address;
251
 
252
      reloc_entry->address += input_section->output_offset;
253
 
254
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
255
      tmp = insn & 0x0000ffff;
256
      tmp += symbol->section->output_section->vma;
257
      tmp += symbol->section->output_offset;
258
      tmp += symbol->value;
259
      insn = (insn & 0xffff0000) | (tmp & 0x0000ffff);
260
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
261
 
262
      return bfd_reloc_ok;
263
    }
264
 
265
  /* Now do the LO16 reloc in the usual way.  */
266
  return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
267
                                input_section, output_bfd, error_message);
268
}
269
 
270
static bfd_reloc_status_type
271
or32_elf_jumptarg_reloc (bfd *abfd,
272
                         arelent *reloc_entry,
273
                         asymbol *symbol ATTRIBUTE_UNUSED,
274
                         void * data,
275
                         asection *input_section,
276
                         bfd *output_bfd,
277
                         char **error_message ATTRIBUTE_UNUSED)
278
{
279
  if (output_bfd != NULL)
280
    {
281
      unsigned long insn, tmp;
282
      bfd_size_type addr = reloc_entry->address;
283
 
284
      reloc_entry->address += input_section->output_offset;
285
 
286
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
287
      tmp = insn | 0xfc000000;
288
      tmp -= (input_section->output_offset >> 2);
289
      insn = (insn & 0xfc000000) | (tmp & 0x03ffffff);
290
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
291
 
292
      return bfd_reloc_ok;
293
    }
294
 
295
  return bfd_reloc_continue;
296
}
297
 
298
static reloc_howto_type elf_or32_howto_table[] =
299
{
300
  /* This reloc does nothing.  */
301
  HOWTO (R_OR32_NONE,           /* type */
302
         0,                      /* rightshift */
303
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
304
         32,                    /* bitsize */
305
         FALSE,                 /* pc_relative */
306
         0,                      /* bitpos */
307
         complain_overflow_bitfield, /* complain_on_overflow */
308
         bfd_elf_generic_reloc, /* special_function */
309
         "R_OR32_NONE",         /* name */
310
         FALSE,                 /* partial_inplace */
311
         0,                      /* src_mask */
312
         0,                      /* dst_mask */
313
         FALSE),                /* pcrel_offset */
314
 
315
  /* A standard 32 bit relocation.  */
316
  HOWTO (R_OR32_32,             /* type */
317
         0,                      /* rightshift */
318
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
319
         32,                    /* bitsize */
320
         FALSE,                 /* pc_relative */
321
         0,                      /* bitpos */
322
         complain_overflow_bitfield, /* complain_on_overflow */
323
         or32_elf_32_reloc,     /* special_function */
324
         "R_OR32_32",           /* name */
325
         FALSE,                 /* partial_inplace */
326
         0xffffffff,            /* src_mask */
327
         0xffffffff,            /* dst_mask */
328
         FALSE),                /* pcrel_offset */
329
 
330
  /* A standard 16 bit relocation.  */
331
  HOWTO (R_OR32_16,             /* type */
332
         0,                      /* rightshift */
333
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
334
         16,                    /* bitsize */
335
         FALSE,                 /* pc_relative */
336
         0,                      /* bitpos */
337
         complain_overflow_bitfield, /* complain_on_overflow */
338
         or32_elf_16_reloc,     /* special_function */
339
         "R_OR32_16",           /* name */
340
         FALSE,                 /* partial_inplace */
341
         0x0000ffff,            /* src_mask */
342
         0x0000ffff,            /* dst_mask */
343
         FALSE),                /* pcrel_offset */
344
 
345
  /* A standard 8 bit relocation.  */
346
  HOWTO (R_OR32_8,              /* type */
347
         0,                      /* rightshift */
348
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
349
         8,                     /* bitsize */
350
         FALSE,                 /* pc_relative */
351
         0,                      /* bitpos */
352
         complain_overflow_bitfield, /* complain_on_overflow */
353
         or32_elf_8_reloc,      /* special_function */
354
         "R_OR32_8",            /* name */
355
         FALSE,                 /* partial_inplace */
356
         0x000000ff,            /* src_mask */
357
         0x000000ff,            /* dst_mask */
358
         FALSE),                /* pcrel_offset */
359
 
360
  /* A standard low 16 bit relocation.  */
361
  HOWTO (R_OR32_CONST,          /* type */
362
         0,                      /* rightshift */
363
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
364
         16,                    /* bitsize */
365
         FALSE,                 /* pc_relative */
366
         0,                      /* bitpos */
367
         complain_overflow_dont, /* complain_on_overflow */
368
         or32_elf_const_reloc,  /* special_function */
369
         "R_OR32_CONST",        /* name */
370
         FALSE,                 /* partial_inplace */
371
         0x0000ffff,            /* src_mask */
372
         0x0000ffff,            /* dst_mask */
373
         FALSE),                /* pcrel_offset */
374
 
375
  /* A standard high 16 bit relocation.  */
376
  HOWTO (R_OR32_CONSTH,         /* type */
377
         16,                    /* rightshift */
378
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
379
         16,                    /* bitsize */
380
         TRUE,                  /* pc_relative */
381
         0,                      /* bitpos */
382
         complain_overflow_dont, /* complain_on_overflow */
383
         or32_elf_consth_reloc, /* special_function */
384
         "R_OR32_CONSTH",       /* name */
385
         FALSE,                 /* partial_inplace */
386
         0xffff0000,            /* src_mask */
387
         0x0000ffff,            /* dst_mask */
388
         FALSE),                /* pcrel_offset */
389
 
390
  /* A standard branch relocation.  */
391
  HOWTO (R_OR32_JUMPTARG,       /* type */
392
         2,                     /* rightshift */
393
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
394
         28,                    /* bitsize */
395
         TRUE,                  /* pc_relative */
396
         0,                      /* bitpos */
397
         complain_overflow_signed, /* complain_on_overflow */
398
         or32_elf_jumptarg_reloc,/* special_function */
399
         "R_OR32_JUMPTARG",     /* name */
400
         FALSE,                 /* partial_inplace */
401
         0,                      /* src_mask */
402
         0x03ffffff,            /* dst_mask */
403
         TRUE),                 /* pcrel_offset */
404
 
405
  /* GNU extension to record C++ vtable hierarchy.  */
406
  HOWTO (R_OR32_GNU_VTINHERIT, /* type */
407
         0,                     /* rightshift */
408
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
409
         0,                     /* bitsize */
410
         FALSE,                 /* pc_relative */
411
         0,                     /* bitpos */
412
         complain_overflow_dont, /* complain_on_overflow */
413
         NULL,                  /* special_function */
414
         "R_OR32_GNU_VTINHERIT", /* name */
415
         FALSE,                 /* partial_inplace */
416
         0,                     /* src_mask */
417
         0,                     /* dst_mask */
418
         FALSE),                /* pcrel_offset */
419
 
420
  /* GNU extension to record C++ vtable member usage.  */
421
  HOWTO (R_OR32_GNU_VTENTRY,     /* type */
422
         0,                     /* rightshift */
423
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
424
         0,                     /* bitsize */
425
         FALSE,                 /* pc_relative */
426
         0,                     /* bitpos */
427
         complain_overflow_dont, /* complain_on_overflow */
428
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
429
         "R_OR32_GNU_VTENTRY",   /* name */
430
         FALSE,                 /* partial_inplace */
431
         0,                     /* src_mask */
432
         0,                     /* dst_mask */
433
         FALSE),                /* pcrel_offset */
434
};
435
 
436
/* Map BFD reloc types to OR32 ELF reloc types.  */
437
 
438
struct or32_reloc_map
439
{
440
  bfd_reloc_code_real_type  bfd_reloc_val;
441
  unsigned char             elf_reloc_val;
442
};
443
 
444
static const struct or32_reloc_map or32_reloc_map[] =
445
{
446
  { BFD_RELOC_NONE, R_OR32_NONE },
447
  { BFD_RELOC_32, R_OR32_32 },
448
  { BFD_RELOC_16, R_OR32_16 },
449
  { BFD_RELOC_8, R_OR32_8 },
450
  { BFD_RELOC_LO16, R_OR32_CONST },
451
  { BFD_RELOC_HI16, R_OR32_CONSTH },
452
  { BFD_RELOC_32_GOT_PCREL, R_OR32_JUMPTARG },
453
  { BFD_RELOC_VTABLE_INHERIT, R_OR32_GNU_VTINHERIT },
454
  { BFD_RELOC_VTABLE_ENTRY, R_OR32_GNU_VTENTRY },
455
};
456
 
457
static reloc_howto_type *
458
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
459
                                 bfd_reloc_code_real_type code)
460
{
461
  unsigned int i;
462
 
463
  for (i = ARRAY_SIZE (or32_reloc_map); i--;)
464
    if (or32_reloc_map[i].bfd_reloc_val == code)
465
      return &elf_or32_howto_table[or32_reloc_map[i].elf_reloc_val];
466
 
467
  return NULL;
468
}
469
 
470
static reloc_howto_type *
471
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
472
                                 const char *r_name)
473
{
474
  unsigned int i;
475
 
476
  for (i = 0;
477
       i < sizeof (elf_or32_howto_table) / sizeof (elf_or32_howto_table[0]);
478
       i++)
479
    if (elf_or32_howto_table[i].name != NULL
480
        && strcasecmp (elf_or32_howto_table[i].name, r_name) == 0)
481
      return &elf_or32_howto_table[i];
482
 
483
  return NULL;
484
}
485
 
486
/* Set the howto pointer for an OR32 ELF reloc.  */
487
 
488
static void
489
or32_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
490
                        arelent *cache_ptr,
491
                        Elf_Internal_Rela *dst)
492
{
493
  unsigned int r_type;
494
 
495
  r_type = ELF32_R_TYPE (dst->r_info);
496
  BFD_ASSERT (r_type < (unsigned int) R_OR32_max);
497
  cache_ptr->howto = &elf_or32_howto_table[r_type];
498
}
499
 
500
#define TARGET_LITTLE_SYM       bfd_elf32_or32_little_vec
501
#define TARGET_LITTLE_NAME      "elf32-littleor32"
502
#define TARGET_BIG_SYM          bfd_elf32_or32_big_vec
503
#define TARGET_BIG_NAME         "elf32-or32"
504
#define ELF_ARCH                bfd_arch_or32
505
#define ELF_MACHINE_CODE        EM_OR32
506
#define ELF_MAXPAGESIZE         0x1000
507
 
508
#define elf_info_to_howto       0
509
#define elf_info_to_howto_rel   or32_info_to_howto_rel
510
#define elf_backend_object_p    or32_elf_object_p
511
#define elf_backend_final_write_processing \
512
                                or32_elf_final_write_processing
513
 
514
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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