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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 14 khays
/* IQ2000-specific support for 32-bit ELF.
2
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3
   Free Software Foundation, Inc.
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, MA 02110-1301, USA.  */
20
 
21
#include "sysdep.h"
22
#include "bfd.h"
23
#include "libbfd.h"
24
#include "elf-bfd.h"
25
#include "elf/iq2000.h"
26
 
27
/* Forward declarations.  */
28
 
29
static bfd_reloc_status_type iq2000_elf_howto_hi16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
30
 
31
 
32
static reloc_howto_type iq2000_elf_howto_table [] =
33
{
34
  /* This reloc does nothing.  */
35
 
36
  HOWTO (R_IQ2000_NONE,              /* type */
37
         0,                           /* rightshift */
38
         2,                          /* size (0 = byte, 1 = short, 2 = long) */
39
         32,                         /* bitsize */
40
         FALSE,                      /* pc_relative */
41
         0,                           /* bitpos */
42
         complain_overflow_bitfield, /* complain_on_overflow */
43
         bfd_elf_generic_reloc,      /* special_function */
44
         "R_IQ2000_NONE",            /* name */
45
         FALSE,                      /* partial_inplace */
46
         0,                           /* src_mask */
47
         0,                           /* dst_mask */
48
         FALSE),                     /* pcrel_offset */
49
 
50
  /* A 16 bit absolute relocation.  */
51
  HOWTO (R_IQ2000_16,                /* type */
52
         0,                           /* rightshift */
53
         1,                          /* size (0 = byte, 1 = short, 2 = long) */
54
         16,                         /* bitsize */
55
         FALSE,                      /* pc_relative */
56
         0,                           /* bitpos */
57
         complain_overflow_bitfield, /* complain_on_overflow */
58
         bfd_elf_generic_reloc,      /* special_function */
59
         "R_IQ2000_16",              /* name */
60
         FALSE,                      /* partial_inplace */
61
         0x0000,                     /* src_mask */
62
         0xffff,                     /* dst_mask */
63
         FALSE),                     /* pcrel_offset */
64
 
65
  /* A 32 bit absolute relocation.  */
66
  HOWTO (R_IQ2000_32,                /* type */
67
         0,                           /* rightshift */
68
         2,                          /* size (0 = byte, 1 = short, 2 = long) */
69
         31,                         /* bitsize */
70
         FALSE,                      /* pc_relative */
71
         0,                           /* bitpos */
72
         complain_overflow_bitfield, /* complain_on_overflow */
73
         bfd_elf_generic_reloc,      /* special_function */
74
         "R_IQ2000_32",              /* name */
75
         FALSE,                      /* partial_inplace */
76
         0x00000000,                 /* src_mask */
77
         0x7fffffff,                 /* dst_mask */
78
         FALSE),                     /* pcrel_offset */
79
 
80
  /* 26 bit branch address.  */
81
  HOWTO (R_IQ2000_26,           /* type */
82
         2,                     /* rightshift */
83
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
84
         26,                    /* bitsize */
85
         FALSE,                 /* pc_relative */
86
         0,                      /* bitpos */
87
         complain_overflow_dont, /* complain_on_overflow */
88
                                /* This needs complex overflow
89
                                   detection, because the upper four
90
                                   bits must match the PC.  */
91
         bfd_elf_generic_reloc, /* special_function */
92
         "R_IQ2000_26",         /* name */
93
         FALSE,                 /* partial_inplace */
94
         0x00000000,            /* src_mask */
95
         0x03ffffff,            /* dst_mask */
96
         FALSE),                /* pcrel_offset */
97
 
98
  /* 16 bit PC relative reference.  */
99
  HOWTO (R_IQ2000_PC16,         /* type */
100
         2,                     /* rightshift */
101
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
102
         16,                    /* bitsize */
103
         TRUE,                  /* pc_relative */
104
         0,                      /* bitpos */
105
         complain_overflow_signed, /* complain_on_overflow */
106
         bfd_elf_generic_reloc, /* special_function */
107
         "R_IQ2000_PC16",       /* name */
108
         FALSE,                 /* partial_inplace */
109
         0x0000,                /* src_mask */
110
         0xffff,                /* dst_mask */
111
         TRUE),                 /* pcrel_offset */
112
 
113
  /* high 16 bits of symbol value.  */
114
  HOWTO (R_IQ2000_HI16,         /* type */
115
         16,                    /* rightshift */
116
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
117
         15,                    /* bitsize */
118
         FALSE,                 /* pc_relative */
119
         0,                      /* bitpos */
120
         complain_overflow_dont, /* complain_on_overflow */
121
         iq2000_elf_howto_hi16_reloc,   /* special_function */
122
         "R_IQ2000_HI16",       /* name */
123
         FALSE,                 /* partial_inplace */
124
         0x0000,                /* src_mask */
125
         0x7fff,                /* dst_mask */
126
         FALSE),                /* pcrel_offset */
127
 
128
  /* Low 16 bits of symbol value.  */
129
  HOWTO (R_IQ2000_LO16,         /* type */
130
         0,                      /* rightshift */
131
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
132
         16,                    /* bitsize */
133
         FALSE,                 /* pc_relative */
134
         0,                      /* bitpos */
135
         complain_overflow_dont, /* complain_on_overflow */
136
         bfd_elf_generic_reloc, /* special_function */
137
         "R_IQ2000_LO16",       /* name */
138
         FALSE,                 /* partial_inplace */
139
         0x0000,                /* src_mask */
140
         0xffff,                /* dst_mask */
141
         FALSE),                /* pcrel_offset */
142
 
143
  /* 16-bit jump offset.  */
144
  HOWTO (R_IQ2000_OFFSET_16,    /* type */
145
         2,                     /* rightshift */
146
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
147
         16,                    /* bitsize */
148
         FALSE,                 /* pc_relative */
149
         0,                      /* bitpos */
150
         complain_overflow_dont, /* complain_on_overflow */
151
         bfd_elf_generic_reloc, /* special_function */
152
         "R_IQ2000_OFFSET_16",  /* name */
153
         FALSE,                 /* partial_inplace */
154
         0x0000,                /* src_mask */
155
         0xffff,                /* dst_mask */
156
         FALSE),                /* pcrel_offset */
157
 
158
  /* 21-bit jump offset.  */
159
  HOWTO (R_IQ2000_OFFSET_21,    /* type */
160
         2,                     /* rightshift */
161
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
162
         21,                    /* bitsize */
163
         FALSE,                 /* pc_relative */
164
         0,                      /* bitpos */
165
         complain_overflow_dont, /* complain_on_overflow */
166
         bfd_elf_generic_reloc, /* special_function */
167
         "R_IQ2000_OFFSET_21",  /* name */
168
         FALSE,                 /* partial_inplace */
169
         0x000000,              /* src_mask */
170
         0x1fffff,              /* dst_mask */
171
         FALSE),                /* pcrel_offset */
172
 
173
  /* unsigned high 16 bits of value.  */
174
  HOWTO (R_IQ2000_OFFSET_21,    /* type */
175
         16,                    /* rightshift */
176
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
177
         16,                    /* bitsize */
178
         FALSE,                 /* pc_relative */
179
         0,                      /* bitpos */
180
         complain_overflow_dont, /* complain_on_overflow */
181
         bfd_elf_generic_reloc, /* special_function */
182
         "R_IQ2000_UHI16",      /* name */
183
         FALSE,                 /* partial_inplace */
184
         0x0000,                /* src_mask */
185
         0x7fff,                /* dst_mask */
186
         FALSE),                /* pcrel_offset */
187
 
188
  /* A 32 bit absolute debug relocation.  */
189
  HOWTO (R_IQ2000_32_DEBUG,          /* type */
190
         0,                           /* rightshift */
191
         2,                          /* size (0 = byte, 1 = short, 2 = long) */
192
         32,                         /* bitsize */
193
         FALSE,                      /* pc_relative */
194
         0,                           /* bitpos */
195
         complain_overflow_bitfield, /* complain_on_overflow */
196
         bfd_elf_generic_reloc,      /* special_function */
197
         "R_IQ2000_32",              /* name */
198
         FALSE,                      /* partial_inplace */
199
         0x00000000,                 /* src_mask */
200
         0xffffffff,                 /* dst_mask */
201
         FALSE),                     /* pcrel_offset */
202
 
203
};
204
 
