Back to index

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

Go to the source code of this file.

Classes

struct  msp430_reloc_map
struct  rcodes_s

Defines

#define NUMB_RELAX_CODES   12
#define ELF_ARCH   bfd_arch_msp430
#define ELF_MACHINE_CODE   EM_MSP430
#define ELF_MACHINE_ALT1   EM_MSP430_OLD
#define ELF_MAXPAGESIZE   1
#define ELF_OSABI   ELFOSABI_STANDALONE
#define TARGET_LITTLE_SYM   bfd_elf32_msp430_vec
#define TARGET_LITTLE_NAME   "elf32-msp430"
#define elf_info_to_howto   msp430_info_to_howto_rela
#define elf_info_to_howto_rel   NULL
#define elf_backend_relocate_section   elf32_msp430_relocate_section
#define elf_backend_check_relocs   elf32_msp430_check_relocs
#define elf_backend_can_gc_sections   1
#define elf_backend_final_write_processing   bfd_elf_msp430_final_write_processing
#define elf_backend_object_p   elf32_msp430_object_p
#define elf_backend_post_process_headers   _bfd_elf_set_osabi
#define bfd_elf32_bfd_relax_section   msp430_elf_relax_section

Functions

static reloc_howto_type * bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void msp430_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst)
static bfd_boolean elf32_msp430_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs)
static bfd_reloc_status_type msp430_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, asection *input_section, bfd_byte *contents, Elf_Internal_Rela *rel, bfd_vma relocation)
static bfd_boolean elf32_msp430_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 void bfd_elf_msp430_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
static bfd_boolean elf32_msp430_object_p (bfd *abfd)
static bfd_boolean msp430_elf_symbol_address_p (bfd *abfd, asection *sec, Elf_Internal_Sym *isym, bfd_vma addr)
static bfd_boolean msp430_elf_relax_adjust_locals (bfd *abfd, asection *sec, bfd_vma addr, int count, unsigned int sec_shndx, bfd_vma toaddr)
static bfd_boolean msp430_elf_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
static bfd_boolean msp430_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again)

Variables

static reloc_howto_type elf_msp430_howto_table []
static struct msp430_reloc_map []
static struct rcodes_s rcode []

Class Documentation

struct msp430_reloc_map

Definition at line 170 of file elf32-msp430.c.

Class Members
bfd_reloc_code_real_type bfd_reloc_val
unsigned int elf_reloc_val
struct rcodes_s

Definition at line 737 of file elf32-msp430.c.

Class Members
int bs
int cdx
int f0
int f1
int index
int labels
long lop0
long lop1
long lop2
long lpos
char * name
int ncl
int off
int sop
int t0
int t1

Define Documentation

Definition at line 1192 of file elf32-msp430.c.

#define ELF_ARCH   bfd_arch_msp430

Definition at line 1175 of file elf32-msp430.c.

Definition at line 1188 of file elf32-msp430.c.

Definition at line 1187 of file elf32-msp430.c.

Definition at line 1189 of file elf32-msp430.c.

Definition at line 1190 of file elf32-msp430.c.

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

Definition at line 1186 of file elf32-msp430.c.

Definition at line 1184 of file elf32-msp430.c.

Definition at line 1185 of file elf32-msp430.c.

Definition at line 1177 of file elf32-msp430.c.

Definition at line 1176 of file elf32-msp430.c.

#define ELF_MAXPAGESIZE   1

Definition at line 1178 of file elf32-msp430.c.

Definition at line 1179 of file elf32-msp430.c.

#define NUMB_RELAX_CODES   12

Definition at line 736 of file elf32-msp430.c.

#define TARGET_LITTLE_NAME   "elf32-msp430"

Definition at line 1182 of file elf32-msp430.c.

Definition at line 1181 of file elf32-msp430.c.


Function Documentation

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

Definition at line 204 of file elf32-msp430.c.

{
  unsigned int i;

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

  return NULL;
}

Here is the call graph for this function:

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

