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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [elf32-d10v.c] - Blame information for rev 1181

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

Line No. Rev Author Line
1 1181 sfurman
/* D10V-specific support for 32-bit ELF
2
   Copyright 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
   Contributed by Martin Hunt (hunt@cygnus.com).
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/d10v.h"
26
 
27
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
28
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
29
static void d10v_info_to_howto_rel
30
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
31
static asection * elf32_d10v_gc_mark_hook
32
  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
33
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
34
static boolean elf32_d10v_gc_sweep_hook
35
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
36
           const Elf_Internal_Rela *));
37
static boolean elf32_d10v_check_relocs
38
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
39
           const Elf_Internal_Rela *));
40
static boolean elf32_d10v_relocate_section
41
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
42
           bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
43
           asection **));
44
 
45
/* Use REL instead of RELA to save space.  */
46
#define USE_REL
47
 
48
static reloc_howto_type elf_d10v_howto_table[] =
49
  {
50
    /* This reloc does nothing.  */
51
    HOWTO (R_D10V_NONE,         /* type */
52
           0,                    /* rightshift */
53
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
54
           32,                  /* bitsize */
55
           false,               /* pc_relative */
56
           0,                    /* bitpos */
57
           complain_overflow_dont, /* complain_on_overflow */
58
           bfd_elf_generic_reloc, /* special_function */
59
           "R_D10V_NONE",       /* name */
60
           false,               /* partial_inplace */
61
           0,                    /* src_mask */
62
           0,                    /* dst_mask */
63
           false),              /* pcrel_offset */
64
 
65
    /* An PC Relative 10-bit relocation, shifted by 2  */
66
    /* right container */
67
    HOWTO (R_D10V_10_PCREL_R,   /* type */
68
           2,                   /* rightshift */
69
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
70
           7,                   /* bitsize */
71
           true,                /* pc_relative */
72
           0,                    /* bitpos */
73
           complain_overflow_bitfield, /* complain_on_overflow */
74
           bfd_elf_generic_reloc, /* special_function */
75
           "R_D10V_10_PCREL_R", /* name */
76
           false,               /* partial_inplace */
77
           0xff,                /* src_mask */
78
           0xff,                /* dst_mask */
79
           true),               /* pcrel_offset */
80
 
81
    /* An PC Relative 10-bit relocation, shifted by 2  */
82
    /* left container */
83
    HOWTO (R_D10V_10_PCREL_L,   /* type */
84
           2,                   /* rightshift */
85
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
86
           7,                   /* bitsize */
87
           true,                /* pc_relative */
88
           15,                  /* bitpos */
89
           complain_overflow_bitfield, /* complain_on_overflow */
90
           bfd_elf_generic_reloc, /* special_function */
91
           "R_D10V_10_PCREL_L", /* name */
92
           false,               /* partial_inplace */
93
           0x07f8000,           /* src_mask */
94
           0x07f8000,           /* dst_mask */
95
           true),               /* pcrel_offset */
96
 
97
    /* A 16 bit absolute relocation */
98
    HOWTO (R_D10V_16,           /* type */
99
           0,                    /* rightshift */
100
           1,                   /* size (0 = byte, 1 = short, 2 = long) */
101
           16,                  /* bitsize */
102
           false,               /* pc_relative */
103
           0,                    /* bitpos */
104
           complain_overflow_dont, /* complain_on_overflow */
105
           bfd_elf_generic_reloc, /* special_function */
106
           "R_D10V_16",         /* name */
107
           false,               /* partial_inplace */
108
           0xffff,              /* src_mask */
109
           0xffff,              /* dst_mask */
110
           false),              /* pcrel_offset */
111
 
112
    /* An 18 bit absolute relocation, right shifted 2 */
113
    HOWTO (R_D10V_18,           /* type */
114
           2,                   /* rightshift */
115
           1,                   /* size (0 = byte, 1 = short, 2 = long) */
116
           16,                  /* bitsize */
117
           false,               /* pc_relative */
118
           0,                    /* bitpos */
119
           complain_overflow_dont, /* complain_on_overflow */
120
           bfd_elf_generic_reloc, /* special_function */
121
           "R_D10V_18",         /* name */
122
           false,               /* partial_inplace */
123
           0xffff,              /* src_mask */
124
           0xffff,              /* dst_mask */
125
           false),              /* pcrel_offset */
126
 
127
    /* A relative 18 bit relocation, right shifted by 2  */
128
    HOWTO (R_D10V_18_PCREL,     /* type */
129
           2,                   /* rightshift */
130
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
131
           15,                  /* bitsize */
132
           true,                /* pc_relative */
133
           0,                    /* bitpos */
134
           complain_overflow_bitfield, /* complain_on_overflow */
135
           bfd_elf_generic_reloc, /* special_function */
136
           "R_D10V_18_PCREL",   /* name */
137
           false,               /* partial_inplace */
138
           0xffff,              /* src_mask */
139
           0xffff,              /* dst_mask */
140
           true),                       /* pcrel_offset */
141
 
142
    /* A 32 bit absolute relocation */
143
    HOWTO (R_D10V_32,           /* type */
144
           0,                    /* rightshift */
145
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
146
           32,                  /* bitsize */
147
           false,               /* pc_relative */
148
           0,                    /* bitpos */
149
           complain_overflow_dont, /* complain_on_overflow */
150
           bfd_elf_generic_reloc, /* special_function */
151
           "R_D10V_32",         /* name */
152
           false,               /* partial_inplace */
153
           0xffffffff,          /* src_mask */
154
           0xffffffff,          /* dst_mask */
155
           false),              /* pcrel_offset */
156
 
157
    /* GNU extension to record C++ vtable hierarchy */
158
    HOWTO (R_D10V_GNU_VTINHERIT, /* type */
159
           0,                     /* rightshift */
160
           2,                     /* size (0 = byte, 1 = short, 2 = long) */
161
           0,                     /* bitsize */
162
           false,                 /* pc_relative */
163
           0,                     /* bitpos */
164
           complain_overflow_dont, /* complain_on_overflow */
165
           NULL,                  /* special_function */
166
           "R_D10V_GNU_VTINHERIT", /* name */
167
           false,                 /* partial_inplace */
168
           0,                     /* src_mask */
169
           0,                     /* dst_mask */
170
           false),                /* pcrel_offset */
171
 
172
    /* GNU extension to record C++ vtable member usage */
173
    HOWTO (R_D10V_GNU_VTENTRY,     /* type */
174
           0,                     /* rightshift */
175
           2,                     /* size (0 = byte, 1 = short, 2 = long) */
176
           0,                     /* bitsize */
177
           false,                 /* pc_relative */
178
           0,                     /* bitpos */
179
           complain_overflow_dont, /* complain_on_overflow */
180
           _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
181
           "R_D10V_GNU_VTENTRY",   /* name */
182
           false,                 /* partial_inplace */
183
           0,                     /* src_mask */
184
           0,                     /* dst_mask */
185
           false),                /* pcrel_offset */
186
  };
