~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to bfd/elf32-d10v.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-03-18 13:07:52 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050318130752-j4i37zgqclj53b94
Tags: 2.15-5ubuntu2
debian/rules: Call pkgstriptranslations if present (the package does not
use debhelper, thus it does not happen automatically).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* D10V-specific support for 32-bit ELF
2
 
   Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003
 
2
   Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3
3
   Free Software Foundation, Inc.
4
4
   Contributed by Martin Hunt (hunt@cygnus.com).
5
5
 
38
38
static bfd_boolean elf32_d10v_check_relocs
39
39
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
40
40
           const Elf_Internal_Rela *));
 
41
static bfd_vma extract_rel_addend
 
42
  PARAMS ((bfd *, bfd_byte *, reloc_howto_type *));
 
43
static void insert_rel_addend
 
44
  PARAMS ((bfd *, bfd_byte *, reloc_howto_type *, bfd_vma));
41
45
static bfd_boolean elf32_d10v_relocate_section
42
46
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
43
47
           bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
330
334
        /* This relocation describes the C++ object vtable hierarchy.
331
335
           Reconstruct it for later use during GC.  */
332
336
        case R_D10V_GNU_VTINHERIT:
333
 
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
 
337
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
334
338
            return FALSE;
335
339
          break;
336
340
 
337
341
        /* This relocation describes which C++ vtable entries are actually
338
342
           used.  Record for later use during GC.  */
339
343
        case R_D10V_GNU_VTENTRY:
340
 
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
 
344
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
341
345
            return FALSE;
342
346
          break;
343
347
        }
346
350
  return TRUE;
347
351
}
348
352
 
 
353
static bfd_vma
 
354
extract_rel_addend (abfd, where, howto)
 
355
     bfd *abfd;
 
356
     bfd_byte *where;
 
357
     reloc_howto_type *howto;
 
358
{
 
359
  bfd_vma insn, val;
 
360
 
 
361
  switch (howto->size)
 
362
    {
 
363
    case 0:
 
364
      insn = bfd_get_8 (abfd, where);
 
365
      break;
 
366
    case 1:
 
367
      insn = bfd_get_16 (abfd, where);
 
368
      break;
 
369
    case 2:
 
370
      insn = bfd_get_32 (abfd, where);
 
371
      break;
 
372
    default:
 
373
      abort ();
 
374
    }
 
375
 
 
376
  val = (insn & howto->dst_mask) >> howto->bitpos << howto->rightshift;
 
377
  /* We should really be testing for signed addends here, but we don't
 
378
     have that info directly in the howto.  */
 
379
  if (howto->pc_relative)
 
380
    {
 
381
      bfd_vma sign;
 
382
      sign = howto->dst_mask & (~howto->dst_mask >> 1 | ~(-(bfd_vma) 1 >> 1));
 
383
      sign = sign >> howto->bitpos << howto->rightshift;
 
384
      val = (val ^ sign) - sign;
 
385
    }
 
386
  return val;
 
387
}
 
388
 
 
389
static void
 
390
insert_rel_addend (abfd, where, howto, addend)
 
391
     bfd *abfd;
 
392
     bfd_byte *where;
 
393
     reloc_howto_type *howto;
 
394
     bfd_vma addend;
 
395
{
 
396
  bfd_vma insn;
 
397
 
 
398
  addend = (addend >> howto->rightshift << howto->bitpos) & howto->dst_mask;
 
399
  insn = ~howto->dst_mask;
 
400
  switch (howto->size)
 
401
    {
 
402
    case 0:
 
403
      insn &= bfd_get_8 (abfd, where);
 
404
      insn |= addend;
 
405
      bfd_put_8 (abfd, insn, where);
 
406
      break;
 
407
    case 1:
 
408
      insn &= bfd_get_16 (abfd, where);
 
409
      insn |= addend;
 
410
      bfd_put_16 (abfd, insn, where);
 
411
      break;
 
412
    case 2:
 
413
      insn &= bfd_get_32 (abfd, where);
 
414
      insn |= addend;
 
415
      bfd_put_32 (abfd, insn, where);
 
416
      break;
 
417
    default:
 
418
      abort ();
 
419
    }
 
420
}
 
