Blame bfd/elf32-mep.c

Packit bbfece
/* MeP-specific support for 32-bit ELF.
Packit bbfece
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit bbfece
Packit bbfece
   This file is part of BFD, the Binary File Descriptor library.
Packit bbfece
Packit bbfece
   This program is free software; you can redistribute it and/or modify
Packit bbfece
   it under the terms of the GNU General Public License as published by
Packit bbfece
   the Free Software Foundation; either version 3 of the License, or
Packit bbfece
   (at your option) any later version.
Packit bbfece
Packit bbfece
   This program is distributed in the hope that it will be useful,
Packit bbfece
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bbfece
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bbfece
   GNU General Public License for more details.
Packit bbfece
Packit bbfece
   You should have received a copy of the GNU General Public License
Packit bbfece
   along with this program; if not, write to the Free Software
Packit bbfece
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
Packit bbfece
   MA 02110-1301, USA.  */
Packit bbfece
Packit bbfece
#include "sysdep.h"
Packit bbfece
#include "bfd.h"
Packit bbfece
#include "libbfd.h"
Packit bbfece
#include "elf-bfd.h"
Packit bbfece
#include "elf/mep.h"
Packit bbfece
#include "libiberty.h"
Packit bbfece
Packit bbfece
/* Forward declarations.  */
Packit bbfece
Packit bbfece
/* Private relocation functions.  */
Packit bbfece

