Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
elf32-h8300.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/h8.h"
#include "elf32-target.h"

Go to the source code of this file.

Classes

struct  elf_reloc_map

Defines

#define R_H8_NONE_X   0
#define R_H8_DIR32_X   (R_H8_NONE_X + 1)
#define R_H8_DIR16_X   (R_H8_DIR32_X + 1)
#define R_H8_DIR8_X   (R_H8_DIR16_X + 1)
#define R_H8_DIR16A8_X   (R_H8_DIR8_X + 1)
#define R_H8_DIR16R8_X   (R_H8_DIR16A8_X + 1)
#define R_H8_DIR24A8_X   (R_H8_DIR16R8_X + 1)
#define R_H8_DIR24R8_X   (R_H8_DIR24A8_X + 1)
#define R_H8_DIR32A16_X   (R_H8_DIR24R8_X + 1)
#define R_H8_PCREL16_X   (R_H8_DIR32A16_X + 1)
#define R_H8_PCREL8_X   (R_H8_PCREL16_X + 1)
#define TARGET_BIG_SYM   bfd_elf32_h8300_vec
#define TARGET_BIG_NAME   "elf32-h8300"
#define ELF_ARCH   bfd_arch_h8300
#define ELF_MACHINE_CODE   EM_H8_300
#define ELF_MAXPAGESIZE   0x1
#define bfd_elf32_bfd_reloc_type_lookup   elf32_h8_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup   elf32_h8_reloc_name_lookup
#define elf_info_to_howto   elf32_h8_info_to_howto
#define elf_info_to_howto_rel   elf32_h8_info_to_howto_rel
#define elf_backend_final_write_processing   elf32_h8_final_write_processing
#define elf_backend_object_p   elf32_h8_object_p
#define bfd_elf32_bfd_merge_private_bfd_data   elf32_h8_merge_private_bfd_data
#define bfd_elf32_bfd_link_hash_table_create   _bfd_elf_link_hash_table_create
#define elf_backend_relocate_section   elf32_h8_relocate_section
#define elf_backend_rela_normal   1
#define elf_backend_can_gc_sections   1
#define bfd_elf32_bfd_relax_section   elf32_h8_relax_section
#define bfd_elf32_bfd_get_relocated_section_contents   elf32_h8_get_relocated_section_contents

Functions

static reloc_howto_type * elf32_h8_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
static void elf32_h8_info_to_howto (bfd *, arelent *, Elf_Internal_Rela *)
static void elf32_h8_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *)
static unsigned long elf32_h8_mach (flagword)
static void elf32_h8_final_write_processing (bfd *, bfd_boolean)
static bfd_boolean elf32_h8_object_p (bfd *)
static bfd_boolean elf32_h8_merge_private_bfd_data (bfd *, bfd *)
static bfd_boolean elf32_h8_relax_section (bfd *, asection *, struct bfd_link_info *, bfd_boolean *)
static bfd_boolean elf32_h8_relax_delete_bytes (bfd *, asection *, bfd_vma, int)
static bfd_boolean elf32_h8_symbol_address_p (bfd *, asection *, bfd_vma)
static bfd_byteelf32_h8_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **)
static bfd_reloc_status_type elf32_h8_final_link_relocate (unsigned long, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int)
static bfd_boolean elf32_h8_relocate_section (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)
static bfd_reloc_status_type special (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)
static reloc_howto_type * elf32_h8_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * elf32_h8_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void elf32_h8_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc)
static void elf32_h8_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED)
static bfd_reloc_status_type special (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry ATTRIBUTE_UNUSED, asymbol *symbol ATTRIBUTE_UNUSED, PTR data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
static bfd_reloc_status_type elf32_h8_final_link_relocate (unsigned long r_type, bfd *input_bfd, bfd *output_bfd ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED, bfd_byte *contents, bfd_vma offset, bfd_vma value, bfd_vma addend, struct bfd_link_info *info ATTRIBUTE_UNUSED, asection *sym_sec ATTRIBUTE_UNUSED, int is_local ATTRIBUTE_UNUSED)
static void elf32_h8_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)

Variables

static reloc_howto_type h8_elf_howto_table []
static struct elf_reloc_map []

Class Documentation

struct elf_reloc_map

Definition at line 403 of file elf32-dlx.c.

Class Members
bfd_reloc_code_real_type bfd_reloc_val
bfd_reloc_code_real_type bfd_val
unsigned char elf_reloc_val
int elf_reloc_val
unsigned char howto_index

Define Documentation

Definition at line 1548 of file elf32-h8300.c.

Definition at line 1539 of file elf32-h8300.c.

Definition at line 1531 of file elf32-h8300.c.

Definition at line 1547 of file elf32-h8300.c.

Definition at line 1521 of file elf32-h8300.c.

Definition at line 1520 of file elf32-h8300.c.

#define ELF_ARCH   bfd_arch_h8300

Definition at line 1517 of file elf32-h8300.c.

Definition at line 1544 of file elf32-h8300.c.

Definition at line 1527 of file elf32-h8300.c.

Definition at line 1529 of file elf32-h8300.c.