205
/* GNU extension to record C++ vtable hierarchy.  */
206
static reloc_howto_type iq2000_elf_vtinherit_howto =
207
  HOWTO (R_IQ2000_GNU_VTINHERIT,    /* type */
208
         0,                         /* rightshift */
209
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
210
         0,                         /* bitsize */
211
         FALSE,                    /* pc_relative */
212
         0,                         /* bitpos */
213
         complain_overflow_dont,   /* complain_on_overflow */
214
         NULL,                     /* special_function */
215
         "R_IQ2000_GNU_VTINHERIT",  /* name */
216
         FALSE,                    /* partial_inplace */
217
         0,                         /* src_mask */
218
         0,                         /* dst_mask */
219
         FALSE);                   /* pcrel_offset */
220
 
221
/* GNU extension to record C++ vtable member usage.  */
222
static reloc_howto_type iq2000_elf_vtentry_howto =
223
  HOWTO (R_IQ2000_GNU_VTENTRY,     /* type */
224
         0,                         /* rightshift */
225
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
226
         0,                         /* bitsize */
227
         FALSE,                    /* pc_relative */
228
         0,                         /* bitpos */
229
         complain_overflow_dont,   /* complain_on_overflow */
230
         NULL,                     /* special_function */
231
         "R_IQ2000_GNU_VTENTRY",    /* name */
232
         FALSE,                    /* partial_inplace */
233
         0,                         /* src_mask */
234
         0,                         /* dst_mask */
235
         FALSE);                   /* pcrel_offset */