421
 
349
422
/* Relocate a D10V ELF section.  */
350
423
static bfd_boolean
351
424
elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
391
464
 
392
465
      if (info->relocatable)
393
466
        {
 
467
          bfd_vma val;
 
468
          bfd_byte *where;
 
469
 
394
470
          /* This is a relocatable link.  We don't have to change
395
471
             anything, unless the reloc is against a section symbol,
396
472
             in which case we have to adjust according to where the
397
473
             section symbol winds up in the output section.  */
398
 
          if (r_symndx < symtab_hdr->sh_info)
399
 
            {
400
 
              sym = local_syms + r_symndx;
401
 
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
402
 
                {
403
 
                  sec = local_sections[r_symndx];
404
 
                  rel->r_addend += sec->output_offset + sym->st_value;
405
 
                }
406
 
            }
407
 
 
 
474
          if (r_symndx >= symtab_hdr->sh_info)
 
475
            continue;
 
476
 
 
477
          sym = local_syms + r_symndx;
 
478
          if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
 
479
            continue;
 
480
 
 
481
          sec = local_sections[r_symndx];
 
482
          val = sec->output_offset;
 
483
          if (val == 0)
 
484
            continue;
 
485
 
 
486
          where = contents + rel->r_offset;
 
487
          val += extract_rel_addend (input_bfd, where, howto);
 
488
          insert_rel_addend (input_bfd, where, howto, val);
408
489
          continue;
409
490
        }
410
491
 
416
497
        {
417
498
          sym = local_syms + r_symndx;
418
499
          sec = local_sections[r_symndx];
419
 
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
 
500
          relocation = (sec->output_section->vma
 
501
                        + sec->output_offset
 
502
                        + sym->st_value);
 
503
          if ((sec->flags & SEC_MERGE)
 
504
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
 
505
            {
 
506
              asection *msec;
 
507
              bfd_vma addend;
 
508
              bfd_byte *where = contents + rel->r_offset;
 
509
 
 
510
              addend = extract_rel_addend (input_bfd, where, howto);
 
511
              msec = sec;
 
512
              addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
 
513
              addend -= relocation;
 
514
              addend += msec->output_section->vma + msec->output_offset;
 
515
              insert_rel_addend (input_bfd, where, howto, addend);
 
516
            }
420
517
        }
421
518
      else
422
519
        {
423
 
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
424
 
          while (h->root.type == bfd_link_hash_indirect
425
 
                 || h->root.type == bfd_link_hash_warning)
426
 
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
427
 
          if (h->root.type == bfd_link_hash_defined
428
 
              || h->root.type == bfd_link_hash_defweak)
429
 
            {
430
 
              sec = h->root.u.def.section;
431
 
              relocation = (h->root.u.def.value
432
 
                            + sec->output_section->vma
433
 
                            + sec->output_offset);
434
 
            }
435
 
          else if (h->root.type == bfd_link_hash_undefweak)
436
 
            relocation = 0;
437
 
          else
438
 
            {
439
 
              if (!((*info->callbacks->undefined_symbol)
440
 
                    (info, h->root.root.string, input_bfd,
441
 
                     input_section, rel->r_offset, TRUE)))
442
 
                return FALSE;
443
 
              relocation = 0;
444
 
            }
 
520
          bfd_boolean unresolved_reloc, warned;
 
521
 
 
522
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
 
523
                                   r_symndx, symtab_hdr, sym_hashes,
 
524
                                   h, sec, relocation,
 
525
                                   unresolved_reloc, warned);
445
526
        }
446
527
 
447
528
      if (h != NULL)
456
537
 
457
538
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
458
539
                                    contents, rel->r_offset,
459
 
                                    relocation, rel->r_addend);
 
540
                                    relocation, (bfd_vma) 0);
460
541
 
461
542
      if (r != bfd_reloc_ok)
462
543
        {