187
 
188
/* Map BFD reloc types to D10V ELF reloc types.  */
189
 
190
struct d10v_reloc_map
191
  {
192
    bfd_reloc_code_real_type bfd_reloc_val;
193
    unsigned char elf_reloc_val;
194
  };
195
 
196
static const struct d10v_reloc_map d10v_reloc_map[] =
197
  {
198
    { BFD_RELOC_NONE, R_D10V_NONE, },
199
    { BFD_RELOC_D10V_10_PCREL_R, R_D10V_10_PCREL_R },
200
    { BFD_RELOC_D10V_10_PCREL_L, R_D10V_10_PCREL_L },
201
    { BFD_RELOC_16, R_D10V_16 },
202
    { BFD_RELOC_D10V_18, R_D10V_18 },
203
    { BFD_RELOC_D10V_18_PCREL, R_D10V_18_PCREL },
204
    { BFD_RELOC_32, R_D10V_32 },
205
    { BFD_RELOC_VTABLE_INHERIT, R_D10V_GNU_VTINHERIT },
206
    { BFD_RELOC_VTABLE_ENTRY, R_D10V_GNU_VTENTRY },
207
  };
208
 
209
static reloc_howto_type *
210
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
211
     bfd *abfd ATTRIBUTE_UNUSED;
212
     bfd_reloc_code_real_type code;
213
{
214
  unsigned int i;
215
 
216
  for (i = 0;
217
       i < sizeof (d10v_reloc_map) / sizeof (struct d10v_reloc_map);
218
       i++)
219
    {
220
      if (d10v_reloc_map[i].bfd_reloc_val == code)
221
        return &elf_d10v_howto_table[d10v_reloc_map[i].elf_reloc_val];
222
    }
223
 
224
  return NULL;
225
}
226
 
227
/* Set the howto pointer for an D10V ELF reloc.  */
228
 
229
static void
230
d10v_info_to_howto_rel (abfd, cache_ptr, dst)
231
     bfd *abfd ATTRIBUTE_UNUSED;
232
     arelent *cache_ptr;
233
     Elf32_Internal_Rel *dst;
234
{
235
  unsigned int r_type;
236
 
237
  r_type = ELF32_R_TYPE (dst->r_info);
238
  BFD_ASSERT (r_type < (unsigned int) R_D10V_max);
239
  cache_ptr->howto = &elf_d10v_howto_table[r_type];
240
}
241
 