236
 
237
 
238
static bfd_reloc_status_type
239
iq2000_elf_howto_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
240
                             arelent *reloc_entry,
241
                             asymbol *symbol,
242
                             void * data,
243
                             asection *input_section,
244
                             bfd *output_bfd,
245
                             char **error_message ATTRIBUTE_UNUSED)
246
{
247
  bfd_reloc_status_type ret;
248
  bfd_vma relocation;
249
 
250
  /* If we're relocating and this an external symbol,
251
     we don't want to change anything.  */
252
  if (output_bfd != (bfd *) NULL
253
      && (symbol->flags & BSF_SECTION_SYM) == 0
254
      && reloc_entry->addend == 0)
255
    {
256
      reloc_entry->address += input_section->output_offset;
257
      return bfd_reloc_ok;
258
    }
259
 
260
  if (bfd_is_com_section (symbol->section))
261
    relocation = 0;
262
  else
263
    relocation = symbol->value;
264
 
265
  relocation += symbol->section->output_section->vma;
266
  relocation += symbol->section->output_offset;
267
  relocation += reloc_entry->addend;
268
 
269
  /* If %lo will have sign-extension, compensate by add 0x10000 to hi portion.  */
270
  if (relocation & 0x8000)
271
    reloc_entry->addend += 0x10000;
272
 
273
  /* Now do the reloc in the usual way.  */
274
  ret = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
275
                                input_section, output_bfd, error_message);
276
 
277
  /* Put it back the way it was.  */
278
  if (relocation & 0x8000)
279
    reloc_entry->addend -= 0x10000;
280
 
281
  return ret;
282
}
283
 
284
static bfd_reloc_status_type
285
iq2000_elf_relocate_hi16 (bfd *input_bfd,
286
                          Elf_Internal_Rela *relhi,
287
                          bfd_byte *contents,
288
                          bfd_vma value)
289
{
290
  bfd_vma insn;
291
 
292
  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
293
 
294
  value += relhi->r_addend;
295
  value &= 0x7fffffff; /* Mask off top-bit which is Harvard mask bit.  */
296
 
297
  /* If top-bit of %lo value is on, this means that %lo will
298
     sign-propagate and so we compensate by adding 1 to %hi value.  */
299
  if (value & 0x8000)
300
    value += 0x10000;
301
 
302
  value >>= 16;
303
  insn = ((insn & ~0xFFFF) | value);
304
 
305
  bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
306
  return bfd_reloc_ok;
307
}
308
 
309
static bfd_reloc_status_type
310
iq2000_elf_relocate_offset16 (bfd *input_bfd,
311
                              Elf_Internal_Rela *rel,
312
                              bfd_byte *contents,
313
                              bfd_vma value,
314
                              bfd_vma location)
315
{
316
  bfd_vma insn;
317
  bfd_vma jtarget;
318
 
319
  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
320
 
321
  value += rel->r_addend;
322
 
323
  if (value & 3)
324
    return bfd_reloc_dangerous;
325
 
326
  jtarget = (value & 0x3fffc) | (location & 0xf0000000L);
327
 
328
  if (jtarget != value)
329
    return bfd_reloc_overflow;
330
 
331
  insn = (insn & ~0xFFFF) | ((value >> 2) & 0xFFFF);
332
 
333
  bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
334
  return bfd_reloc_ok;
335
}
336
 
