Back to index

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

Go to the source code of this file.

Classes

struct  m32c_reloc_map
struct  relax_plt_data
struct  EncodingTable

Defines

#define OFFSET_FOR_RELOC(rel)   m32c_offset_for_reloc (abfd, rel, symtab_hdr, shndx_buf, intsyms)
#define RLA_RELOCS   0x0000000f
#define RLA_NBYTES   0x00000ff0
#define ELF_ARCH   bfd_arch_m32c
#define ELF_MACHINE_CODE   EM_M32C
#define ELF_MAXPAGESIZE   0x1000
#define TARGET_LITTLE_SYM   bfd_elf32_m32c_vec
#define TARGET_LITTLE_NAME   "elf32-m32c"
#define elf_info_to_howto_rel   NULL
#define elf_info_to_howto   m32c_info_to_howto_rela
#define elf_backend_object_p   m32c_elf_object_p
#define elf_backend_relocate_section   m32c_elf_relocate_section
#define elf_backend_check_relocs   m32c_elf_check_relocs
#define elf_backend_object_p   m32c_elf_object_p
#define elf_symbol_leading_char   ('_')
#define elf_backend_always_size_sections   m32c_elf_always_size_sections
#define elf_backend_finish_dynamic_sections   m32c_elf_finish_dynamic_sections
#define elf_backend_can_gc_sections   1
#define bfd_elf32_bfd_reloc_type_lookup   m32c_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup   m32c_reloc_name_lookup
#define bfd_elf32_bfd_relax_section   m32c_elf_relax_section
#define bfd_elf32_bfd_set_private_flags   m32c_elf_set_private_flags
#define bfd_elf32_bfd_merge_private_bfd_data   m32c_elf_merge_private_bfd_data
#define bfd_elf32_bfd_print_private_bfd_data   m32c_elf_print_private_bfd_data

Functions

static reloc_howto_type * m32c_reloc_type_lookup (bfd *, bfd_reloc_code_real_type)
static void m32c_info_to_howto_rela (bfd *, arelent *, Elf_Internal_Rela *)
static bfd_boolean m32c_elf_relocate_section (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)
static bfd_boolean m32c_elf_check_relocs (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)
static bfd_boolean m32c_elf_relax_delete_bytes (bfd *, asection *, bfd_vma, int)
static bfd_boolean m32c_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again)
static reloc_howto_type * m32c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * m32c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void m32c_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst)
static bfd_boolean m32c_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, 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 bfd_boolean m32c_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
static bfd_boolean m32c_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
static bfd_boolean m32c_elf_set_private_flags (bfd *abfd, flagword flags)
static bfd_boolean m32c_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
static bfd_boolean m32c_elf_print_private_bfd_data (bfd *abfd, PTR ptr)
static int elf32_m32c_machine (bfd *abfd)
static bfd_boolean m32c_elf_object_p (bfd *abfd)
static bfd_boolean m32c_relax_plt_check (struct elf_link_hash_entry *h, PTR xdata)
static bfd_boolean m32c_relax_plt_realloc (struct elf_link_hash_entry *h, PTR xdata)
static bfd_boolean m32c_elf_relax_plt_section (bfd *dynobj, asection *splt, struct bfd_link_info *info, bfd_boolean *again)
static int compare_reloc (const void *e1, const void *e2)
static bfd_vma m32c_offset_for_reloc (bfd *abfd, Elf_Internal_Rela *rel, Elf_Internal_Shdr *symtab_hdr, Elf_External_Sym_Shndx *shndx_buf, Elf_Internal_Sym *intsyms)

Variables

static reloc_howto_type m32c_elf_howto_table []
static struct m32c_reloc_map []
static int bytes_saved = 0
static int bytes_to_reloc []
static EncodingTable m16c_addr_encodings []
static EncodingTable m16c_jmpaddr_encodings []
static EncodingTable m32c_addr_encodings []

Class Documentation

struct m32c_reloc_map

Definition at line 238 of file elf32-m32c.c.

Class Members
bfd_reloc_code_real_type bfd_reloc_val
unsigned int m32c_reloc_val
struct relax_plt_data

Definition at line 992 of file elf32-m32c.c.

Collaboration diagram for relax_plt_data:
Class Members
bfd_boolean * again
asection * splt
struct EncodingTable

Definition at line 1263 of file elf32-m32c.c.

Class Members
int bytes
unsigned int max_disp
unsigned char new_encoding

Define Documentation

Definition at line 2024 of file elf32-m32c.c.

Definition at line 2025 of file elf32-m32c.c.

Definition at line 2022 of file elf32-m32c.c.

Definition at line 2021 of file elf32-m32c.c.

Definition at line 2020 of file elf32-m32c.c.

Definition at line 2023 of file elf32-m32c.c.

#define ELF_ARCH   bfd_arch_m32c

Definition at line 1994 of file elf32-m32c.c.

Definition at line 2013 of file elf32-m32c.c.

Definition at line 2018 of file elf32-m32c.c.

Definition at line 2010 of file elf32-m32c.c.

Definition at line 2015 of file elf32-m32c.c.

Definition at line 2011 of file elf32-m32c.c.

Definition at line 2011 of file elf32-m32c.c.

Definition at line 2009 of file elf32-m32c.c.

Definition at line 2007 of file elf32-m32c.c.

Definition at line 2006 of file elf32-m32c.c.

#define ELF_MACHINE_CODE   EM_M32C

Definition at line 1995 of file elf32-m32c.c.

#define ELF_MAXPAGESIZE   0x1000

Definition at line 1996 of file elf32-m32c.c.

#define elf_symbol_leading_char   ('_')

Definition at line 2012 of file elf32-m32c.c.

#define OFFSET_FOR_RELOC (   rel)    m32c_offset_for_reloc (abfd, rel, symtab_hdr, shndx_buf, intsyms)

Definition at line 1191 of file elf32-m32c.c.

#define RLA_NBYTES   0x00000ff0

Definition at line 1258 of file elf32-m32c.c.