#define elf_backend_rela_normal   1

Definition at line 1543 of file elf32-h8300.c.

Definition at line 1542 of file elf32-h8300.c.

Definition at line 1522 of file elf32-h8300.c.

Definition at line 1523 of file elf32-h8300.c.

Definition at line 1518 of file elf32-h8300.c.

#define ELF_MAXPAGESIZE   0x1

Definition at line 1519 of file elf32-h8300.c.

#define R_H8_DIR16_X   (R_H8_DIR32_X + 1)
#define R_H8_DIR16A8_X   (R_H8_DIR8_X + 1)
#define R_H8_DIR16R8_X   (R_H8_DIR16A8_X + 1)
#define R_H8_DIR24A8_X   (R_H8_DIR16R8_X + 1)
#define R_H8_DIR24R8_X   (R_H8_DIR24A8_X + 1)
#define R_H8_DIR32_X   (R_H8_NONE_X + 1)
#define R_H8_DIR32A16_X   (R_H8_DIR24R8_X + 1)
#define R_H8_DIR8_X   (R_H8_DIR16_X + 1)
#define R_H8_NONE_X   0
#define R_H8_PCREL16_X   (R_H8_DIR32A16_X + 1)
#define R_H8_PCREL8_X   (R_H8_PCREL16_X + 1)
#define TARGET_BIG_NAME   "elf32-h8300"

Definition at line 1516 of file elf32-h8300.c.

Definition at line 1515 of file elf32-h8300.c.


Function Documentation

static bfd_reloc_status_type elf32_h8_final_link_relocate ( unsigned  long,
bfd ,
bfd ,
asection ,
bfd_byte ,
bfd_vma  ,
bfd_vma  ,
bfd_vma  ,
struct bfd_link_info ,
asection ,
int   
) [static]

Here is the caller graph for this function:

static bfd_reloc_status_type elf32_h8_final_link_relocate ( unsigned long  r_type,
bfd input_bfd,
bfd *output_bfd  ATTRIBUTE_UNUSED,
asection *input_section  ATTRIBUTE_UNUSED,
bfd_byte contents,
bfd_vma  offset,
bfd_vma  value,
bfd_vma  addend,
struct bfd_link_info *info  ATTRIBUTE_UNUSED,
asection *sym_sec  ATTRIBUTE_UNUSED,
int is_local  ATTRIBUTE_UNUSED 
) [static]

Definition at line 321 of file elf32-h8300.c.

{
  bfd_byte *hit_data = contents + offset;

  switch (r_type)
    {
    case R_H8_NONE:
      return bfd_reloc_ok;

    case R_H8_DIR32:
    case R_H8_DIR32A16:
    case R_H8_DIR24A8:
      value += addend;
      bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_H8_DIR16:
    case R_H8_DIR16A8:
    case R_H8_DIR16R8:
      value += addend;
      bfd_put_16 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    /* AKA R_RELBYTE */
    case R_H8_DIR8:
      value += addend;

      bfd_put_8 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_H8_DIR24R8:
      value += addend;

      /* HIT_DATA is the address for the first byte for the relocated
        value.  Subtract 1 so that we can manipulate the data in 32-bit
        hunks.  */
      hit_data--;

      /* Clear out the top byte in value.  */
      value &= 0xffffff;

      /* Retrieve the type byte for value from the section contents.  */
      value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);

      /* Now scribble it out in one 32-bit hunk.  */
      bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_H8_PCREL16:
      value -= (input_section->output_section->vma
              + input_section->output_offset);
      value -= offset;
      value += addend;

      /* The value is relative to the start of the instruction,
        not the relocation offset.  Subtract 2 to account for
        this minor issue.  */
      value -= 2;

      bfd_put_16 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_H8_PCREL8:
      value -= (input_section->output_section->vma
              + input_section->output_offset);
      value -= offset;
      value += addend;

      /* The value is relative to the start of the instruction,
        not the relocation offset.  Subtract 1 to account for
        this minor issue.  */
      value -= 1;

      bfd_put_8 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    default:
      return bfd_reloc_notsupported;
    }
}
static void elf32_h8_final_write_processing ( bfd ,
bfd_boolean   
) [static]
static void elf32_h8_final_write_processing ( bfd abfd,
bfd_boolean linker  ATTRIBUTE_UNUSED 
) [static]

Definition at line 582 of file elf32-h8300.c.

{
  unsigned long val;

  switch (bfd_get_mach (abfd))
    {
    default:
    case bfd_mach_h8300:
      val = E_H8_MACH_H8300;
      break;

    case bfd_mach_h8300h:
      val = E_H8_MACH_H8300H;
      break;

    case bfd_mach_h8300s:
      val = E_H8_MACH_H8300S;
      break;

    case bfd_mach_h8300hn:
      val = E_H8_MACH_H8300HN;
      break;

    case bfd_mach_h8300sn:
      val = E_H8_MACH_H8300SN;
      break;

    case bfd_mach_h8300sx:
      val = E_H8_MACH_H8300SX;
      break;

    case bfd_mach_h8300sxn:
      val = E_H8_MACH_H8300SXN;
      break;
    }

  elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
  elf_elfheader (abfd)->e_flags |= val;
}

