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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-score.c] - Diff between revs 157 and 225

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 157 Rev 225
Line 1... Line 1...
/* 32-bit ELF support for S+core.
/* 32-bit ELF support for S+core.
   Copyright 2006, 2007 Free Software Foundation, Inc.
   Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
   Contributed by
   Contributed by
 
   Brain.lin (brain.lin@sunplusct.com)
   Mei Ligang (ligang@sunnorth.com.cn)
   Mei Ligang (ligang@sunnorth.com.cn)
   Pei-Lin Tsai (pltsai@sunplus.com)
   Pei-Lin Tsai (pltsai@sunplus.com)
 
 
   This file is part of BFD, the Binary File Descriptor library.
   This file is part of BFD, the Binary File Descriptor library.
 
 
Line 28... Line 29...
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf/score.h"
#include "elf/score.h"
#include "elf/common.h"
#include "elf/common.h"
#include "elf/internal.h"
#include "elf/internal.h"
#include "hashtab.h"
#include "hashtab.h"
 
#include "elf32-score.h"
 
 
 
 
/* Score ELF linker hash table.  */
int score3 = 0;
 
int score7 = 1;
 
 
 
/* Score ELF linker hash table.  */
struct score_elf_link_hash_table
struct score_elf_link_hash_table
{
{
  /* The main hash table.  */
  /* The main hash table.  */
  struct elf_link_hash_table root;
  struct elf_link_hash_table root;
};
};
 
 
/* The SCORE ELF linker needs additional information for each symbol in
/* The SCORE ELF linker needs additional information for each symbol in
   the global hash table.  */
   the global hash table.  */
 
 
struct score_elf_link_hash_entry
struct score_elf_link_hash_entry
{
{
  struct elf_link_hash_entry root;
  struct elf_link_hash_entry root;
 
 
  /* Number of R_SCORE_ABS32, R_SCORE_REL32 relocs against this symbol.  */
  /* Number of R_SCORE_ABS32, R_SCORE_REL32 relocs against this symbol.  */
Line 196... Line 199...
 
 
/* The default alignment for sections, as a power of two.  */
/* The default alignment for sections, as a power of two.  */
#define SCORE_ELF_LOG_FILE_ALIGN(abfd)\
#define SCORE_ELF_LOG_FILE_ALIGN(abfd)\
  (get_elf_backend_data (abfd)->s->log_file_align)
  (get_elf_backend_data (abfd)->s->log_file_align)
 
 
#ifndef NUM_ELEM
 
#define NUM_ELEM(a)  (sizeof (a) / (sizeof (a)[0]))
 
#endif
 
 
 
static bfd_byte *hi16_rel_addr;
static bfd_byte *hi16_rel_addr;
 
 
/* This will be used when we sort the dynamic relocation records.  */
/* This will be used when we sort the dynamic relocation records.  */
static bfd *reldyn_sorting_bfd;
static bfd *reldyn_sorting_bfd;
 
 
Line 214... Line 213...
   section.  This approach is copied from ecoff.c.  */
   section.  This approach is copied from ecoff.c.  */
static asection score_elf_scom_section;
static asection score_elf_scom_section;
static asymbol  score_elf_scom_symbol;
static asymbol  score_elf_scom_symbol;
static asymbol  *score_elf_scom_symbol_ptr;
static asymbol  *score_elf_scom_symbol_ptr;
 
 
 
static bfd_vma
 
score_bfd_get_16 (bfd *abfd, const void *data)
 
{
 
  return bfd_get_16 (abfd, data);
 
}
 
 
 
static bfd_vma
 
score3_bfd_getl32 (const void *p)
 
{
 
  const bfd_byte *addr = p;
 
  unsigned long v;
 
 
 
  v = (unsigned long) addr[2];
 
  v |= (unsigned long) addr[3] << 8;
 
  v |= (unsigned long) addr[0] << 16;
 
  v |= (unsigned long) addr[1] << 24;
 
  return v;
 
}
 
 
 
static bfd_vma
 
score3_bfd_getl48 (const void *p)
 
{
 
  const bfd_byte *addr = p;
 
  unsigned long long v;
 
 
 
  v = (unsigned long long) addr[4];
 
  v |= (unsigned long long) addr[5] << 8;
 
  v |= (unsigned long long) addr[2] << 16;
 
  v |= (unsigned long long) addr[3] << 24;
 
  v |= (unsigned long long) addr[0] << 32;
 
  v |= (unsigned long long) addr[1] << 40;
 
  return v;
 
}
 
 
 
static bfd_vma
 
score_bfd_get_32 (bfd *abfd, const void *data)
 
{
 
  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
 
    return score3_bfd_getl32 (data);
 
  else
 
    return bfd_get_32 (abfd, data);
 
}
 
 
 
static bfd_vma
 
score_bfd_get_48 (bfd *abfd, const void *p)
 
{
 
  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
 
    return score3_bfd_getl48 (p);
 
  else
 
    return bfd_get_bits (p, 48, 1);
 
}
 
 
 
static void
 
score_bfd_put_16 (bfd *abfd, bfd_vma addr, void *data)
 
{
 
  return bfd_put_16 (abfd, addr, data);
 
}
 
 
 
static void
 
score3_bfd_putl32 (bfd_vma data, void *p)
 
{
 
  bfd_byte *addr = p;
 
  addr[0] = (data >> 16) & 0xff;
 
  addr[1] = (data >> 24) & 0xff;
 
  addr[2] = data & 0xff;
 
  addr[3] = (data >>  8) & 0xff;
 
}
 
 
 
static void
 
score3_bfd_putl48 (bfd_vma data, void *p)
 
{
 
  bfd_byte *addr = p;
 
  addr[0] = (data >> 32) & 0xff;
 
  addr[1] = (data >> 40) & 0xff;
 
  addr[2] = (data >> 16) & 0xff;
 
  addr[3] = (data >> 24) & 0xff;
 
  addr[4] = data & 0xff;
 
  addr[5] = (data >>  8) & 0xff;
 
}
 
 
 
static void
 
score_bfd_put_32 (bfd *abfd, bfd_vma addr, void *data)
 
{
 
  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
 
    return score3_bfd_putl32 (addr, data);
 
  else
 
    return bfd_put_32 (abfd, addr, data);
 
}
 
 
 
static void
 
score_bfd_put_48 (bfd *abfd, bfd_vma val, void *p)
 
{
 
  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
 
    return score3_bfd_putl48 (val, p);
 
  else
 
    return bfd_put_bits (val, p, 48, 1);
 
}
 
 
static bfd_reloc_status_type
static bfd_reloc_status_type
score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                      arelent *reloc_entry,
                      arelent *reloc_entry,
                      asymbol *symbol ATTRIBUTE_UNUSED,
                      asymbol *symbol ATTRIBUTE_UNUSED,
                      void * data,
                      void * data,
Line 240... Line 337...
{
{
  bfd_vma addend = 0, offset = 0;
  bfd_vma addend = 0, offset = 0;
  unsigned long val;
  unsigned long val;
  unsigned long hi16_offset, hi16_value, uvalue;
  unsigned long hi16_offset, hi16_value, uvalue;
 
 
  hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
  hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
  hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
  hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
  addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
  offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
  val = reloc_entry->addend;
  val = reloc_entry->addend;
  if (reloc_entry->address > input_section->size)
  if (reloc_entry->address > input_section->size)
    return bfd_reloc_outofrange;
    return bfd_reloc_outofrange;
  uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
  uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
  hi16_offset = (uvalue >> 16) << 1;
  hi16_offset = (uvalue >> 16) << 1;
  hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
  hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
  bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
  score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
  offset = (uvalue & 0xffff) << 1;
  offset = (uvalue & 0xffff) << 1;
  addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
  addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
  bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
  score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
  return bfd_reloc_ok;
  return bfd_reloc_ok;
}
}
 
 
/* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
/* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
   dangerous relocation.  */
   dangerous relocation.  */
Line 311... Line 408...
/* We have to figure out the gp value, so that we can adjust the
/* We have to figure out the gp value, so that we can adjust the
   symbol value correctly.  We look up the symbol _gp in the output
   symbol value correctly.  We look up the symbol _gp in the output
   BFD.  If we can't find it, we're stuck.  We cache it in the ELF
   BFD.  If we can't find it, we're stuck.  We cache it in the ELF
   target data.  We don't need to adjust the symbol value for an
   target data.  We don't need to adjust the symbol value for an
   external symbol if we are producing relocatable output.  */
   external symbol if we are producing relocatable output.  */
 
 
static bfd_reloc_status_type
static bfd_reloc_status_type
score_elf_final_gp (bfd *output_bfd,
score_elf_final_gp (bfd *output_bfd,
                    asymbol *symbol,
                    asymbol *symbol,
                    bfd_boolean relocatable,
                    bfd_boolean relocatable,
                    char **error_message,
                    char **error_message,
Line 370... Line 466...
  relocation += symbol->section->output_section->vma;
  relocation += symbol->section->output_section->vma;
  relocation += symbol->section->output_offset;
  relocation += symbol->section->output_offset;
  if (reloc_entry->address > input_section->size)
  if (reloc_entry->address > input_section->size)
    return bfd_reloc_outofrange;
    return bfd_reloc_outofrange;
 
 
  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  insn = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  if (((reloc_entry->addend & 0xffffc000) != 0)
  if (((reloc_entry->addend & 0xffffc000) != 0)
      && ((reloc_entry->addend & 0xffffc000) != 0xffffc000))
      && ((reloc_entry->addend & 0xffffc000) != 0xffffc000))
    return bfd_reloc_overflow;
    return bfd_reloc_overflow;
 
 
  insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff);
  insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff);
  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
  score_bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
  if (relocateable)
  if (relocateable)
    reloc_entry->address += input_section->output_offset;
    reloc_entry->address += input_section->output_offset;
 
 
  return bfd_reloc_ok;
  return bfd_reloc_ok;
}
}
Line 406... Line 502...
 
 
  /* Set val to the offset into the section or symbol.  */
  /* Set val to the offset into the section or symbol.  */
  val = reloc_entry->addend;
  val = reloc_entry->addend;
 
 
  if (reloc_entry->howto->partial_inplace)
  if (reloc_entry->howto->partial_inplace)
    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
    val += score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
 
  /* Adjust val for the final section location and GP value.  If we
  /* Adjust val for the final section location and GP value.  If we
     are producing relocatable output, we don't want to do this for
     are producing relocatable output, we don't want to do this for
     an external symbol.  */
     an external symbol.  */
  if (! relocatable
  if (! relocatable
      || (symbol->flags & BSF_SECTION_SYM) != 0)
      || (symbol->flags & BSF_SECTION_SYM) != 0)
    val += relocation - gp;
    val += relocation - gp;
 
 
  if (reloc_entry->howto->partial_inplace)
  if (reloc_entry->howto->partial_inplace)
    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
    score_bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
  else
  else
    reloc_entry->addend = val;
    reloc_entry->addend = val;
 
 
  if (relocatable)
  if (relocatable)
    reloc_entry->address += input_section->output_offset;
    reloc_entry->address += input_section->output_offset;
Line 439... Line 535...
{
{
  bfd_boolean relocateable;
  bfd_boolean relocateable;
  bfd_reloc_status_type ret;
  bfd_reloc_status_type ret;
  bfd_vma gp;
  bfd_vma gp;
 
 
  if (output_bfd != (bfd *) NULL
  if (output_bfd != NULL
      && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0)
      && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0)
    {
    {
      reloc_entry->address += input_section->output_offset;
      reloc_entry->address += input_section->output_offset;
      return bfd_reloc_ok;
      return bfd_reloc_ok;
    }
    }
  if (output_bfd != (bfd *) NULL)
  if (output_bfd != NULL)
    relocateable = TRUE;
    relocateable = TRUE;
  else
  else
    {
    {
      relocateable = FALSE;
      relocateable = FALSE;
      output_bfd = symbol->section->output_section->owner;
      output_bfd = symbol->section->output_section->owner;
Line 495... Line 591...
 
 
  ret = score_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp);
  ret = score_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp);
  if (ret != bfd_reloc_ok)
  if (ret != bfd_reloc_ok)
    return ret;
    return ret;
 
 
  gp = 0;   /* FIXME.  */
  gp = 0;
  return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
  return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
                          relocatable, data, gp);
                          relocatable, data, gp);
}
}
 
 
/* A howto special_function for R_SCORE_GOT15 relocations.  This is just
/* A howto special_function for R_SCORE_GOT15 relocations.  This is just
   like any other 16-bit relocation when applied to global symbols, but is
   like any other 16-bit relocation when applied to global symbols, but is
   treated in the same as R_SCORE_HI16 when applied to local symbols.  */
   treated in the same as R_SCORE_HI16 when applied to local symbols.  */
 
 