337
/* Map BFD reloc types to IQ2000 ELF reloc types.  */
338
 
339
static reloc_howto_type *
340
iq2000_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
341
                          bfd_reloc_code_real_type code)
342
{
343
  /* Note that the iq2000_elf_howto_table is indxed by the R_
344
     constants.  Thus, the order that the howto records appear in the
345
     table *must* match the order of the relocation types defined in
346
     include/elf/iq2000.h.  */
347
 
348
  switch (code)
349
    {
350
    case BFD_RELOC_NONE:
351
      return &iq2000_elf_howto_table[ (int) R_IQ2000_NONE];
352
    case BFD_RELOC_16:
353
      return &iq2000_elf_howto_table[ (int) R_IQ2000_16];
354
    case BFD_RELOC_32:
355
      return &iq2000_elf_howto_table[ (int) R_IQ2000_32];
356
    case BFD_RELOC_MIPS_JMP:
357
      return &iq2000_elf_howto_table[ (int) R_IQ2000_26];
358
    case BFD_RELOC_IQ2000_OFFSET_16:
359
      return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_16];
360
    case BFD_RELOC_IQ2000_OFFSET_21:
361
      return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_21];
362
    case BFD_RELOC_16_PCREL_S2:
363
      return &iq2000_elf_howto_table[ (int) R_IQ2000_PC16];
364
    case BFD_RELOC_HI16:
365
      return &iq2000_elf_howto_table[ (int) R_IQ2000_HI16];
366
    case BFD_RELOC_IQ2000_UHI16:
367
      return &iq2000_elf_howto_table[ (int) R_IQ2000_UHI16];
368
    case BFD_RELOC_LO16:
369
      return &iq2000_elf_howto_table[ (int) R_IQ2000_LO16];
370
    case BFD_RELOC_VTABLE_INHERIT:
371
      return &iq2000_elf_vtinherit_howto;
372
    case BFD_RELOC_VTABLE_ENTRY:
373
      return &iq2000_elf_vtentry_howto;
374
    default:
375
      /* Pacify gcc -Wall.  */
376
      return NULL;
377
    }
378
  return NULL;
379
}
380
 
381
static reloc_howto_type *
382
iq2000_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
383
{
384
  unsigned int i;
385
 
386
  for (i = 0;
387
       i < (sizeof (iq2000_elf_howto_table)
388
            / sizeof (iq2000_elf_howto_table[0]));
389
       i++)
390
    if (iq2000_elf_howto_table[i].name != NULL
391
        && strcasecmp (iq2000_elf_howto_table[i].name, r_name) == 0)
392
      return &iq2000_elf_howto_table[i];
393
 
394
  if (strcasecmp (iq2000_elf_vtinherit_howto.name, r_name) == 0)
395
    return &iq2000_elf_vtinherit_howto;
396
  if (strcasecmp (iq2000_elf_vtentry_howto.name, r_name) == 0)
397
    return &iq2000_elf_vtentry_howto;
398
 
399
  return NULL;
400
}
401
 
402
/* Perform a single relocation.  By default we use the standard BFD
403
   routines.  */
404
 
405
static bfd_reloc_status_type
406
iq2000_final_link_relocate (reloc_howto_type *  howto,
407
                            bfd *               input_bfd,
408
                            asection *          input_section,
409
                            bfd_byte *          contents,
410
                            Elf_Internal_Rela * rel,
411
                            bfd_vma             relocation)
412
{
413
  return _bfd_final_link_relocate (howto, input_bfd, input_section,
414
                                   contents, rel->r_offset,
415
                                   relocation, rel->r_addend);
416
}
417
 
418
/* Set the howto pointer for a IQ2000 ELF reloc.  */
419
 
420
static void
421
iq2000_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
422
                           arelent * cache_ptr,
423
                           Elf_Internal_Rela * dst)