Definition at line 191 of file elf32-msp430.c.

{
  unsigned int i;

  for (i = 0; i < ARRAY_SIZE (msp430_reloc_map); i++)
    if (msp430_reloc_map[i].bfd_reloc_val == code)
      return &elf_msp430_howto_table[msp430_reloc_map[i].elf_reloc_val];

  return NULL;
}
static void bfd_elf_msp430_final_write_processing ( bfd abfd,
bfd_boolean linker  ATTRIBUTE_UNUSED 
) [static]

Definition at line 530 of file elf32-msp430.c.

{
  unsigned long val;

  switch (bfd_get_mach (abfd))
    {
    default:
    case bfd_mach_msp110:
      val = E_MSP430_MACH_MSP430x11x1;
      break;

    case bfd_mach_msp11:
      val = E_MSP430_MACH_MSP430x11;
      break;

    case bfd_mach_msp12:
      val = E_MSP430_MACH_MSP430x12;
      break;

    case bfd_mach_msp13:
      val = E_MSP430_MACH_MSP430x13;
      break;

    case bfd_mach_msp14:
      val = E_MSP430_MACH_MSP430x14;
      break;

    case bfd_mach_msp15:
      val = E_MSP430_MACH_MSP430x15;
      break;

    case bfd_mach_msp16:
      val = E_MSP430_MACH_MSP430x16;
      break;

    case bfd_mach_msp31:
      val = E_MSP430_MACH_MSP430x31;
      break;

    case bfd_mach_msp32:
      val = E_MSP430_MACH_MSP430x32;
      break;

    case bfd_mach_msp33:
      val = E_MSP430_MACH_MSP430x33;
      break;

    case bfd_mach_msp41:
      val = E_MSP430_MACH_MSP430x41;
      break;

    case bfd_mach_msp42:
      val = E_MSP430_MACH_MSP430x42;
      break;

    case bfd_mach_msp43:
      val = E_MSP430_MACH_MSP430x43;
      break;

    case bfd_mach_msp44:
      val = E_MSP430_MACH_MSP430x44;
      break;
    }

  elf_elfheader (abfd)->e_machine = EM_MSP430;
  elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH;
  elf_elfheader (abfd)->e_flags |= val;
}

Here is the call graph for this function:

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

Definition at line 239 of file elf32-msp430.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
  const Elf_Internal_Rela *rel;
  const Elf_Internal_Rela *rel_end;

  if (info->relocatable)
    return TRUE;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  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;

      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;
       }
    }

  return TRUE;
}
static bfd_boolean elf32_msp430_object_p ( bfd abfd) [static]

Definition at line 603 of file elf32-msp430.c.

{
  int e_set = bfd_mach_msp14;

  if (elf_elfheader (abfd)->e_machine == EM_MSP430
      || elf_elfheader (abfd)->e_machine == EM_MSP430_OLD)
    {
      int e_mach = elf_elfheader (abfd)->e_flags & EF_MSP430_MACH;

      switch (e_mach)
       {
       default:
       case E_MSP430_MACH_MSP430x11:
         e_set = bfd_mach_msp11;
         break;

       case E_MSP430_MACH_MSP430x11x1:
         e_set = bfd_mach_msp110;
         break;

       case E_MSP430_MACH_MSP430x12:
         e_set = bfd_mach_msp12;
         break;

       case E_MSP430_MACH_MSP430x13:
         e_set = bfd_mach_msp13;
         break;

       case E_MSP430_MACH_MSP430x14:
         e_set = bfd_mach_msp14;
         break;

       case E_MSP430_MACH_MSP430x15:
         e_set = bfd_mach_msp15;
         break;

       case E_MSP430_MACH_MSP430x16:
         e_set = bfd_mach_msp16;
         break;

       case E_MSP430_MACH_MSP430x31:
         e_set = bfd_mach_msp31;
         break;

       case E_MSP430_MACH_MSP430x32:
         e_set = bfd_mach_msp32;
         break;

       case E_MSP430_MACH_MSP430x33:
         e_set = bfd_mach_msp33;
         break;

       case E_MSP430_MACH_MSP430x41:
         e_set = bfd_mach_msp41;
         break;

       case E_MSP430_MACH_MSP430x42:
         e_set = bfd_mach_msp42;
         break;

       case E_MSP430_MACH_MSP430x43:
         e_set = bfd_mach_msp43;
         break;

       case E_MSP430_MACH_MSP430x44:
         e_set = bfd_mach_msp44;
         break;
       }
    }

  return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set);
}