static bfd_reloc_status_type
static bfd_reloc_status_type
score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                       void *data, asection *input_section,
                       void *data, asection *input_section,
                       bfd *output_bfd, char **error_message)
                       bfd *output_bfd, char **error_message)
{
{
Line 534... Line 629...
{
{
  bfd_vma addend = 0, offset = 0;
  bfd_vma addend = 0, offset = 0;
  signed long val;
  signed long val;
  signed long hi16_offset, hi16_value, uvalue;
  signed long hi16_offset, hi16_value, uvalue;
 
 
  hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
  hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
  hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
  hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
  addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
  offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
  val = reloc_entry->addend;
  val = reloc_entry->addend;
  if (reloc_entry->address > input_section->size)
  if (reloc_entry->address > input_section->size)
    return bfd_reloc_outofrange;
    return bfd_reloc_outofrange;
  uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
  uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
  if ((uvalue > -0x8000) && (uvalue < 0x7fff))
  if ((uvalue > -0x8000) && (uvalue < 0x7fff))
    hi16_offset = 0;
    hi16_offset = 0;
  else
  else
    hi16_offset = (uvalue >> 16) & 0x7fff;
    hi16_offset = (uvalue >> 16) & 0x7fff;
  hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
  hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
  bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
  score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
  offset = (uvalue & 0xffff) << 1;
  offset = (uvalue & 0xffff) << 1;
  addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
  addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
  bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
  score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
  return bfd_reloc_ok;
  return bfd_reloc_ok;
}
}
 
 
static reloc_howto_type elf32_score_howto_table[] =
static reloc_howto_type elf32_score_howto_table[] =
{
{
Line 601... Line 696...
         TRUE,                  /* partial_inplace */
         TRUE,                  /* partial_inplace */
         0x37fff,               /* src_mask */
         0x37fff,               /* src_mask */
         0x37fff,               /* dst_mask */
         0x37fff,               /* dst_mask */
         FALSE),                /* pcrel_offset */
         FALSE),                /* pcrel_offset */
 
 
  /*  R_SCORE_DUMMY1 */
  /*  R_SCORE_BCMP */
  HOWTO (R_SCORE_DUMMY1,        /* type */
  HOWTO (R_SCORE_BCMP,          /* type */
         0,                     /* rightshift */
         1,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         TRUE,                  /* pc_relative */
         1,                     /* bitpos */
         1,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
         complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         bfd_elf_generic_reloc, /* special_function */
         "R_SCORE_DUMMY1",      /* name */
         "R_SCORE_BCMP",        /* name */
         TRUE,                  /* partial_inplace */
         FALSE,                 /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x03e00381,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         0x03e00381,            /* dst_mask */
         FALSE),                /* pcrel_offset */
         FALSE),                /* pcrel_offset */
 
 
  /*R_SCORE_24 */
  /*R_SCORE_24 */
  HOWTO (R_SCORE_24,            /* type */
  HOWTO (R_SCORE_24,            /* type */
         1,                     /* rightshift */
         1,                     /* rightshift */
Line 665... Line 760...
 
 
  /* R_SCORE16_PC8 */
  /* R_SCORE16_PC8 */
  HOWTO (R_SCORE16_PC8,         /* type */
  HOWTO (R_SCORE16_PC8,         /* type */
         1,                     /* rightshift */
         1,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         8,                     /* bitsize */
         9,                     /* bitsize */
         TRUE,                  /* pc_relative */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         0,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
         complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         bfd_elf_generic_reloc, /* special_function */
         "R_SCORE16_PC8",       /* name */
         "R_SCORE16_PC8",       /* name */
         FALSE,                 /* partial_inplace */
         FALSE,                 /* partial_inplace */
         0x000000ff,            /* src_mask */
         0x000001ff,            /* src_mask */
         0x000000ff,            /* dst_mask */
         0x000001ff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
         FALSE),                /* pcrel_offset */
 
 
  /* 32 bit absolute */
  /* 32 bit absolute */
  HOWTO (R_SCORE_ABS32,         /* type  8 */
  HOWTO (R_SCORE_ABS32,         /* type  8 */
         0,                     /* rightshift */
         0,                     /* rightshift */
Line 855... Line 950...
         "R_SCORE_DUMMY_HI16",  /* name */
         "R_SCORE_DUMMY_HI16",  /* name */
         TRUE,                  /* partial_inplace */
         TRUE,                  /* partial_inplace */
         0x37fff,               /* src_mask */
         0x37fff,               /* src_mask */
         0x37fff,               /* dst_mask */
         0x37fff,               /* dst_mask */
         FALSE),                /* pcrel_offset */
         FALSE),                /* pcrel_offset */
 
 
 
  /* R_SCORE_IMM30 */
 
  HOWTO (R_SCORE_IMM30,         /* type */
 
         2,                     /* rightshift */
 
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
         30,                    /* bitsize */
 
         FALSE,                 /* pc_relative */
 
         7,                     /* bitpos */
 
         complain_overflow_dont,/* complain_on_overflow */
 
         bfd_elf_generic_reloc, /* special_function */
 
         "R_SCORE_IMM30",       /* name */
 
         FALSE,                 /* partial_inplace */
 
         0x7f7fff7f80LL,        /* src_mask */
 
         0x7f7fff7f80LL,        /* dst_mask */
 
         FALSE),                /* pcrel_offset */
 
 
 
  /* R_SCORE_IMM32 */
 
  HOWTO (R_SCORE_IMM32,         /* type */
 
         0,                     /* rightshift */
 
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
         32,                    /* bitsize */
 
         FALSE,                 /* pc_relative */
 
         5,                     /* bitpos */
 
         complain_overflow_dont,/* complain_on_overflow */
 
         bfd_elf_generic_reloc, /* special_function */
 
         "R_SCORE_IMM32",       /* name */
 
         FALSE,                 /* partial_inplace */
 
         0x7f7fff7fe0LL,        /* src_mask */
 
         0x7f7fff7fe0LL,        /* dst_mask */
 
         FALSE),                /* pcrel_offset */
};
};
 
 
struct score_reloc_map
struct score_reloc_map
{
{
  bfd_reloc_code_real_type bfd_reloc_val;
  bfd_reloc_code_real_type bfd_reloc_val;
Line 868... Line 993...
static const struct score_reloc_map elf32_score_reloc_map[] =
static const struct score_reloc_map elf32_score_reloc_map[] =
{
{
  {BFD_RELOC_NONE,               R_SCORE_NONE},
  {BFD_RELOC_NONE,               R_SCORE_NONE},
  {BFD_RELOC_HI16_S,             R_SCORE_HI16},
  {BFD_RELOC_HI16_S,             R_SCORE_HI16},
  {BFD_RELOC_LO16,               R_SCORE_LO16},
  {BFD_RELOC_LO16,               R_SCORE_LO16},
  {BFD_RELOC_SCORE_DUMMY1,       R_SCORE_DUMMY1},
  {BFD_RELOC_SCORE_BCMP,         R_SCORE_BCMP},
  {BFD_RELOC_SCORE_JMP,          R_SCORE_24},
  {BFD_RELOC_SCORE_JMP,          R_SCORE_24},
  {BFD_RELOC_SCORE_BRANCH,       R_SCORE_PC19},
  {BFD_RELOC_SCORE_BRANCH,       R_SCORE_PC19},
  {BFD_RELOC_SCORE16_JMP,        R_SCORE16_11},
  {BFD_RELOC_SCORE16_JMP,        R_SCORE16_11},
  {BFD_RELOC_SCORE16_BRANCH,     R_SCORE16_PC8},
  {BFD_RELOC_SCORE16_BRANCH,     R_SCORE16_PC8},
  {BFD_RELOC_32,                 R_SCORE_ABS32},
  {BFD_RELOC_32,                 R_SCORE_ABS32},
Line 885... Line 1010...
  {BFD_RELOC_SCORE_GOT_LO16,     R_SCORE_GOT_LO16},
  {BFD_RELOC_SCORE_GOT_LO16,     R_SCORE_GOT_LO16},
  {BFD_RELOC_SCORE_CALL15,       R_SCORE_CALL15},
  {BFD_RELOC_SCORE_CALL15,       R_SCORE_CALL15},
  {BFD_RELOC_GPREL32,            R_SCORE_GPREL32},
  {BFD_RELOC_GPREL32,            R_SCORE_GPREL32},
  {BFD_RELOC_32_PCREL,           R_SCORE_REL32},
  {BFD_RELOC_32_PCREL,           R_SCORE_REL32},
  {BFD_RELOC_SCORE_DUMMY_HI16,   R_SCORE_DUMMY_HI16},
  {BFD_RELOC_SCORE_DUMMY_HI16,   R_SCORE_DUMMY_HI16},
 
  {BFD_RELOC_SCORE_IMM30,        R_SCORE_IMM30},
 
  {BFD_RELOC_SCORE_IMM32,        R_SCORE_IMM32},
};
};
 
 
/* got_entries only match if they're identical, except for gotidx, so
/* got_entries only match if they're identical, except for gotidx, so
   use all fields to compute the hash, and compare the appropriate
   use all fields to compute the hash, and compare the appropriate
   union members.  */
   union members.  */
 
 
static hashval_t
static hashval_t
score_elf_got_entry_hash (const void *entry_)
score_elf_got_entry_hash (const void *entry_)
{
{
  const struct score_got_entry *entry = (struct score_got_entry *)entry_;
  const struct score_got_entry *entry = (struct score_got_entry *)entry_;
 
 
Line 915... Line 1041...
}
}
 
 
/* If H needs a GOT entry, assign it the highest available dynamic
/* If H needs a GOT entry, assign it the highest available dynamic
   index.  Otherwise, assign it the lowest available dynamic
   index.  Otherwise, assign it the lowest available dynamic
   index.  */
   index.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data)
score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data)
{
{
  struct score_elf_hash_sort_data *hsd = data;
  struct score_elf_hash_sort_data *hsd = data;
 
 
Line 961... Line 1086...
  return sgot;
  return sgot;
}
}
 
 
/* Returns the GOT information associated with the link indicated by
/* Returns the GOT information associated with the link indicated by
   INFO.  If SGOTP is non-NULL, it is filled in with the GOT section.  */
   INFO.  If SGOTP is non-NULL, it is filled in with the GOT section.  */
 
 
static struct score_got_info *
static struct score_got_info *
score_elf_got_info (bfd *abfd, asection **sgotp)
score_elf_got_info (bfd *abfd, asection **sgotp)
{
{
  asection *sgot;
  asection *sgot;
  struct score_got_info *g;
  struct score_got_info *g;
Line 983... Line 1107...
 
 
/* Sort the dynamic symbol table so that symbols that need GOT entries
/* Sort the dynamic symbol table so that symbols that need GOT entries
   appear towards the end.  This reduces the amount of GOT space
   appear towards the end.  This reduces the amount of GOT space
   required.  MAX_LOCAL is used to set the number of local symbols
   required.  MAX_LOCAL is used to set the number of local symbols
   known to be in the dynamic symbol table.  During
   known to be in the dynamic symbol table.  During
   _bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
   s3_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
   section symbols are added and the count is higher.  */
   section symbols are added and the count is higher.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_sort_hash_table (struct bfd_link_info *info,
score_elf_sort_hash_table (struct bfd_link_info *info,
                           unsigned long max_local)
                           unsigned long max_local)
{
{
  struct score_elf_hash_sort_data hsd;
  struct score_elf_hash_sort_data hsd;
Line 1029... Line 1152...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Create an entry in an score ELF linker hash table.  */
/* Create an entry in an score ELF linker hash table.  */
 
 
static struct bfd_hash_entry *
static struct bfd_hash_entry *
score_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
score_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
                             struct bfd_hash_table *table,
                             struct bfd_hash_table *table,
                             const char *string)
                             const char *string)
{
{
Line 1060... Line 1182...
  return (struct bfd_hash_entry *)ret;
  return (struct bfd_hash_entry *)ret;
}
}
 
 
/* Returns the first relocation of type r_type found, beginning with
/* Returns the first relocation of type r_type found, beginning with
   RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
   RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
 
 
static const Elf_Internal_Rela *
static const Elf_Internal_Rela *
score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
                           const Elf_Internal_Rela *relocation,
                           const Elf_Internal_Rela *relocation,
                           const Elf_Internal_Rela *relend)
                           const Elf_Internal_Rela *relend)
{
{
Line 1081... Line 1202...
  return NULL;
  return NULL;
}
}
 
 
/* This function is called via qsort() to sort the dynamic relocation
/* This function is called via qsort() to sort the dynamic relocation
   entries by increasing r_symndx value.  */
   entries by increasing r_symndx value.  */
 
 
static int
static int
score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2)
score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2)
{
{
  Elf_Internal_Rela int_reloc1;
  Elf_Internal_Rela int_reloc1;
  Elf_Internal_Rela int_reloc2;
  Elf_Internal_Rela int_reloc2;
Line 1095... Line 1215...
 
 
  return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info));
  return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info));
}
}
 
 
/* Return whether a relocation is against a local symbol.  */
/* Return whether a relocation is against a local symbol.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_local_relocation_p (bfd *input_bfd,
score_elf_local_relocation_p (bfd *input_bfd,
                              const Elf_Internal_Rela *relocation,
                              const Elf_Internal_Rela *relocation,
 
                              asection **local_sections,
                              bfd_boolean check_forced)
                              bfd_boolean check_forced)
{
{
  unsigned long r_symndx;
  unsigned long r_symndx;
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Shdr *symtab_hdr;
  struct score_elf_link_hash_entry *h;
  struct score_elf_link_hash_entry *h;
  size_t extsymoff;
  size_t extsymoff;
 
 
  r_symndx = ELF32_R_SYM (relocation->r_info);
  r_symndx = ELF32_R_SYM (relocation->r_info);
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  extsymoff = symtab_hdr->sh_info;
  extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
 
 
  if (r_symndx < extsymoff)
  if (r_symndx < extsymoff)
    return TRUE;
    return TRUE;
 
  if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
 
    return TRUE;
 
 
  if (check_forced)
  if (check_forced)
    {
    {
      /* Look up the hash table to check whether the symbol was forced local.  */
      /* Look up the hash table to check whether the symbol was forced local.  */
      h = (struct score_elf_link_hash_entry *)
      h = (struct score_elf_link_hash_entry *)
