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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [bfd/] [elf32-or32.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* OR32-specific support for 32-bit ELF
2
   Copyright (C) 2002 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "bfd.h"
22
#include "sysdep.h"
23
#include "libbfd.h"
24
#include "elf-bfd.h"
25
#include "elf/or32.h"
26
#include "libiberty.h"
27
 
28
static reloc_howto_type *     bfd_elf32_bfd_reloc_type_lookup  PARAMS ((bfd *, bfd_reloc_code_real_type));
29
static void                   or32_info_to_howto_rel           PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
30
static boolean                or32_elf_object_p                PARAMS ((bfd *));
31
static void                   or32_elf_final_write_processing  PARAMS ((bfd *, boolean));
32
static bfd_reloc_status_type  or32_elf_32_reloc                PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
33
static bfd_reloc_status_type  or32_elf_16_reloc                PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
34
static bfd_reloc_status_type  or32_elf_8_reloc                 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
35
static bfd_reloc_status_type  or32_elf_const_reloc             PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36
static bfd_reloc_status_type  or32_elf_consth_reloc            PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
37
static bfd_reloc_status_type  or32_elf_jumptarg_reloc          PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38
 
39
/* Try to minimize the amount of space occupied by relocation tables
40
   on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
41
#define USE_REL
42
 
43
static reloc_howto_type elf_or32_howto_table[] =
44
{
45
  /* This reloc does nothing.  */
46
  HOWTO (R_OR32_NONE,           /* type */
47
         0,                      /* rightshift */
48
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
49
         32,                    /* bitsize */
50
         false,                 /* pc_relative */
51
         0,                      /* bitpos */
52
         complain_overflow_bitfield, /* complain_on_overflow */
53
         bfd_elf_generic_reloc, /* special_function */
54
         "R_OR32_NONE",         /* name */
55
         false,                 /* partial_inplace */
56
         0,                      /* src_mask */
57
         0,                      /* dst_mask */
58
         false),                /* pcrel_offset */
59
 
60
  /* A standard 32 bit relocation.  */
61
  HOWTO (R_OR32_32,             /* type */
62
         0,                      /* rightshift */
63
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
64
         32,                    /* bitsize */
65
         false,                 /* pc_relative */
66
         0,                      /* bitpos */
67
         complain_overflow_bitfield, /* complain_on_overflow */
68
         or32_elf_32_reloc,     /* special_function */
69
         "R_OR32_32",           /* name */
70
         false,                 /* partial_inplace */
71
         0xffffffff,            /* src_mask */
72
         0xffffffff,            /* dst_mask */
73
         false),                /* pcrel_offset */
74
 
75
  /* A standard 16 bit relocation.  */
76
  HOWTO (R_OR32_16,             /* type */
77
         0,                      /* rightshift */
78
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
79
         16,                    /* bitsize */
80
         false,                 /* pc_relative */
81
         0,                      /* bitpos */
82
         complain_overflow_bitfield, /* complain_on_overflow */
83
         or32_elf_16_reloc,     /* special_function */
84
         "R_OR32_16",           /* name */
85
         false,                 /* partial_inplace */
86
         0x0000ffff,            /* src_mask */
87
         0x0000ffff,            /* dst_mask */
88
         false),                /* pcrel_offset */
89
 
90
  /* A standard 8 bit relocation.  */
91
  HOWTO (R_OR32_8,              /* type */
92
         0,                      /* rightshift */
93
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
94
         8,                     /* bitsize */
95
         false,                 /* pc_relative */
96
         0,                      /* bitpos */
97
         complain_overflow_bitfield, /* complain_on_overflow */
98
         or32_elf_8_reloc,      /* special_function */
99
         "R_OR32_8",            /* name */
100
         false,                 /* partial_inplace */
101
         0x000000ff,            /* src_mask */
102
         0x000000ff,            /* dst_mask */
103
         false),                /* pcrel_offset */
104
 
105
  /* A standard low 16 bit relocation.  */
106
  HOWTO (R_OR32_CONST,          /* type */
107
         0,                      /* rightshift */
108
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
109
         16,                    /* bitsize */
110
         false,                 /* pc_relative */
111
         0,                      /* bitpos */
112
         complain_overflow_dont, /* complain_on_overflow */
113
         or32_elf_const_reloc,  /* special_function */
114
         "R_OR32_CONST",        /* name */
115
         false,                 /* partial_inplace */
116
         0x0000ffff,            /* src_mask */
117
         0x0000ffff,            /* dst_mask */
118
         false),                /* pcrel_offset */
119
 
120
  /* A standard high 16 bit relocation.  */
121
  HOWTO (R_OR32_CONSTH,         /* type */
122
         16,                    /* rightshift */
123
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
124
         16,                    /* bitsize */
125
         true,                  /* pc_relative */
126
         0,                      /* bitpos */
127
         complain_overflow_dont, /* complain_on_overflow */
128
         or32_elf_consth_reloc, /* special_function */
129
         "R_OR32_CONSTH",       /* name */
130
         false,                 /* partial_inplace */
131
         0xffff0000,            /* src_mask */
132
         0x0000ffff,            /* dst_mask */
133
         false),                /* pcrel_offset */
134
 
135
  /* A standard branch relocation.  */
136
  HOWTO (R_OR32_JUMPTARG,       /* type */
137
         2,                     /* rightshift */
138
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
139
         28,                    /* bitsize */
140
         true,                  /* pc_relative */
141
         0,                      /* bitpos */
142
         complain_overflow_signed, /* complain_on_overflow */
143
         or32_elf_jumptarg_reloc,/* special_function */
144
         "R_OR32_JUMPTARG",     /* name */
145
         false,                 /* partial_inplace */
146
         0,                      /* src_mask */
147
         0x03ffffff,            /* dst_mask */
148
         true),                 /* pcrel_offset */
149
 
150
  /* GNU extension to record C++ vtable hierarchy.  */
151
  HOWTO (R_OR32_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_OR32_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_OR32_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_OR32_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 OR32 ELF reloc types.  */
182
 
183
struct or32_reloc_map
184
{
185
  bfd_reloc_code_real_type  bfd_reloc_val;
186
  unsigned char             elf_reloc_val;
187
};
188
 
189
static const struct or32_reloc_map or32_reloc_map[] =
190
{
191
  { BFD_RELOC_NONE, R_OR32_NONE },
192
  { BFD_RELOC_32, R_OR32_32 },
193
  { BFD_RELOC_16, R_OR32_16 },
194
  { BFD_RELOC_8, R_OR32_8 },
195
  { BFD_RELOC_LO16, R_OR32_CONST },
196
  { BFD_RELOC_HI16, R_OR32_CONSTH },
197
  { BFD_RELOC_32_GOT_PCREL, R_OR32_JUMPTARG },
198
  { BFD_RELOC_VTABLE_INHERIT, R_OR32_GNU_VTINHERIT },
199
  { BFD_RELOC_VTABLE_ENTRY, R_OR32_GNU_VTENTRY },
200
};
201
 
202
static reloc_howto_type *
203
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
204
     bfd *abfd ATTRIBUTE_UNUSED;
205
     bfd_reloc_code_real_type code;
206
{
207
  unsigned int i;
208
 
209 1183 sfurman
  for (i = 0; i < sizeof (or32_reloc_map) / sizeof (or32_reloc_map[0]); i++)
210 1181 sfurman
    {
211
      if (or32_reloc_map[i].bfd_reloc_val == code)
212
        return &elf_or32_howto_table[or32_reloc_map[i].elf_reloc_val];
213
    }
214
 
215
  return NULL;
216
}
217
 
218
/* Set the howto pointer for an OR32 ELF reloc.  */
219
 
220
static void
221
or32_info_to_howto_rel (abfd, cache_ptr, dst)
222
     bfd *abfd ATTRIBUTE_UNUSED;
223
     arelent *cache_ptr;
224
     Elf32_Internal_Rel *dst;
225
{
226
  unsigned int r_type;
227
 
228
  r_type = ELF32_R_TYPE (dst->r_info);
229
  BFD_ASSERT (r_type < (unsigned int) R_OR32_max);
230
  cache_ptr->howto = &elf_or32_howto_table[r_type];
231
}
232
 
233
/* Set the right machine number for an OR32 ELF file.  */
234
 
235
static boolean
236
or32_elf_object_p (abfd)
237
     bfd *abfd;
238
{
239
  (void) bfd_default_set_arch_mach (abfd, bfd_arch_or32, 0);
240
  return true;
241
}
242
 
243
/* The final processing done just before writing out an OR32 ELF object file.
244
   This gets the OR32 architecture right based on the machine number.  */
245
 
246
static void
247
or32_elf_final_write_processing (abfd, linker)
248
     bfd *abfd;
249
     boolean linker ATTRIBUTE_UNUSED;
250
{
251
  int mach;
252
  unsigned long val;
253
 
254
  switch (mach = bfd_get_mach (abfd))
255
    {
256
    /*
257
    case bfd_mach_arc_base:
258
      val = E_OR32_MACH_BASE;
259
      break;
260
    */
261
    default:
262
      val = 0;
263
      return;
264
    }
265
 
266
  elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
267
  elf_elfheader (abfd)->e_flags |= val;
268
}
269
 
270
bfd_reloc_status_type
271
or32_elf_32_reloc (abfd, reloc_entry, symbol, data, input_section,
272
                   output_bfd, error_message)
273
     bfd *abfd;
274
     arelent *reloc_entry;
275
     asymbol *symbol;
276
     PTR data;
277
     asection *input_section;
278
     bfd *output_bfd;
279
     char **error_message ATTRIBUTE_UNUSED;
280 1183 sfurman
{
281 1181 sfurman
  if (output_bfd != (bfd *) NULL)
282
    {
283
      unsigned long insn;
284
      bfd_size_type addr = reloc_entry->address;
285
 
286
      reloc_entry->address += input_section->output_offset;
287 1183 sfurman
 
288 1181 sfurman
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
289
      insn += symbol->section->output_section->vma;
290
      insn += symbol->section->output_offset;
291
      insn += symbol->value;
292 1183 sfurman
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
293 1181 sfurman
 
294
      return bfd_reloc_ok;
295
    }
296
 
297
  return bfd_reloc_continue;
298
}
299
 
300
bfd_reloc_status_type
301
or32_elf_16_reloc (abfd, reloc_entry, symbol, data, input_section,
302
                   output_bfd, error_message)
303
     bfd *abfd;
304
     arelent *reloc_entry;
305
     asymbol *symbol;
306
     PTR data;
307
     asection *input_section;
308
     bfd *output_bfd;
309
     char **error_message ATTRIBUTE_UNUSED;
310 1183 sfurman
{
311 1181 sfurman
  if (output_bfd != (bfd *) NULL)
312
    {
313
      unsigned short insn;
314
      bfd_size_type addr = reloc_entry->address;
315
 
316
      reloc_entry->address += input_section->output_offset;
317
 
318
      insn = bfd_get_16 (abfd, (bfd_byte *) data + addr);
319
      insn += symbol->section->output_section->vma;
320
      insn += symbol->section->output_offset;
321
      insn += symbol->value;
322 1183 sfurman
      bfd_put_16 (abfd, insn, (bfd_byte *) data + addr);
323 1181 sfurman
 
324
      return bfd_reloc_ok;
325
    }
326
 
327
  return bfd_reloc_continue;
328
}
329
 
330
bfd_reloc_status_type
331
or32_elf_8_reloc (abfd, reloc_entry, symbol, data, input_section,
332
                  output_bfd, error_message)
333
     bfd *abfd ATTRIBUTE_UNUSED;
334
     arelent *reloc_entry;
335
     asymbol *symbol;
336
     PTR data;
337
     asection *input_section;
338
     bfd *output_bfd;
339
     char **error_message ATTRIBUTE_UNUSED;
340 1183 sfurman
{
341 1181 sfurman
  if (output_bfd != (bfd *) NULL)
342
    {
343
      unsigned char insn;
344
      bfd_size_type addr = reloc_entry->address;
345
 
346
      reloc_entry->address += input_section->output_offset;
347
 
348
      insn = bfd_get_8 (abfd, (bfd_byte *) data + addr);
349
      insn += symbol->section->output_section->vma;
350
      insn += symbol->section->output_offset;
351
      insn += symbol->value;
352 1183 sfurman
      bfd_put_8 (abfd, insn, (bfd_byte *) data + addr);
353 1181 sfurman
 
354
      return bfd_reloc_ok;
355
    }
356
 
357
  return bfd_reloc_continue;
358
}
359
 
360
/* Do a R_OR32_CONSTH relocation.  This has to be done in combination
361
   with a R_OR32_CONST reloc, because there is a carry from the LO16 to
362
   the HI16.  Here we just save the information we need; we do the
363
   actual relocation when we see the LO16.  OR32 ELF requires that the
364
   LO16 immediately follow the HI16.  As a GNU extension, we permit an
365
   arbitrary number of HI16 relocs to be associated with a single LO16
366
   reloc.  This extension permits gcc to output the HI and LO relocs
367
   itself. This code is copied from the elf32-mips.c.  */
368
 
369
struct or32_consth
370
{
371
  struct or32_consth *next;
372
  bfd_byte *addr;
373
  bfd_vma addend;
374
};
375
 
376
/* FIXME: This should not be a static variable.  */
377
 
378
static struct or32_consth *or32_consth_list;
379
 
380
bfd_reloc_status_type
381
or32_elf_consth_reloc (abfd, reloc_entry, symbol, data, input_section,
382
                       output_bfd, error_message)
383
     bfd *abfd ATTRIBUTE_UNUSED;
384
     arelent *reloc_entry;
385
     asymbol *symbol;
386
     PTR data;
387
     asection *input_section;
388
     bfd *output_bfd;
389
     char **error_message ATTRIBUTE_UNUSED;
390
{
391
  bfd_reloc_status_type ret;
392
  bfd_vma relocation;
393
  struct or32_consth *n;
394 1183 sfurman
 
395 1181 sfurman
  ret = bfd_reloc_ok;
396
 
397
  if (bfd_is_und_section (symbol->section)
398
      && output_bfd == (bfd *) NULL)
399
    ret = bfd_reloc_undefined;
400
 
401
  if (bfd_is_com_section (symbol->section))
402
    relocation = 0;
403
  else
404
    relocation = symbol->value;
405
 
406
  relocation += symbol->section->output_section->vma;
407
  relocation += symbol->section->output_offset;
408
  relocation += reloc_entry->addend;
409
 
410
  if (reloc_entry->address > input_section->_cooked_size)
411
    return bfd_reloc_outofrange;
412
 
413
  /* Save the information, and let LO16 do the actual relocation.  */
414
  n = (struct or32_consth *) bfd_malloc (sizeof *n);
415
  if (n == NULL)
416
    return bfd_reloc_outofrange;
417
  n->addr = (bfd_byte *) data + reloc_entry->address;
418
  n->addend = relocation;
419
  n->next = or32_consth_list;
420
  or32_consth_list = n;
421
 
422
  if (output_bfd != (bfd *) NULL)
423
    reloc_entry->address += input_section->output_offset;
424
 
425
  return ret;
426
}
427
 
428
/* Do a R_OR32_CONST relocation.  This is a straightforward 16 bit
429
   inplace relocation; this function exists in order to do the
430
   R_OR32_CONSTH relocation described above.  */
431
 
432
bfd_reloc_status_type
433
or32_elf_const_reloc (abfd, reloc_entry, symbol, data, input_section,
434
                      output_bfd, error_message)
435
     bfd *abfd;
436
     arelent *reloc_entry;
437
     asymbol *symbol;
438
     PTR data;
439
     asection *input_section;
440
     bfd *output_bfd;
441
     char **error_message;
442
{
443
  if (or32_consth_list != NULL)
444
    {
445
      struct or32_consth *l;
446
 
447
      l = or32_consth_list;
448
      while (l != NULL)
449
        {
450
          unsigned long insn;
451
          unsigned long val;
452
          unsigned long vallo;
453
          struct or32_consth *next;
454
 
455
          /* Do the HI16 relocation.  Note that we actually don't need
456
             to know anything about the LO16 itself, except where to
457
             find the low 16 bits of the addend needed by the LO16.  */
458
          insn = bfd_get_32 (abfd, l->addr);
459
          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
460
                   & 0xffff);
461
          val = ((insn & 0xffff) << 16) + vallo;
462
          val += l->addend;
463
 
464
          insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
465
          bfd_put_32 (abfd, insn, l->addr);
466
 
467
          next = l->next;
468
          free (l);
469
          l = next;
470
        }
471
 
472
      or32_consth_list = NULL;
473
    }
474
 
475
  if (output_bfd != (bfd *) NULL)
476
    {
477
      unsigned long insn, tmp;
478
      bfd_size_type addr = reloc_entry->address;
479
 
480
      reloc_entry->address += input_section->output_offset;
481
 
482
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
483
      tmp = insn & 0x0000ffff;
484
      tmp += symbol->section->output_section->vma;
485
      tmp += symbol->section->output_offset;
486
      tmp += symbol->value;
487
      insn = (insn & 0xffff0000) | (tmp & 0x0000ffff);
488
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
489
 
490
      return bfd_reloc_ok;
491
    }
492
 
493
  /* Now do the LO16 reloc in the usual way.  */
494
  return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
495
                                input_section, output_bfd, error_message);
496
}
497
 