424
{
425
  unsigned int r_type;
426
 
427
  r_type = ELF32_R_TYPE (dst->r_info);
428
  switch (r_type)
429
    {
430
    case R_IQ2000_GNU_VTINHERIT:
431
      cache_ptr->howto = & iq2000_elf_vtinherit_howto;
432
      break;
433
 
434
    case R_IQ2000_GNU_VTENTRY:
435
      cache_ptr->howto = & iq2000_elf_vtentry_howto;
436
      break;
437
 
438
    default:
439
      cache_ptr->howto = & iq2000_elf_howto_table [r_type];
440
      break;
441
    }
442
}
443
 
444
/* Look through the relocs for a section during the first phase.
445
   Since we don't do .gots or .plts, we just need to consider the
446
   virtual table relocs for gc.  */
447
 
448
static bfd_boolean
449
iq2000_elf_check_relocs (bfd *abfd,
450
                         struct bfd_link_info *info,
451
                         asection *sec,
452
                         const Elf_Internal_Rela *relocs)
453
{
454
  Elf_Internal_Shdr *symtab_hdr;
455
  struct elf_link_hash_entry **sym_hashes;
456
  const Elf_Internal_Rela *rel;
457
  const Elf_Internal_Rela *rel_end;
458
  bfd_boolean changed = FALSE;
459
 
460
  if (info->relocatable)
461
    return TRUE;
462
 
463
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
464
  sym_hashes = elf_sym_hashes (abfd);
465
 
466
  rel_end = relocs + sec->reloc_count;
467
  for (rel = relocs; rel < rel_end; rel++)
468
    {
469
      struct elf_link_hash_entry *h;
470
      unsigned long r_symndx;
471
 
472
      r_symndx = ELF32_R_SYM (rel->r_info);
473
      if (r_symndx < symtab_hdr->sh_info)
474
        h = NULL;
475
      else
476
        {
477
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
478
          while (h->root.type == bfd_link_hash_indirect
479
                 || h->root.type == bfd_link_hash_warning)
480
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
481
        }
482
 
483
      switch (ELF32_R_TYPE (rel->r_info))
484
        {
485
          /* This relocation describes the C++ object vtable
486
             hierarchy.  Reconstruct it for later use during GC.  */
487
        case R_IQ2000_GNU_VTINHERIT:
488
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
489
            return FALSE;
490
          break;
491
 
492
          /* This relocation describes which C++ vtable entries
493
             are actually used.  Record for later use during GC.  */
494
        case R_IQ2000_GNU_VTENTRY:
495
          BFD_ASSERT (h != NULL);
496
          if (h != NULL
497
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
498
            return FALSE;
499
          break;
500
 
501
        case R_IQ2000_32:
502
          /* For debug section, change to special harvard-aware relocations.  */
503
          if (CONST_STRNEQ (sec->name, ".debug")
504
              || CONST_STRNEQ (sec->name, ".stab")
505
              || CONST_STRNEQ (sec->name, ".eh_frame"))
506
            {
507
              ((Elf_Internal_Rela *) rel)->r_info
508
                = ELF32_R_INFO (ELF32_R_SYM (rel->r_info), R_IQ2000_32_DEBUG);
509
              changed = TRUE;
510
            }
511
          break;
512
        }
513
    }
514
 
515
  if (changed)
516
    /* Note that we've changed relocs, otherwise if !info->keep_memory
517
       we'll free the relocs and lose our changes.  */
518
    elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs;
519
 
520
  return TRUE;
521
}
522
 
523
 
524
/* Relocate a IQ2000 ELF section.
525
   There is some attempt to make this function usable for many architectures,
526
   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
527
   if only to serve as a learning tool.
528
 
529
   The RELOCATE_SECTION function is called by the new ELF backend linker
530
   to handle the relocations for a section.
531
 
532
   The relocs are always passed as Rela structures; if the section
533
   actually uses Rel structures, the r_addend field will always be
534
   zero.
535
 
536
   This function is responsible for adjusting the section contents as
537
   necessary, and (if using Rela relocs and generating a relocatable
538
   output file) adjusting the reloc addend as necessary.
539
 
540
   This function does not have to worry about setting the reloc
541
   address or the reloc symbol index.
542
 
543
   LOCAL_SYMS is a pointer to the swapped in local symbols.
544
 
545
   LOCAL_SECTIONS is an array giving the section in the input file
546
   corresponding to the st_shndx field of each local symbol.
547
 
548
   The global hash table entry for the global symbols can be found
549
   via elf_sym_hashes (input_bfd).
550
 
551
   When generating relocatable output, this function must handle
552
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
553
   going to be the section symbol corresponding to the output
554
   section, which means that the addend must be adjusted
555
   accordingly.  */
556
 
557
static bfd_boolean
558
iq2000_elf_relocate_section (bfd *                   output_bfd ATTRIBUTE_UNUSED,
559
                             struct bfd_link_info *  info,
560
                             bfd *                   input_bfd,
561
                             asection *              input_section,
562
                             bfd_byte *              contents,
563
                             Elf_Internal_Rela *     relocs,
564
                             Elf_Internal_Sym *      local_syms,
565
                             asection **             local_sections)
566
{
567
  Elf_Internal_Shdr *           symtab_hdr;
568
  struct elf_link_hash_entry ** sym_hashes;
569
  Elf_Internal_Rela *           rel;
570
  Elf_Internal_Rela *           relend;
571
 
572
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
573
  sym_hashes = elf_sym_hashes (input_bfd);
574
  relend     = relocs + input_section->reloc_count;
575
 
576
  for (rel = relocs; rel < relend; rel ++)
577
    {
578
      reloc_howto_type *           howto;
579
      unsigned long                r_symndx;
580
      Elf_Internal_Sym *           sym;
581
      asection *                   sec;
582
      struct elf_link_hash_entry * h;
583
      bfd_vma                      relocation;
584
      bfd_reloc_status_type        r;
585
      const char *                 name = NULL;
586
      int                          r_type;
587
 
588
      r_type = ELF32_R_TYPE (rel->r_info);
589
 
590
      if (   r_type == R_IQ2000_GNU_VTINHERIT
591
          || r_type == R_IQ2000_GNU_VTENTRY)
592
        continue;
593
 
594
      r_symndx = ELF32_R_SYM (rel->r_info);
595
 
596
      howto  = iq2000_elf_howto_table + ELF32_R_TYPE (rel->r_info);
597
      h      = NULL;
598
      sym    = NULL;
599
      sec    = NULL;
600
 
601
      if (r_symndx < symtab_hdr->sh_info)
602
        {
603
          asection *osec;
604
 
605
          sym = local_syms + r_symndx;
606
          osec = sec = local_sections [r_symndx];
607
          if ((sec->flags & SEC_MERGE)
608
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
609
            /* This relocation is relative to a section symbol that is
610
               going to be merged.  Change it so that it is relative
611
               to the merged section symbol.  */
612
            rel->r_addend = _bfd_elf_rel_local_sym (output_bfd, sym, &sec,
613
                                                    rel->r_addend);
614
 
615
          relocation = (sec->output_section->vma
616
                        + sec->output_offset
617
                        + sym->st_value);
618
 
619
          name = bfd_elf_string_from_elf_section
620
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
621
          name = (name == NULL) ? bfd_section_name (input_bfd, osec) : name;
622
        }
623
      else
624
        {
625
          bfd_boolean unresolved_reloc;
626
          bfd_boolean warned;
627
 
628
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
629
                                   r_symndx, symtab_hdr, sym_hashes,
630
                                   h, sec, relocation,
631
                                   unresolved_reloc, warned);
632
 
633
          name = h->root.root.string;
634
        }
635
 
636
      if (sec != NULL && elf_discarded_section (sec))
637
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
638
                                         rel, relend, howto, contents);
639
 
640
      if (info->relocatable)
641
        continue;
642
 
643
      switch (r_type)
644
        {
645
        case R_IQ2000_HI16:
646
          r = iq2000_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
647
          break;
648
 
649
        case R_IQ2000_OFFSET_16:
650
          r = iq2000_elf_relocate_offset16 (input_bfd, rel, contents, relocation,
651
                                            input_section->output_section->vma
652
                                            + input_section->output_offset
653
                                            + rel->r_offset);
654
          break;
655
 
656
        case R_IQ2000_PC16:
657
          rel->r_addend -= 4;
658
          /* Fall through.  */
659
 
660
        default:
661
          r = iq2000_final_link_relocate (howto, input_bfd, input_section,
662
                                         contents, rel, relocation);
663
          break;
664
        }
665
 
666
      if (r != bfd_reloc_ok)
667
        {
668
          const char * msg = (const char *) NULL;
669
 
670
          switch (r)
671
            {
672
            case bfd_reloc_overflow:
673
              r = info->callbacks->reloc_overflow
674
                (info, (h ? &h->root : NULL), name, howto->name,
675
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
676
              break;
677
 
678
            case bfd_reloc_undefined:
679
              r = info->callbacks->undefined_symbol
680
                (info, name, input_bfd, input_section, rel->r_offset, TRUE);
681
              break;
682
 
683
            case bfd_reloc_outofrange:
684
              msg = _("internal error: out of range error");
685
              break;
686
 
687
            case bfd_reloc_notsupported:
688
              msg = _("internal error: unsupported relocation error");
689
              break;
690
 
691
            case bfd_reloc_dangerous:
692
              msg = _("internal error: dangerous relocation");
693
              break;
694
 
695
            default:
696
              msg = _("internal error: unknown error");
697
              break;
698
            }
699
 
700
          if (msg)
701
            r = info->callbacks->warning
702
              (info, msg, name, input_bfd, input_section, rel->r_offset);
703
 
704
          if (! r)
705
            return FALSE;
706
        }
707
    }
708
 
709
  return TRUE;
710
}
711
 
712
 
713
/* Return the section that should be marked against GC for a given
714
   relocation.  */
715
 
716
static asection *
717
iq2000_elf_gc_mark_hook (asection *sec,
718
                         struct bfd_link_info *info,
719
                         Elf_Internal_Rela *rel,
720
                         struct elf_link_hash_entry *h,
721
                         Elf_Internal_Sym *sym)
722
{
723
  if (h != NULL)
724
    switch (ELF32_R_TYPE (rel->r_info))
725
      {
726
      case R_IQ2000_GNU_VTINHERIT:
727
      case R_IQ2000_GNU_VTENTRY:
728
        return NULL;
729
      }
730
 
731
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
732
}
733
 
734
 
735
/* Return the MACH for an e_flags value.  */
736
 
737
static int
738
elf32_iq2000_machine (bfd *abfd)
739
{
740
  switch (elf_elfheader (abfd)->e_flags & EF_IQ2000_CPU_MASK)
741
    {
742
    case EF_IQ2000_CPU_IQ10:
743
      return bfd_mach_iq10;
744
 
745
    case EF_IQ2000_CPU_IQ2000:
746
    default:
747
      return bfd_mach_iq2000;
748
    }
749
}
750
 
751
 
752
/* Function to set the ELF flag bits.  */
753
 
754
static bfd_boolean
755
iq2000_elf_set_private_flags (bfd *abfd, flagword flags)
756
{
757
  elf_elfheader (abfd)->e_flags = flags;
758
  elf_flags_init (abfd) = TRUE;
759
  return TRUE;
760
}
761
 
762
/* Copy backend specific data from one object module to another.  */
763
 
764
static bfd_boolean
765
iq2000_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
766
{
767
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
768
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
769
    return TRUE;
770
 
771
  BFD_ASSERT (!elf_flags_init (obfd)
772
              || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
773
 
774
  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
775
  elf_flags_init (obfd) = TRUE;
776
 
777
  /* Copy object attributes.  */
778
  _bfd_elf_copy_obj_attributes (ibfd, obfd);
779
 
780
  return TRUE;
781
}
782
 
783
/* Merge backend specific data from an object
784
   file to the output object file when linking.  */
785
 
786
static bfd_boolean
787
iq2000_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
788
{
789
  flagword old_flags, old_partial;
790
  flagword new_flags, new_partial;
791
  bfd_boolean error = FALSE;
792
  char new_opt[80];
793
  char old_opt[80];
794
 
795
  new_opt[0] = old_opt[0] = '\0';
796
  new_flags = elf_elfheader (ibfd)->e_flags;
797
  old_flags = elf_elfheader (obfd)->e_flags;
798
 
799
  if (!elf_flags_init (obfd))
800
    {
801
      /* First call, no flags set.  */
802
      elf_flags_init (obfd) = TRUE;
803
      elf_elfheader (obfd)->e_flags = new_flags;
804
    }
805
 
806
  else if (new_flags != old_flags)
807
    {
808
      /* Warn if different cpu is used, but allow a
809
         specific cpu to override the generic cpu.  */
810
      new_partial = (new_flags & EF_IQ2000_CPU_MASK);
811
      old_partial = (old_flags & EF_IQ2000_CPU_MASK);
812
 
813
      if (new_partial != old_partial)
814
        {
815
          switch (new_partial)
816
            {
817
            case EF_IQ2000_CPU_IQ10:
818
              strcat (new_opt, " -m10");
819
              break;
820
 
821
            default:
822
            case EF_IQ2000_CPU_IQ2000:
823
              strcat (new_opt, " -m2000");
824
              break;
825
            }
826
 
827
          switch (old_partial)
828
            {
829
            case EF_IQ2000_CPU_IQ10:
830
              strcat (old_opt, " -m10");
831
              break;
832
 
833
            default:
834
            case EF_IQ2000_CPU_IQ2000:
835
              strcat (old_opt, " -m2000");
836
              break;
837
            }
838
        }
839
 
840
      /* Print out any mismatches from above.  */
841
      if (new_opt[0])
842
        {
843
          error = TRUE;
844
          _bfd_error_handler
845
            (_("%s: compiled with %s and linked with modules compiled with %s"),
846
             bfd_get_filename (ibfd), new_opt, old_opt);
847
        }
848
 
849
      new_flags &= ~ EF_IQ2000_ALL_FLAGS;
850
      old_flags &= ~ EF_IQ2000_ALL_FLAGS;
851
 
852
      /* Warn about any other mismatches.  */
853
      if (new_flags != old_flags)
854
        {
855
          error = TRUE;
856
 
857
          _bfd_error_handler
858
            (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
859
             bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
860
        }
861
    }
862
 
863
  if (error)
864
    bfd_set_error (bfd_error_bad_value);
865
 
866
  return !error;
867
}
868
 
869
 
870
static bfd_boolean
871
iq2000_elf_print_private_bfd_data (bfd *abfd, void * ptr)
872
{
873
  FILE *file = (FILE *) ptr;
874
  flagword flags;
875
 
876
  BFD_ASSERT (abfd != NULL && ptr != NULL);
877
 
878
  /* Print normal ELF private data.  */
879
  _bfd_elf_print_private_bfd_data (abfd, ptr);
880
 
881
  flags = elf_elfheader (abfd)->e_flags;
882
  fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
883
 
884
  switch (flags & EF_IQ2000_CPU_MASK)
885
    {
886
    case EF_IQ2000_CPU_IQ10:
887
      fprintf (file, " -m10");
888
      break;
889
    case EF_IQ2000_CPU_IQ2000:
890
      fprintf (file, " -m2000");
891
      break;
892
    default:
893
      break;
894
    }
895
 
896
  fputc ('\n', file);
897
  return TRUE;
898
}
899
 
900
static
901
bfd_boolean
902
iq2000_elf_object_p (bfd *abfd)
903
{
904
  bfd_default_set_arch_mach (abfd, bfd_arch_iq2000,
905
                             elf32_iq2000_machine (abfd));
906
  return TRUE;
907
}
908
 
909
 
910
#define ELF_ARCH                bfd_arch_iq2000
911
#define ELF_MACHINE_CODE        EM_IQ2000
912
#define ELF_MAXPAGESIZE         0x1000
913
 
914
#define TARGET_BIG_SYM          bfd_elf32_iq2000_vec
915
#define TARGET_BIG_NAME         "elf32-iq2000"
916
 
917
#define elf_info_to_howto_rel                   NULL
918
#define elf_info_to_howto                       iq2000_info_to_howto_rela
919
#define elf_backend_relocate_section            iq2000_elf_relocate_section
920
#define elf_backend_gc_mark_hook                iq2000_elf_gc_mark_hook
921
#define elf_backend_check_relocs                iq2000_elf_check_relocs
922
#define elf_backend_object_p                    iq2000_elf_object_p
923
#define elf_backend_rela_normal                 1
924
 
925
#define elf_backend_can_gc_sections             1
926
 
927
#define bfd_elf32_bfd_reloc_type_lookup         iq2000_reloc_type_lookup
928
#define bfd_elf32_bfd_reloc_name_lookup iq2000_reloc_name_lookup
929
#define bfd_elf32_bfd_set_private_flags         iq2000_elf_set_private_flags
930
#define bfd_elf32_bfd_copy_private_bfd_data     iq2000_elf_copy_private_bfd_data
931
#define bfd_elf32_bfd_merge_private_bfd_data    iq2000_elf_merge_private_bfd_data
932
#define bfd_elf32_bfd_print_private_bfd_data    iq2000_elf_print_private_bfd_data
933
 
934
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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