Line 1130... Line 1252...
 
 
  return FALSE;
  return FALSE;
}
}
 
 
/* Returns the dynamic relocation section for DYNOBJ.  */
/* Returns the dynamic relocation section for DYNOBJ.  */
 
 
static asection *
static asection *
score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
{
{
  static const char dname[] = ".rel.dyn";
  static const char dname[] = ".rel.dyn";
  asection *sreloc;
  asection *sreloc;
Line 1176... Line 1297...
 
 
/* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
/* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
   is the original relocation, which is now being transformed into a
   is the original relocation, which is now being transformed into a
   dynamic relocation.  The ADDENDP is adjusted if necessary; the
   dynamic relocation.  The ADDENDP is adjusted if necessary; the
   caller should store the result in place of the original addend.  */
   caller should store the result in place of the original addend.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_create_dynamic_relocation (bfd *output_bfd,
score_elf_create_dynamic_relocation (bfd *output_bfd,
                                     struct bfd_link_info *info,
                                     struct bfd_link_info *info,
                                     const Elf_Internal_Rela *rel,
                                     const Elf_Internal_Rela *rel,
                                     struct score_elf_link_hash_entry *h,
                                     struct score_elf_link_hash_entry *h,
Line 1365... Line 1485...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Calculate the %high function.  */
/* Calculate the %high function.  */
 
 
static bfd_vma
static bfd_vma
score_elf_high (bfd_vma value)
score_elf_high (bfd_vma value)
{
{
  return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
  return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
}
}
 
 
/* Create a local GOT entry for VALUE.  Return the index of the entry,
/* Create a local GOT entry for VALUE.  Return the index of the entry,
   or -1 if it could not be created.  */
   or -1 if it could not be created.  */
 
 
static struct score_got_entry *
static struct score_got_entry *
score_elf_create_local_got_entry (bfd *abfd,
score_elf_create_local_got_entry (bfd *abfd,
                                  bfd *ibfd ATTRIBUTE_UNUSED,
                                  bfd *ibfd ATTRIBUTE_UNUSED,
                                  struct score_got_info *gg,
                                  struct score_got_info *gg,
                                  asection *sgot, bfd_vma value,
                                  asection *sgot, bfd_vma value,
Line 1415... Line 1533...
        (_("not enough GOT space for local GOT entries"));
        (_("not enough GOT space for local GOT entries"));
      bfd_set_error (bfd_error_bad_value);
      bfd_set_error (bfd_error_bad_value);
      return NULL;
      return NULL;
    }
    }
 
 
  bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx));
  score_bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx));
 
 
  return *loc;
  return *loc;
}
}
 
 
/* Find a GOT entry whose higher-order 16 bits are the same as those
/* Find a GOT entry whose higher-order 16 bits are the same as those
   for value.  Return the index into the GOT for this entry.  */
   for value.  Return the index into the GOT for this entry.  */
 
 
static bfd_vma
static bfd_vma
score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
                      bfd_vma value, bfd_boolean external)
                      bfd_vma value, bfd_boolean external)
{
{
  asection *sgot;
  asection *sgot;
Line 1451... Line 1568...
  else
  else
    return MINUS_ONE;
    return MINUS_ONE;
}
}
 
 
static void
static void
_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
s3_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
                            struct elf_link_hash_entry *entry,
                            struct elf_link_hash_entry *entry,
                            bfd_boolean force_local)
                            bfd_boolean force_local)
{
{
  bfd *dynobj;
  bfd *dynobj;
  asection *got;
  asection *got;
Line 1527... Line 1644...
}
}
 
 
/* If H is a symbol that needs a global GOT entry, but has a dynamic
/* If H is a symbol that needs a global GOT entry, but has a dynamic
   symbol table index lower than any we've seen to date, record it for
   symbol table index lower than any we've seen to date, record it for
   posterity.  */
   posterity.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
                                    bfd *abfd,
                                    bfd *abfd,
                                    struct bfd_link_info *info,
                                    struct bfd_link_info *info,
                                    struct score_got_info *g)
                                    struct score_got_info *g)
Line 1543... Line 1659...
    {
    {
      switch (ELF_ST_VISIBILITY (h->other))
      switch (ELF_ST_VISIBILITY (h->other))
        {
        {
        case STV_INTERNAL:
        case STV_INTERNAL:
        case STV_HIDDEN:
        case STV_HIDDEN:
          _bfd_score_elf_hide_symbol (info, h, TRUE);
          s3_bfd_score_elf_hide_symbol (info, h, TRUE);
          break;
          break;
        }
        }
      if (!bfd_elf_link_record_dynamic_symbol (info, h))
      if (!bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
        return FALSE;
    }
    }
Line 1582... Line 1698...
  return TRUE;
  return TRUE;
}
}
 
 
/* Reserve space in G for a GOT entry containing the value of symbol
/* Reserve space in G for a GOT entry containing the value of symbol
   SYMNDX in input bfd ABDF, plus ADDEND.  */
   SYMNDX in input bfd ABDF, plus ADDEND.  */
 
 
static bfd_boolean
static bfd_boolean
score_elf_record_local_got_symbol (bfd *abfd,
score_elf_record_local_got_symbol (bfd *abfd,
                                   long symndx,
                                   long symndx,
                                   bfd_vma addend,
                                   bfd_vma addend,
                                   struct score_got_info *g)
                                   struct score_got_info *g)
Line 1613... Line 1728...
}
}
 
 
/* Returns the GOT offset at which the indicated address can be found.
/* Returns the GOT offset at which the indicated address can be found.
   If there is not yet a GOT entry for this value, create one.
   If there is not yet a GOT entry for this value, create one.
   Returns -1 if no satisfactory GOT offset can be found.  */
   Returns -1 if no satisfactory GOT offset can be found.  */
 
 
static bfd_vma
static bfd_vma
score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
                          bfd_vma value, unsigned long r_symndx,
                          bfd_vma value, unsigned long r_symndx,
                          struct score_elf_link_hash_entry *h, int r_type)
                          struct score_elf_link_hash_entry *h, int r_type)
{
{
Line 1660... Line 1774...
 
 
  return index;
  return index;
}
}
 
 
/* Returns the offset for the entry at the INDEXth position in the GOT.  */
/* Returns the offset for the entry at the INDEXth position in the GOT.  */
 
 
static bfd_vma
static bfd_vma
score_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
score_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
                                 bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index)
                                 bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index)
{
{
  asection *sgot;
  asection *sgot;
Line 1739... Line 1852...
    }
    }
  while (got_entries == NULL);
  while (got_entries == NULL);
}
}
 
 
/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r  */
/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r  */
 
 
static void
static void
score_elf_add_to_rel (bfd *abfd,
score_elf_add_to_rel (bfd *abfd,
                      bfd_byte *address,
                      bfd_byte *address,
                      reloc_howto_type *howto,
                      reloc_howto_type *howto,
                      bfd_signed_vma increment)
                      bfd_signed_vma increment)