242
static asection *
243
elf32_d10v_gc_mark_hook (sec, info, rel, h, sym)
244
     asection *sec;
245
     struct bfd_link_info *info ATTRIBUTE_UNUSED;
246
     Elf_Internal_Rela *rel;
247
     struct elf_link_hash_entry *h;
248
     Elf_Internal_Sym *sym;
249
{
250
  if (h != NULL)
251
    {
252
      switch (ELF32_R_TYPE (rel->r_info))
253
      {
254
      case R_D10V_GNU_VTINHERIT:
255
      case R_D10V_GNU_VTENTRY:
256
        break;
257
 
258
      default:
259
        switch (h->root.type)
260
          {
261
          case bfd_link_hash_defined:
262
          case bfd_link_hash_defweak:
263
            return h->root.u.def.section;
264
 
265
          case bfd_link_hash_common:
266
            return h->root.u.c.p->section;
267
 
268
          default:
269
            break;
270
          }
271
       }
272
     }
273
   else
274
     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
275
 
276
  return NULL;
277
}
278
 
279
static boolean
280
elf32_d10v_gc_sweep_hook (abfd, info, sec, relocs)
281
     bfd *abfd ATTRIBUTE_UNUSED;
282
     struct bfd_link_info *info ATTRIBUTE_UNUSED;
283
     asection *sec ATTRIBUTE_UNUSED;
284
     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
285
{
286
  /* we don't use got and plt entries for d10v */
287
  return true;
288
}
289
 
290
/* Look through the relocs for a section during the first phase.
291
   Since we don't do .gots or .plts, we just need to consider the
292
   virtual table relocs for gc.  */
293
 
294
static boolean
295
elf32_d10v_check_relocs (abfd, info, sec, relocs)
296
     bfd *abfd;
297
     struct bfd_link_info *info;
298
     asection *sec;
299
     const Elf_Internal_Rela *relocs;
300
{
301
  Elf_Internal_Shdr *symtab_hdr;
302
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
303
  const Elf_Internal_Rela *rel;
304
  const Elf_Internal_Rela *rel_end;
305
 
306
  if (info->relocateable)
307
    return true;
308
 
309
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
310
  sym_hashes = elf_sym_hashes (abfd);
311
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
312
  if (!elf_bad_symtab (abfd))
313
    sym_hashes_end -= symtab_hdr->sh_info;
314
 
315
  rel_end = relocs + sec->reloc_count;
316
  for (rel = relocs; rel < rel_end; rel++)
317
    {
318
      struct elf_link_hash_entry *h;
319
      unsigned long r_symndx;
320
 
321
      r_symndx = ELF32_R_SYM (rel->r_info);
322
      if (r_symndx < symtab_hdr->sh_info)
323
        h = NULL;
324
      else
325
        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
326
 
327
      switch (ELF32_R_TYPE (rel->r_info))
328
        {
329
        /* This relocation describes the C++ object vtable hierarchy.
330
           Reconstruct it for later use during GC.  */
331
        case R_D10V_GNU_VTINHERIT:
332
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
333
            return false;
334
          break;
335
 
336
        /* This relocation describes which C++ vtable entries are actually
337
           used.  Record for later use during GC.  */
338
        case R_D10V_GNU_VTENTRY:
339
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
340
            return false;
341
          break;
342
        }
343
    }
344
 
345
  return true;
346
}
347
 
348
/* Relocate a D10V ELF section.  */
349
static boolean
350
elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
351
                            contents, relocs, local_syms, local_sections)
352
     bfd *output_bfd;
353
     struct bfd_link_info *info;
354
     bfd *input_bfd;
355
     asection *input_section;
356
     bfd_byte *contents;
357
     Elf_Internal_Rela *relocs;
358
     Elf_Internal_Sym *local_syms;
359
     asection **local_sections;
