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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [elf32-sh64-com.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* SuperH SH64-specific support for 32-bit ELF
/* SuperH SH64-specific support for 32-bit ELF
   Copyright 2000, 2001, 2002, 2003, 2004, 2007
   Copyright 2000, 2001, 2002, 2003, 2004, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of BFD, the Binary File Descriptor library.
   This file is part of BFD, the Binary File Descriptor library.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#define SH64_ELF
#define SH64_ELF
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "libbfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf/sh.h"
#include "elf/sh.h"
#include "elf32-sh64.h"
#include "elf32-sh64.h"
#include "../opcodes/sh64-opc.h"
#include "../opcodes/sh64-opc.h"
 
 
static bfd_boolean sh64_address_in_cranges
static bfd_boolean sh64_address_in_cranges
  (asection *cranges, bfd_vma, sh64_elf_crange *);
  (asection *cranges, bfd_vma, sh64_elf_crange *);
 
 
/* Ordering functions of a crange, for the qsort and bsearch calls and for
/* Ordering functions of a crange, for the qsort and bsearch calls and for
   different endianness.  */
   different endianness.  */
 
 
int
int
_bfd_sh64_crange_qsort_cmpb (const void *p1, const void *p2)
_bfd_sh64_crange_qsort_cmpb (const void *p1, const void *p2)
{
{
  bfd_vma a1 = bfd_getb32 (p1);
  bfd_vma a1 = bfd_getb32 (p1);
  bfd_vma a2 = bfd_getb32 (p2);
  bfd_vma a2 = bfd_getb32 (p2);
 
 
  /* Preserve order if there's ambiguous contents.  */
  /* Preserve order if there's ambiguous contents.  */
  if (a1 == a2)
  if (a1 == a2)
    return (char *) p1 - (char *) p2;
    return (char *) p1 - (char *) p2;
 
 
  return a1 - a2;
  return a1 - a2;
}
}
 
 
int
int
_bfd_sh64_crange_qsort_cmpl (const void *p1, const void *p2)
_bfd_sh64_crange_qsort_cmpl (const void *p1, const void *p2)
{
{
  bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
  bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
 
 
  /* Preserve order if there's ambiguous contents.  */
  /* Preserve order if there's ambiguous contents.  */
  if (a1 == a2)
  if (a1 == a2)
    return (char *) p1 - (char *) p2;
    return (char *) p1 - (char *) p2;
 
 
  return a1 - a2;
  return a1 - a2;
}
}
 
 
int
int
_bfd_sh64_crange_bsearch_cmpb (const void *p1, const void *p2)
_bfd_sh64_crange_bsearch_cmpb (const void *p1, const void *p2)
{
{
  bfd_vma a1 = *(bfd_vma *) p1;
  bfd_vma a1 = *(bfd_vma *) p1;
  bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
  bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
  bfd_size_type size
  bfd_size_type size
    = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
    = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
 
 
  if (a1 >= a2 + size)
  if (a1 >= a2 + size)
    return 1;
    return 1;
  if (a1 < a2)
  if (a1 < a2)
    return -1;
    return -1;
  return 0;
  return 0;
}
}
 
 
int
int
_bfd_sh64_crange_bsearch_cmpl (const void *p1, const void *p2)
_bfd_sh64_crange_bsearch_cmpl (const void *p1, const void *p2)
{
{
  bfd_vma a1 = *(bfd_vma *) p1;
  bfd_vma a1 = *(bfd_vma *) p1;
  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
  bfd_size_type size
  bfd_size_type size
    = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
    = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
 
 
  if (a1 >= a2 + size)
  if (a1 >= a2 + size)
    return 1;
    return 1;
  if (a1 < a2)
  if (a1 < a2)
    return -1;
    return -1;
  return 0;
  return 0;
}
}
 
 
/* Check whether a specific address is specified within a .cranges
/* Check whether a specific address is specified within a .cranges
   section.  Return FALSE if not found, and TRUE if found, and the region
   section.  Return FALSE if not found, and TRUE if found, and the region
   filled into RANGEP if non-NULL.  */
   filled into RANGEP if non-NULL.  */
 
 
static bfd_boolean
static bfd_boolean
sh64_address_in_cranges (asection *cranges, bfd_vma addr,
sh64_address_in_cranges (asection *cranges, bfd_vma addr,
                         sh64_elf_crange *rangep)
                         sh64_elf_crange *rangep)
{
{
  bfd_byte *cranges_contents;
  bfd_byte *cranges_contents;
  bfd_byte *found_rangep;
  bfd_byte *found_rangep;
  bfd_size_type cranges_size = cranges->size;
  bfd_size_type cranges_size = cranges->size;
 
 
  /* If the size is not a multiple of the cranges entry size, then
  /* If the size is not a multiple of the cranges entry size, then
     something is badly wrong.  */
     something is badly wrong.  */
  if ((cranges_size % SH64_CRANGE_SIZE) != 0)
  if ((cranges_size % SH64_CRANGE_SIZE) != 0)
    return FALSE;
    return FALSE;
 
 
  /* If this section has relocations, then we can't do anything sane.  */
  /* If this section has relocations, then we can't do anything sane.  */
  if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
  if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
    return FALSE;
    return FALSE;
 
 
  /* Has some kind soul (or previous call) left processed, sorted contents
  /* Has some kind soul (or previous call) left processed, sorted contents
     for us?  */
     for us?  */
  if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
  if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
      && elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
      && elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
    cranges_contents = cranges->contents;
    cranges_contents = cranges->contents;
  else
  else
    {
    {
      if (!bfd_malloc_and_get_section (cranges->owner, cranges,
      if (!bfd_malloc_and_get_section (cranges->owner, cranges,
                                       &cranges_contents))
                                       &cranges_contents))
        goto error_return;
        goto error_return;
 
 
      /* Is it sorted?  */
      /* Is it sorted?  */
      if (elf_section_data (cranges)->this_hdr.sh_type
      if (elf_section_data (cranges)->this_hdr.sh_type
          != SHT_SH5_CR_SORTED)
          != SHT_SH5_CR_SORTED)
        /* Nope.  Lets sort it.  */
        /* Nope.  Lets sort it.  */
        qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
        qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
               SH64_CRANGE_SIZE,
               SH64_CRANGE_SIZE,
               bfd_big_endian (cranges->owner)
               bfd_big_endian (cranges->owner)
               ? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
               ? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
 
 
      /* Let's keep it around.  */
      /* Let's keep it around.  */
      cranges->contents = cranges_contents;
      cranges->contents = cranges_contents;
      bfd_set_section_flags (cranges->owner, cranges,
      bfd_set_section_flags (cranges->owner, cranges,
                             bfd_get_section_flags (cranges->owner, cranges)
                             bfd_get_section_flags (cranges->owner, cranges)
                             | SEC_IN_MEMORY);
                             | SEC_IN_MEMORY);
 
 
      /* It's sorted now.  */
      /* It's sorted now.  */
      elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
      elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
    }
    }
 
 
  /* Try and find a matching range.  */
  /* Try and find a matching range.  */
  found_rangep
  found_rangep
    = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
    = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
               SH64_CRANGE_SIZE,
               SH64_CRANGE_SIZE,
               bfd_big_endian (cranges->owner)
               bfd_big_endian (cranges->owner)
               ? _bfd_sh64_crange_bsearch_cmpb
               ? _bfd_sh64_crange_bsearch_cmpb
               : _bfd_sh64_crange_bsearch_cmpl);
               : _bfd_sh64_crange_bsearch_cmpl);
 
 
  /* Fill in a few return values if we found a matching range.  */
  /* Fill in a few return values if we found a matching range.  */
  if (found_rangep)
  if (found_rangep)
    {
    {
      enum sh64_elf_cr_type cr_type
      enum sh64_elf_cr_type cr_type
        = bfd_get_16 (cranges->owner,
        = bfd_get_16 (cranges->owner,
                      SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
                      SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
      bfd_vma cr_addr
      bfd_vma cr_addr
        = bfd_get_32 (cranges->owner,
        = bfd_get_32 (cranges->owner,
                      SH64_CRANGE_CR_ADDR_OFFSET
                      SH64_CRANGE_CR_ADDR_OFFSET
                      + (char *) found_rangep);
                      + (char *) found_rangep);
      bfd_size_type cr_size
      bfd_size_type cr_size
        = bfd_get_32 (cranges->owner,
        = bfd_get_32 (cranges->owner,
                      SH64_CRANGE_CR_SIZE_OFFSET
                      SH64_CRANGE_CR_SIZE_OFFSET
                      + (char *) found_rangep);
                      + (char *) found_rangep);
 
 
      rangep->cr_addr = cr_addr;
      rangep->cr_addr = cr_addr;
      rangep->cr_size = cr_size;
      rangep->cr_size = cr_size;
      rangep->cr_type = cr_type;
      rangep->cr_type = cr_type;
 
 
      return TRUE;
      return TRUE;
    }
    }
 
 
  /* There is a .cranges section, but it does not have a descriptor
  /* There is a .cranges section, but it does not have a descriptor
     matching this address.  */
     matching this address.  */
  return FALSE;
  return FALSE;
 
 
error_return:
error_return:
  if (cranges_contents != NULL)
  if (cranges_contents != NULL)
    free (cranges_contents);
    free (cranges_contents);
  return FALSE;
  return FALSE;
}
}
 
 
/* Determine what ADDR points to in SEC, and fill in a range descriptor in
/* Determine what ADDR points to in SEC, and fill in a range descriptor in
   *RANGEP if it's non-NULL.  */
   *RANGEP if it's non-NULL.  */
 
 
enum sh64_elf_cr_type
enum sh64_elf_cr_type
sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep)
sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep)
{
{
  asection *cranges;
  asection *cranges;
 
 
  /* Fill in the range with the boundaries of the section as a default.  */
  /* Fill in the range with the boundaries of the section as a default.  */
  if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
  if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
      && elf_elfheader (sec->owner)->e_type == ET_EXEC)
      && elf_elfheader (sec->owner)->e_type == ET_EXEC)
    {
    {
      rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
      rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
      rangep->cr_size = sec->size;
      rangep->cr_size = sec->size;
      rangep->cr_type = CRT_NONE;
      rangep->cr_type = CRT_NONE;
    }
    }
  else
  else
    return FALSE;
    return FALSE;
 
 
  /* If none of the pertinent bits are set, then it's a SHcompact (or at
  /* If none of the pertinent bits are set, then it's a SHcompact (or at
     least not SHmedia).  */
     least not SHmedia).  */
  if ((elf_section_data (sec)->this_hdr.sh_flags
  if ((elf_section_data (sec)->this_hdr.sh_flags
       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
    {
    {
      enum sh64_elf_cr_type cr_type
      enum sh64_elf_cr_type cr_type
        = ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
        = ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
           ? CRT_SH5_ISA16 : CRT_DATA);
           ? CRT_SH5_ISA16 : CRT_DATA);
      rangep->cr_type = cr_type;
      rangep->cr_type = cr_type;
      return cr_type;
      return cr_type;
    }
    }
 
 
  /* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia.  */
  /* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia.  */
  if ((elf_section_data (sec)->this_hdr.sh_flags
  if ((elf_section_data (sec)->this_hdr.sh_flags
       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
    {
    {
      rangep->cr_type = CRT_SH5_ISA32;
      rangep->cr_type = CRT_SH5_ISA32;
      return CRT_SH5_ISA32;
      return CRT_SH5_ISA32;
    }
    }
 
 
  /* Otherwise, we have to look up the .cranges section.  */
  /* Otherwise, we have to look up the .cranges section.  */
  cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
  cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
 
 
  if (cranges == NULL)
  if (cranges == NULL)
    /* A mixed section but there's no .cranges section.  This is probably
    /* A mixed section but there's no .cranges section.  This is probably
       bad input; it does not comply to specs.  */
       bad input; it does not comply to specs.  */
    return CRT_NONE;
    return CRT_NONE;
 
 
  /* If this call fails, we will still have CRT_NONE in rangep->cr_type
  /* If this call fails, we will still have CRT_NONE in rangep->cr_type
     and that will be suitable to return.  */
     and that will be suitable to return.  */
  sh64_address_in_cranges (cranges, addr, rangep);
  sh64_address_in_cranges (cranges, addr, rangep);
 
 
  return rangep->cr_type;
  return rangep->cr_type;
}
}
 
 
/* This is a simpler exported interface for the benefit of gdb et al.  */
/* This is a simpler exported interface for the benefit of gdb et al.  */
 
 
bfd_boolean
bfd_boolean
sh64_address_is_shmedia (asection *sec, bfd_vma addr)
sh64_address_is_shmedia (asection *sec, bfd_vma addr)
{
{
  sh64_elf_crange dummy;
  sh64_elf_crange dummy;
  return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
  return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
}
}
 
 

powered by: WebSVN 2.1.0

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