Line 1752... Line 1864...
  bfd_vma contents;
  bfd_vma contents;
  unsigned long offset;
  unsigned long offset;
  unsigned long r_type = howto->type;
  unsigned long r_type = howto->type;
  unsigned long hi16_addend, hi16_offset, hi16_value, uvalue;
  unsigned long hi16_addend, hi16_offset, hi16_value, uvalue;
 
 
  contents = bfd_get_32 (abfd, address);
  contents = score_bfd_get_32 (abfd, address);
  /* Get the (signed) value from the instruction.  */
  /* Get the (signed) value from the instruction.  */
  addend = contents & howto->src_mask;
  addend = contents & howto->src_mask;
  if (addend & ((howto->src_mask + 1) >> 1))
  if (addend & ((howto->src_mask + 1) >> 1))
    {
    {
      bfd_signed_vma mask;
      bfd_signed_vma mask;
Line 1773... Line 1885...
        (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff);
        (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff);
      offset += increment;
      offset += increment;
      contents =
      contents =
        (contents & ~howto->
        (contents & ~howto->
         src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff);
         src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff);
      bfd_put_32 (abfd, contents, address);
      score_bfd_put_32 (abfd, contents, address);
      break;
      break;
    case R_SCORE_HI16:
    case R_SCORE_HI16:
      break;
      break;
    case R_SCORE_LO16:
    case R_SCORE_LO16:
      hi16_addend = bfd_get_32 (abfd, address - 4);
      hi16_addend = score_bfd_get_32 (abfd, address - 4);
      hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
      hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
      offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1;
      offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1;
      offset = (hi16_offset << 16) | (offset & 0xffff);
      offset = (hi16_offset << 16) | (offset & 0xffff);
      uvalue = increment + offset;
      uvalue = increment + offset;
      hi16_offset = (uvalue >> 16) << 1;
      hi16_offset = (uvalue >> 16) << 1;
      hi16_value = (hi16_addend & (~(howto->dst_mask)))
      hi16_value = (hi16_addend & (~(howto->dst_mask)))
        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
      bfd_put_32 (abfd, hi16_value, address - 4);
      score_bfd_put_32 (abfd, hi16_value, address - 4);
      offset = (uvalue & 0xffff) << 1;
      offset = (uvalue & 0xffff) << 1;
      contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
      contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
      bfd_put_32 (abfd, contents, address);
      score_bfd_put_32 (abfd, contents, address);
      break;
      break;
    case R_SCORE_24:
    case R_SCORE_24:
      offset =
      offset =
        (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff);
        (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff);
      offset += increment;
      offset += increment;
      contents =
      contents =
        (contents & ~howto->
        (contents & ~howto->
         src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff);
         src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff);
      bfd_put_32 (abfd, contents, address);
      score_bfd_put_32 (abfd, contents, address);
      break;
      break;
 
 
    case R_SCORE16_11:
    case R_SCORE16_11:
 
 
      contents = bfd_get_16 (abfd, address);
      contents = score_bfd_get_16 (abfd, address);
      offset = contents & howto->src_mask;
      offset = contents & howto->src_mask;
      offset += increment;
      offset += increment;
      contents = (contents & ~howto->src_mask) | (offset & howto->src_mask);
      contents = (contents & ~howto->src_mask) | (offset & howto->src_mask);
      bfd_put_16 (abfd, contents, address);
      score_bfd_put_16 (abfd, contents, address);
 
 
      break;
      break;
    case R_SCORE16_PC8:
    case R_SCORE16_PC8:
 
 
      contents = bfd_get_16 (abfd, address);
      contents = score_bfd_get_16 (abfd, address);
      offset = (contents & howto->src_mask) + ((increment >> 1) & 0xff);
      offset = (contents & howto->src_mask) + ((increment >> 1) & 0x1ff);
 
      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
 
      score_bfd_put_16 (abfd, contents, address);
 
 
 
      break;
 
 
 
    case R_SCORE_BCMP:
 
      contents = score_bfd_get_32 (abfd, address);
 
      offset = (contents & howto->src_mask);
 
      offset <<= howto->rightshift;
 
      offset += increment;
 
      offset >>= howto->rightshift;
 
      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
 
      score_bfd_put_32 (abfd, contents, address);
 
      break;
 
 
 
    case R_SCORE_IMM30:
 
      contents = score_bfd_get_48 (abfd, address);
 
      offset = (contents & howto->src_mask);
 
      offset <<= howto->rightshift;
 
      offset += increment;
 
      offset >>= howto->rightshift;
      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
      bfd_put_16 (abfd, contents, address);
      score_bfd_put_48 (abfd, contents, address);
 
      break;
 
 
 
    case R_SCORE_IMM32:
 
      contents = score_bfd_get_48 (abfd, address);
 
      offset = (contents & howto->src_mask);
 
      offset += increment;
 
      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
 
      score_bfd_put_48 (abfd, contents, address);
      break;
      break;
 
 
    default:
    default:
      addend += increment;
      addend += increment;
      contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask);
      contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask);
      bfd_put_32 (abfd, contents, address);
      score_bfd_put_32 (abfd, contents, address);
      break;
      break;
    }
    }
}
}
 
 
/* Perform a relocation as part of a final link.  */
/* Perform a relocation as part of a final link.  */
 
 
static bfd_reloc_status_type
static bfd_reloc_status_type
score_elf_final_link_relocate (reloc_howto_type *howto,
score_elf_final_link_relocate (reloc_howto_type *howto,
                               bfd *input_bfd,
                               bfd *input_bfd,
                               bfd *output_bfd,
                               bfd *output_bfd,
                               asection *input_section,
                               asection *input_section,
Line 1840... Line 1981...
                               bfd_vma symbol,
                               bfd_vma symbol,
                               struct bfd_link_info *info,
                               struct bfd_link_info *info,
                               const char *sym_name ATTRIBUTE_UNUSED,
                               const char *sym_name ATTRIBUTE_UNUSED,
                               int sym_flags ATTRIBUTE_UNUSED,
                               int sym_flags ATTRIBUTE_UNUSED,
                               struct score_elf_link_hash_entry *h,
                               struct score_elf_link_hash_entry *h,
 
                               asection **local_sections,
                               bfd_boolean gp_disp_p)
                               bfd_boolean gp_disp_p)
{
{
  unsigned long r_type;
  unsigned long r_type;
  unsigned long r_symndx;
  unsigned long r_symndx;
  bfd_byte *hit_data = contents + rel->r_offset;
  bfd_byte *hit_data = contents + rel->r_offset;
Line 1862... Line 2004...
  bfd_boolean local_p;
  bfd_boolean local_p;
  /* The eventual value we will relocate.  */
  /* The eventual value we will relocate.  */
  bfd_vma value = symbol;
  bfd_vma value = symbol;
  unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0;
  unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0;
 
 
 
 
  if (elf_gp (output_bfd) == 0)
  if (elf_gp (output_bfd) == 0)
    {
    {
      struct bfd_link_hash_entry *bh;
      struct bfd_link_hash_entry *bh;
      asection *o;
      asection *o;
 
 
      bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1);
      bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1);
      if (bh != (struct bfd_link_hash_entry *)NULL && bh->type == bfd_link_hash_defined)
      if (bh != NULL && bh->type == bfd_link_hash_defined)
        elf_gp (output_bfd) = (bh->u.def.value
        elf_gp (output_bfd) = (bh->u.def.value
                               + bh->u.def.section->output_section->vma
                               + bh->u.def.section->output_section->vma
                               + bh->u.def.section->output_offset);
                               + bh->u.def.section->output_offset);
      else if (info->relocatable)
      else if (info->relocatable)
        {
        {
          bfd_vma lo = -1;
          bfd_vma lo = -1;
 
 
          /* Find the GP-relative section with the lowest offset.  */
          /* Find the GP-relative section with the lowest offset.  */
          for (o = output_bfd->sections; o != (asection *) NULL; o = o->next)
          for (o = output_bfd->sections; o != NULL; o = o->next)
            if (o->vma < lo)
            if (o->vma < lo)
              lo = o->vma;
              lo = o->vma;
          /* And calculate GP relative to that.  */
          /* And calculate GP relative to that.  */
          elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd);
          elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd);
        }
        }
Line 1895... Line 2038...
 
 
  /* Parse the relocation.  */
  /* Parse the relocation.  */
  r_symndx = ELF32_R_SYM (rel->r_info);
  r_symndx = ELF32_R_SYM (rel->r_info);
  r_type = ELF32_R_TYPE (rel->r_info);
  r_type = ELF32_R_TYPE (rel->r_info);
  rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
  rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
  local_p = score_elf_local_relocation_p (input_bfd, rel, TRUE);
  local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE);
 
 
  if (r_type == R_SCORE_GOT15)
  if (r_type == R_SCORE_GOT15)
    {
    {
      const Elf_Internal_Rela *relend;
      const Elf_Internal_Rela *relend;
      const Elf_Internal_Rela *lo16_rel;
      const Elf_Internal_Rela *lo16_rel;
Line 1910... Line 2053...
      relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
      relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
      lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
      lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
      if ((local_p) && (lo16_rel != NULL))
      if ((local_p) && (lo16_rel != NULL))
        {
        {
          bfd_vma tmp = 0;
          bfd_vma tmp = 0;
          tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
          tmp = score_bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
          lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
          lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
        }
        }
      addend = lo_value;
      addend = lo_value;
    }
    }
  else
  /* For score3 R_SCORE_ABS32.  */
 
  else if (r_type == R_SCORE_ABS32 || r_type == R_SCORE_REL32)
    {
    {
      addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
      addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
    }
    }
 
  else
 
    {
 
      addend = (score_bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
 
    }
 
 
  /* If we haven't already determined the GOT offset, or the GP value,
  /* If we haven't already determined the GOT offset, or the GP value,
     and we're going to need it, get it now.  */
     and we're going to need it, get it now.  */
  switch (r_type)
  switch (r_type)
    {
    {
Line 1940... Line 2088...
              /* This is a static link or a -Bsymbolic link.  The
              /* This is a static link or a -Bsymbolic link.  The
                 symbol is defined locally, or was forced to be local.
                 symbol is defined locally, or was forced to be local.
                 We must initialize this entry in the GOT.  */
                 We must initialize this entry in the GOT.  */
              bfd *tmpbfd = elf_hash_table (info)->dynobj;
              bfd *tmpbfd = elf_hash_table (info)->dynobj;
              asection *sgot = score_elf_got_section (tmpbfd, FALSE);
              asection *sgot = score_elf_got_section (tmpbfd, FALSE);
              bfd_put_32 (tmpbfd, value, sgot->contents + g);
              score_bfd_put_32 (tmpbfd, value, sgot->contents + g);
            }
            }
        }
        }
      else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
      else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
        {
        {
          /* There's no need to create a local GOT entry here; the
          /* There's no need to create a local GOT entry here; the
Line 2001... Line 2149...
          if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h,
          if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h,
                                                    symbol, &value,
                                                    symbol, &value,
                                                    input_section))
                                                    input_section))
            return bfd_reloc_undefined;
            return bfd_reloc_undefined;
        }
        }
 
      else if (r_symndx == 0)
 
        /* r_symndx will be zero only for relocs against symbols
 
           from removed linkonce sections, or sections discarded by
 
           a linker script.  */
 
        value = 0;
      else
      else
        {
        {
          if (r_type != R_SCORE_REL32)
          if (r_type != R_SCORE_REL32)
            value = symbol + addend;
            value = symbol + addend;
          else
          else
Line 2016... Line 2169...
 
 
    case R_SCORE_ABS16:
    case R_SCORE_ABS16:
      value += addend;
      value += addend;
      if ((long)value > 0x7fff || (long)value < -0x8000)
      if ((long)value > 0x7fff || (long)value < -0x8000)
        return bfd_reloc_overflow;
        return bfd_reloc_overflow;
      bfd_put_16 (input_bfd, value, hit_data);
      score_bfd_put_16 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_24:
    case R_SCORE_24:
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff);
      offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff);
      if ((offset & 0x1000000) != 0)
      if ((offset & 0x1000000) != 0)
        offset |= 0xfe000000;
        offset |= 0xfe000000;
      value += offset;
      value += offset;
 
      abs_value = abs (value - rel_addr);
 
      if ((abs_value & 0xfe000000) != 0)
 
        return bfd_reloc_overflow;
      addend = (addend & ~howto->src_mask)
      addend = (addend & ~howto->src_mask)
                | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff);
                | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff);
      bfd_put_32 (input_bfd, addend, hit_data);
      score_bfd_put_32 (input_bfd, addend, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
 
    /* signed imm32.  */
 
    case R_SCORE_IMM30:
 
      {
 
        int not_word_align_p = 0;
 
        bfd_vma imm_offset = 0;
 
        addend = score_bfd_get_48 (input_bfd, hit_data);
 
        imm_offset = ((addend >> 7) & 0xff)
 
                     | (((addend >> 16) & 0x7fff) << 8)
 
                     | (((addend >> 32) & 0x7f) << 23);
 
        imm_offset <<= howto->rightshift;
 
        value += imm_offset;
 
        value &= 0xffffffff;
 
 
 
        /* Check lw48/sw48 rd, value/label word align.  */
 
        if ((value & 0x3) != 0)
 
          not_word_align_p = 1;
 
 
 
        value >>= howto->rightshift;
 
        addend = (addend & ~howto->src_mask)
 
                 | (((value & 0xff) >> 0) << 7)
 
                 | (((value & 0x7fff00) >> 8) << 16)
 
                 | (((value & 0x3f800000) >> 23) << 32);
 
        score_bfd_put_48 (input_bfd, addend, hit_data);
 
        if (not_word_align_p)
 
          return bfd_reloc_other;
 
        else
 
          return bfd_reloc_ok;
 
      }
 
 
 
    case R_SCORE_IMM32:
 
      {
 
        bfd_vma imm_offset = 0;
 
        addend = score_bfd_get_48 (input_bfd, hit_data);
 
        imm_offset = ((addend >> 5) & 0x3ff)
 
                     | (((addend >> 16) & 0x7fff) << 10)
 
                     | (((addend >> 32) & 0x7f) << 25);
 
        value += imm_offset;
 
        value &= 0xffffffff;
 
        addend = (addend & ~howto->src_mask)
 
                 | ((value & 0x3ff) << 5)
 
                 | (((value >> 10) & 0x7fff) << 16)
 
                 | (((value >> 25) & 0x7f) << 32);
 
        score_bfd_put_48 (input_bfd, addend, hit_data);
 
        return bfd_reloc_ok;
 
      }
 
 
    case R_SCORE_PC19:
    case R_SCORE_PC19:
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff);
      offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff);
      if ((offset & 0x80000) != 0)
      if ((offset & 0x80000) != 0)
        offset |= 0xfff00000;
        offset |= 0xfff00000;
      abs_value = value = value - rel_addr + offset;
      abs_value = value = value - rel_addr + offset;
      /* exceed 20 bit : overflow.  */
      /* exceed 20 bit : overflow.  */