498
bfd_reloc_status_type
499
or32_elf_jumptarg_reloc (abfd, reloc_entry, symbol, data, input_section,
500
                         output_bfd, error_message)
501
     bfd *abfd;
502
     arelent *reloc_entry;
503
     asymbol *symbol ATTRIBUTE_UNUSED;
504
     PTR data;
505
     asection *input_section;
506
     bfd *output_bfd;
507
     char **error_message ATTRIBUTE_UNUSED;
508 1183 sfurman
{
509 1181 sfurman
  if (output_bfd != (bfd *) NULL)
510
    {
511
      unsigned long insn, tmp;
512
      bfd_size_type addr = reloc_entry->address;
513
 
514
      reloc_entry->address += input_section->output_offset;
515
 
516
      insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
517
      tmp = insn | 0xfc000000;
518
      tmp -= (input_section->output_offset >> 2);
519
      insn = (insn & 0xfc000000) | (tmp & 0x03ffffff);
520 1183 sfurman
      bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
521 1181 sfurman
 
522
      return bfd_reloc_ok;
523
    }
524
 
525
  return bfd_reloc_continue;
526
}
527
 
528
#define TARGET_LITTLE_SYM       bfd_elf32_or32_little_vec
529
#define TARGET_LITTLE_NAME      "elf32-littleor32"
530
#define TARGET_BIG_SYM          bfd_elf32_or32_big_vec
531
#define TARGET_BIG_NAME         "elf32-or32"
532
#define ELF_ARCH                bfd_arch_or32
533
#define ELF_MACHINE_CODE        EM_OR32
534
#define ELF_MAXPAGESIZE         0x1000
535
 
536
#define elf_info_to_howto       0
537
#define elf_info_to_howto_rel   or32_info_to_howto_rel
538
#define elf_backend_object_p    or32_elf_object_p
539
#define elf_backend_final_write_processing \
540
                                or32_elf_final_write_processing
541
 
542
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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