#define RLA_RELOCS   0x0000000f

Definition at line 1256 of file elf32-m32c.c.

#define TARGET_LITTLE_NAME   "elf32-m32c"

Definition at line 2003 of file elf32-m32c.c.

Definition at line 2002 of file elf32-m32c.c.


Function Documentation

static int compare_reloc ( const void *  e1,
const void *  e2 
) [static]

Definition at line 1180 of file elf32-m32c.c.

{
  const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
  const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;

  if (i1->r_offset == i2->r_offset)
    return 0;
  else
    return i1->r_offset < i2->r_offset ? -1 : 1;
}

Here is the caller graph for this function:

static int elf32_m32c_machine ( bfd abfd) [static]

Definition at line 871 of file elf32-m32c.c.

{
  switch (elf_elfheader (abfd)->e_flags & EF_M32C_CPU_MASK)
    {
    case EF_M32C_CPU_M16C:  return bfd_mach_m16c;
    case EF_M32C_CPU_M32C:         return bfd_mach_m32c;
    }

  return bfd_mach_m16c;
}

Here is the caller graph for this function:

static bfd_boolean m32c_elf_always_size_sections ( bfd *output_bfd  ATTRIBUTE_UNUSED,
struct bfd_link_info info 
) [static]

Definition at line 722 of file elf32-m32c.c.

{
  bfd *dynobj;
  asection *splt;

  if (info->relocatable)
    return TRUE;

  dynobj = elf_hash_table (info)->dynobj;
  if (dynobj == NULL)
    return TRUE;

  splt = bfd_get_section_by_name (dynobj, ".plt");
  BFD_ASSERT (splt != NULL);

  splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->size);
  if (splt->contents == NULL)
    return FALSE;

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean m32c_elf_check_relocs ( bfd abfd,
struct bfd_link_info info,
asection sec,
const Elf_Internal_Rela relocs 
) [static]

Definition at line 593 of file elf32-m32c.c.

{
  Elf_Internal_Shdr *           symtab_hdr;
  struct elf_link_hash_entry ** sym_hashes;
  struct elf_link_hash_entry ** sym_hashes_end;
  const Elf_Internal_Rela *     rel;
  const Elf_Internal_Rela *     rel_end;
  bfd_vma *local_plt_offsets;
  asection *splt;
  bfd *dynobj;
 
  if (info->relocatable)
    return TRUE;
 
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  local_plt_offsets = elf_local_got_offsets (abfd);
  splt = NULL;
  dynobj = elf_hash_table(info)->dynobj;

  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
  if (!elf_bad_symtab (abfd))
    sym_hashes_end -= symtab_hdr->sh_info;
 
  rel_end = relocs + sec->reloc_count;
  for (rel = relocs; rel < rel_end; rel++)
    {
      struct elf_link_hash_entry *h;
      unsigned long r_symndx;
      bfd_vma *offset;
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx < symtab_hdr->sh_info)
        h = NULL;
      else
       {
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
         while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
           h = (struct elf_link_hash_entry *) h->root.u.i.link;
       }
 
      switch (ELF32_R_TYPE (rel->r_info))
        {
         /* This relocation describes a 16-bit pointer to a function.
            We may need to allocate a thunk in low memory; reserve memory
            for it now.  */
       case R_M32C_16:
         if (dynobj == NULL)
           elf_hash_table (info)->dynobj = dynobj = abfd;
         if (splt == NULL)
           {
             splt = bfd_get_section_by_name (dynobj, ".plt");
             if (splt == NULL)
              {
                flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
                                | SEC_IN_MEMORY | SEC_LINKER_CREATED
                                | SEC_READONLY | SEC_CODE);
                splt = bfd_make_section_with_flags (dynobj, ".plt", flags);
                if (splt == NULL
                    || ! bfd_set_section_alignment (dynobj, splt, 1))
                  return FALSE;
              }
           }

         if (h != NULL)
           offset = &h->plt.offset;
         else
           {
             if (local_plt_offsets == NULL)
              {
                size_t size;
                unsigned int i;

                size = symtab_hdr->sh_info * sizeof (bfd_vma);
                local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size);
                if (local_plt_offsets == NULL)
                  return FALSE;
                elf_local_got_offsets (abfd) = local_plt_offsets;

                for (i = 0; i < symtab_hdr->sh_info; i++)
                  local_plt_offsets[i] = (bfd_vma) -1;
              }
             offset = &local_plt_offsets[r_symndx];
           }

         if (*offset == (bfd_vma) -1)
           {
             *offset = splt->size;
             splt->size += 4;
           }
         break;
        }
    }
 
  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean m32c_elf_finish_dynamic_sections ( bfd *abfd  ATTRIBUTE_UNUSED,
struct bfd_link_info info 
) [static]

Definition at line 697 of file elf32-m32c.c.