Line 2043... Line 2245...
        abs_value = 0xffffffff - value + 1;
        abs_value = 0xffffffff - value + 1;
      if ((abs_value & 0xfff80000) != 0)
      if ((abs_value & 0xfff80000) != 0)
        return bfd_reloc_overflow;
        return bfd_reloc_overflow;
      addend = (addend & ~howto->src_mask)
      addend = (addend & ~howto->src_mask)
                | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff);
                | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff);
      bfd_put_32 (input_bfd, addend, hit_data);
      score_bfd_put_32 (input_bfd, addend, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE16_11:
    case R_SCORE16_11:
      addend = bfd_get_16 (input_bfd, hit_data);
      addend = score_bfd_get_16 (input_bfd, hit_data);
      offset = addend & howto->src_mask;
      offset = addend & howto->src_mask;
      if ((offset & 0x800) != 0)        /* Offset is negative.  */
      if ((offset & 0x800) != 0)        /* Offset is negative.  */
        offset |= 0xfffff000;
        offset |= 0xfffff000;
      value += offset;
      value += offset;
 
      abs_value = abs (value - rel_addr);
 
      if ((abs_value & 0xfffff000) != 0)
 
        return bfd_reloc_overflow;
      addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
      addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
      bfd_put_16 (input_bfd, addend, hit_data);
      score_bfd_put_16 (input_bfd, addend, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE16_PC8:
    case R_SCORE16_PC8:
      addend = bfd_get_16 (input_bfd, hit_data);
      addend = score_bfd_get_16 (input_bfd, hit_data);
      offset = (addend & howto->src_mask) << 1;
      offset = (addend & howto->src_mask) << 1;
      if ((offset & 0x100) != 0)        /* Offset is negative.  */
      if ((offset & 0x200) != 0)        /* Offset is negative.  */
        offset |= 0xfffffe00;
        offset |= 0xfffffe00;
      abs_value = value = value - rel_addr + offset;
      abs_value = value = value - rel_addr + offset;
      /* Sign bit + exceed 9 bit.  */
      /* Sign bit + exceed 9 bit.  */
      if (((value & 0xffffff00) != 0) && ((value & 0xffffff00) != 0xffffff00))
      if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
        return bfd_reloc_overflow;
        return bfd_reloc_overflow;
      value >>= 1;
      value >>= 1;
      addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
      addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
      bfd_put_16 (input_bfd, addend, hit_data);
      score_bfd_put_16 (input_bfd, addend, hit_data);
 
      return bfd_reloc_ok;
 
 
 
    case R_SCORE_BCMP:
 
      addend = score_bfd_get_32 (input_bfd, hit_data);
 
      offset = (addend & howto->src_mask) << howto->rightshift;
 
      if ((offset & 0x200) != 0)        /* Offset is negative.  */
 
        offset |= 0xfffffe00;
 
      value = value - rel_addr + offset;
 
      /* Sign bit + exceed 9 bit.  */
 
      if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
 
        return bfd_reloc_overflow;
 
      value >>= howto->rightshift;
 
      addend = (addend & ~howto->src_mask)
 
               | (value & 0x1)
 
               | (((value >> 1) & 0x7) << 7)
 
               | (((value >> 4) & 0x1f) << 21);
 
      score_bfd_put_32 (input_bfd, addend, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_HI16:
    case R_SCORE_HI16:
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_LO16:
    case R_SCORE_LO16:
      hi16_addend = bfd_get_32 (input_bfd, hit_data - 4);
      hi16_addend = score_bfd_get_32 (input_bfd, hit_data - 4);
      hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
      hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
      offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
      offset = (hi16_offset << 16) | (offset & 0xffff);
      offset = (hi16_offset << 16) | (offset & 0xffff);
 
 
      if (!gp_disp_p)
      if (!gp_disp_p)
        uvalue = value + offset;
        uvalue = value + offset;
Line 2088... Line 2310...
        uvalue = offset + gp - rel_addr + 4;
        uvalue = offset + gp - rel_addr + 4;
 
 
      hi16_offset = (uvalue >> 16) << 1;
      hi16_offset = (uvalue >> 16) << 1;
      hi16_value = (hi16_addend & (~(howto->dst_mask)))
      hi16_value = (hi16_addend & (~(howto->dst_mask)))
                        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
                        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
      bfd_put_32 (input_bfd, hi16_value, hit_data - 4);
      score_bfd_put_32 (input_bfd, hi16_value, hit_data - 4);
      offset = (uvalue & 0xffff) << 1;
      offset = (uvalue & 0xffff) << 1;
      value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
      value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
      bfd_put_32 (input_bfd, value, hit_data);
      score_bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_GP15:
    case R_SCORE_GP15:
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      offset = addend & 0x7fff;
      offset = addend & 0x7fff;
      if ((offset & 0x4000) == 0x4000)
      if ((offset & 0x4000) == 0x4000)
        offset |= 0xffffc000;
        offset |= 0xffffc000;
      value = value + offset - gp;
      value = value + offset - gp;
      if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000))
      if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000))
        return bfd_reloc_overflow;
        return bfd_reloc_overflow;
      value = (addend & ~howto->src_mask) | (value & howto->src_mask);
      value = (addend & ~howto->src_mask) | (value & howto->src_mask);
      bfd_put_32 (input_bfd, value, hit_data);
      score_bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_GOT15:
    case R_SCORE_GOT15:
    case R_SCORE_CALL15:
    case R_SCORE_CALL15:
      if (local_p)
      if (local_p)
        {
        {
          bfd_boolean forced;
          bfd_boolean forced;
 
 
          /* The special case is when the symbol is forced to be local.  We need the
          /* The special case is when the symbol is forced to be local.  We need the
             full address in the GOT since no R_SCORE_GOT_LO16 relocation follows.  */
             full address in the GOT since no R_SCORE_GOT_LO16 relocation follows.  */
          forced = ! score_elf_local_relocation_p (input_bfd, rel, FALSE);
          forced = ! score_elf_local_relocation_p (input_bfd, rel,
 
                                                   local_sections, FALSE);
          value = score_elf_got16_entry (output_bfd, input_bfd, info,
          value = score_elf_got16_entry (output_bfd, input_bfd, info,
                                         symbol + addend, forced);
                                         symbol + addend, forced);
          if (value == MINUS_ONE)
          if (value == MINUS_ONE)
            return bfd_reloc_outofrange;
            return bfd_reloc_outofrange;
          value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
          value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
Line 2130... Line 2353...
        }
        }
 
 
      if ((long) value > 0x3fff || (long) value < -0x4000)
      if ((long) value > 0x3fff || (long) value < -0x4000)
        return bfd_reloc_overflow;
        return bfd_reloc_overflow;
 
 
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
      value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
      bfd_put_32 (input_bfd, value, hit_data);
      score_bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_GPREL32:
    case R_SCORE_GPREL32:
      value = (addend + symbol - gp);
      value = (addend + symbol - gp);
      value &= howto->dst_mask;
      value &= howto->dst_mask;
      bfd_put_32 (input_bfd, value, hit_data);
      score_bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_GOT_LO16:
    case R_SCORE_GOT_LO16:
      addend = bfd_get_32 (input_bfd, hit_data);
      addend = score_bfd_get_32 (input_bfd, hit_data);
      value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
      value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
      value += symbol;
      value += symbol;
      value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)
      value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)
               | (((value >> 14) & 0x3) << 16);
               | (((value >> 14) & 0x3) << 16);
 
 
      bfd_put_32 (input_bfd, value, hit_data);
      score_bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
    case R_SCORE_DUMMY_HI16:
    case R_SCORE_DUMMY_HI16:
      return bfd_reloc_ok;
      return bfd_reloc_ok;
 
 