Here is the call graph for this function:

static bfd_byte * elf32_h8_get_relocated_section_contents ( bfd output_bfd,
struct bfd_link_info link_info,
struct bfd_link_order link_order,
bfd_byte data,
bfd_boolean  relocatable,
asymbol **  symbols 
) [static]

Definition at line 1411 of file elf32-h8300.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  asection *input_section = link_order->u.indirect.section;
  bfd *input_bfd = input_section->owner;
  asection **sections = NULL;
  Elf_Internal_Rela *internal_relocs = NULL;
  Elf_Internal_Sym *isymbuf = NULL;

  /* We only need to handle the case of relaxing, or of having a
     particular set of section contents, specially.  */
  if (relocatable
      || elf_section_data (input_section)->this_hdr.contents == NULL)
    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
                                                 link_order, data,
                                                 relocatable,
                                                 symbols);

  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;

  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
         (size_t) input_section->size);

  if ((input_section->flags & SEC_RELOC) != 0
      && input_section->reloc_count > 0)
    {
      asection **secpp;
      Elf_Internal_Sym *isym, *isymend;
      bfd_size_type amt;

      internal_relocs = (_bfd_elf_link_read_relocs
                      (input_bfd, input_section, (PTR) NULL,
                       (Elf_Internal_Rela *) NULL, FALSE));
      if (internal_relocs == NULL)
       goto error_return;

      if (symtab_hdr->sh_info != 0)
       {
         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
         if (isymbuf == NULL)
           isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
                                       symtab_hdr->sh_info, 0,
                                       NULL, NULL, NULL);
         if (isymbuf == NULL)
           goto error_return;
       }

      amt = symtab_hdr->sh_info;
      amt *= sizeof (asection *);
      sections = (asection **) bfd_malloc (amt);
      if (sections == NULL && amt != 0)
       goto error_return;

      isymend = isymbuf + symtab_hdr->sh_info;
      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
       {
         asection *isec;

         if (isym->st_shndx == SHN_UNDEF)
           isec = bfd_und_section_ptr;
         else if (isym->st_shndx == SHN_ABS)
           isec = bfd_abs_section_ptr;
         else if (isym->st_shndx == SHN_COMMON)
           isec = bfd_com_section_ptr;
         else
           isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);

         *secpp = isec;
       }

      if (! elf32_h8_relocate_section (output_bfd, link_info, input_bfd,
                                   input_section, data, internal_relocs,
                                   isymbuf, sections))
       goto error_return;

      if (sections != NULL)
       free (sections);
      if (isymbuf != NULL
         && symtab_hdr->contents != (unsigned char *) isymbuf)
       free (isymbuf);
      if (elf_section_data (input_section)->relocs != internal_relocs)
       free (internal_relocs);
    }

  return data;

 error_return:
  if (sections != NULL)
    free (sections);
  if (isymbuf != NULL
      && symtab_hdr->contents != (unsigned char *) isymbuf)
    free (isymbuf);
  if (internal_relocs != NULL
      && elf_section_data (input_section)->relocs != internal_relocs)
    free (internal_relocs);
  return NULL;
}

Here is the call graph for this function:

static void elf32_h8_info_to_howto ( bfd ,
arelent ,
Elf_Internal_Rela  
) [static]

Here is the caller graph for this function:

static void elf32_h8_info_to_howto ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent bfd_reloc,
Elf_Internal_Rela elf_reloc 
) [static]

Definition at line 271 of file elf32-h8300.c.

{
  unsigned int r;
  unsigned int i;

  r = ELF32_R_TYPE (elf_reloc->r_info);
  for (i = 0; i < sizeof (h8_elf_howto_table) / sizeof (reloc_howto_type); i++)
    if (h8_elf_howto_table[i].type == r)
      {
       bfd_reloc->howto = &h8_elf_howto_table[i];
       return;
      }
  abort ();
}
static void elf32_h8_info_to_howto_rel ( bfd ,
arelent ,
Elf_Internal_Rela  
) [static]
static void elf32_h8_info_to_howto_rel ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent bfd_reloc,
Elf_Internal_Rela *elf_reloc  ATTRIBUTE_UNUSED 
) [static]

Definition at line 288 of file elf32-h8300.c.

{
  unsigned int r;

  abort ();
  r = ELF32_R_TYPE (elf_reloc->r_info);
  bfd_reloc->howto = &h8_elf_howto_table[r];
}
static unsigned long elf32_h8_mach ( flagword  flags) [static]

Definition at line 549 of file elf32-h8300.c.

Here is the caller graph for this function:

static bfd_boolean elf32_h8_merge_private_bfd_data ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 639 of file elf32-h8300.c.

{
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return TRUE;

  if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
      && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
    {
      if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
                            bfd_get_mach (ibfd)))
       return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_h8_object_p ( bfd abfd) [static]

Definition at line 627 of file elf32-h8300.c.

Here is the call graph for this function:

static bfd_boolean elf32_h8_relax_delete_bytes ( bfd abfd,
asection sec,
bfd_vma  addr,
int  count 
) [static]

Definition at line 1290 of file elf32-h8300.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  unsigned int sec_shndx;
  bfd_byte *contents;
  Elf_Internal_Rela *irel, *irelend;
  Elf_Internal_Rela *irelalign;
  Elf_Internal_Sym *isym;
  Elf_Internal_Sym *isymend;
  bfd_vma toaddr;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **end_hashes;
  unsigned int symcount;

  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);

  contents = elf_section_data (sec)->this_hdr.contents;

  /* The deletion must stop at the next ALIGN reloc for an aligment
     power larger than the number of bytes we are deleting.  */

  irelalign = NULL;
  toaddr = sec->size;

  irel = elf_section_data (sec)->relocs;
  irelend = irel + sec->reloc_count;

  /* Actually delete the bytes.  */
  memmove (contents + addr, contents + addr + count,
          (size_t) (toaddr - addr - count));
  sec->size -= count;

  /* Adjust all the relocs.  */
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
    {
      /* Get the new reloc address.  */
      if ((irel->r_offset > addr
          && irel->r_offset < toaddr))
       irel->r_offset -= count;
    }

  /* Adjust the local symbols defined in this section.  */
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
  isymend = isym + symtab_hdr->sh_info;
  for (; isym < isymend; isym++)
    {
      if (isym->st_shndx == sec_shndx
         && isym->st_value > addr
         && isym->st_value < toaddr)
       isym->st_value -= count;
    }

  /* Now adjust the global symbols defined in this section.  */
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
             - symtab_hdr->sh_info);
  sym_hashes = elf_sym_hashes (abfd);
  end_hashes = sym_hashes + symcount;
  for (; sym_hashes < end_hashes; sym_hashes++)
    {
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
      if ((sym_hash->root.type == bfd_link_hash_defined
          || sym_hash->root.type == bfd_link_hash_defweak)
         && sym_hash->root.u.def.section == sec
         && sym_hash->root.u.def.value > addr
         && sym_hash->root.u.def.value < toaddr)
       {
         sym_hash->root.u.def.value -= count;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_h8_relax_section ( bfd abfd,
asection sec,
struct bfd_link_info link_info,
bfd_boolean again 
) [static]

Definition at line 681 of file elf32-h8300.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Rela *internal_relocs;
  Elf_Internal_Rela *irel, *irelend;
  bfd_byte *contents = NULL;
  Elf_Internal_Sym *isymbuf = NULL;
  static asection *last_input_section = NULL;
  static Elf_Internal_Rela *last_reloc = NULL;

  /* Assume nothing changes.  */
  *again = FALSE;

  /* We don't have to do anything for a relocatable link, if
     this section does not have relocs, or if this is not a
     code section.  */
  if (link_info->relocatable
      || (sec->flags & SEC_RELOC) == 0
      || sec->reloc_count == 0
      || (sec->flags & SEC_CODE) == 0)
    return TRUE;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;

  /* Get a copy of the native relocations.  */
  internal_relocs = (_bfd_elf_link_read_relocs
                   (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                    link_info->keep_memory));
  if (internal_relocs == NULL)
    goto error_return;

  if (sec != last_input_section)
    last_reloc = NULL;

  last_input_section = sec;

  /* Walk through the relocs looking for relaxing opportunities.  */
  irelend = internal_relocs + sec->reloc_count;
  for (irel = internal_relocs; irel < irelend; irel++)
    {
      bfd_vma symval;

      /* Keep track of the previous reloc so that we can delete
        some long jumps created by the compiler.  */
      if (irel != internal_relocs)
       last_reloc = irel - 1;

      if (ELF32_R_TYPE (irel->r_info) != R_H8_DIR24R8
         && ELF32_R_TYPE (irel->r_info) != R_H8_PCREL16
         && ELF32_R_TYPE (irel->r_info) != R_H8_DIR16A8
         && ELF32_R_TYPE (irel->r_info) != R_H8_DIR24A8
         && ELF32_R_TYPE (irel->r_info) != R_H8_DIR32A16)
       continue;

      /* Get the section contents if we haven't done so already.  */
      if (contents == NULL)
       {
         /* Get cached copy if it exists.  */
         if (elf_section_data (sec)->this_hdr.contents != NULL)
           contents = elf_section_data (sec)->this_hdr.contents;
         else
           {
             /* Go get them off disk.  */
             if (!bfd_malloc_and_get_section (abfd, sec, &contents))
              goto error_return;
           }
       }

      /* Read this BFD's local symbols if we haven't done so already.  */
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
       {
         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
         if (isymbuf == NULL)
           isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
                                       symtab_hdr->sh_info, 0,
                                       NULL, NULL, NULL);
         if (isymbuf == NULL)
           goto error_return;
       }

      /* Get the value of the symbol referred to by the reloc.  */
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
       {
         /* A local symbol.  */
         Elf_Internal_Sym *isym;
         asection *sym_sec;

         isym = isymbuf + ELF32_R_SYM (irel->r_info);
         sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
         symval = isym->st_value;
         /* If the reloc is absolute, it will not have
            a symbol or section associated with it.  */
         if (sym_sec)
           symval += sym_sec->output_section->vma
             + sym_sec->output_offset;
       }
      else
       {
         unsigned long indx;
         struct elf_link_hash_entry *h;

         /* An external symbol.  */
         indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
         h = elf_sym_hashes (abfd)[indx];
         BFD_ASSERT (h != NULL);
         if (h->root.type != bfd_link_hash_defined
             && h->root.type != bfd_link_hash_defweak)
           {
             /* This appears to be a reference to an undefined
                 symbol.  Just ignore it--it will be caught by the
                 regular reloc processing.  */
             continue;
           }

         symval = (h->root.u.def.value
                  + h->root.u.def.section->output_section->vma
                  + h->root.u.def.section->output_offset);
       }

      /* For simplicity of coding, we are going to modify the section
        contents, the section relocs, and the BFD symbol table.  We
        must tell the rest of the code not to free up this
        information.  It would be possible to instead create a table
        of changes which have to be made, as is done in coff-mips.c;
        that would be more work, but would require less memory when
        the linker is run.  */
      switch (ELF32_R_TYPE (irel->r_info))
       {
        /* Try to turn a 24-bit absolute branch/call into an 8-bit
          pc-relative branch/call.  */
       case R_H8_DIR24R8:
         {
           bfd_vma value = symval + irel->r_addend;
           bfd_vma dot, gap;

           /* Get the address of this instruction.  */
           dot = (sec->output_section->vma
                 + sec->output_offset + irel->r_offset - 1);

           /* Compute the distance from this insn to the branch target.  */
           gap = value - dot;

           /* If the distance is within -126..+130 inclusive, then we can
              relax this jump.  +130 is valid since the target will move
              two bytes closer if we do relax this branch.  */
           if ((int) gap >= -126 && (int) gap <= 130)
             {
              unsigned char code;

              /* Note that we've changed the relocs, section contents,
                 etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              elf_section_data (sec)->this_hdr.contents = contents;
              symtab_hdr->contents = (unsigned char *) isymbuf;

              /* Get the instruction code being relaxed.  */
              code = bfd_get_8 (abfd, contents + irel->r_offset - 1);

              /* If the previous instruction conditionally jumped around
                 this instruction, we may be able to reverse the condition
                 and redirect the previous instruction to the target of
                 this instruction.

                 Such sequences are used by the compiler to deal with
                 long conditional branches.

                 Only perform this optimisation for jumps (code 0x5a) not
                 subroutine calls, as otherwise it could transform:

                                  mov.w   r0,r0
                                  beq     .L1
                                 jsr     @_bar
                            .L1:   rts
                            _bar:  rts
                 into:
                                  mov.w   r0,r0
                                  bne     _bar
                                  rts
                           _bar:  rts

                 which changes the call (jsr) into a branch (bne).  */
              if (code == 0x5a
                  && (int) gap <= 130
                  && (int) gap >= -128
                  && last_reloc
                  && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8
                  && ELF32_R_SYM (last_reloc->r_info) < symtab_hdr->sh_info)
                {
                  bfd_vma last_value;
                  asection *last_sym_sec;
                  Elf_Internal_Sym *last_sym;

                  /* We will need to examine the symbol used by the
                     previous relocation.  */

                  last_sym = isymbuf + ELF32_R_SYM (last_reloc->r_info);
                  last_sym_sec
                    = bfd_section_from_elf_index (abfd, last_sym->st_shndx);
                  last_value = (last_sym->st_value
                              + last_sym_sec->output_section->vma
                              + last_sym_sec->output_offset);

                  /* Verify that the previous relocation was for a
                     branch around this instruction and that no symbol
                     exists at the current location.  */
                  if (last_value == dot + 4
                     && last_reloc->r_offset + 2 == irel->r_offset
                     && ! elf32_h8_symbol_address_p (abfd, sec, dot))
                    {
                     /* We can eliminate this jump.  Twiddle the
                        previous relocation as necessary.  */
                     irel->r_info
                       = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                     ELF32_R_TYPE (R_H8_NONE));

                     last_reloc->r_info
                       = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                     ELF32_R_TYPE (R_H8_PCREL8));
                     last_reloc->r_addend = irel->r_addend;

                     code = bfd_get_8 (abfd,
                                     contents + last_reloc->r_offset - 1);
                     code ^= 1;
                     bfd_put_8 (abfd,
                               code,
                     contents + last_reloc->r_offset - 1);

                     /* Delete four bytes of data.  */
                     if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                                   irel->r_offset - 1,
                                                   4))
                       goto error_return;

                     *again = TRUE;
                     break;
                    }
                }

              if (code == 0x5e)
                /* This is jsr.  */
                bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 1);
              else if (code == 0x5a)
                /* This is jmp.  */
                bfd_put_8 (abfd, 0x40, contents + irel->r_offset - 1);
              else
                abort ();

              /* Fix the relocation's type.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_H8_PCREL8);

              /* Delete two bytes of data.  */
              if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                            irel->r_offset + 1, 2))
                goto error_return;

              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
              *again = TRUE;
             }
           break;
         }

       /* Try to turn a 16-bit pc-relative branch into a 8-bit pc-relative
          branch.  */
       case R_H8_PCREL16:
         {
           bfd_vma value = symval + irel->r_addend;
           bfd_vma dot;
           bfd_vma gap;

           /* Get the address of this instruction.  */
           dot = (sec->output_section->vma
                 + sec->output_offset
                 + irel->r_offset - 2);

           gap = value - dot;

           /* If the distance is within -126..+130 inclusive, then we can
              relax this jump.  +130 is valid since the target will move
              two bytes closer if we do relax this branch.  */
           if ((int) gap >= -126 && (int) gap <= 130)
             {
              unsigned char code;

              /* Note that we've changed the relocs, section contents,
                 etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              elf_section_data (sec)->this_hdr.contents = contents;
              symtab_hdr->contents = (unsigned char *) isymbuf;

              /* Get the opcode.  */
              code = bfd_get_8 (abfd, contents + irel->r_offset - 2);

              if (code == 0x58)
                {
                  /* bCC:16 -> bCC:8 */
                  /* Get the second byte of the original insn, which
                     contains the condition code.  */
                  code = bfd_get_8 (abfd, contents + irel->r_offset - 1);

                  /* Compute the fisrt byte of the relaxed
                     instruction.  The original sequence 0x58 0xX0
                     is relaxed to 0x4X, where X represents the
                     condition code.  */
                  code &= 0xf0;
                  code >>= 4;
                  code |= 0x40;
                  bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
                }
              else if (code == 0x5c)
                /* This is bsr.  */
                bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
              else
                abort ();

              /* Fix the relocation's type.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_H8_PCREL8);
              irel->r_offset--;

              /* Delete two bytes of data.  */
              if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                            irel->r_offset + 1, 2))
                goto error_return;

              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
              *again = TRUE;
             }
           break;
         }

       /* This is a 16-bit absolute address in one of the following
          instructions:

            "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
            "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
            "mov.b"

          We may relax this into an 8-bit absolute address if it's in
          the right range.  */
       case R_H8_DIR16A8:
         {
           bfd_vma value;

           value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
           if (value >= 0xffffff00u)
             {
              unsigned char code;
              unsigned char temp_code;

              /* Note that we've changed the relocs, section contents,
                 etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              elf_section_data (sec)->this_hdr.contents = contents;
              symtab_hdr->contents = (unsigned char *) isymbuf;

              /* Get the opcode.  */
              code = bfd_get_8 (abfd, contents + irel->r_offset - 2);

              /* All instructions with R_H8_DIR16A8 start with
                 0x6a.  */
              if (code != 0x6a)
                abort ();

              temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
              /* If this is a mov.b instruction, clear the lower
                 nibble, which contains the source/destination
                 register number.  */
              if ((temp_code & 0x10) != 0x10)
                temp_code &= 0xf0;

              switch (temp_code)
                {
                case 0x00:
                  /* This is mov.b @aa:16,Rd.  */
                  bfd_put_8 (abfd, (code & 0xf) | 0x20,
                            contents + irel->r_offset - 2);
                  break;
                case 0x80:
                  /* This is mov.b Rs,@aa:16.  */
                  bfd_put_8 (abfd, (code & 0xf) | 0x30,
                            contents + irel->r_offset - 2);
                  break;
                case 0x18:
                  /* This is a bit-maniputation instruction that
                     stores one bit into memory, one of "bclr",
                     "bist", "bnot", "bset", and "bst".  */
                  bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
                  break;
                case 0x10:
                  /* This is a bit-maniputation instruction that
                     loads one bit from memory, one of "band",
                     "biand", "bild", "bior", "bixor", "bld", "bor",
                     "btst", and "bxor".  */
                  bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
                  break;
                default:
                  abort ();
                }

              /* Fix the relocation's type.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_H8_DIR8);

              /* Move the relocation.  */
              irel->r_offset--;

              /* Delete two bytes of data.  */
              if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                            irel->r_offset + 1, 2))
                goto error_return;

              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
              *again = TRUE;
             }
           break;
         }

       /* This is a 24-bit absolute address in one of the following
          instructions:

            "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
            "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
            "mov.b"

          We may relax this into an 8-bit absolute address if it's in
          the right range.  */
       case R_H8_DIR24A8:
         {
           bfd_vma value;

           value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
           if (value >= 0xffffff00u)
             {
              unsigned char code;
              unsigned char temp_code;

              /* Note that we've changed the relocs, section contents,
                 etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              elf_section_data (sec)->this_hdr.contents = contents;
              symtab_hdr->contents = (unsigned char *) isymbuf;

              /* Get the opcode.  */
              code = bfd_get_8 (abfd, contents + irel->r_offset - 2);

              /* All instructions with R_H8_DIR24A8 start with
                 0x6a.  */
              if (code != 0x6a)
                abort ();

              temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);

              /* If this is a mov.b instruction, clear the lower
                 nibble, which contains the source/destination
                 register number.  */
              if ((temp_code & 0x30) != 0x30)
                temp_code &= 0xf0;

              switch (temp_code)
                {
                case 0x20:
                  /* This is mov.b @aa:24/32,Rd.  */
                  bfd_put_8 (abfd, (code & 0xf) | 0x20,
                            contents + irel->r_offset - 2);
                  break;
                case 0xa0:
                  /* This is mov.b Rs,@aa:24/32.  */
                  bfd_put_8 (abfd, (code & 0xf) | 0x30,
                            contents + irel->r_offset - 2);
                  break;
                case 0x38:
                  /* This is a bit-maniputation instruction that
                     stores one bit into memory, one of "bclr",
                     "bist", "bnot", "bset", and "bst".  */
                  bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
                  break;
                case 0x30:
                  /* This is a bit-maniputation instruction that
                     loads one bit from memory, one of "band",
                     "biand", "bild", "bior", "bixor", "bld", "bor",
                     "btst", and "bxor".  */
                  bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
                  break;
                default:
                  abort();
                }

              /* Fix the relocation's type.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_H8_DIR8);
              irel->r_offset--;

              /* Delete two bytes of data.  */
              if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                            irel->r_offset + 1, 4))
                goto error_return;

              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
              *again = TRUE;
              break;
             }
         }

         /* Fall through.  */

         /* This is a 24-/32-bit absolute address in one of the
            following instructions:

              "band", "bclr", "biand", "bild", "bior", "bist",
              "bixor", "bld", "bnot", "bor", "bset", "bst", "btst",
              "bxor", "ldc.w", "stc.w" and "mov.[bwl]"

            We may relax this into an 16-bit absolute address if it's
            in the right range.  */
       case R_H8_DIR32A16:
         {
           bfd_vma value;

           value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
           if (value <= 0x7fff || value >= 0xffff8000u)
             {
              unsigned char code;

              /* Note that we've changed the relocs, section contents,
                 etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              elf_section_data (sec)->this_hdr.contents = contents;
              symtab_hdr->contents = (unsigned char *) isymbuf;

              /* Get the opcode.  */
              code = bfd_get_8 (abfd, contents + irel->r_offset - 1);

              /* Fix the opcode.  For all the instructions that
                 belong to this relaxation, we simply need to turn
                 off bit 0x20 in the previous byte.  */
              code &= ~0x20;

              bfd_put_8 (abfd, code, contents + irel->r_offset - 1);

              /* Fix the relocation's type.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                        R_H8_DIR16);

              /* Delete two bytes of data.  */
              if (!elf32_h8_relax_delete_bytes (abfd, sec,
                                            irel->r_offset + 1, 2))
                goto error_return;

              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
              *again = TRUE;
             }
           break;
         }

       default:
         break;
       }
    }

  if (isymbuf != NULL
      && symtab_hdr->contents != (unsigned char *) isymbuf)
    {
      if (! link_info->keep_memory)
       free (isymbuf);
      else
       symtab_hdr->contents = (unsigned char *) isymbuf;
    }

  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    {
      if (! link_info->keep_memory)
       free (contents);
      else
       {
         /* Cache the section contents for elf_link_input_bfd.  */
         elf_section_data (sec)->this_hdr.contents = contents;
       }
    }

  if (internal_relocs != NULL
      && elf_section_data (sec)->relocs != internal_relocs)
    free (internal_relocs);

  return TRUE;

 error_return:
  if (isymbuf != NULL
      && symtab_hdr->contents != (unsigned char *) isymbuf)
    free (isymbuf);
  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    free (contents);
  if (internal_relocs != NULL
      && elf_section_data (sec)->relocs != internal_relocs)
    free (internal_relocs);
  return FALSE;
}