Here is the call graph for this function:

static bfd_boolean elf32_msp430_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 403 of file elf32-msp430.c.

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

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

  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);
      r_symndx = ELF32_R_SYM (rel->r_info);
      howto = elf_msp430_howto_table + 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);

         name = bfd_elf_string_from_elf_section
             (input_bfd, symtab_hdr->sh_link, sym->st_name);
         name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
       }
      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 = msp430_final_link_relocate (howto, input_bfd, input_section,
                                  contents, rel, relocation);

      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 msp430_elf_relax_adjust_locals ( bfd abfd,
asection sec,
bfd_vma  addr,
int  count,
unsigned int  sec_shndx,
bfd_vma  toaddr 
) [static]

Definition at line 809 of file elf32-msp430.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Rela *irel;
  Elf_Internal_Rela *irelend;
  Elf_Internal_Sym *isym;

  irel = elf_section_data (sec)->relocs;
  irelend = irel + sec->reloc_count;
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
  
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
    {
      int sidx = ELF32_R_SYM(irel->r_info);
      Elf_Internal_Sym *lsym = isym + sidx;
      
      /* Adjust symbols referenced by .sec+0xXX */
      if (irel->r_addend > addr && irel->r_addend < toaddr 
         && lsym->st_shndx == sec_shndx)
       irel->r_addend -= count;
    }
  
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 839 of file elf32-msp430.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  unsigned 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;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **end_hashes;
  unsigned int symcount;
  asection *p;

  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.  */
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
  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;
    }

  for (p = abfd->sections; p != NULL; p = p->next)
    msp430_elf_relax_adjust_locals(abfd,p,addr,count,sec_shndx,toaddr);
  
  /* Adjust the local symbols defined in this section.  */
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
  for (isymend = isym + symtab_hdr->sh_info; 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 msp430_elf_relax_section ( bfd abfd,
asection sec,
struct bfd_link_info link_info,
bfd_boolean again 
) [static]

Definition at line 917 of file elf32-msp430.c.

{
  Elf_Internal_Shdr * symtab_hdr;
  Elf_Internal_Rela * internal_relocs;
  Elf_Internal_Rela * irel;
  Elf_Internal_Rela * irelend;
  bfd_byte *          contents = NULL;
  Elf_Internal_Sym *  isymbuf = 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, NULL, NULL, link_info->keep_memory);
  if (internal_relocs == NULL)
    goto error_return;

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

      /* If this isn't something that can be relaxed, then ignore
         this reloc.  */
      if (ELF32_R_TYPE (irel->r_info) != (int) R_MSP430_RL_PCREL)
       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 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);
         if (isym->st_shndx == SHN_UNDEF)
           sym_sec = bfd_und_section_ptr;
         else if (isym->st_shndx == SHN_ABS)
           sym_sec = bfd_abs_section_ptr;
         else if (isym->st_shndx == SHN_COMMON)
           sym_sec = bfd_com_section_ptr;
         else
           sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
         symval = (isym->st_value
                  + 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.  */

      /* Try to turn a 16bit pc-relative branch into a 10bit pc-relative
         branch.  */
      /* Paranoia? paranoia...  */      
      if (ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
       {
         bfd_vma value = symval;

         /* Deal with pc-relative gunk.  */
         value -= (sec->output_section->vma + sec->output_offset);
         value -= irel->r_offset;
         value += irel->r_addend;

         /* See if the value will fit in 10 bits, note the high value is
            1016 as the target will be two bytes closer if we are
            able to relax. */
         if ((long) value < 1016 && (long) value > -1016)
           {
             int code0 = 0, code1 = 0, code2 = 0;
             int i;
             struct rcodes_s *rx;

             /* Get the opcode.  */
             if (irel->r_offset >= 6)
              code0 = bfd_get_16 (abfd, contents + irel->r_offset - 6);

             if (irel->r_offset >= 4)
              code1 = bfd_get_16 (abfd, contents + irel->r_offset - 4);

             code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);

             if (code2 != 0x4010)
              continue;

             /* Check r4 and r3.  */
             for (i = NUMB_RELAX_CODES - 1; i >= 0; i--)
              {
                rx = &rcode[i];
                if (rx->cdx == 2 && rx->f0 == code0 && rx->f1 == code1)
                  break;
                else if (rx->cdx == 1 && rx->f1 == code1)
                  break;
                else if (rx->cdx == 0)    /* This is an unconditional jump.  */
                  break;
              }

             /* Check labels:
                 .Label0:       ; we do not care about this label
                    jeq    +6
                 .Label1:       ; make sure there is no label here
                    jl     +4
                 .Label2:       ; make sure there is no label here
                    br .Label_dst

                So, if there is .Label1 or .Label2 we cannot relax this code.
                This actually should not happen, cause for relaxable
               instructions we use RL_PCREL reloc instead of 16_PCREL.
               Will change this in the future. */

             if (rx->cdx > 0
                && msp430_elf_symbol_address_p (abfd, sec, isymbuf,
                                            irel->r_offset - 2))
              continue;
             if (rx->cdx > 1
                && msp430_elf_symbol_address_p (abfd, sec, isymbuf,
                                            irel->r_offset - 4))
              continue;

             /* 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;

             /* Fix the relocation's type.  */
             if (rx->labels == 3)  /* Handle special cases.  */
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                      R_MSP430_2X_PCREL);
             else
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                      R_MSP430_10_PCREL);

             /* Fix the opcode right way.  */
             bfd_put_16 (abfd, rx->t0, contents + irel->r_offset - rx->off);
             if (rx->t1)
              bfd_put_16 (abfd, rx->t1,
                         contents + irel->r_offset - rx->off + 2);

             /* Delete bytes. */
             if (!msp430_elf_relax_delete_bytes (abfd, sec,
                                            irel->r_offset - rx->off +
                                            rx->ncl, rx->bs))
              goto error_return;

             /* Handle unconditional jumps.  */
             if (rx->cdx == 0)
              irel->r_offset -= 2;

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

  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
    {
      if (!link_info->keep_memory)
       free (isymbuf);
      else
       {
         /* Cache the symbols for elf_link_input_bfd.  */
         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 bfd_boolean msp430_elf_symbol_address_p ( bfd abfd,
asection sec,
Elf_Internal_Sym *  isym,
bfd_vma  addr 
) [static]

Definition at line 768 of file elf32-msp430.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  unsigned int sec_shndx;
  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 local symbols.  */
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  for (isymend = isym + symtab_hdr->sh_info; 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 msp430_final_link_relocate ( reloc_howto_type *  howto,
bfd input_bfd,
asection input_section,
bfd_byte contents,
Elf_Internal_Rela rel,
bfd_vma  relocation 
) [static]

Definition at line 282 of file elf32-msp430.c.

{
  bfd_reloc_status_type r = bfd_reloc_ok;
  bfd_vma x;
  bfd_signed_vma srel;

  switch (howto->type)
    {
    case R_MSP430_10_PCREL:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;
      srel -= rel->r_offset;
      srel -= 2;            /* Branch instructions add 2 to the PC...  */
      srel -= (input_section->output_section->vma +
              input_section->output_offset);

      if (srel & 1)
       return bfd_reloc_outofrange;

      /* MSP430 addresses commands as words.  */
      srel >>= 1;

      /* Check for an overflow.  */
      if (srel < -512 || srel > 511)
       return bfd_reloc_overflow;

      x = bfd_get_16 (input_bfd, contents);
      x = (x & 0xfc00) | (srel & 0x3ff);
      bfd_put_16 (input_bfd, x, contents);
      break;

    case R_MSP430_2X_PCREL:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;
      srel -= rel->r_offset;
      srel -= 2;            /* Branch instructions add 2 to the PC...  */
      srel -= (input_section->output_section->vma +
              input_section->output_offset);

      if (srel & 1)
       return bfd_reloc_outofrange;

      /* MSP430 addresses commands as words.  */
      srel >>= 1;

      /* Check for an overflow.  */
      if (srel < -512 || srel > 511)
       return bfd_reloc_overflow;

      x = bfd_get_16 (input_bfd, contents);
      x = (x & 0xfc00) | (srel & 0x3ff);
      bfd_put_16 (input_bfd, x, contents);
      /* Handle second jump instruction.  */
      x = bfd_get_16 (input_bfd, contents - 2);
      srel += 1;
      x = (x & 0xfc00) | (srel & 0x3ff);
      bfd_put_16 (input_bfd, x, contents - 2);
      break;

    case R_MSP430_16_PCREL:
    case R_MSP430_RL_PCREL:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;
      srel -= rel->r_offset;
      /* Only branch instructions add 2 to the PC...  */
      srel -= (input_section->output_section->vma +
              input_section->output_offset);

      if (srel & 1)
       return bfd_reloc_outofrange;

      bfd_put_16 (input_bfd, srel & 0xffff, contents);
      break;

    case R_MSP430_16_PCREL_BYTE:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;
      srel -= rel->r_offset;
      /* Only branch instructions add 2 to the PC...  */
      srel -= (input_section->output_section->vma +
              input_section->output_offset);

      bfd_put_16 (input_bfd, srel & 0xffff, contents);
      break;

    case R_MSP430_16_BYTE:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;
      bfd_put_16 (input_bfd, srel & 0xffff, contents);
      break;

    case R_MSP430_16:
      contents += rel->r_offset;
      srel = (bfd_signed_vma) relocation;
      srel += rel->r_addend;

      if (srel & 1)
       return bfd_reloc_notsupported;

      bfd_put_16 (input_bfd, srel & 0xffff, contents);
      break;

    default:
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                contents, rel->r_offset,
                                relocation, rel->r_addend);
    }

  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void msp430_info_to_howto_rela ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent cache_ptr,
Elf_Internal_Rela dst 
) [static]

Definition at line 223 of file elf32-msp430.c.

{
  unsigned int r_type;

  r_type = ELF32_R_TYPE (dst->r_info);
  BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
  cache_ptr->howto = &elf_msp430_howto_table[r_type];
}

Variable Documentation

reloc_howto_type elf_msp430_howto_table[] [static]

Definition at line 32 of file elf32-msp430.c.

Initial value:
  {
    {BFD_RELOC_NONE,                 R_MSP430_NONE},
    {BFD_RELOC_32,                   R_MSP430_32},
    {BFD_RELOC_MSP430_10_PCREL,      R_MSP430_10_PCREL},
    {BFD_RELOC_16,                   R_MSP430_16_BYTE},
    {BFD_RELOC_MSP430_16_PCREL,      R_MSP430_16_PCREL},
    {BFD_RELOC_MSP430_16,            R_MSP430_16},
    {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE},
    {BFD_RELOC_MSP430_16_BYTE,       R_MSP430_16_BYTE},
    {BFD_RELOC_MSP430_2X_PCREL,      R_MSP430_2X_PCREL},
    {BFD_RELOC_MSP430_RL_PCREL,      R_MSP430_RL_PCREL}
  }

Definition at line 176 of file elf32-msp430.c.

struct rcodes_s rcode[] [static]