Line 2165... Line 2388...
      return bfd_reloc_notsupported;
      return bfd_reloc_notsupported;
    }
    }
}
}
 
 
/* Score backend functions.  */
/* Score backend functions.  */
 
 
static void
static void
_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
s3_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
                          arelent *bfd_reloc,
                          arelent *bfd_reloc,
                          Elf_Internal_Rela *elf_reloc)
                          Elf_Internal_Rela *elf_reloc)
{
{
  unsigned int r_type;
  unsigned int r_type;
 
 
  r_type = ELF32_R_TYPE (elf_reloc->r_info);
  r_type = ELF32_R_TYPE (elf_reloc->r_info);
  if (r_type >= NUM_ELEM (elf32_score_howto_table))
  if (r_type >= ARRAY_SIZE (elf32_score_howto_table))
    bfd_reloc->howto = NULL;
    bfd_reloc->howto = NULL;
  else
  else
    bfd_reloc->howto = &elf32_score_howto_table[r_type];
    bfd_reloc->howto = &elf32_score_howto_table[r_type];
}
}
 
 
/* Relocate an score ELF section.  */
/* Relocate an score ELF section.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_relocate_section (bfd *output_bfd,
s3_bfd_score_elf_relocate_section (bfd *output_bfd,
                                 struct bfd_link_info *info,
                                 struct bfd_link_info *info,
                                 bfd *input_bfd,
                                 bfd *input_bfd,
                                 asection *input_section,
                                 asection *input_section,
                                 bfd_byte *contents,
                                 bfd_byte *contents,
                                 Elf_Internal_Rela *relocs,
                                 Elf_Internal_Rela *relocs,
Line 2223... Line 2444...
      if (!score_elf_sort_hash_table (info, dynsecsymcount + 1))
      if (!score_elf_sort_hash_table (info, dynsecsymcount + 1))
        return FALSE;
        return FALSE;
    }
    }
 
 
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  extsymoff = symtab_hdr->sh_info;
  extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
  sym_hashes = elf_sym_hashes (input_bfd);
  sym_hashes = elf_sym_hashes (input_bfd);
  rel = relocs;
  rel = relocs;
  relend = relocs + input_section->reloc_count;
  relend = relocs + input_section->reloc_count;
  for (; rel < relend; rel++)
  for (; rel < relend; rel++)
    {
    {
Line 2242... Line 2463...
      arelent bfd_reloc;
      arelent bfd_reloc;
 
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
 
 
      _bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel);
      s3_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel);
      howto = bfd_reloc.howto;
      howto = bfd_reloc.howto;
 
 
      h = NULL;
      h = NULL;
      sym = NULL;
      sym = NULL;
      sec = NULL;
      sec = NULL;
Line 2259... Line 2480...
                        + sec->output_offset
                        + sec->output_offset
                        + sym->st_value);
                        + sym->st_value);
          name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
          name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
 
 
          if (!info->relocatable
          if (!info->relocatable
              && (sec->flags & SEC_MERGE) != 0
              && (sec->flags & SEC_MERGE)
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
            {
            {
              asection *msec;
              asection *msec;
              bfd_vma addend, value;
              bfd_vma addend, value;
 
 
              switch (r_type)
              switch (r_type)
                {
                {
                case R_SCORE_HI16:
                case R_SCORE_HI16:
                  break;
                  break;
                case R_SCORE_LO16:
                case R_SCORE_LO16:
                  hi16_addend = bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
                  hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
                  hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
                  hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
                  offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
                  offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
                  addend = (hi16_offset << 16) | (offset & 0xffff);
                  addend = (hi16_offset << 16) | (offset & 0xffff);
                  msec = sec;
                  msec = sec;
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
                  addend -= relocation;
                  addend -= relocation;
                  addend += msec->output_section->vma + msec->output_offset;
                  addend += msec->output_section->vma + msec->output_offset;
                  uvalue = addend;
                  uvalue = addend;
                  hi16_offset = (uvalue >> 16) << 1;
                  hi16_offset = (uvalue >> 16) << 1;
                  hi16_value = (hi16_addend & (~(howto->dst_mask)))
                  hi16_value = (hi16_addend & (~(howto->dst_mask)))
                    | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
                    | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
                  bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
                  score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
                  offset = (uvalue & 0xffff) << 1;
                  offset = (uvalue & 0xffff) << 1;
                  value = (value & (~(howto->dst_mask)))
                  value = (value & (~(howto->dst_mask)))
                    | (offset & 0x7fff) | ((offset << 1) & 0x30000);
                    | (offset & 0x7fff) | ((offset << 1) & 0x30000);
                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  break;
                  break;
 
 
 
                case R_SCORE_IMM32:
 
                  {
 
                    value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
 
                    addend = ((value >> 5) & 0x3ff)
 
                              | (((value >> 16) & 0x7fff) << 10)
 
                              | (((value >> 32) & 0x7f) << 25);
 
                    msec = sec;
 
                    addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
 
                    addend -= relocation;
 
                    addend += msec->output_section->vma + msec->output_offset;
 
                    addend &= 0xffffffff;
 
                    value = (value & ~howto->src_mask)
 
                             | ((addend & 0x3ff) << 5)
 
                             | (((addend >> 10) & 0x7fff) << 16)
 
                             | (((addend >> 25) & 0x7f) << 32);
 
                    score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
 
                    break;
 
                  }
 
 
 
                case R_SCORE_IMM30:
 
                  {
 
                    int not_word_align_p = 0;
 
                    value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
 
                    addend = ((value >> 7) & 0xff)
 
                              | (((value >> 16) & 0x7fff) << 8)
 
                              | (((value >> 32) & 0x7f) << 23);
 
                    addend <<= howto->rightshift;
 
                    msec = sec;
 
                    addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
 
                    addend -= relocation;
 
                    addend += msec->output_section->vma + msec->output_offset;
 
                    addend &= 0xffffffff;
 
 
 
                    /* Check lw48/sw48 rd, value/label word align.  */
 
                    if ((addend & 0x3) != 0)
 
                      not_word_align_p = 1;
 
 
 
                    addend >>= howto->rightshift;
 
                    value = (value & ~howto->src_mask)
 
                             | (((addend & 0xff) >> 0) << 7)
 
                             | (((addend & 0x7fff00) >> 8) << 16)
 
                             | (((addend & 0x3f800000) >> 23) << 32);
 
                    score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
 
 
 
                    if (not_word_align_p)
 
                      return bfd_reloc_other;
 
                    else
 
                      break;
 
                  }
 
 
                case R_SCORE_GOT_LO16:
                case R_SCORE_GOT_LO16:
                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
                  addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
                  addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
                  msec = sec;
                  msec = sec;
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
                  addend += msec->output_section->vma + msec->output_offset;
                  addend += msec->output_section->vma + msec->output_offset;
                  value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
                  value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
                           | (((addend >> 14) & 0x3) << 16);
                           | (((addend >> 14) & 0x3) << 16);
 
 
                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  break;
                  break;
                default:
 
 
                case R_SCORE_ABS32:
 
                case R_SCORE_REL32:
                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  /* Get the (signed) value from the instruction.  */
                  /* Get the (signed) value from the instruction.  */
                  addend = value & howto->src_mask;
                  addend = value & howto->src_mask;
                  if (addend & ((howto->src_mask + 1) >> 1))
                  if (addend & ((howto->src_mask + 1) >> 1))
                    {
                    {
Line 2318... Line 2592...
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
                  addend += msec->output_section->vma + msec->output_offset;
                  addend += msec->output_section->vma + msec->output_offset;
                  value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
                  value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                  break;
                  break;
 
 
 
                default:
 
                  value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
 
                  /* Get the (signed) value from the instruction.  */
 
                  addend = value & howto->src_mask;
 
                  if (addend & ((howto->src_mask + 1) >> 1))
 
                    {
 
                      bfd_signed_vma mask;
 
 
 
                      mask = -1;
 
                      mask &= ~howto->src_mask;
 
                      addend |= mask;
 
                    }
 
                  msec = sec;
 
                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
 
                  addend += msec->output_section->vma + msec->output_offset;
 
                  value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
 
                  score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
 
                  break;
                }
                }
            }
            }
        }
        }
      else
      else
        {
        {
Line 2375... Line 2668...
                   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
                   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
            relocation = 0;
            relocation = 0;
          else if (strcmp (name, "_DYNAMIC_LINK") == 0)
          else if (strcmp (name, "_DYNAMIC_LINK") == 0)
            {
            {
              /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
              /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
                 in _bfd_score_elf_create_dynamic_sections.  Otherwise, we should define
                 in s3_bfd_score_elf_create_dynamic_sections.  Otherwise, we should define
                 the symbol with a value of 0.  */
                 the symbol with a value of 0.  */
              BFD_ASSERT (! info->shared);
              BFD_ASSERT (! info->shared);
              BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
              BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
              relocation = 0;
              relocation = 0;
            }
            }
Line 2410... Line 2703...
        {
        {
          /* This is a relocatable link.  We don't have to change
          /* This is a relocatable link.  We don't have to change
             anything, unless the reloc is against a section symbol,
             anything, unless the reloc is against a section symbol,
             in which case we have to adjust according to where the
             in which case we have to adjust according to where the
             section symbol winds up in the output section.  */
             section symbol winds up in the output section.  */
          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
          if (r_symndx < symtab_hdr->sh_info)
 
            {
 
              sym = local_syms + r_symndx;
 
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
 
                {
 
                  sec = local_sections[r_symndx];
            score_elf_add_to_rel (input_bfd, contents + rel->r_offset,
            score_elf_add_to_rel (input_bfd, contents + rel->r_offset,
                                  howto, (bfd_signed_vma) sec->output_offset);
                                    howto, (bfd_signed_vma) (sec->output_offset + sym->st_value));
 
                }
 
            }
          continue;
          continue;
        }
        }
 
 
 
      /* This is a final link.  */
      r = score_elf_final_link_relocate (howto, input_bfd, output_bfd,
      r = score_elf_final_link_relocate (howto, input_bfd, output_bfd,
                                         input_section, contents, rel, relocs,
                                         input_section, contents, rel, relocs,
                                         relocation, info, name,
                                         relocation, info, name,
                                         (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) :
                                         (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) :
                                         ELF_ST_TYPE ((unsigned int)sym->st_info)), h,
                                         ELF_ST_TYPE ((unsigned int)sym->st_info)), h, local_sections,
                                         gp_disp_p);
                                         gp_disp_p);
 
 
      if (r != bfd_reloc_ok)
      if (r != bfd_reloc_ok)
        {
        {
          const char *msg = (const char *)0;
          const char *msg = (const char *)0;
Line 2457... Line 2758...
 
 
            case bfd_reloc_dangerous:
            case bfd_reloc_dangerous:
              msg = _("internal error: dangerous error");
              msg = _("internal error: dangerous error");
              goto common_error;
              goto common_error;
 
 
 
            /* Use bfd_reloc_other to check lw48, sw48 word align.  */
 
            case bfd_reloc_other:
 
              msg = _("address not word align");
 
              goto common_error;
 
 
            default:
            default:
              msg = _("internal error: unknown error");
              msg = _("internal error: unknown error");
              /* fall through */
              /* fall through */
 
 
            common_error:
            common_error:
Line 2475... Line 2781...
  return TRUE;
  return TRUE;
}
}
 
 
/* Look through the relocs for a section during the first phase, and
/* Look through the relocs for a section during the first phase, and
   allocate space in the global offset table.  */
   allocate space in the global offset table.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_check_relocs (bfd *abfd,
s3_bfd_score_elf_check_relocs (bfd *abfd,
                             struct bfd_link_info *info,
                             struct bfd_link_info *info,
                             asection *sec,
                             asection *sec,
                             const Elf_Internal_Rela *relocs)
                             const Elf_Internal_Rela *relocs)
{
{
  const char *name;
  const char *name;
Line 2500... Line 2805...
    return TRUE;
    return TRUE;
 
 
  dynobj = elf_hash_table (info)->dynobj;
  dynobj = elf_hash_table (info)->dynobj;
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  sym_hashes = elf_sym_hashes (abfd);
  extsymoff = symtab_hdr->sh_info;
  extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
 
 
  name = bfd_get_section_name (abfd, sec);
  name = bfd_get_section_name (abfd, sec);
 
 
  if (dynobj == NULL)
  if (dynobj == NULL)
    {
    {
Line 2676... Line 2981...
          break;
          break;
 
 
          /* This relocation describes which C++ vtable entries are actually
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
             used.  Record for later use during GC.  */
        case R_SCORE_GNU_VTENTRY:
        case R_SCORE_GNU_VTENTRY:
          BFD_ASSERT (h != NULL);
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
          if (h != NULL
 
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
 
            return FALSE;
            return FALSE;
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
Line 2707... Line 3010...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_add_symbol_hook (bfd *abfd,
s3_bfd_score_elf_add_symbol_hook (bfd *abfd,
                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
                                Elf_Internal_Sym *sym,
                                Elf_Internal_Sym *sym,
                                const char **namep ATTRIBUTE_UNUSED,
                                const char **namep ATTRIBUTE_UNUSED,
                                flagword *flagsp ATTRIBUTE_UNUSED,
                                flagword *flagsp ATTRIBUTE_UNUSED,
                                asection **secp,
                                asection **secp,
Line 2732... Line 3035...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static void
static void
_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
s3_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
{
{
  elf_symbol_type *elfsym;
  elf_symbol_type *elfsym;
 
 
  elfsym = (elf_symbol_type *) asym;
  elfsym = (elf_symbol_type *) asym;
  switch (elfsym->internal_elf_sym.st_shndx)
  switch (elfsym->internal_elf_sym.st_shndx)
Line 2763... Line 3066...
      asym->value = elfsym->internal_elf_sym.st_size;
      asym->value = elfsym->internal_elf_sym.st_size;
      break;
      break;
    }
    }
}
}
 
 
static bfd_boolean
static int
_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
s3_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
     const char *name ATTRIBUTE_UNUSED,
     const char *name ATTRIBUTE_UNUSED,
     Elf_Internal_Sym *sym,
     Elf_Internal_Sym *sym,
     asection *input_sec,
     asection *input_sec,
     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
{
{
Line 2776... Line 3079...
     if a symbol was small common in an input file, mark it as small
     if a symbol was small common in an input file, mark it as small
     common in the output file.  */
     common in the output file.  */
  if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
  if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
    sym->st_shndx = SHN_SCORE_SCOMMON;
    sym->st_shndx = SHN_SCORE_SCOMMON;
 
 
  return TRUE;
  return 1;
}
}
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
s3_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
                                         asection *sec,
                                         asection *sec,
                                         int *retval)
                                         int *retval)
{
{
  if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
  if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
    {
    {
Line 2797... Line 3100...
 
 
/* Adjust a symbol defined by a dynamic object and referenced by a
/* Adjust a symbol defined by a dynamic object and referenced by a
   regular object.  The current definition is in some section of the
   regular object.  The current definition is in some section of the
   dynamic object, but we're not including those sections.  We have to
   dynamic object, but we're not including those sections.  We have to
   change the definition to something the rest of the link can understand.  */
   change the definition to something the rest of the link can understand.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
s3_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
                                      struct elf_link_hash_entry *h)
                                      struct elf_link_hash_entry *h)
{
{
  bfd *dynobj;
  bfd *dynobj;
  struct score_elf_link_hash_entry *hscore;
  struct score_elf_link_hash_entry *hscore;
  asection *s;
  asection *s;
Line 2886... Line 3188...
  return TRUE;
  return TRUE;
}
}
 
 
/* This function is called after all the input files have been read,
/* This function is called after all the input files have been read,
   and the input sections have been assigned to output sections.  */
   and the input sections have been assigned to output sections.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_always_size_sections (bfd *output_bfd,
s3_bfd_score_elf_always_size_sections (bfd *output_bfd,
                                     struct bfd_link_info *info)
                                     struct bfd_link_info *info)
{
{
  bfd *dynobj;
  bfd *dynobj;
  asection *s;
  asection *s;
  struct score_got_info *g;
  struct score_got_info *g;
Line 2964... Line 3265...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Set the sizes of the dynamic sections.  */
/* Set the sizes of the dynamic sections.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
{
{
  bfd *dynobj;
  bfd *dynobj;
  asection *s;
  asection *s;
  bfd_boolean reltext;
  bfd_boolean reltext;
 
 
Line 3043... Line 3343...
                s->reloc_count = 0;
                s->reloc_count = 0;
            }
            }
        }
        }
      else if (CONST_STRNEQ (name, ".got"))
      else if (CONST_STRNEQ (name, ".got"))
        {
        {
          /* _bfd_score_elf_always_size_sections() has already done
          /* s3_bfd_score_elf_always_size_sections() has already done
             most of the work, but some symbols may have been mapped
             most of the work, but some symbols may have been mapped
             to versions that we must now resolve in the got_entries
             to versions that we must now resolve in the got_entries
             hash tables.  */
             hash tables.  */
        }
        }
      else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0)
      else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0)
Line 3072... Line 3372...
    }
    }
 
 
  if (elf_hash_table (info)->dynamic_sections_created)
  if (elf_hash_table (info)->dynamic_sections_created)
    {
    {
      /* Add some entries to the .dynamic section.  We fill in the
      /* Add some entries to the .dynamic section.  We fill in the
         values later, in _bfd_score_elf_finish_dynamic_sections, but we
         values later, in s3_bfd_score_elf_finish_dynamic_sections, but we
         must add the entries now so that we get the correct size for
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
         dynamic linker and used by the debugger.  */
 
 
      if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
      if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
Line 3127... Line 3427...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
{
{
  struct elf_link_hash_entry *h;
  struct elf_link_hash_entry *h;
  struct bfd_link_hash_entry *bh;
  struct bfd_link_hash_entry *bh;
  flagword flags;
  flagword flags;
  asection *s;
  asection *s;
Line 3171... Line 3471...
 
 
      name = "_DYNAMIC_LINK";
      name = "_DYNAMIC_LINK";
      bh = NULL;
      bh = NULL;
      if (!(_bfd_generic_link_add_one_symbol
      if (!(_bfd_generic_link_add_one_symbol
            (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
            (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
             (bfd_vma) 0, (const char *)NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
             (bfd_vma) 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
        return FALSE;
        return FALSE;
 
 
      h = (struct elf_link_hash_entry *)bh;
      h = (struct elf_link_hash_entry *)bh;
      h->non_elf = 0;
      h->non_elf = 0;
      h->def_regular = 1;
      h->def_regular = 1;
Line 3189... Line 3489...
}
}
 
 
 
 
/* Finish up dynamic symbol handling.  We set the contents of various
/* Finish up dynamic symbol handling.  We set the contents of various
   dynamic sections here.  */
   dynamic sections here.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
                                      struct bfd_link_info *info,
                                      struct bfd_link_info *info,
                                      struct elf_link_hash_entry *h,
                                      struct elf_link_hash_entry *h,
                                      Elf_Internal_Sym *sym)
                                      Elf_Internal_Sym *sym)
{
{
  bfd *dynobj;
  bfd *dynobj;
Line 3219... Line 3518...
      /* FIXME: Can h->dynindex be more than 64K?  */
      /* FIXME: Can h->dynindex be more than 64K?  */
      if (h->dynindx & 0xffff0000)
      if (h->dynindx & 0xffff0000)
        return FALSE;
        return FALSE;
 
 
      /* Fill the stub.  */
      /* Fill the stub.  */
      bfd_put_32 (output_bfd, STUB_LW, stub);
      score_bfd_put_32 (output_bfd, STUB_LW, stub);
      bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
      score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
      bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
      score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
      bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
      score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
 
 
      BFD_ASSERT (h->plt.offset <= s->size);
      BFD_ASSERT (h->plt.offset <= s->size);
      memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE);
      memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE);
 
 
      /* Mark the symbol as undefined.  plt.offset != -1 occurs
      /* Mark the symbol as undefined.  plt.offset != -1 occurs
Line 3254... Line 3553...
      bfd_vma offset;
      bfd_vma offset;
      bfd_vma value;
      bfd_vma value;
 
 
      value = sym->st_value;
      value = sym->st_value;
      offset = score_elf_global_got_index (dynobj, h);
      offset = score_elf_global_got_index (dynobj, h);
      bfd_put_32 (output_bfd, value, sgot->contents + offset);
      score_bfd_put_32 (output_bfd, value, sgot->contents + offset);
    }
    }
 
 
  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
  name = h->root.root.string;
  name = h->root.root.string;
  if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
  if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
Line 3278... Line 3577...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish up the dynamic sections.  */
/* Finish up the dynamic sections.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
                                        struct bfd_link_info *info)
                                        struct bfd_link_info *info)
{
{
  bfd *dynobj;
  bfd *dynobj;
  asection *sdyn;
  asection *sdyn;
  asection *sgot;
  asection *sgot;
Line 3400... Line 3698...
  /* The first entry of the global offset table will be filled at
  /* The first entry of the global offset table will be filled at
     runtime. The second entry will be used by some runtime loaders.
     runtime. The second entry will be used by some runtime loaders.
     This isn't the case of IRIX rld.  */
     This isn't the case of IRIX rld.  */
  if (sgot != NULL && sgot->size > 0)
  if (sgot != NULL && sgot->size > 0)
    {
    {
      bfd_put_32 (output_bfd, 0, sgot->contents);
      score_bfd_put_32 (output_bfd, 0, sgot->contents);
      bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
      score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
    }
    }
 
 
  if (sgot != NULL)
  if (sgot != NULL)
    elf_section_data (sgot->output_section)->this_hdr.sh_entsize
    elf_section_data (sgot->output_section)->this_hdr.sh_entsize
      = SCORE_ELF_GOT_SIZE (output_bfd);
      = SCORE_ELF_GOT_SIZE (output_bfd);
Line 3424... Line 3722...
  return TRUE;
  return TRUE;
}
}
 
 
/* This function set up the ELF section header for a BFD section in preparation for writing
/* This function set up the ELF section header for a BFD section in preparation for writing
   it out.  This is where the flags and type fields are set for unusual sections.  */
   it out.  This is where the flags and type fields are set for unusual sections.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
                              Elf_Internal_Shdr *hdr,
                              Elf_Internal_Shdr *hdr,
                              asection *sec)
                              asection *sec)
{
{
  const char *name;
  const char *name;
 
 
Line 3450... Line 3747...
 
 
/* assign_file_positions_except_relocs() check section flag and if it is allocatable,
/* assign_file_positions_except_relocs() check section flag and if it is allocatable,
   warning message will be issued.  backend_fake_section is called before
   warning message will be issued.  backend_fake_section is called before
   assign_file_positions_except_relocs(); backend_section_processing after it.  so, we
   assign_file_positions_except_relocs(); backend_section_processing after it.  so, we
   modify section flag there, but not backend_fake_section.  */
   modify section flag there, but not backend_fake_section.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
{
{
  if (hdr->bfd_section != NULL)
  if (hdr->bfd_section != NULL)
    {
    {
      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
 
 
Line 3479... Line 3775...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_write_section (bfd *output_bfd,
s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents)
                              struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
 
                              asection *sec, bfd_byte *contents)
 
{
{
  bfd_byte *to, *from, *end;
  bfd_byte *to, *from, *end;
  int i;
  int i;
 
 
  if (strcmp (sec->name, ".pdr") != 0)
  if (strcmp (sec->name, ".pdr") != 0)
Line 3512... Line 3806...
  return TRUE;
  return TRUE;
}
}
 
 
/* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old
/* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old
   indirect symbol.  Process additional relocation information.  */
   indirect symbol.  Process additional relocation information.  */
 
 
static void
static void
_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
                                     struct elf_link_hash_entry *dir,
                                     struct elf_link_hash_entry *dir,
                                     struct elf_link_hash_entry *ind)
                                     struct elf_link_hash_entry *ind)
{
{
  struct score_elf_link_hash_entry *dirscore, *indscore;
  struct score_elf_link_hash_entry *dirscore, *indscore;
 
 
Line 3537... Line 3830...
  if (indscore->no_fn_stub)
  if (indscore->no_fn_stub)
    dirscore->no_fn_stub = TRUE;
    dirscore->no_fn_stub = TRUE;
}
}
 
 
/* Remove information about discarded functions from other sections which mention them.  */
/* Remove information about discarded functions from other sections which mention them.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
                         struct bfd_link_info *info)
                         struct bfd_link_info *info)
{
{
  asection *o;
  asection *o;
  bfd_boolean ret = FALSE;
  bfd_boolean ret = FALSE;
  unsigned char *tdata;
  unsigned char *tdata;
Line 3591... Line 3883...
 
 
  return ret;
  return ret;
}
}
 
 
/* Signal that discard_info() has removed the discarded relocations for this section.  */
/* Signal that discard_info() has removed the discarded relocations for this section.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_ignore_discarded_relocs (asection *sec)
s3_bfd_score_elf_ignore_discarded_relocs (asection *sec)
{
{
  if (strcmp (sec->name, ".pdr") == 0)
  if (strcmp (sec->name, ".pdr") == 0)
    return TRUE;
    return TRUE;
  return FALSE;
  return FALSE;
}
}
 
 
/* Return the section that should be marked against GC for a given
/* Return the section that should be marked against GC for a given
   relocation.  */
   relocation.  */
 
 
static asection *
static asection *
_bfd_score_elf_gc_mark_hook (asection *sec,
s3_bfd_score_elf_gc_mark_hook (asection *sec,
                             struct bfd_link_info *info,
                             struct bfd_link_info *info,
                             Elf_Internal_Rela *rel,
                             Elf_Internal_Rela *rel,
                             struct elf_link_hash_entry *h,
                             struct elf_link_hash_entry *h,
                             Elf_Internal_Sym *sym)
                             Elf_Internal_Sym *sym)
{
{
Line 3624... Line 3914...
}
}
 
 
/* Support for core dump NOTE sections.  */
/* Support for core dump NOTE sections.  */
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
{
  int offset;
  int offset;
  unsigned int raw_size;
  unsigned int raw_size;
 
 
  switch (note->descsz)
  switch (note->descsz)
Line 3636... Line 3926...
    default:
    default:
      return FALSE;
      return FALSE;
 
 
    case 148:                  /* Linux/Score 32-bit.  */
    case 148:                  /* Linux/Score 32-bit.  */
      /* pr_cursig */
      /* pr_cursig */
      elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
      elf_tdata (abfd)->core_signal = score_bfd_get_16 (abfd, note->descdata + 12);
 
 
      /* pr_pid */
      /* pr_pid */
      elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
      elf_tdata (abfd)->core_pid = score_bfd_get_32 (abfd, note->descdata + 24);
 
 
      /* pr_reg */
      /* pr_reg */
      offset = 72;
      offset = 72;
      raw_size = 72;
      raw_size = 72;
 
 
Line 3653... Line 3943...
  /* Make a ".reg/999" section.  */
  /* Make a ".reg/999" section.  */
  return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, note->descpos + offset);
  return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, note->descpos + offset);
}
}
 
 
static bfd_boolean
static bfd_boolean
_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
{
  switch (note->descsz)
  switch (note->descsz)
    {
    {
    default:
    default:
      return FALSE;
      return FALSE;
Line 3682... Line 3972...
  return TRUE;
  return TRUE;
}
}
 
 
 
 
/* Score BFD functions.  */
/* Score BFD functions.  */
 
 
static reloc_howto_type *
static reloc_howto_type *
elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
{
{
  unsigned int i;
  unsigned int i;
 
 
  for (i = 0; i < NUM_ELEM (elf32_score_reloc_map); i++)
  for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++)
    if (elf32_score_reloc_map[i].bfd_reloc_val == code)
    if (elf32_score_reloc_map[i].bfd_reloc_val == code)
      return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val];
      return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val];
 
 
  return NULL;
  return NULL;
}
}
Line 3715... Line 4004...
}
}
 
 
/* Create a score elf linker hash table.  */
/* Create a score elf linker hash table.  */
 
 
static struct bfd_link_hash_table *
static struct bfd_link_hash_table *
elf32_score_link_hash_table_create (bfd *abfd)
s3_elf32_score_link_hash_table_create (bfd *abfd)
{
{
  struct score_elf_link_hash_table *ret;
  struct score_elf_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct score_elf_link_hash_table);
  bfd_size_type amt = sizeof (struct score_elf_link_hash_table);
 
 
  ret = bfd_malloc (amt);
  ret = bfd_malloc (amt);
Line 3735... Line 4024...
 
 
  return &ret->root.root;
  return &ret->root.root;
}
}
 
 
static bfd_boolean
static bfd_boolean
elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
{
{
  FILE *file = (FILE *) ptr;
  FILE *file = (FILE *) ptr;
 
 
  BFD_ASSERT (abfd != NULL && ptr != NULL);
  BFD_ASSERT (abfd != NULL && ptr != NULL);
 
 
Line 3760... Line 4049...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static bfd_boolean
static bfd_boolean
elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
s3_elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
{
{
  flagword in_flags;
  flagword in_flags;
  flagword out_flags;
  flagword out_flags;
 
 
  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
Line 3803... Line 4092...
 
 
  return TRUE;
  return TRUE;
}
}
 
 
static bfd_boolean
static bfd_boolean
elf32_score_new_section_hook (bfd *abfd, asection *sec)
s3_elf32_score_new_section_hook (bfd *abfd, asection *sec)
{
{
  struct _score_elf_section_data *sdata;
  struct _score_elf_section_data *sdata;
  bfd_size_type amt = sizeof (*sdata);
  bfd_size_type amt = sizeof (*sdata);
 
 
  sdata = bfd_zalloc (abfd, amt);
  sdata = bfd_zalloc (abfd, amt);
Line 3816... Line 4105...
  sec->used_by_bfd = sdata;
  sec->used_by_bfd = sdata;
 
 
  return _bfd_elf_new_section_hook (abfd, sec);
  return _bfd_elf_new_section_hook (abfd, sec);
}
}
 
 
 
/*****************************************************************************/
 
 
 
/* s3_s7: backend hooks.  */
 
static void
 
_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
 
                          arelent *bfd_reloc,
 
                          Elf_Internal_Rela *elf_reloc)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
 
  else
 
    return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_relocate_section (bfd *output_bfd,
 
                                 struct bfd_link_info *info,
 
                                 bfd *input_bfd,
 
                                 asection *input_section,
 
                                 bfd_byte *contents,
 
                                 Elf_Internal_Rela *relocs,
 
                                 Elf_Internal_Sym *local_syms,
 
                                 asection **local_sections)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_relocate_section (output_bfd,
 
             info, input_bfd, input_section, contents, relocs,
 
             local_syms, local_sections);
 
  else
 
    return s7_bfd_score_elf_relocate_section (output_bfd,
 
             info, input_bfd, input_section, contents, relocs,
 
             local_syms, local_sections);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_check_relocs (bfd *abfd,
 
                             struct bfd_link_info *info,
 
                             asection *sec,
 
                             const Elf_Internal_Rela *relocs)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
 
  else
 
    return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_add_symbol_hook (bfd *abfd,
 
                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
                                Elf_Internal_Sym *sym,
 
                                const char **namep ATTRIBUTE_UNUSED,
 
                                flagword *flagsp ATTRIBUTE_UNUSED,
 
                                asection **secp,
 
                                bfd_vma *valp)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
 
                                             secp, valp);
 
  else
 
    return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
 
                                             secp, valp);
 
}
 
 
 