Here is the call graph for this function:

static reloc_howto_type* elf32_h8_reloc_name_lookup ( bfd *abfd  ATTRIBUTE_UNUSED,
const char *  r_name 
) [static]

Definition at line 255 of file elf32-h8300.c.

{
  unsigned int i;

  for (i = 0;
       i < sizeof (h8_elf_howto_table) / sizeof (h8_elf_howto_table[0]);
       i++)
    if (h8_elf_howto_table[i].name != NULL
       && strcasecmp (h8_elf_howto_table[i].name, r_name) == 0)
      return &h8_elf_howto_table[i];

  return NULL;
}

Here is the call graph for this function:

static reloc_howto_type* elf32_h8_reloc_type_lookup ( bfd abfd,
bfd_reloc_code_real_type  code 
) [static]
static reloc_howto_type* elf32_h8_reloc_type_lookup ( bfd *abfd  ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type  code 
) [static]

Definition at line 241 of file elf32-h8300.c.

{
  unsigned int i;

  for (i = 0; i < sizeof (h8_reloc_map) / sizeof (struct elf_reloc_map); i++)
    {
      if (h8_reloc_map[i].bfd_reloc_val == code)
       return &h8_elf_howto_table[(int) h8_reloc_map[i].howto_index];
    }
  return NULL;
}
static bfd_boolean elf32_h8_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 
) [static]