{
  bfd *dynobj;
  asection *splt;

  /* As an extra sanity check, verify that all plt entries have
     been filled in.  */

  if ((dynobj = elf_hash_table (info)->dynobj) != NULL
      && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
    {
      bfd_byte *contents = splt->contents;
      unsigned int i, size = splt->size;
      for (i = 0; i < size; i += 4)
       {
         unsigned int x = bfd_get_32 (dynobj, contents + i);
         BFD_ASSERT (x != 0);
       }
    }

  return TRUE;
}

Here is the call graph for this function:

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

Definition at line 759 of file elf32-m32c.c.

{
  flagword old_flags, old_partial;
  flagword new_flags, new_partial;
  bfd_boolean error = FALSE;
  char new_opt[80];
  char old_opt[80];

  new_opt[0] = old_opt[0] = '\0';
  new_flags = elf_elfheader (ibfd)->e_flags;
  old_flags = elf_elfheader (obfd)->e_flags;

#ifdef DEBUG
  (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
                      old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
                      bfd_get_filename (ibfd));
#endif

  if (!elf_flags_init (obfd))
    {
      /* First call, no flags set.  */
      elf_flags_init (obfd) = TRUE;
      elf_elfheader (obfd)->e_flags = new_flags;
    }

  else if (new_flags == old_flags)
    /* Compatible flags are ok.     */
    ;

  else        /* Possibly incompatible flags.     */
    {
      /* Warn if different cpu is used (allow a specific cpu to override
        the generic cpu).  */
      new_partial = (new_flags & EF_M32C_CPU_MASK);
      old_partial = (old_flags & EF_M32C_CPU_MASK);
      if (new_partial == old_partial)
       ;

      else
       {
         switch (new_partial)
           {
           default:           strcat (new_opt, " -m16c");      break;
           case EF_M32C_CPU_M16C:  strcat (new_opt, " -m16c");  break;
           case EF_M32C_CPU_M32C:  strcat (new_opt, " -m32c");  break;
           }

         switch (old_partial)
           {
           default:           strcat (old_opt, " -m16c");      break;
           case EF_M32C_CPU_M16C:  strcat (old_opt, " -m16c");  break;
           case EF_M32C_CPU_M32C:  strcat (old_opt, " -m32c");  break;
           }
       }
      
      /* Print out any mismatches from above.  */
      if (new_opt[0])
       {
         error = TRUE;
         (*_bfd_error_handler)
           (_("%s: compiled with %s and linked with modules compiled with %s"),
            bfd_get_filename (ibfd), new_opt, old_opt);
       }

      new_flags &= ~ EF_M32C_ALL_FLAGS;
      old_flags &= ~ EF_M32C_ALL_FLAGS;

      /* Warn about any other mismatches.  */
      if (new_flags != old_flags)
       {
         error = TRUE;
         (*_bfd_error_handler)
           (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
            bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
       }
    }

  if (error)
    bfd_set_error (bfd_error_bad_value);

  return !error;
}

Here is the call graph for this function:

static bfd_boolean m32c_elf_object_p ( bfd abfd) [static]

Definition at line 883 of file elf32-m32c.c.

Here is the call graph for this function:

static bfd_boolean m32c_elf_print_private_bfd_data ( bfd abfd,
PTR  ptr 
) [static]

Definition at line 844 of file elf32-m32c.c.

{
  FILE *file = (FILE *) ptr;
  flagword flags;

  BFD_ASSERT (abfd != NULL && ptr != NULL);

  /* Print normal ELF private data.  */
  _bfd_elf_print_private_bfd_data (abfd, ptr);

  flags = elf_elfheader (abfd)->e_flags;
  fprintf (file, _("private flags = 0x%lx:"), (long)flags);

  switch (flags & EF_M32C_CPU_MASK)
    {
    default:                                            break;
    case EF_M32C_CPU_M16C:  fprintf (file, " -m16c");   break;
    case EF_M32C_CPU_M32C:  fprintf (file, " -m32c");   break;
    }

  fputc ('\n', file);
  return TRUE;
}

Here is the call graph for this function:

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

Definition at line 1867 of file elf32-m32c.c.

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

  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;

      if (ELF32_R_TYPE(irel->r_info) == R_M32C_RL_JUMP
         && irel->r_addend == 0x10 /* one byte insn, no relocs */
         && irel->r_offset + 1 < addr
         && irel->r_offset + 7 > addr)
       {
         bfd_vma disp;
         unsigned char *insn = &contents[irel->r_offset];
         disp = *insn;
         /* This is a JMP.S, which we have to manually update. */
         if (elf32_m32c_machine (abfd) == bfd_mach_m16c)
           {
             if ((*insn & 0xf8) != 0x60)
              continue;
             disp = (disp & 7);
           }
         else
           {
             if ((*insn & 0xce) != 0x4a)
              continue;
             disp = ((disp & 0x30) >> 3) | (disp & 1);
           }
         if (irel->r_offset + disp + 2 >= addr+count)
           {
             disp -= count;
             if (elf32_m32c_machine (abfd) == bfd_mach_m16c)
              {
                *insn = (*insn & 0xf8) | disp;
              }
             else
              {
                *insn = (*insn & 0xce) | ((disp & 6) << 3) | (disp & 1);
              }
           }
       }
    }

  /* Adjust the local symbols defined in this section.  */
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
  intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
  isym = intsyms;
  isymend = isym + symtab_hdr->sh_info;

  sec_shndx  = _bfd_elf_section_from_bfd_section (abfd, sec);
  shndx_hdr  = & elf_tdata (abfd)->symtab_shndx_hdr;
  shndx_buf  = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
  shndx = shndx_buf;

  for (; isym < isymend; isym++, shndx = (shndx ? shndx + 1 : NULL))
    {

      if ((int) 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);
  //  sym_hashes += symtab_hdr->sh_info;
  end_hashes = sym_hashes + symcount;

  for (; sym_hashes < end_hashes; sym_hashes ++)
    {
      struct elf_link_hash_entry * sym_hash = * sym_hashes;

      if (sym_hash &&
         (   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 m32c_elf_relax_plt_section ( bfd dynobj,
asection splt,
struct bfd_link_info info,
bfd_boolean again 
) [static]

Definition at line 1052 of file elf32-m32c.c.

{
  struct relax_plt_data relax_plt_data;
  bfd *ibfd;

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

  if (info->relocatable)
    return TRUE;

  /* We only relax the .plt section at the moment.  */
  if (dynobj != elf_hash_table (info)->dynobj
      || strcmp (splt->name, ".plt") != 0)
    return TRUE;

  /* Quick check for an empty plt.  */
  if (splt->size == 0)
    return TRUE;

  /* Map across all global symbols; see which ones happen to
     fall in the low 64k.  */
  relax_plt_data.splt = splt;
  relax_plt_data.again = again;
  elf_link_hash_traverse (elf_hash_table (info), m32c_relax_plt_check,
                       &relax_plt_data);

  /* Likewise for local symbols, though that's somewhat less convenient
     as we have to walk the list of input bfds and swap in symbol data.  */
  for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
    {
      bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
      Elf_Internal_Shdr *symtab_hdr;
      Elf_Internal_Sym *isymbuf = NULL;
      unsigned int idx;

      if (! local_plt_offsets)
       continue;

      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
      if (symtab_hdr->sh_info != 0)
       {
         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
         if (isymbuf == NULL)
           isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
                                       symtab_hdr->sh_info, 0,
                                       NULL, NULL, NULL);
         if (isymbuf == NULL)
           return FALSE;
       }

      for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
       {
         Elf_Internal_Sym *isym;
         asection *tsec;
         bfd_vma address;

         if (local_plt_offsets[idx] == (bfd_vma) -1)
           continue;

         isym = &isymbuf[idx];
         if (isym->st_shndx == SHN_UNDEF)
           continue;
         else if (isym->st_shndx == SHN_ABS)
           tsec = bfd_abs_section_ptr;
         else if (isym->st_shndx == SHN_COMMON)
           tsec = bfd_com_section_ptr;
         else
           tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);

         address = (tsec->output_section->vma
                   + tsec->output_offset
                   + isym->st_value);
         if (address <= 0xffff)
           {
             local_plt_offsets[idx] = -1;
             splt->size -= 4;
             *again = TRUE;
           }
       }

      if (isymbuf != NULL
         && symtab_hdr->contents != (unsigned char *) isymbuf)
       {
         if (! info->keep_memory)
           free (isymbuf);
         else
           {
             /* Cache the symbols for elf_link_input_bfd.  */
             symtab_hdr->contents = (unsigned char *) isymbuf;
           }
       }
    }

  /* If we changed anything, walk the symbols again to reallocate
     .plt entry addresses.  */
  if (*again && splt->size > 0)
    {
      bfd_vma entry = 0;

      elf_link_hash_traverse (elf_hash_table (info),
                           m32c_relax_plt_realloc, &entry);

      for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
       {
         bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
         unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
         unsigned int idx;

         if (! local_plt_offsets)
           continue;

         for (idx = 0; idx < nlocals; ++idx)
           if (local_plt_offsets[idx] != (bfd_vma) -1)
             {
               local_plt_offsets[idx] = entry;
              entry += 4;
             }
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1344 of file elf32-m32c.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Shdr *shndx_hdr;
  Elf_Internal_Rela *internal_relocs;
  Elf_Internal_Rela *free_relocs = NULL;
  Elf_Internal_Rela *irel, *irelend, *srel;
  bfd_byte * contents = NULL;
  bfd_byte * free_contents = NULL;
  Elf_Internal_Sym *intsyms = NULL;
  Elf_Internal_Sym *free_intsyms = NULL;
  Elf_External_Sym_Shndx *shndx_buf = NULL;
  int machine;

  if (abfd == elf_hash_table (link_info)->dynobj
      && strcmp (sec->name, ".plt") == 0)
    return m32c_elf_relax_plt_section (abfd, sec, link_info, again);

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

  machine = elf32_m32c_machine (abfd);

  /* 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;
  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;

  /* Get the section contents.  */
  if (elf_section_data (sec)->this_hdr.contents != NULL)
    contents = elf_section_data (sec)->this_hdr.contents;
  /* Go get them off disk.  */
  else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
    goto error_return;

  /* Read this BFD's symbols.  */
  /* Get cached copy if it exists.  */
  if (symtab_hdr->contents != NULL)
    {
      intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
    }
  else
    {
      intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL);
      symtab_hdr->contents = (bfd_byte *) intsyms;
    }

  if (shndx_hdr->sh_size != 0)
    {
      bfd_size_type amt;

      amt = symtab_hdr->sh_info;
      amt *= sizeof (Elf_External_Sym_Shndx);
      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
      if (shndx_buf == NULL)
       goto error_return;
      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
         || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
       goto error_return;
      shndx_hdr->contents = (bfd_byte *) shndx_buf;
    }

  /* 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 (! link_info->keep_memory)
    free_relocs = internal_relocs;

  /* The RL_ relocs must be just before the operand relocs they go
     with, so we must sort them to guarantee this.  */
  qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
         compare_reloc);

  /* Walk through them looking for relaxing opportunities.  */
  irelend = internal_relocs + sec->reloc_count;

  for (irel = internal_relocs; irel < irelend; irel++)
    {
      bfd_vma symval;
      unsigned char *insn, *gap, *einsn;
      bfd_vma pc;
      bfd_signed_vma pcrel;
      int relax_relocs;
      int gap_size;
      int new_type;
      int posn;
      int enc;
      EncodingTable *enctbl;
      EncodingTable *e;

      if (ELF32_R_TYPE(irel->r_info) != R_M32C_RL_JUMP
         && ELF32_R_TYPE(irel->r_info) != R_M32C_RL_1ADDR
         && ELF32_R_TYPE(irel->r_info) != R_M32C_RL_2ADDR)
       continue;

      srel = irel;

      /* There will always be room for the relaxed insn, since it is smaller
        than the one it would replace.  */
      BFD_ASSERT (irel->r_offset < sec->size);

      insn = contents + irel->r_offset;
      relax_relocs = irel->r_addend % 16;

      /* Ok, we only have three relocs we care about, and they're all
        fake.  The lower four bits of the addend is always the number
        of following relocs (hence the qsort above) that are assigned
        to this opcode.  The next 8 bits of the addend indicates the
        number of bytes in the insn.  We use the rest of them
        ourselves as flags for the more expensive operations (defines
        above).  The three relocs are:

        RL_JUMP: This marks all direct jump insns.  We check the
              displacement and replace them with shorter jumps if
              they're in range.  We also use this to find JMP.S
              insns and manually shorten them when we delete bytes.
              We have to decode these insns to figure out what to
              do.

        RL_1ADDR: This is a :G or :Q insn, which has a single
              "standard" operand.  We have to extract the type
              field, see if it's a wide displacement, then figure
              out if we can replace it with a narrow displacement.
              We don't have to decode these insns.

        RL_2ADDR: Similarly, but two "standard" operands.  Note that
              r_addend may still be 1, as standard operands don't
              always have displacements.  Gas shouldn't give us one
              with zero operands, but since we don't know which one
              has the displacement, we check them both anyway.

        These all point to the beginning of the insn itself, not the
        operands.

        Note that we only relax one step at a time, relying on the
        linker to call us repeatedly.  Thus, there is no code for
        JMP.A->JMP.B although that will happen in two steps.
        Likewise, for 2ADDR relaxes, we do one operand per cycle.
      */

      /* Get the value of the symbol referred to by the reloc.  Just
         in case this is the last reloc in the list, use the RL's
         addend to choose between this reloc (no addend) or the next
         (yes addend, which means at least one following reloc).  */
      srel = irel + (relax_relocs ? 1 : 0);
      symval = OFFSET_FOR_RELOC (srel);

      /* Setting gap_size nonzero is the flag which means "something
        shrunk".  */
      gap_size = 0;
      gap = NULL;
      new_type = ELF32_R_TYPE(srel->r_info);

      pc = sec->output_section->vma + sec->output_offset
       + srel->r_offset;
      pcrel = symval - pc + srel->r_addend;

      if (machine == bfd_mach_m16c)
       {
         /* R8C / M16C */

         switch (ELF32_R_TYPE(irel->r_info))
           {

           case R_M32C_RL_JUMP:
             switch (insn[0])
              {
              case 0xfe: /* jmp.b */
                if (pcrel >= 2 && pcrel <= 9)
                  {
                    /* Relax JMP.B -> JMP.S.  We need to get rid of
                      the following reloc though. */
                    insn[0] = 0x60 | (pcrel - 2);
                    new_type = R_M32C_NONE;
                    irel->r_addend = 0x10;
                    gap_size = 1;
                    gap = insn + 1;
                  }
                break;

              case 0xf4: /* jmp.w */
                /* 128 is allowed because it will be one byte closer
                   after relaxing.  Likewise for all other pc-rel
                   jumps.  */
                if (pcrel <= 128 && pcrel >= -128)
                  {
                    /* Relax JMP.W -> JMP.B */
                    insn[0] = 0xfe;
                    insn[1] = 0;
                    new_type = R_M32C_8_PCREL;
                    gap_size = 1;
                    gap = insn + 2;
                  }
                break;

              case 0xfc: /* jmp.a */
                if (pcrel <= 32768 && pcrel >= -32768)
                  {
                    /* Relax JMP.A -> JMP.W */
                    insn[0] = 0xf4;
                    insn[1] = 0;
                    insn[2] = 0;
                    new_type = R_M32C_16_PCREL;
                    gap_size = 1;
                    gap = insn + 3;
                  }
                break;

              case 0xfd: /* jsr.a */
                if (pcrel <= 32768 && pcrel >= -32768)
                  {
                    /* Relax JSR.A -> JSR.W */
                    insn[0] = 0xf5;
                    insn[1] = 0;
                    insn[2] = 0;
                    new_type = R_M32C_16_PCREL;
                    gap_size = 1;
                    gap = insn + 3;
                  }
                break;
              }
             break;

           case R_M32C_RL_2ADDR:
             /* xxxx xxxx srce dest [src-disp] [dest-disp]*/

             enctbl = m16c_addr_encodings;
             posn = 2;
             enc = (insn[1] >> 4) & 0x0f;
             e = & enctbl[enc];

             if (srel->r_offset == irel->r_offset + posn
                && e->new_encoding != enc
                && symval <= e->max_disp)
              {
                insn[1] &= 0x0f;
                insn[1] |= e->new_encoding << 4;
                gap_size = e->bytes - enctbl[e->new_encoding].bytes;
                gap = insn + posn + enctbl[e->new_encoding].bytes;
                new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
                break;
              }
             if (relax_relocs == 2)
              srel ++;
             posn += e->bytes;

             goto try_1addr_16;

           case R_M32C_RL_1ADDR:
             /* xxxx xxxx xxxx dest [disp] */

             enctbl = m16c_addr_encodings;
             posn = 2;
             
             /* Check the opcode for jumps.  We know it's safe to
               do this because all 2ADDR insns are at least two
               bytes long.  */
             enc = insn[0] * 256 + insn[1];
             enc &= 0xfff0;
             if (enc == 0x7d20
                || enc == 0x7d00
                || enc == 0x7d30
                || enc == 0x7d10)
              {
                enctbl = m16c_jmpaddr_encodings;
              }

           try_1addr_16:
             /* srel, posn, and enc must be set here.  */

             symval = OFFSET_FOR_RELOC (srel);
             enc = insn[1] & 0x0f;
             e = & enctbl[enc];

             if (srel->r_offset == irel->r_offset + posn
                && e->new_encoding != enc
                && symval <= e->max_disp)
              {
                insn[1] &= 0xf0;
                insn[1] |= e->new_encoding;
                gap_size = e->bytes - enctbl[e->new_encoding].bytes;
                gap = insn + posn + enctbl[e->new_encoding].bytes;
                new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
                break;
              }

             break;

           } /* Ends switch (reloc type) for m16c.  */
       }
      else /* machine == bfd_mach_m32c */
       {
         /* M32CM / M32C */

         switch (ELF32_R_TYPE(irel->r_info))
           {

           case R_M32C_RL_JUMP:
             switch (insn[0])
              {
              case 0xbb: /* jmp.b */
                if (pcrel >= 2 && pcrel <= 9)
                  {
                    int p = pcrel - 2;
                    /* Relax JMP.B -> JMP.S.  We need to get rid of
                      the following reloc though. */
                    insn[0] = 0x4a | ((p << 3) & 0x30) | (p & 1);
                    new_type = R_M32C_NONE;
                    irel->r_addend = 0x10;
                    gap_size = 1;
                    gap = insn + 1;
                  }
                break;

              case 0xce: /* jmp.w */
                if (pcrel <= 128 && pcrel >= -128)
                  {
                    /* Relax JMP.W -> JMP.B */
                    insn[0] = 0xbb;
                    insn[1] = 0;
                    new_type = R_M32C_8_PCREL;
                    gap_size = 1;
                    gap = insn + 2;
                  }
                break;

              case 0xcc: /* jmp.a */
                if (pcrel <= 32768 && pcrel >= -32768)
                  {
                    /* Relax JMP.A -> JMP.W */
                    insn[0] = 0xce;
                    insn[1] = 0;
                    insn[2] = 0;
                    new_type = R_M32C_16_PCREL;
                    gap_size = 1;
                    gap = insn + 3;
                  }
                break;

              case 0xcd: /* jsr.a */
                if (pcrel <= 32768 && pcrel >= -32768)
                  {
                    /* Relax JSR.A -> JSR.W */
                    insn[0] = 0xcf;
                    insn[1] = 0;
                    insn[2] = 0;
                    new_type = R_M32C_16_PCREL;
                    gap_size = 1;
                    gap = insn + 3;
                  }
                break;
              }
             break;

           case R_M32C_RL_2ADDR:
             /* xSSS DDDx DDSS xxxx [src-disp] [dest-disp]*/

             einsn = insn;
             posn = 2;
             if (einsn[0] == 1)
              {
                /* prefix; remove it as far as the RL reloc is concerned.  */
                einsn ++;
                posn ++;
              }

             enctbl = m32c_addr_encodings;
             enc = ((einsn[0] & 0x70) >> 2) | ((einsn[1] & 0x30) >> 4);
             e = & enctbl[enc];

             if (srel->r_offset == irel->r_offset + posn
                && e->new_encoding != enc
                && symval <= e->max_disp)
              {
                einsn[0] &= 0x8f;
                einsn[0] |= (e->new_encoding & 0x1c) << 2;
                einsn[1] &= 0xcf;
                einsn[1] |= (e->new_encoding & 0x03) << 4;
                gap_size = e->bytes - enctbl[e->new_encoding].bytes;
                gap = insn + posn + enctbl[e->new_encoding].bytes;
                new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
                break;
              }
             if (relax_relocs == 2)
                srel ++;
             posn += e->bytes;

             goto try_1addr_32;

           case R_M32C_RL_1ADDR:
             /* xxxx DDDx DDxx xxxx [disp] */

             einsn = insn;
             posn = 2;
             if (einsn[0] == 1)
              {
                /* prefix; remove it as far as the RL reloc is concerned.  */
                einsn ++;
                posn ++;
              }

             enctbl = m32c_addr_encodings;

           try_1addr_32:
             /* srel, posn, and enc must be set here.  */

             symval = OFFSET_FOR_RELOC (srel);
             enc = ((einsn[0] & 0x0e) << 1) |  ((einsn[1] & 0xc0) >> 6);
             e = & enctbl[enc];

             if (srel->r_offset == irel->r_offset + posn
                && e->new_encoding != enc
                && symval <= e->max_disp)
              {
                einsn[0] &= 0xf1;
                einsn[0] |= (e->new_encoding & 0x1c) >> 1;
                einsn[1] &= 0x3f;
                einsn[1] |= (e->new_encoding & 0x03) << 6;
                gap_size = e->bytes - enctbl[e->new_encoding].bytes;
                gap = insn + posn + enctbl[e->new_encoding].bytes;
                new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
                break;
              }

             break;

           } /* Ends switch (reloc type) for m32c.  */
       }

      if (gap_size == 0)
       continue;

      *again = TRUE;

      srel->r_info = ELF32_R_INFO (ELF32_R_SYM (srel->r_info), new_type);

      /* Note that we've changed the relocs, section contents, etc.  */
      elf_section_data (sec)->relocs = internal_relocs;
      free_relocs = NULL;
      
      elf_section_data (sec)->this_hdr.contents = contents;
      free_contents = NULL;

      symtab_hdr->contents = (bfd_byte *) intsyms;
      free_intsyms = NULL;

      bytes_saved += gap_size;

      if (! m32c_elf_relax_delete_bytes(abfd, sec, gap - contents, gap_size))
       goto error_return;

    } /* next relocation */

  if (free_relocs != NULL)
    {
      free (free_relocs);
      free_relocs = NULL;
    }

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

      free_contents = NULL;
    }

  if (shndx_buf != NULL)
    {
      shndx_hdr->contents = NULL;
      free (shndx_buf);
    }

  if (free_intsyms != NULL)
    {
      if (! link_info->keep_memory)
       free (free_intsyms);
      /* Cache the symbols for elf_link_input_bfd.  */
      else
       {
       symtab_hdr->contents = NULL /* (unsigned char *) intsyms*/;
       }

      free_intsyms = NULL;
    }

  return TRUE;

 error_return:
  if (free_relocs != NULL)
    free (free_relocs);
  if (free_contents != NULL)
    free (free_contents);
  if (shndx_buf != NULL)
    {
      shndx_hdr->contents = NULL;
      free (shndx_buf);
    }
  if (free_intsyms != NULL)
    free (free_intsyms);
  return FALSE;
}

Here is the call graph for this function:

static bfd_boolean m32c_elf_relocate_section ( bfd ,
struct bfd_link_info ,
bfd ,
asection ,
bfd_byte ,
Elf_Internal_Rela ,
Elf_Internal_Sym *  ,
asection **   
) [static]
static bfd_boolean m32c_elf_relocate_section ( bfd *output_bfd  ATTRIBUTE_UNUSED,
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 342 of file elf32-m32c.c.

{
  Elf_Internal_Shdr *           symtab_hdr;
  struct elf_link_hash_entry ** sym_hashes;
  Elf_Internal_Rela *           rel;
  Elf_Internal_Rela *           relend;
  bfd *dynobj;
  asection *splt;

  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);
  relend     = relocs + input_section->reloc_count;

  dynobj = elf_hash_table (info)->dynobj;
  splt = NULL;
  if (dynobj != NULL)
    splt = bfd_get_section_by_name (dynobj, ".plt");

  for (rel = relocs; rel < relend; rel ++)
    {
      reloc_howto_type *           howto;
      unsigned long                r_symndx;
      Elf_Internal_Sym *           sym;
      asection *                   sec;
      struct elf_link_hash_entry * h;
      bfd_vma                      relocation;
      bfd_reloc_status_type        r;
      const char *                 name = NULL;
      int                          r_type;
      
      r_type = ELF32_R_TYPE (rel->r_info);

      /* These are only used for relaxing; we don't actually relocate
        anything with them, so skip them.  */
      if (r_type == R_M32C_RL_JUMP
         || r_type == R_M32C_RL_1ADDR
         || r_type == R_M32C_RL_2ADDR)
       continue;
      
      r_symndx = ELF32_R_SYM (rel->r_info);

      howto  = m32c_elf_howto_table + ELF32_R_TYPE (rel->r_info);
      h      = NULL;
      sym    = NULL;
      sec    = NULL;
      relocation = 0;

      if (r_symndx < symtab_hdr->sh_info)
       {
         sym = local_syms + r_symndx;
         sec = local_sections [r_symndx];
         relocation = (sec->output_section->vma
                     + sec->output_offset
                     + sym->st_value);
         
         name = bfd_elf_string_from_elf_section
           (input_bfd, symtab_hdr->sh_link, sym->st_name);
         name = (sym->st_name == 0) ? bfd_section_name (input_bfd, sec) : name;
       }
      else
       {
         h = sym_hashes [r_symndx - symtab_hdr->sh_info];
         
         while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
           h = (struct elf_link_hash_entry *) h->root.u.i.link;

         name = h->root.root.string;
         
         if (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak)
           {
             sec = h->root.u.def.section;
             relocation = (h->root.u.def.value
                         + sec->output_section->vma
                         + sec->output_offset);
           }
         else if (h->root.type == bfd_link_hash_undefweak)
           ;
         else if (!info->relocatable)
           {
             if (! ((*info->callbacks->undefined_symbol)
                   (info, h->root.root.string, input_bfd,
                    input_section, rel->r_offset, TRUE)))
              return FALSE;
           }
       }

      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)
       {
         /* This is a relocatable link.  We don't have to change
             anything, unless the reloc is against a section symbol,
             in which case we have to adjust according to where the
             section symbol winds up in the output section.  */
         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
           rel->r_addend += sec->output_offset;
         continue;
       }

      switch (ELF32_R_TYPE (rel->r_info))
       {
       case R_M32C_16:
         {
           bfd_vma *plt_offset;

           if (h != NULL)
             plt_offset = &h->plt.offset;
           else
             plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;

           /*     printf("%s: rel %x plt %d\n", h ? h->root.root.string : "(none)",
                  relocation, *plt_offset);*/
           if (relocation <= 0xffff)
             {
               /* If the symbol is in range for a 16-bit address, we should
                 have deallocated the plt entry in relax_section.  */
               BFD_ASSERT (*plt_offset == (bfd_vma) -1);
             }
           else
             {
              /* If the symbol is out of range for a 16-bit address,
                 we must have allocated a plt entry.  */
              BFD_ASSERT (*plt_offset != (bfd_vma) -1);

              /* If this is the first time we've processed this symbol,
                 fill in the plt entry with the correct symbol address.  */
              if ((*plt_offset & 1) == 0)
                {
                  unsigned int x;

                  x = 0x000000fc;  /* jmpf */
                  x |= (relocation << 8) & 0xffffff00;
                  bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
                  *plt_offset |= 1;
                }

              relocation = (splt->output_section->vma
                           + splt->output_offset
                           + (*plt_offset & -2));
              if (name)
              {
                char *newname = bfd_malloc (strlen(name)+5);
                strcpy (newname, name);
                strcat(newname, ".plt");
                _bfd_generic_link_add_one_symbol (info,
                                              input_bfd,
                                              newname,
                                              BSF_FUNCTION | BSF_WEAK,
                                              splt,
                                              (*plt_offset & -2),
                                              0,
                                              1,
                                              0,
                                              0);
              }
             }
         }
         break;

       case R_M32C_HI8:
       case R_M32C_HI16:
         relocation >>= 16;
         break;
       }

#if 0
      printf ("relocate %s at %06lx relocation %06lx addend %ld  ",
             m32c_elf_howto_table[ELF32_R_TYPE(rel->r_info)].name,
             rel->r_offset + input_section->output_section->vma + input_section->output_offset,
             relocation, rel->r_addend);
      {
       int i;
       for (i=0; i<4; i++)
         printf (" %02x", contents[rel->r_offset+i]);
       printf ("\n");
      }
#endif
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset, relocation,
                                    rel->r_addend);

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

         switch (r)
           {
           case bfd_reloc_overflow:
             r = info->callbacks->reloc_overflow
              (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
               input_bfd, input_section, rel->r_offset);
             break;
             
           case bfd_reloc_undefined:
             r = info->callbacks->undefined_symbol
              (info, name, input_bfd, input_section, rel->r_offset,
               TRUE);
             break;
             
           case bfd_reloc_outofrange:
             msg = _("internal error: out of range error");
             break;

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

           case bfd_reloc_dangerous:
             msg = _("internal error: dangerous relocation");
             break;

           default:
             msg = _("internal error: unknown error");
             break;
           }

         if (msg)
           r = info->callbacks->warning
             (info, msg, name, input_bfd, input_section, rel->r_offset);

         if (! r)
           return FALSE;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean m32c_elf_set_private_flags ( bfd abfd,
flagword  flags 
) [static]

Definition at line 748 of file elf32-m32c.c.

{
  elf_elfheader (abfd)->e_flags = flags;
  elf_flags_init (abfd) = TRUE;
  return TRUE;
}
static void m32c_info_to_howto_rela ( bfd ,
arelent ,
Elf_Internal_Rela  
) [static]
static void m32c_info_to_howto_rela ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent cache_ptr,
Elf_Internal_Rela dst 
) [static]

Definition at line 294 of file elf32-m32c.c.

{
  unsigned int r_type;

  r_type = ELF32_R_TYPE (dst->r_info);
  BFD_ASSERT (r_type < (unsigned int) R_M32C_max);
  cache_ptr->howto = & m32c_elf_howto_table [r_type];
}
static bfd_vma m32c_offset_for_reloc ( bfd abfd,
Elf_Internal_Rela rel,
Elf_Internal_Shdr symtab_hdr,
Elf_External_Sym_Shndx shndx_buf,
Elf_Internal_Sym *  intsyms 
) [static]

Definition at line 1193 of file elf32-m32c.c.

{
  bfd_vma symval;

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


      isym = intsyms + ELF32_R_SYM (rel->r_info);
      ssec = bfd_section_from_elf_index (abfd, isym->st_shndx);
      shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (rel->r_info) : 0);

      symval = isym->st_value;
      if (ssec)
       symval += ssec->output_section->vma
         + ssec->output_offset;
    }
  else
    {
      unsigned long indx;
      struct elf_link_hash_entry *h;

      /* An external symbol.  */
      indx = ELF32_R_SYM (rel->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.  */
       return 0;

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

Here is the call graph for this function:

static bfd_boolean m32c_relax_plt_check ( struct elf_link_hash_entry h,
PTR  xdata 
) [static]

Definition at line 999 of file elf32-m32c.c.

{
  struct relax_plt_data *data = (struct relax_plt_data *) xdata;

  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;

  if (h->plt.offset != (bfd_vma) -1)
    {
      bfd_vma address;

      if (h->root.type == bfd_link_hash_undefined
         || h->root.type == bfd_link_hash_undefweak)
       address = 0;
      else
       address = (h->root.u.def.section->output_section->vma
                 + h->root.u.def.section->output_offset
                 + h->root.u.def.value);

      if (address <= 0xffff)
       {
         h->plt.offset = -1;
         data->splt->size -= 4;
         *data->again = TRUE;
       }
    }

  return TRUE;
}

Here is the caller graph for this function:

static bfd_boolean m32c_relax_plt_realloc ( struct elf_link_hash_entry h,
PTR  xdata 
) [static]

Definition at line 1034 of file elf32-m32c.c.

{
  bfd_vma *entry = (bfd_vma *) xdata;

  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;

  if (h->plt.offset != (bfd_vma) -1)
    {
      h->plt.offset = *entry;
      *entry += 4;
    }

  return TRUE;
}

Here is the caller graph for this function:

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

Definition at line 276 of file elf32-m32c.c.

{
  unsigned int i;

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

  return NULL;
}

Here is the call graph for this function:

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

Definition at line 263 of file elf32-m32c.c.

{
  unsigned int i;

  for (i = ARRAY_SIZE (m32c_reloc_map); --i;)
    if (m32c_reloc_map [i].bfd_reloc_val == code)
      return & m32c_elf_howto_table [m32c_reloc_map[i].m32c_reloc_val];
  
  return NULL;
}

Variable Documentation

int bytes_saved = 0 [static]

Definition at line 1243 of file elf32-m32c.c.

int bytes_to_reloc[] [static]
Initial value:
 {
  R_M32C_NONE,
  R_M32C_8,
  R_M32C_16,
  R_M32C_24,
  R_M32C_32
}

Definition at line 1245 of file elf32-m32c.c.

Initial value:
 {
  { 0,   0,  0 }, 
  { 0,   0,  1 }, 
  { 0,   0,  2 }, 
  { 0,   0,  3 }, 
  { 0,   0,  4 }, 
  { 0,   0,  5 }, 
  { 0,   0,  6 }, 
  { 0,   0,  7 }, 
  { 1,   0,  6 }, 
  { 1,   0,  7 }, 
  { 1,   0, 10 }, 
  { 1,   0, 11 }, 
  { 2, 255,  8 }, 
  { 2, 255,  9 }, 
  { 2, 255, 10 }, 
  { 2,   0, 15 }, 
}

Definition at line 1269 of file elf32-m32c.c.

Initial value:
 {
  { 0,   0,  0 }, 
  { 0,   0,  1 }, 
  { 0,   0,  2 }, 
  { 0,   0,  3 }, 
  { 0,   0,  4 }, 
  { 0,   0,  5 }, 
  { 0,   0,  6 }, 
  { 0,   0,  7 }, 
  { 1,   0,  6 }, 
  { 1,   0,  7 }, 
  { 1,   0, 10 }, 
  { 1,   0, 11 }, 
  { 3, 255,  8 }, 
  { 3, 255,  9 }, 
  { 2, 255, 10 }, 
  { 2,   0, 15 }, 
}

Definition at line 1288 of file elf32-m32c.c.

Definition at line 1307 of file elf32-m32c.c.

reloc_howto_type m32c_elf_howto_table[] [static]

Definition at line 46 of file elf32-m32c.c.

struct m32c_reloc_map[] [static]
Initial value:
{
  { BFD_RELOC_NONE,         R_M32C_NONE },
  { BFD_RELOC_16,           R_M32C_16 },
  { BFD_RELOC_24,               R_M32C_24 },
  { BFD_RELOC_32,           R_M32C_32 },
  { BFD_RELOC_8_PCREL,          R_M32C_8_PCREL },
  { BFD_RELOC_16_PCREL,         R_M32C_16_PCREL },
  { BFD_RELOC_8,            R_M32C_8 },
  { BFD_RELOC_LO16,         R_M32C_LO16 },
  { BFD_RELOC_HI16,         R_M32C_HI16 },
  { BFD_RELOC_M32C_HI8,            R_M32C_HI8 },
  { BFD_RELOC_M32C_RL_JUMP, R_M32C_RL_JUMP },
  { BFD_RELOC_M32C_RL_1ADDR,       R_M32C_RL_1ADDR },
  { BFD_RELOC_M32C_RL_2ADDR,       R_M32C_RL_2ADDR }
}

Definition at line 244 of file elf32-m32c.c.