static void
 
_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_symbol_processing (abfd, asym);
 
  else
 
    return s7_bfd_score_elf_symbol_processing (abfd, asym);
 
}
 
 
 
static int
 
_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
     const char *name ATTRIBUTE_UNUSED,
 
     Elf_Internal_Sym *sym,
 
     asection *input_sec,
 
     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
 
{
 
  /* If link a empty .o, then this filed is NULL.  */
 
  if (info->input_bfds == NULL)
 
    {
 
      /* If we see a common symbol, which implies a relocatable link, then
 
         if a symbol was small common in an input file, mark it as small
 
         common in the output file.  */
 
      if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
 
        sym->st_shndx = SHN_SCORE_SCOMMON;
 
      return 1;
 
    }
 
 
 
  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
 
    return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
 
  else
 
    return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
 
                                         asection *sec,
 
                                         int *retval)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
 
  else
 
    return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
                                      struct elf_link_hash_entry *h)
 
{
 
  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
 
    return s3_bfd_score_elf_adjust_dynamic_symbol (info, h);
 
  else
 
    return s7_bfd_score_elf_adjust_dynamic_symbol (info, h);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_always_size_sections (bfd *output_bfd,
 
                                     struct bfd_link_info *info)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_always_size_sections (output_bfd, info);
 