Packit bbfece
#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
Packit bbfece
  {(unsigned)type, right, size, bits, pcrel, left, overflow, bfd_elf_generic_reloc, #type, FALSE, 0, mask, 0 }
Packit bbfece
Packit bbfece
#define N complain_overflow_dont
Packit bbfece
#define S complain_overflow_signed
Packit bbfece
#define U complain_overflow_unsigned
Packit bbfece
Packit bbfece
static reloc_howto_type mep_elf_howto_table [] =
Packit bbfece
{
Packit bbfece
  /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
Packit bbfece
  MEPREL (R_MEP_NONE,	  3,  0, 0, 0, 0, N, 0),
Packit bbfece
  MEPREL (R_RELC,	  0,  0, 0, 0, 0, N, 0),
Packit bbfece
  /* MEPRELOC:HOWTO */
Packit bbfece
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
Packit bbfece
  MEPREL (R_MEP_8,	  0,  8, 0, 0, 0, U, 0xff),
Packit bbfece
  MEPREL (R_MEP_16,	  1, 16, 0, 0, 0, U, 0xffff),
Packit bbfece
  MEPREL (R_MEP_32,	  2, 32, 0, 0, 0, U, 0xffffffff),
Packit bbfece
  MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
Packit bbfece
  MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
Packit bbfece
  MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
Packit bbfece
  MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
Packit bbfece
  MEPREL (R_MEP_LOW16,	  2, 16, 0, 0, 0, N, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_HI16U,	  2, 32, 0,16, 0, N, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_HI16S,	  2, 32, 0,16, 0, N, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_GPREL,	  2, 16, 0, 0, 0, S, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_TPREL,	  2, 16, 0, 0, 0, S, 0x0000ffff),
Packit bbfece
  MEPREL (R_MEP_TPREL7,	  1,  7, 0, 0, 0, U, 0x007f),
Packit bbfece
  MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
Packit bbfece
  MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
Packit bbfece
  MEPREL (R_MEP_UIMM24,	  2, 24, 0, 0, 0, U, 0x00ffffff),
Packit bbfece
  MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
Packit bbfece
  MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
Packit bbfece
  MEPREL (R_MEP_GNU_VTENTRY,1,	0,16,32, 0, N, 0x0000),
Packit bbfece
  /* MEPRELOC:END */
Packit bbfece
};
Packit bbfece
Packit bbfece
#define VALID_MEP_RELOC(N) ((N) >= 0 \
Packit bbfece
  && (N) < ARRAY_SIZE (mep_elf_howto_table)
Packit bbfece
Packit bbfece
#undef N
Packit bbfece
#undef S
Packit bbfece
#undef U
Packit bbfece

Packit bbfece
Packit bbfece
#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
Packit bbfece
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
Packit bbfece
#define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
Packit bbfece
#else
Packit bbfece
#define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
Packit bbfece
#endif
Packit bbfece
Packit bbfece
static reloc_howto_type *
Packit bbfece
mep_reloc_type_lookup
Packit bbfece
    (bfd * abfd ATTRIBUTE_UNUSED,
Packit bbfece
     bfd_reloc_code_real_type code)
Packit bbfece
{
Packit bbfece
  unsigned int type = 0;
Packit bbfece
Packit bbfece
  switch (code)
Packit bbfece
    {
Packit bbfece
    MAP(NONE);
Packit bbfece
    case BFD_RELOC_8:
Packit bbfece
      type = R_MEP_8;
Packit bbfece
      break;
Packit bbfece
    case BFD_RELOC_16:
Packit bbfece
      type = R_MEP_16;
Packit bbfece
      break;
Packit bbfece
    case BFD_RELOC_32:
Packit bbfece
      type = R_MEP_32;
Packit bbfece
      break;
Packit bbfece
    case BFD_RELOC_VTABLE_ENTRY:
Packit bbfece
      type = R_MEP_GNU_VTENTRY;
Packit bbfece
      break;
Packit bbfece
    case BFD_RELOC_VTABLE_INHERIT:
Packit bbfece
      type = R_MEP_GNU_VTINHERIT;
Packit bbfece
      break;
Packit bbfece
    case BFD_RELOC_RELC:
Packit bbfece
      type = R_RELC;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    /* MEPRELOC:MAP */
Packit bbfece
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
Packit bbfece
    MAP(8);
Packit bbfece
    MAP(16);
Packit bbfece
    MAP(32);
Packit bbfece
    MAP(PCREL8A2);
Packit bbfece
    MAP(PCREL12A2);
Packit bbfece
    MAP(PCREL17A2);
Packit bbfece
    MAP(PCREL24A2);
Packit bbfece
    MAP(PCABS24A2);
Packit bbfece
    MAP(LOW16);
Packit bbfece
    MAP(HI16U);
Packit bbfece
    MAP(HI16S);
Packit bbfece
    MAP(GPREL);
Packit bbfece
    MAP(TPREL);
Packit bbfece
    MAP(TPREL7);
Packit bbfece
    MAP(TPREL7A2);
Packit bbfece
    MAP(TPREL7A4);
Packit bbfece
    MAP(UIMM24);
Packit bbfece
    MAP(ADDR24A4);
Packit bbfece
    MAP(GNU_VTINHERIT);
Packit bbfece
    MAP(GNU_VTENTRY);
Packit bbfece
    /* MEPRELOC:END */
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      /* Pacify gcc -Wall.  */
Packit bbfece
      _bfd_error_handler (_("mep: no reloc for code %d"), code);
Packit bbfece
      return NULL;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (mep_elf_howto_table[type].type != type)
Packit bbfece
    {
Packit bbfece
      /* xgettext:c-format */
Packit bbfece
      _bfd_error_handler (_("MeP: howto %d has type %d"),
Packit bbfece
			  type, mep_elf_howto_table[type].type);
Packit bbfece
      abort ();
Packit bbfece
    }
Packit bbfece
Packit bbfece
  return mep_elf_howto_table + type;
Packit bbfece
}
Packit bbfece
Packit bbfece
#undef MAP
Packit bbfece
Packit bbfece
static reloc_howto_type *
Packit bbfece
mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
Packit bbfece
{
Packit bbfece
  unsigned int i;
Packit bbfece
Packit bbfece
  for (i = 0;
Packit bbfece
       i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
Packit bbfece
       i++)
Packit bbfece
    if (mep_elf_howto_table[i].name != NULL
Packit bbfece
	&& strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
Packit bbfece
      return &mep_elf_howto_table[i];
Packit bbfece
Packit bbfece
  return NULL;
Packit bbfece
}
Packit bbfece

Packit bbfece
/* Perform a single relocation.  */
Packit bbfece
Packit bbfece
static struct bfd_link_info *mep_info;
Packit bbfece
static int warn_tp = 0, warn_sda = 0;
Packit bbfece
Packit bbfece
static bfd_vma
Packit bbfece
mep_lookup_global
Packit bbfece
    (char *    name,
Packit bbfece
     bfd_vma   ofs,
Packit bbfece
     bfd_vma * cache,
Packit bbfece
     int *     warn)
Packit bbfece
{
Packit bbfece
  struct bfd_link_hash_entry *h;
Packit bbfece
Packit bbfece
  if (*cache || *warn)
Packit bbfece
    return *cache;
Packit bbfece
Packit bbfece
  h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
Packit bbfece
  if (h == 0 || h->type != bfd_link_hash_defined)
Packit bbfece
    {
Packit bbfece
      *warn = ofs + 1;
Packit bbfece
      return 0;
Packit bbfece
    }
Packit bbfece
  *cache = (h->u.def.value
Packit bbfece
	  + h->u.def.section->output_section->vma
Packit bbfece
	  + h->u.def.section->output_offset);
Packit bbfece
  return *cache;
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_vma
Packit bbfece
mep_tpoff_base (bfd_vma ofs)
Packit bbfece
{
Packit bbfece
  static bfd_vma cache = 0;
Packit bbfece
  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_vma
Packit bbfece
mep_sdaoff_base (bfd_vma ofs)
Packit bbfece
{
Packit bbfece
  static bfd_vma cache = 0;
Packit bbfece
  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_reloc_status_type
Packit bbfece
mep_final_link_relocate
Packit bbfece
    (reloc_howto_type *	 howto,
Packit bbfece
     bfd *		 input_bfd,
Packit bbfece
     asection *		 input_section,
Packit bbfece
     bfd_byte *		 contents,
Packit bbfece
     Elf_Internal_Rela * rel,
Packit bbfece
     bfd_vma		 relocation)
Packit bbfece
{
Packit bbfece
  unsigned long u;
Packit bbfece
  long s;
Packit bbfece
  unsigned char *byte;
Packit bbfece
  bfd_vma pc;
Packit bbfece
  bfd_reloc_status_type r = bfd_reloc_ok;
Packit bbfece
  int e2, e4;
Packit bbfece
Packit bbfece
  if (bfd_big_endian (input_bfd))
Packit bbfece
    {
Packit bbfece
      e2 = 0;
Packit bbfece
      e4 = 0;
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      e2 = 1;
Packit bbfece
      e4 = 3;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  pc = (input_section->output_section->vma
Packit bbfece
	+ input_section->output_offset
Packit bbfece
	+ rel->r_offset);
Packit bbfece
Packit bbfece
  s = relocation + rel->r_addend;
Packit bbfece
Packit bbfece
  byte = (unsigned char *)contents + rel->r_offset;
Packit bbfece
Packit bbfece
  if (howto->type == R_MEP_PCREL24A2
Packit bbfece
      && s == 0
Packit bbfece
      && pc >= 0x800000)
Packit bbfece
    {
Packit bbfece
      /* This is an unreachable branch to an undefined weak function.
Packit bbfece
	 Silently ignore it, since the opcode can't do that but should
Packit bbfece
	 never be executed anyway.  */
Packit bbfece
      return bfd_reloc_ok;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (howto->pc_relative)
Packit bbfece
    s -= pc;
Packit bbfece
Packit bbfece
  u = (unsigned long) s;
Packit bbfece
Packit bbfece
  switch (howto->type)
Packit bbfece
    {
Packit bbfece
    /* MEPRELOC:APPLY */
Packit bbfece
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
Packit bbfece
    case R_MEP_8: /* 76543210 */
Packit bbfece
      if (u > 255) r = bfd_reloc_overflow;
Packit bbfece
      byte[0] = (u & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_16: /* fedcba9876543210 */
Packit bbfece
      if (u > 65535) r = bfd_reloc_overflow;
Packit bbfece
      byte[0^e2] = ((u >> 8) & 0xff);
Packit bbfece
      byte[1^e2] = (u & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
Packit bbfece
      byte[0^e4] = ((u >> 24) & 0xff);
Packit bbfece
      byte[1^e4] = ((u >> 16) & 0xff);
Packit bbfece
      byte[2^e4] = ((u >> 8) & 0xff);
Packit bbfece
      byte[3^e4] = (u & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_PCREL8A2: /* --------7654321- */
Packit bbfece
      if (-128 > s || s > 127) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_PCREL12A2: /* ----ba987654321- */
Packit bbfece
      if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
Packit bbfece
      byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
Packit bbfece
      if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
Packit bbfece
      byte[2^e2] = ((s >> 9) & 0xff);
Packit bbfece
      byte[3^e2] = ((s >> 1) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
Packit bbfece
      if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
Packit bbfece
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
Packit bbfece
      byte[2^e2] = ((s >> 16) & 0xff);
Packit bbfece
      byte[3^e2] = ((s >> 8) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
Packit bbfece
      if (u > 16777215) r = bfd_reloc_overflow;
Packit bbfece
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
Packit bbfece
      byte[2^e2] = ((u >> 16) & 0xff);
Packit bbfece
      byte[3^e2] = ((u >> 8) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_LOW16: /* ----------------fedcba9876543210 */
Packit bbfece
      byte[2^e2] = ((u >> 8) & 0xff);
Packit bbfece
      byte[3^e2] = (u & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
Packit bbfece
      byte[2^e2] = ((u >> 24) & 0xff);
Packit bbfece
      byte[3^e2] = ((u >> 16) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
Packit bbfece
      if (s & 0x8000)
Packit bbfece
	s += 0x10000;
Packit bbfece
      byte[2^e2] = ((s >> 24) & 0xff);
Packit bbfece
      byte[3^e2] = ((s >> 16) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_GPREL: /* ----------------fedcba9876543210 */
Packit bbfece
      s -= mep_sdaoff_base(rel->r_offset);
Packit bbfece
      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
Packit bbfece
      byte[2^e2] = ((s >> 8) & 0xff);
Packit bbfece
      byte[3^e2] = (s & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_TPREL: /* ----------------fedcba9876543210 */
Packit bbfece
      s -= mep_tpoff_base(rel->r_offset);
Packit bbfece
      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
Packit bbfece
      byte[2^e2] = ((s >> 8) & 0xff);
Packit bbfece
      byte[3^e2] = (s & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_TPREL7: /* ---------6543210 */
Packit bbfece
      u -= mep_tpoff_base(rel->r_offset);
Packit bbfece
      if (u > 127) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_TPREL7A2: /* ---------654321- */
Packit bbfece
      u -= mep_tpoff_base(rel->r_offset);
Packit bbfece
      if (u > 127) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_TPREL7A4: /* ---------65432-- */
Packit bbfece
      u -= mep_tpoff_base(rel->r_offset);
Packit bbfece
      if (u > 127) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
Packit bbfece
      if (u > 16777215) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (u & 0xff);
Packit bbfece
      byte[2^e2] = ((u >> 16) & 0xff);
Packit bbfece
      byte[3^e2] = ((u >> 8) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
Packit bbfece
      if (u > 16777215) r = bfd_reloc_overflow;
Packit bbfece
      byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
Packit bbfece
      byte[2^e2] = ((u >> 16) & 0xff);
Packit bbfece
      byte[3^e2] = ((u >> 8) & 0xff);
Packit bbfece
      break;
Packit bbfece
    case R_MEP_GNU_VTINHERIT: /* ---------------- */
Packit bbfece
      break;
Packit bbfece
    case R_MEP_GNU_VTENTRY: /* ---------------- */
Packit bbfece
      break;
Packit bbfece
    /* MEPRELOC:END */
Packit bbfece
    default:
Packit bbfece
      abort ();
Packit bbfece
    }
Packit bbfece
Packit bbfece
  return r;
Packit bbfece
}
Packit bbfece

Packit bbfece
/* Set the howto pointer for a MEP ELF reloc.  */
Packit bbfece
Packit bbfece
static void
Packit bbfece
mep_info_to_howto_rela
Packit bbfece
    (bfd *		 abfd ATTRIBUTE_UNUSED,
Packit bbfece
     arelent *		 cache_ptr,
Packit bbfece
     Elf_Internal_Rela * dst)
Packit bbfece
{
Packit bbfece
  unsigned int r_type;
Packit bbfece
Packit bbfece
  r_type = ELF32_R_TYPE (dst->r_info);
Packit bbfece
  if (r_type >= R_MEP_max)
Packit bbfece
    {
Packit bbfece
      /* xgettext:c-format */
Packit bbfece
      _bfd_error_handler (_("%B: invalid MEP reloc number: %d"), abfd, r_type);
Packit bbfece
      r_type = 0;
Packit bbfece
    }
Packit bbfece
  cache_ptr->howto = & mep_elf_howto_table [r_type];
Packit bbfece
}
Packit bbfece

Packit bbfece
/* Relocate a MEP ELF section.
Packit bbfece
   There is some attempt to make this function usable for many architectures,
Packit bbfece
   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
Packit bbfece
   if only to serve as a learning tool.
Packit bbfece
Packit bbfece
   The RELOCATE_SECTION function is called by the new ELF backend linker
Packit bbfece
   to handle the relocations for a section.
Packit bbfece
Packit bbfece
   The relocs are always passed as Rela structures; if the section
Packit bbfece
   actually uses Rel structures, the r_addend field will always be
Packit bbfece
   zero.
Packit bbfece
Packit bbfece
   This function is responsible for adjusting the section contents as
Packit bbfece
   necessary, and (if using Rela relocs and generating a relocatable
Packit bbfece
   output file) adjusting the reloc addend as necessary.
Packit bbfece
Packit bbfece
   This function does not have to worry about setting the reloc
Packit bbfece
   address or the reloc symbol index.
Packit bbfece
Packit bbfece
   LOCAL_SYMS is a pointer to the swapped in local symbols.
Packit bbfece
Packit bbfece
   LOCAL_SECTIONS is an array giving the section in the input file
Packit bbfece
   corresponding to the st_shndx field of each local symbol.
Packit bbfece
Packit bbfece
   The global hash table entry for the global symbols can be found
Packit bbfece
   via elf_sym_hashes (input_bfd).
Packit bbfece
Packit bbfece
   When generating relocatable output, this function must handle
Packit bbfece
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
Packit bbfece
   going to be the section symbol corresponding to the output
Packit bbfece
   section, which means that the addend must be adjusted
Packit bbfece
   accordingly.  */
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_relocate_section
Packit bbfece
    (bfd *		     output_bfd ATTRIBUTE_UNUSED,
Packit bbfece
     struct bfd_link_info *  info,
Packit bbfece
     bfd *		     input_bfd,
Packit bbfece
     asection *		     input_section,
Packit bbfece
     bfd_byte *		     contents,
Packit bbfece
     Elf_Internal_Rela *     relocs,
Packit bbfece
     Elf_Internal_Sym *	     local_syms,
Packit bbfece
     asection **	     local_sections)
Packit bbfece
{
Packit bbfece
  Elf_Internal_Shdr *		symtab_hdr;
Packit bbfece
  struct elf_link_hash_entry ** sym_hashes;
Packit bbfece
  Elf_Internal_Rela *		rel;
Packit bbfece
  Elf_Internal_Rela *		relend;
Packit bbfece
Packit bbfece
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
Packit bbfece
  sym_hashes = elf_sym_hashes (input_bfd);
Packit bbfece
  relend     = relocs + input_section->reloc_count;
Packit bbfece
Packit bbfece
  mep_info = info;
Packit bbfece
Packit bbfece
  for (rel = relocs; rel < relend; rel ++)
Packit bbfece
    {
Packit bbfece
      reloc_howto_type *	   howto;
Packit bbfece
      unsigned long		   r_symndx;
Packit bbfece
      Elf_Internal_Sym *	   sym;
Packit bbfece
      asection *		   sec;
Packit bbfece
      struct elf_link_hash_entry * h;
Packit bbfece
      bfd_vma			   relocation;
Packit bbfece
      bfd_reloc_status_type	   r;
Packit bbfece
      const char *		   name = NULL;
Packit bbfece
      int			   r_type;
Packit bbfece
Packit bbfece
      r_type = ELF32_R_TYPE (rel->r_info);
Packit bbfece
      r_symndx = ELF32_R_SYM (rel->r_info);
Packit bbfece
      howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
Packit bbfece
      h      = NULL;
Packit bbfece
      sym    = NULL;
Packit bbfece
      sec    = NULL;
Packit bbfece
Packit bbfece
      if (r_symndx < symtab_hdr->sh_info)
Packit bbfece
	{
Packit bbfece
	  sym = local_syms + r_symndx;
Packit bbfece
	  sec = local_sections [r_symndx];
Packit bbfece
	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
Packit bbfece
Packit bbfece
	  name = bfd_elf_string_from_elf_section
Packit bbfece
	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
Packit bbfece
	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  bfd_boolean warned, unresolved_reloc, ignored;
Packit bbfece
Packit bbfece
	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
Packit bbfece
				  r_symndx, symtab_hdr, sym_hashes,
Packit bbfece
				  h, sec, relocation,
Packit bbfece
				  unresolved_reloc, warned, ignored);
Packit bbfece
Packit bbfece
	  name = h->root.root.string;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (sec != NULL && discarded_section (sec))
Packit bbfece
	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
Packit bbfece
					 rel, 1, relend, howto, 0, contents);
Packit bbfece
Packit bbfece
      if (bfd_link_relocatable (info))
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      if (r_type == R_RELC)
Packit bbfece
	r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
Packit bbfece
						contents, rel, relocation);
Packit bbfece
      else
Packit bbfece
	r = mep_final_link_relocate (howto, input_bfd, input_section,
Packit bbfece
				     contents, rel, relocation);
Packit bbfece
Packit bbfece
      if (r != bfd_reloc_ok)
Packit bbfece
	{
Packit bbfece
	  const char * msg = (const char *) NULL;
Packit bbfece
Packit bbfece
	  switch (r)
Packit bbfece
	    {
Packit bbfece
	    case bfd_reloc_overflow:
Packit bbfece
	      (*info->callbacks->reloc_overflow)
Packit bbfece
		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
Packit bbfece
		 input_bfd, input_section, rel->r_offset);
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case bfd_reloc_undefined:
Packit bbfece
	      (*info->callbacks->undefined_symbol)
Packit bbfece
		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case bfd_reloc_outofrange:
Packit bbfece
	      msg = _("internal error: out of range error");
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case bfd_reloc_notsupported:
Packit bbfece
	      msg = _("internal error: unsupported relocation error");
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case bfd_reloc_dangerous:
Packit bbfece
	      msg = _("internal error: dangerous relocation");
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    default:
Packit bbfece
	      msg = _("internal error: unknown error");
Packit bbfece
	      break;
Packit bbfece
	    }
Packit bbfece
Packit bbfece
	  if (msg)
Packit bbfece
	    (*info->callbacks->warning) (info, msg, name, input_bfd,
Packit bbfece
					 input_section, rel->r_offset);
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (warn_tp)
Packit bbfece
    info->callbacks->undefined_symbol
Packit bbfece
      (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
Packit bbfece
  if (warn_sda)
Packit bbfece
    info->callbacks->undefined_symbol
Packit bbfece
      (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
Packit bbfece
  if (warn_sda || warn_tp)
Packit bbfece
    return FALSE;
Packit bbfece
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece

Packit bbfece
/* Function to set the ELF flag bits.  */
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_set_private_flags (bfd *    abfd,
Packit bbfece
			   flagword flags)
Packit bbfece
{
Packit bbfece
  elf_elfheader (abfd)->e_flags = flags;
Packit bbfece
  elf_flags_init (abfd) = TRUE;
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Merge backend specific data from an object file to the output
Packit bbfece
   object file when linking.  */
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
Packit bbfece
{
Packit bbfece
  bfd *obfd = info->output_bfd;
Packit bbfece
  static bfd *last_ibfd = 0;
Packit bbfece
  flagword old_flags, new_flags;
Packit bbfece
  flagword old_partial, new_partial;
Packit bbfece
Packit bbfece
  /* Check if we have the same endianness.  */
Packit bbfece
  if (!_bfd_generic_verify_endian_match (ibfd, info))
Packit bbfece
    return FALSE;
Packit bbfece
Packit bbfece
  new_flags = elf_elfheader (ibfd)->e_flags;
Packit bbfece
  old_flags = elf_elfheader (obfd)->e_flags;
Packit bbfece
Packit bbfece
#ifdef DEBUG
Packit bbfece
  _bfd_error_handler ("%B: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
Packit bbfece
		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
Packit bbfece
#endif
Packit bbfece
Packit bbfece
    /* First call, no flags set.  */
Packit bbfece
    if (!elf_flags_init (obfd))
Packit bbfece
    {
Packit bbfece
      elf_flags_init (obfd) = TRUE;
Packit bbfece
      old_flags = new_flags;
Packit bbfece
    }
Packit bbfece
  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
Packit bbfece
    {
Packit bbfece
      /* Non-library flags trump library flags.  The choice doesn't really
Packit bbfece
	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
Packit bbfece
      if (old_flags & EF_MEP_LIBRARY)
Packit bbfece
	old_flags = new_flags;
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
Packit bbfece
	 mach.  */
Packit bbfece
      new_partial = (new_flags & EF_MEP_CPU_MASK);
Packit bbfece
      old_partial = (old_flags & EF_MEP_CPU_MASK);
Packit bbfece
      if (new_partial == old_partial)
Packit bbfece
	;
Packit bbfece
      else if (new_partial == EF_MEP_CPU_MEP)
Packit bbfece
	;
Packit bbfece
      else if (old_partial == EF_MEP_CPU_MEP)
Packit bbfece
	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  /* xgettext:c-format */
Packit bbfece
	  _bfd_error_handler (_("%B and %B are for different cores"),
Packit bbfece
			      last_ibfd, ibfd);
Packit bbfece
	  bfd_set_error (bfd_error_invalid_target);
Packit bbfece
	  return FALSE;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Make sure they're for the same me_module.  Allow basic config to
Packit bbfece
	 mix with any other.  */
Packit bbfece
      new_partial = (new_flags & EF_MEP_INDEX_MASK);
Packit bbfece
      old_partial = (old_flags & EF_MEP_INDEX_MASK);
Packit bbfece
      if (new_partial == old_partial)
Packit bbfece
	;
Packit bbfece
      else if (new_partial == 0)
Packit bbfece
	;
Packit bbfece
      else if (old_partial == 0)
Packit bbfece
	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  /* xgettext:c-format */
Packit bbfece
	  _bfd_error_handler (_("%B and %B are for different configurations"),
Packit bbfece
			      last_ibfd, ibfd);
Packit bbfece
	  bfd_set_error (bfd_error_invalid_target);
Packit bbfece
	  return FALSE;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  elf_elfheader (obfd)->e_flags = old_flags;
Packit bbfece
  last_ibfd = ibfd;
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece
/* This will be edited by the MeP configration tool.  */
Packit bbfece
static const char * config_names[] =
Packit bbfece
{
Packit bbfece
  "basic"
Packit bbfece
  /* start-mepcfgtool */
Packit bbfece
  ,"default"
Packit bbfece
  /* end-mepcfgtool */
Packit bbfece
};
Packit bbfece
Packit bbfece
static const char * core_names[] =
Packit bbfece
{
Packit bbfece
  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
Packit bbfece
};
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
Packit bbfece
{
Packit bbfece
  FILE *   file = (FILE *) ptr;
Packit bbfece
  flagword flags, partial_flags;
Packit bbfece
Packit bbfece
  BFD_ASSERT (abfd != NULL && ptr != NULL);
Packit bbfece
Packit bbfece
  /* Print normal ELF private data.  */
Packit bbfece
  _bfd_elf_print_private_bfd_data (abfd, ptr);
Packit bbfece
Packit bbfece
  flags = elf_elfheader (abfd)->e_flags;
Packit bbfece
  fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
Packit bbfece
Packit bbfece
  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
Packit bbfece
  if (partial_flags < ARRAY_SIZE (core_names))
Packit bbfece
    fprintf (file, "  core: %s", core_names[(long)partial_flags]);
Packit bbfece
Packit bbfece
  partial_flags = flags & EF_MEP_INDEX_MASK;
Packit bbfece
  if (partial_flags < ARRAY_SIZE (config_names))
Packit bbfece
    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
Packit bbfece
Packit bbfece
  fputc ('\n', file);
Packit bbfece
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Return the machine subcode from the ELF e_flags header.  */
Packit bbfece
Packit bbfece
static int
Packit bbfece
elf32_mep_machine (bfd * abfd)
Packit bbfece
{
Packit bbfece
  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
Packit bbfece
    {
Packit bbfece
    default: break;
Packit bbfece
    case EF_MEP_CPU_C2: return bfd_mach_mep;
Packit bbfece
    case EF_MEP_CPU_C3: return bfd_mach_mep;
Packit bbfece
    case EF_MEP_CPU_C4: return bfd_mach_mep;
Packit bbfece
    case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
Packit bbfece
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  return bfd_mach_mep;
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_object_p (bfd * abfd)
Packit bbfece
{
Packit bbfece
  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
Packit bbfece
{
Packit bbfece
  if (hdr->sh_flags & SHF_MEP_VLIW)
Packit bbfece
    * flags |= SEC_MEP_VLIW;
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
mep_elf_fake_sections (bfd *		   abfd ATTRIBUTE_UNUSED,
Packit bbfece
		       Elf_Internal_Shdr * hdr,
Packit bbfece
		       asection *	   sec)
Packit bbfece
{
Packit bbfece
  if (sec->flags & SEC_MEP_VLIW)
Packit bbfece
    hdr->sh_flags |= SHF_MEP_VLIW;
Packit bbfece
  return TRUE;
Packit bbfece
}
Packit bbfece
Packit bbfece

Packit bbfece
#define ELF_ARCH		bfd_arch_mep
Packit bbfece
#define ELF_MACHINE_CODE	EM_CYGNUS_MEP
Packit bbfece
#define ELF_MAXPAGESIZE		0x1000
Packit bbfece
Packit bbfece
#define TARGET_BIG_SYM		mep_elf32_vec
Packit bbfece
#define TARGET_BIG_NAME		"elf32-mep"
Packit bbfece
Packit bbfece
#define TARGET_LITTLE_SYM	mep_elf32_le_vec
Packit bbfece
#define TARGET_LITTLE_NAME	"elf32-mep-little"
Packit bbfece
Packit bbfece
#define elf_info_to_howto_rel			NULL
Packit bbfece
#define elf_info_to_howto			mep_info_to_howto_rela
Packit bbfece
#define elf_backend_relocate_section		mep_elf_relocate_section
Packit bbfece
#define elf_backend_object_p			mep_elf_object_p
Packit bbfece
#define elf_backend_section_flags		mep_elf_section_flags
Packit bbfece
#define elf_backend_fake_sections		mep_elf_fake_sections
Packit bbfece
Packit bbfece
#define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
Packit bbfece
#define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
Packit bbfece
#define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
Packit bbfece
#define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
Packit bbfece
#define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
Packit bbfece
Packit bbfece
#define elf_backend_rela_normal			1
Packit bbfece
Packit bbfece
#include "elf32-target.h"