360
{
361
  Elf_Internal_Shdr *symtab_hdr;
362
  struct elf_link_hash_entry **sym_hashes;
363
  Elf_Internal_Rela *rel, *relend;
364
  const char *name;
365
 
366
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
367
  sym_hashes = elf_sym_hashes (input_bfd);
368
 
369
  rel = relocs;
370
  relend = relocs + input_section->reloc_count;
371
  for (; rel < relend; rel++)
372
    {
373
      int r_type;
374
      reloc_howto_type *howto;
375
      unsigned long r_symndx;
376
      Elf_Internal_Sym *sym;
377
      asection *sec;
378
      struct elf_link_hash_entry *h;
379
      bfd_vma relocation;
380
      bfd_reloc_status_type r;
381
 
382
      r_symndx = ELF32_R_SYM (rel->r_info);
383
      r_type = ELF32_R_TYPE (rel->r_info);
384
 
385
      if (r_type == R_D10V_GNU_VTENTRY
386
          || r_type == R_D10V_GNU_VTINHERIT )
387
        continue;
388
 
389
      howto = elf_d10v_howto_table + r_type;
390
 
391
      if (info->relocateable)
392
        {
393
          /* This is a relocateable link.  We don't have to change
394
             anything, unless the reloc is against a section symbol,
395
             in which case we have to adjust according to where the
396
             section symbol winds up in the output section.  */
397
          if (r_symndx < symtab_hdr->sh_info)
398
            {
399
              sym = local_syms + r_symndx;
400
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
401
                {
402
                  sec = local_sections[r_symndx];
403
                  rel->r_addend += sec->output_offset + sym->st_value;
404
                }
405
            }
406
 
407
          continue;
408
        }
409
 
410
      /* This is a final link.  */
411
      h = NULL;
412
      sym = NULL;
413
      sec = NULL;
414
      if (r_symndx < symtab_hdr->sh_info)
415
        {
416
          sym = local_syms + r_symndx;
417
          sec = local_sections[r_symndx];
418
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
419
        }
420
      else
421
        {
422
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
423
          while (h->root.type == bfd_link_hash_indirect
424
                 || h->root.type == bfd_link_hash_warning)
425
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
426
          if (h->root.type == bfd_link_hash_defined
427
              || h->root.type == bfd_link_hash_defweak)
428
            {
429
              sec = h->root.u.def.section;
430
              relocation = (h->root.u.def.value
431
                            + sec->output_section->vma
432
                            + sec->output_offset);
433
            }
434
          else if (h->root.type == bfd_link_hash_undefweak)
435
            relocation = 0;
436
          else
437
            {
438
              if (!((*info->callbacks->undefined_symbol)
439
                    (info, h->root.root.string, input_bfd,
440
                     input_section, rel->r_offset, true)))
441
                return false;
442
              relocation = 0;
443
            }
444
        }
445
 
446
      if (h != NULL)
447
        name = h->root.root.string;
448
      else
449
        {
450
          name = (bfd_elf_string_from_elf_section
451
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
452
          if (name == NULL || *name == '\0')
453
            name = bfd_section_name (input_bfd, sec);
454
        }
455
 
456
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
457
                                    contents, rel->r_offset,
458
                                    relocation, rel->r_addend);
459
 
460
      if (r != bfd_reloc_ok)
461
        {
462
          const char * msg = (const char *) 0;
463
 
464
          switch (r)
465
            {
466
            case bfd_reloc_overflow:
467
              if (!((*info->callbacks->reloc_overflow)
468
                    (info, name, howto->name, (bfd_vma) 0,
469
                     input_bfd, input_section, rel->r_offset)))
470
                return false;
471
              break;
472
 
473
            case bfd_reloc_undefined:
474
              if (!((*info->callbacks->undefined_symbol)
475
                    (info, name, input_bfd, input_section,
476
                     rel->r_offset, true)))
477
                return false;
478
              break;
479
 
480
            case bfd_reloc_outofrange:
481
              msg = _("internal error: out of range error");
482
              goto common_error;
483
 
484
            case bfd_reloc_notsupported:
485
              msg = _("internal error: unsupported relocation error");
486
              goto common_error;
487
 
488
            case bfd_reloc_dangerous:
489
              msg = _("internal error: dangerous error");
490
              goto common_error;
491
 
492
            default:
493
              msg = _("internal error: unknown error");
494
              /* fall through */
495
 
496
            common_error:
497
              if (!((*info->callbacks->warning)
498
                    (info, msg, name, input_bfd, input_section,
499
                     rel->r_offset)))
500
                return false;
501
              break;
502
            }
503
        }
504
    }
505
 
506
  return true;
507
}
508
#define ELF_ARCH                bfd_arch_d10v
509
#define ELF_MACHINE_CODE        EM_D10V
510
#define ELF_MACHINE_ALT1        EM_CYGNUS_D10V
511
#define ELF_MAXPAGESIZE         0x1000
512
 
513
#define TARGET_BIG_SYM          bfd_elf32_d10v_vec
514
#define TARGET_BIG_NAME         "elf32-d10v"
515
 
516
#define elf_info_to_howto                    0
517
#define elf_info_to_howto_rel                d10v_info_to_howto_rel
518
#define elf_backend_object_p                 0
519
#define elf_backend_final_write_processing   0
520
#define elf_backend_gc_mark_hook             elf32_d10v_gc_mark_hook
521
#define elf_backend_gc_sweep_hook            elf32_d10v_gc_sweep_hook
522
#define elf_backend_check_relocs             elf32_d10v_check_relocs
523
#define elf_backend_relocate_section         elf32_d10v_relocate_section
524
#define elf_backend_can_gc_sections          1
525
 
526
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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