  else
 
    return s7_bfd_score_elf_always_size_sections (output_bfd, info);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info);
 
  else
 
    return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_create_dynamic_sections (abfd, info);
 
  else
 
    return s7_bfd_score_elf_create_dynamic_sections (abfd, info);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
 
                                      struct bfd_link_info *info,
 
                                      struct elf_link_hash_entry *h,
 
                                      Elf_Internal_Sym *sym)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
 
  else
 
    return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
 
                                        struct bfd_link_info *info)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
 
  else
 
    return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
 
                              Elf_Internal_Shdr *hdr,
 
                              asection *sec)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_fake_sections (abfd, hdr, sec);
 
  else
 
    return s7_bfd_score_elf_fake_sections (abfd, hdr, sec);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_section_processing (abfd, hdr);
 
  else
 
    return s7_bfd_score_elf_section_processing (abfd, hdr);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_write_section (bfd *output_bfd,
 
                              struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
 
                              asection *sec, bfd_byte *contents)
 
{
 
  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_write_section (output_bfd, sec, contents);
 
  else
 
    return s7_bfd_score_elf_write_section (output_bfd, sec, contents);
 
}
 
 
 
static void
 
_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
 
                                     struct elf_link_hash_entry *dir,
 
                                     struct elf_link_hash_entry *ind)
 
{
 
  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
 
    return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
 
  else
 
    return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
 
}
 
 
 
static void
 
_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
 
                            struct elf_link_hash_entry *entry,
 
                            bfd_boolean force_local)
 
{
 
  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
 
    return s3_bfd_score_elf_hide_symbol (info, entry, force_local);
 
  else
 
    return s7_bfd_score_elf_hide_symbol (info, entry, force_local);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
 
                         struct bfd_link_info *info)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_discard_info (abfd, cookie, info);
 
  else
 
    return s7_bfd_score_elf_discard_info (abfd, cookie, info);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_ignore_discarded_relocs (asection *sec)
 
{
 
  if (bfd_get_mach (sec->owner) == bfd_mach_score3)
 
    return s3_bfd_score_elf_ignore_discarded_relocs (sec);
 
  else
 
    return s7_bfd_score_elf_ignore_discarded_relocs (sec);
 
}
 
 
 
static asection *
 
_bfd_score_elf_gc_mark_hook (asection *sec,
 
                             struct bfd_link_info *info,
 
                             Elf_Internal_Rela *rel,
 
                             struct elf_link_hash_entry *h,
 
                             Elf_Internal_Sym *sym)
 
{
 
  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
 
    return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
 
  else
 
    return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_grok_prstatus (abfd, note);
 
  else
 
    return s7_bfd_score_elf_grok_prstatus (abfd, note);
 
}
 
 
 
static bfd_boolean
 
_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_bfd_score_elf_grok_psinfo (abfd, note);
 
  else
 
    return s7_bfd_score_elf_grok_psinfo (abfd, note);
 
}
 
 
 
static reloc_howto_type *
 
elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
 
{
 
  /* s3: NOTE!!!
 
     gas will call elf32_score_reloc_type_lookup, and don't write elf file.
 
     So just using score3, but we don't know ld will call this or not.
 
     If so, this way can't work.  */
 
 
 
  if (score3)
 
    return s3_elf32_score_reloc_type_lookup (abfd, code);
 
  else
 
    return s7_elf32_score_reloc_type_lookup (abfd, code);
 
}
 
 
 
static struct bfd_link_hash_table *
 
elf32_score_link_hash_table_create (bfd *abfd)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_elf32_score_link_hash_table_create (abfd);
 
  else
 
    return s7_elf32_score_link_hash_table_create (abfd);
 
}
 
 
 
static bfd_boolean
 
elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_elf32_score_print_private_bfd_data (abfd, ptr);
 
  else
 
    return s7_elf32_score_print_private_bfd_data (abfd, ptr);
 
}
 
 
 
static bfd_boolean
 
elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
{
 
  if (bfd_get_mach (obfd) == bfd_mach_score3)
 
    return s3_elf32_score_merge_private_bfd_data (ibfd, obfd);
 
  else
 
    return s7_elf32_score_merge_private_bfd_data (ibfd, obfd);
 
}
 
 
 
static bfd_boolean
 
elf32_score_new_section_hook (bfd *abfd, asection *sec)
 
{
 
  if (bfd_get_mach (abfd) == bfd_mach_score3)
 
    return s3_elf32_score_new_section_hook (abfd, sec);
 
  else
 
    return s7_elf32_score_new_section_hook (abfd, sec);
 
}
 
 
 
 
 
/* s3_s7: don't need to split.  */
 
 
 
/* Set the right machine number.  */
 
static bfd_boolean
 
_bfd_score_elf_score_object_p (bfd * abfd)
 
{
 
  int e_set = bfd_mach_score7;
 
 
 
  if (elf_elfheader (abfd)->e_machine == EM_SCORE)
 
    {
 
      int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD;
 
      switch (e_mach)
 
        {
 
        /* Set default target is score7.  */
 
        default:
 
        case E_SCORE_MACH_SCORE7:
 
          e_set = bfd_mach_score7;
 
          break;
 
 
 
        case E_SCORE_MACH_SCORE3:
 
          e_set = bfd_mach_score3;
 
          break;
 
        }
 
    }
 
 
 
  return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set);
 
}
 
 
 
bfd_boolean
 
_bfd_score_elf_common_definition (Elf_Internal_Sym *sym)
 
{
 
  return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON);
 
}
 
 
 
/*****************************************************************************/
 
 
 
 
#define USE_REL                         1
#define USE_REL                         1
#define TARGET_LITTLE_SYM               bfd_elf32_littlescore_vec
#define TARGET_LITTLE_SYM               bfd_elf32_littlescore_vec
#define TARGET_LITTLE_NAME              "elf32-littlescore"
#define TARGET_LITTLE_NAME              "elf32-littlescore"
#define TARGET_BIG_SYM                  bfd_elf32_bigscore_vec
#define TARGET_BIG_SYM                  bfd_elf32_bigscore_vec
#define TARGET_BIG_NAME                 "elf32-bigscore"
#define TARGET_BIG_NAME                 "elf32-bigscore"
#define ELF_ARCH                        bfd_arch_score
#define ELF_ARCH                        bfd_arch_score
#define ELF_MACHINE_CODE                EM_SCORE
#define ELF_MACHINE_CODE                EM_SCORE
 
#define ELF_MACHINE_ALT1                EM_SCORE_OLD
#define ELF_MAXPAGESIZE                 0x8000
#define ELF_MAXPAGESIZE                 0x8000
 
 
#define elf_info_to_howto               0
#define elf_info_to_howto               0
#define elf_info_to_howto_rel           _bfd_score_info_to_howto
#define elf_info_to_howto_rel           _bfd_score_info_to_howto
#define elf_backend_relocate_section    _bfd_score_elf_relocate_section
#define elf_backend_relocate_section    _bfd_score_elf_relocate_section
Line 3867... Line 4514...
#define elf_backend_want_plt_sym          0
#define elf_backend_want_plt_sym          0
#define elf_backend_got_header_size       (4 * SCORE_RESERVED_GOTNO)
#define elf_backend_got_header_size       (4 * SCORE_RESERVED_GOTNO)
#define elf_backend_plt_header_size       0
#define elf_backend_plt_header_size       0
#define elf_backend_collect               TRUE
#define elf_backend_collect               TRUE
#define elf_backend_type_change_ok        TRUE
#define elf_backend_type_change_ok        TRUE
 
#define elf_backend_object_p                  _bfd_score_elf_score_object_p
 
 
#define bfd_elf32_bfd_reloc_type_lookup      elf32_score_reloc_type_lookup
#define bfd_elf32_bfd_reloc_type_lookup      elf32_score_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup \
#define bfd_elf32_bfd_reloc_name_lookup \
  elf32_score_reloc_name_lookup
  elf32_score_reloc_name_lookup
#define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create

powered by: WebSVN 2.1.0

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