Definition at line 411 of file elf32-h8300.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  Elf_Internal_Rela *rel, *relend;

  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);

  rel = relocs;
  relend = relocs + input_section->reloc_count;
  for (; rel < relend; rel++)
    {
      unsigned int r_type;
      unsigned long r_symndx;
      Elf_Internal_Sym *sym;
      asection *sec;
      struct elf_link_hash_entry *h;
      bfd_vma relocation;
      bfd_reloc_status_type r;
      arelent bfd_reloc;
      reloc_howto_type *howto;

      elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
      howto = bfd_reloc.howto;

      r_symndx = ELF32_R_SYM (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
      h = NULL;
      sym = NULL;
      sec = NULL;
      if (r_symndx < symtab_hdr->sh_info)
       {
         sym = local_syms + r_symndx;
         sec = local_sections[r_symndx];
         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
       }
      else
       {
         bfd_boolean unresolved_reloc, warned;

         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                               r_symndx, symtab_hdr, sym_hashes,
                               h, sec, relocation,
                               unresolved_reloc, warned);
       }

      if (sec != NULL && elf_discarded_section (sec))
       {
         /* For relocs against symbols from removed linkonce sections,
            or sections discarded by a linker script, we just want the
            section contents zeroed.  Avoid any special processing.  */
         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
         rel->r_info = 0;
         rel->r_addend = 0;
         continue;
       }

      if (info->relocatable)
       continue;

      r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
                                   input_section,
                                   contents, rel->r_offset,
                                   relocation, rel->r_addend,
                                   info, sec, h == NULL);

      if (r != bfd_reloc_ok)
       {
         const char *name;
         const char *msg = (const char *) 0;

         if (h != NULL)
           name = h->root.root.string;
         else
           {
             name = (bfd_elf_string_from_elf_section
                    (input_bfd, symtab_hdr->sh_link, sym->st_name));
             if (name == NULL || *name == '\0')
              name = bfd_section_name (input_bfd, sec);
           }

         switch (r)
           {
           case bfd_reloc_overflow:
             if (! ((*info->callbacks->reloc_overflow)
                   (info, (h ? &h->root : NULL), name, howto->name,
                    (bfd_vma) 0, input_bfd, input_section,
                    rel->r_offset)))
              return FALSE;
             break;

           case bfd_reloc_undefined:
             if (! ((*info->callbacks->undefined_symbol)
                   (info, name, input_bfd, input_section,
                    rel->r_offset, TRUE)))
              return FALSE;
             break;

           case bfd_reloc_outofrange:
             msg = _("internal error: out of range error");
             goto common_error;

           case bfd_reloc_notsupported:
             msg = _("internal error: unsupported relocation error");
             goto common_error;

           case bfd_reloc_dangerous:
             msg = _("internal error: dangerous error");
             goto common_error;

           default:
             msg = _("internal error: unknown error");
             /* fall through */

           common_error:
             if (!((*info->callbacks->warning)
                  (info, msg, name, input_bfd, input_section,
                   rel->r_offset)))
              return FALSE;
             break;
           }
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_h8_symbol_address_p ( bfd abfd,
asection sec,
bfd_vma  addr 
) [static]

Definition at line 1367 of file elf32-h8300.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  unsigned int sec_shndx;
  Elf_Internal_Sym *isym;
  Elf_Internal_Sym *isymend;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **end_hashes;
  unsigned int symcount;

  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);

  /* Examine all the symbols.  */
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
  isymend = isym + symtab_hdr->sh_info;
  for (; isym < isymend; isym++)
    {
      if (isym->st_shndx == sec_shndx
         && isym->st_value == addr)
       return TRUE;
    }

  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
             - symtab_hdr->sh_info);
  sym_hashes = elf_sym_hashes (abfd);
  end_hashes = sym_hashes + symcount;
  for (; sym_hashes < end_hashes; sym_hashes++)
    {
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
      if ((sym_hash->root.type == bfd_link_hash_defined
          || sym_hash->root.type == bfd_link_hash_defweak)
         && sym_hash->root.u.def.section == sec
         && sym_hash->root.u.def.value == addr)
       return TRUE;
    }

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_reloc_status_type special ( bfd ,
arelent ,
asymbol ,
PTR  ,
asection ,
bfd ,
char **   
) [static]
static bfd_reloc_status_type special ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent *reloc_entry  ATTRIBUTE_UNUSED,
asymbol *symbol  ATTRIBUTE_UNUSED,
PTR data  ATTRIBUTE_UNUSED,
asection *input_section  ATTRIBUTE_UNUSED,
bfd output_bfd,
char **error_message  ATTRIBUTE_UNUSED 
) [static]

Definition at line 303 of file elf32-h8300.c.

{
  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  /* Adjust the reloc address to that in the output section.  */
  reloc_entry->address += input_section->output_offset;
  return bfd_reloc_ok;
}

Variable Documentation

struct elf_reloc_map[] [static]
reloc_howto_type h8_elf_howto_table[] [static]

Definition at line 59 of file elf32-h8300.c.