Back to index

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

Go to the source code of this file.

Classes

struct  misc
struct  ip2k_opcode

Defines

#define IS_PAGE_OPCODE(code)   ip2k_is_opcode (code, ip2k_page_opcode)
#define IS_JMP_OPCODE(code)   ip2k_is_opcode (code, ip2k_jmp_opcode)
#define IS_SNC_OPCODE(code)   ip2k_is_opcode (code, ip2k_snc_opcode)
#define IS_INC_1SP_OPCODE(code)   ip2k_is_opcode (code, ip2k_inc_1sp_opcode)
#define IS_ADD_2SP_W_OPCODE(code)   ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)
#define IS_ADD_W_WREG_OPCODE(code)   ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)
#define IS_ADD_PCL_W_OPCODE(code)   ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)
#define IS_SKIP_OPCODE(code)   ip2k_is_opcode (code, ip2k_skip_opcodes)
#define IP2K_HOWTO(t, rs, s, bs, pr, bp, name, sm, dm)
#define PAGENO(ABSADDR)   ((ABSADDR) & 0xFFFFC000)
#define BASEADDR(SEC)   ((SEC)->output_section->vma + (SEC)->output_offset)
#define UNDEFINED_SYMBOL   (~(bfd_vma)0)
#define STRDXOFF   0
#define TYPEOFF   4
#define OTHEROFF   5
#define DESCOFF   6
#define VALOFF   8
#define STABSIZE   12
#define TARGET_BIG_SYM   bfd_elf32_ip2k_vec
#define TARGET_BIG_NAME   "elf32-ip2k"
#define ELF_ARCH   bfd_arch_ip2k
#define ELF_MACHINE_CODE   EM_IP2K
#define ELF_MACHINE_ALT1   EM_IP2K_OLD
#define ELF_MAXPAGESIZE   1 /* No pages on the IP2K. */
#define elf_info_to_howto_rel   NULL
#define elf_info_to_howto   ip2k_info_to_howto_rela
#define elf_backend_can_gc_sections   1
#define elf_backend_rela_normal   1
#define elf_backend_relocate_section   ip2k_elf_relocate_section
#define elf_symbol_leading_char   '_'
#define bfd_elf32_bfd_reloc_type_lookup   ip2k_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup   ip2k_reloc_name_lookup
#define bfd_elf32_bfd_relax_section   ip2k_elf_relax_section

Functions

static reloc_howto_type * ip2k_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * ip2k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void ip2k_get_mem (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *addr, int length, bfd_byte *ptr)
static bfd_boolean ip2k_is_opcode (bfd_byte *code, const struct ip2k_opcode *opcodes)
static bfd_vma symbol_value (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, Elf_Internal_Sym *isymbuf, Elf_Internal_Rela *irel)
static int ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, bfd_vma addr, bfd_byte *contents)
static int ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, bfd_vma addr, bfd_byte *contents)
static bfd_vma ip2k_nominal_page_bits (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, bfd_vma addr, bfd_byte *contents)
static bfd_boolean ip2k_test_page_insn (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, Elf_Internal_Rela *irel, struct misc *misc)
static void adjust_all_relocations (bfd *abfd, asection *sec, bfd_vma addr, bfd_vma endaddr, int count, int noadj)
static bfd_boolean ip2k_elf_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
static bfd_boolean ip2k_delete_page_insn (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, Elf_Internal_Rela *irel, bfd_boolean *again, struct misc *misc)
static bfd_boolean ip2k_relax_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, Elf_Internal_Rela *irel, bfd_boolean *again, struct misc *misc)
static bfd_boolean ip2k_relax_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, Elf_Internal_Rela *irel, bfd_boolean *again, struct misc *misc)
static bfd_boolean ip2k_elf_relax_section_page (bfd *abfd, asection *sec, bfd_boolean *again, struct misc *misc, unsigned long page_start, unsigned long page_end)
static bfd_boolean ip2k_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again)
static void ip2k_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst)
static bfd_reloc_status_type ip2k_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 ip2k_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)

Variables

static bfd_boolean ip2k_relaxed = FALSE
static struct ip2k_opcode []
static reloc_howto_type ip2k_elf_howto_table []

Class Documentation

struct misc

Definition at line 30 of file elf32-ip2k.c.

Collaboration diagram for misc:
Class Members
bfd_byte * contents
Elf_Internal_Rela * irelbase
Elf_Internal_Sym * isymbuf
Elf_Internal_Shdr * symtab_hdr
struct ip2k_opcode

Definition at line 38 of file elf32-ip2k.c.

Class Members
unsigned short mask
unsigned short opcode

Define Documentation

#define BASEADDR (   SEC)    ((SEC)->output_section->vma + (SEC)->output_offset)

Definition at line 268 of file elf32-ip2k.c.

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

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

Definition at line 1546 of file elf32-ip2k.c.

#define DESCOFF   6

Definition at line 563 of file elf32-ip2k.c.

#define ELF_ARCH   bfd_arch_ip2k

Definition at line 1533 of file elf32-ip2k.c.

Definition at line 1541 of file elf32-ip2k.c.

#define elf_backend_rela_normal   1

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

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

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

Definition at line 1538 of file elf32-ip2k.c.

Definition at line 1535 of file elf32-ip2k.c.

#define ELF_MACHINE_CODE   EM_IP2K

Definition at line 1534 of file elf32-ip2k.c.

#define ELF_MAXPAGESIZE   1 /* No pages on the IP2K. */

Definition at line 1536 of file elf32-ip2k.c.

#define elf_symbol_leading_char   '_'

Definition at line 1545 of file elf32-ip2k.c.

#define IP2K_HOWTO (   t,
  rs,
  s,
  bs,
  pr,
  bp,
  name,
  sm,
  dm 
)
Value:
HOWTO(t,                    /* type */ \
          rs,                   /* rightshift */ \
          s,                    /* size (0 = byte, 1 = short, 2 = long) */ \
          bs,                   /* bitsize */ \
          pr,                   /* pc_relative */ \
          bp,                   /* bitpos */ \
          complain_overflow_dont,/* complain_on_overflow */ \
          bfd_elf_generic_reloc,/* special_function */ \
          name,                 /* name */ \
          FALSE,                /* partial_inplace */ \
          sm,                   /* src_mask */ \
          dm,                   /* dst_mask */ \
          pr)                   /* pcrel_offset */
#define IS_ADD_2SP_W_OPCODE (   code)    ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)

Definition at line 88 of file elf32-ip2k.c.

#define IS_ADD_PCL_W_OPCODE (   code)    ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)

Definition at line 107 of file elf32-ip2k.c.

#define IS_ADD_W_WREG_OPCODE (   code)    ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)

Definition at line 98 of file elf32-ip2k.c.

#define IS_INC_1SP_OPCODE (   code)    ip2k_is_opcode (code, ip2k_inc_1sp_opcode)

Definition at line 79 of file elf32-ip2k.c.

#define IS_JMP_OPCODE (   code)    ip2k_is_opcode (code, ip2k_jmp_opcode)

Definition at line 61 of file elf32-ip2k.c.

#define IS_PAGE_OPCODE (   code)    ip2k_is_opcode (code, ip2k_page_opcode)

Definition at line 52 of file elf32-ip2k.c.

#define IS_SKIP_OPCODE (   code)    ip2k_is_opcode (code, ip2k_skip_opcodes)

Definition at line 123 of file elf32-ip2k.c.

#define IS_SNC_OPCODE (   code)    ip2k_is_opcode (code, ip2k_snc_opcode)

Definition at line 70 of file elf32-ip2k.c.

#define OTHEROFF   5

Definition at line 562 of file elf32-ip2k.c.

#define PAGENO (   ABSADDR)    ((ABSADDR) & 0xFFFFC000)

Definition at line 267 of file elf32-ip2k.c.

#define STABSIZE   12

Definition at line 565 of file elf32-ip2k.c.

#define STRDXOFF   0

Definition at line 560 of file elf32-ip2k.c.

#define TARGET_BIG_NAME   "elf32-ip2k"

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

Definition at line 1530 of file elf32-ip2k.c.

#define TYPEOFF   4

Definition at line 561 of file elf32-ip2k.c.

#define UNDEFINED_SYMBOL   (~(bfd_vma)0)

Definition at line 270 of file elf32-ip2k.c.

#define VALOFF   8

Definition at line 564 of file elf32-ip2k.c.


Function Documentation

static void adjust_all_relocations ( bfd abfd,
asection sec,
bfd_vma  addr,
bfd_vma  endaddr,
int  count,
int  noadj 
) [static]

Definition at line 570 of file elf32-ip2k.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Sym *isymbuf, *isym, *isymend;
  unsigned int shndx;
  bfd_byte *contents;
  Elf_Internal_Rela *irel, *irelend, *irelbase;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **end_hashes;
  unsigned int symcount;
  asection *stab;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;

  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);

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

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

  for (irel = irelbase; irel < irelend; irel++)
    {
      if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
        {
          /* Get the value of the symbol referred to by the reloc.  */
          if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
            {
              asection *sym_sec;

              /* A local symbol.  */
             isym = isymbuf + ELF32_R_SYM (irel->r_info);
              sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);

              if (isym->st_shndx == shndx)
                {
                  bfd_vma baseaddr = BASEADDR (sec);
                  bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
                                   + irel->r_addend;

                  if ((baseaddr + addr + noadj) <= symval
                      && symval < (baseaddr + endaddr))
                    irel->r_addend += count;
                }
            }
        }

      /* Do this only for PC space relocations.  */
      if (addr <= irel->r_offset && irel->r_offset < endaddr)
        irel->r_offset += count;
    }

  /* Now fix the stab relocations.  */
  stab = bfd_get_section_by_name (abfd, ".stab");
  if (stab)
    {
      bfd_byte *stabcontents, *stabend, *stabp;
      bfd_size_type stab_size = stab->rawsize ? stab->rawsize : stab->size;

      irelbase = elf_section_data (stab)->relocs;
      irelend = irelbase + stab->reloc_count;

      /* Pull out the contents of the stab section.  */
      if (elf_section_data (stab)->this_hdr.contents != NULL)
       stabcontents = elf_section_data (stab)->this_hdr.contents;
      else
       {
         if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents))
           {
             if (stabcontents != NULL)
              free (stabcontents);
             return;
           }

         /* We need to remember this.  */
         elf_section_data (stab)->this_hdr.contents = stabcontents;
       }

      stabend = stabcontents + stab_size;

      for (irel = irelbase; irel < irelend; irel++)
       {
         if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
           {
             /* Get the value of the symbol referred to by the reloc.  */
             if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
              {
                asection *sym_sec;
                
                /* A local symbol.  */
                isym = isymbuf + ELF32_R_SYM (irel->r_info);
                sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
                
                if (sym_sec == sec)
                  {
                    const char *name;
                    unsigned long strx;
                    unsigned char type, other;
                    unsigned short desc;
                    bfd_vma value;
                    bfd_vma baseaddr = BASEADDR (sec);
                    bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
                     + irel->r_addend;
                    
                    if ((baseaddr + addr) <= symval
                       && symval <= (baseaddr + endaddr))
                     irel->r_addend += count;

                    /* Go hunt up a function and fix its line info if needed.  */
                    stabp = stabcontents + irel->r_offset - 8; 

                    /* Go pullout the stab entry.  */
                    strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
                    type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
                    other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
                    desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
                    value = bfd_h_get_32 (abfd, stabp + VALOFF);
                    
                    name = bfd_get_stab_name (type);
                    
                    if (strcmp (name, "FUN") == 0)
                     {
                       int function_adjusted = 0;

                       if (symval > (baseaddr + addr))
                         /* Not in this function.  */
                         continue;

                       /* Hey we got a function hit.  */
                       stabp += STABSIZE;
                       for (;stabp < stabend; stabp += STABSIZE)
                         {
                           /* Go pullout the stab entry.  */
                           strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
                           type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
                           other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
                           desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
                           value = bfd_h_get_32 (abfd, stabp + VALOFF);

                           name = bfd_get_stab_name (type);

                           if (strcmp (name, "FUN") == 0)
                            {
                              /* Hit another function entry.  */
                              if (function_adjusted)
                                {
                                  /* Adjust the value.  */
                                  value += count;
                              
                                  /* We need to put it back.  */
                                  bfd_h_put_32 (abfd, value,stabp + VALOFF);
                                }

                              /* And then bale out.  */
                              break;
                            }

                           if (strcmp (name, "SLINE") == 0)
                            {
                              /* Got a line entry.  */
                              if ((baseaddr + addr) <= (symval + value))
                                {
                                  /* Adjust the line entry.  */
                                  value += count;

                                  /* We need to put it back.  */
                                  bfd_h_put_32 (abfd, value,stabp + VALOFF);
                                  function_adjusted = 1;
                                }
                            }
                         }
                     }
                  }
              }
           }
       }
    }

  /* When adding an instruction back it is sometimes necessary to move any
     global or local symbol that was referencing the first instruction of
     the moved block to refer to the first instruction of the inserted block.

     For example adding a PAGE instruction before a CALL or JMP requires
     that any label on the CALL or JMP is moved to the PAGE insn.  */
  addr += noadj;

  /* Adjust the local symbols defined in this section.  */
  isymend = isymbuf + symtab_hdr->sh_info;
  for (isym = isymbuf; isym < isymend; isym++)
    {
      if (isym->st_shndx == shndx
         && addr <= isym->st_value
         && isym->st_value < endaddr)
       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)
       {
          if (addr <= sym_hash->root.u.def.value
              && sym_hash->root.u.def.value < endaddr)
           sym_hash->root.u.def.value += count;
       }
    }

  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean ip2k_delete_page_insn ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
Elf_Internal_Rela irel,
bfd_boolean again,
struct misc misc 
) [static]

Definition at line 816 of file elf32-ip2k.c.

{
  /* Note that we've changed the relocs, section contents, etc.  */
  elf_section_data (sec)->relocs = misc->irelbase;
  elf_section_data (sec)->this_hdr.contents = misc->contents;
  misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;

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

  /* Delete the PAGE insn.  */
  if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
    return FALSE;
       
  /* Modified => will need to iterate relaxation again.  */
  *again = TRUE;
  
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 797 of file elf32-ip2k.c.

{
  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
  bfd_vma endaddr = sec->size;

  /* Actually delete the bytes.  */
  memmove (contents + addr, contents + addr + count,
          endaddr - addr - count);

  sec->size -= count;

  adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1075 of file elf32-ip2k.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Rela *internal_relocs;
  bfd_byte *contents = NULL;
  Elf_Internal_Sym *isymbuf = NULL;
  static asection * first_section = NULL;
  static unsigned long search_addr;
  static unsigned long page_start = 0;
  static unsigned long page_end = 0;
  static unsigned int pass = 0;
  static bfd_boolean new_pass = FALSE;
  static bfd_boolean changed = FALSE;
  struct misc misc;
  asection *stab;

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

  if (first_section == NULL)
    {
      ip2k_relaxed = TRUE;
      first_section = sec;
    }

  if (first_section == sec)
    {
      pass++;
      new_pass = TRUE;
    }

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

  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                          link_info->keep_memory);
  if (internal_relocs == NULL)
    goto error_return;

  /* Make sure the stac.rela stuff gets read in.  */
  stab = bfd_get_section_by_name (abfd, ".stab");

  if (stab)
    {
      /* So stab does exits.  */
      Elf_Internal_Rela * irelbase;

      irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
                                       link_info->keep_memory);
    }

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

  /* Read this BFD's symbols cached copy if it exists.  */
  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;
    }

  misc.symtab_hdr = symtab_hdr;
  misc.isymbuf = isymbuf;
  misc.irelbase = internal_relocs;
  misc.contents = contents;

  /* This is where all the relaxation actually get done.  */
  if ((pass == 1) || (new_pass && !changed))
    {
      /* On the first pass we simply search for the lowest page that
         we havn't relaxed yet. Note that the pass count is reset
         each time a page is complete in order to move on to the next page.
         If we can't find any more pages then we are finished.  */
      if (new_pass)
       {
         pass = 1;
         new_pass = FALSE;
         changed = TRUE; /* Pre-initialize to break out of pass 1.  */
         search_addr = 0xFFFFFFFF;
       }

      if ((BASEADDR (sec) + sec->size < search_addr)
         && (BASEADDR (sec) + sec->size > page_end))
       {
         if (BASEADDR (sec) <= page_end)
           search_addr = page_end + 1;
         else
           search_addr = BASEADDR (sec);

         /* Found a page => more work to do.  */
         *again = TRUE;
       }
    }
  else
    {
      if (new_pass)
       {
         new_pass = FALSE;
         changed = FALSE;
         page_start = PAGENO (search_addr);
         page_end = page_start | 0x00003FFF;
       }

      /* Only process sections in range.  */
      if ((BASEADDR (sec) + sec->size >= page_start)
         && (BASEADDR (sec) <= page_end))
       {
          if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end))
           return FALSE;
       }
      *again = TRUE;
    }

  /* Perform some house keeping after relaxing the section.  */

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

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

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

  return TRUE;

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

Here is the call graph for this function:

static bfd_boolean ip2k_elf_relax_section_page ( bfd abfd,
asection sec,
bfd_boolean again,
struct misc misc,
unsigned long  page_start,
unsigned long  page_end 
) [static]

Definition at line 998 of file elf32-ip2k.c.

{
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
  Elf_Internal_Rela *irel;
  int switch_table_128;
  int switch_table_256;
  
  /* Walk thru the section looking for relaxation opportunities.  */
  for (irel = misc->irelbase; irel < irelend; irel++)
    {
      if (ELF32_R_TYPE (irel->r_info) != (int) R_IP2K_PAGE3)
       /* Ignore non page instructions.  */
       continue;

      if (BASEADDR (sec) + irel->r_offset < page_start)
       /* Ignore page instructions on earlier page - they have
          already been processed. Remember that there is code flow
          that crosses a page boundary.  */
       continue;

      if (BASEADDR (sec) + irel->r_offset > page_end)
       /* Flow beyond end of page => nothing more to do for this page.  */
       return TRUE;

      /* Detect switch tables.  */
      switch_table_128 = ip2k_is_switch_table_128 (abfd, sec, irel->r_offset, misc->contents);
      switch_table_256 = ip2k_is_switch_table_256 (abfd, sec, irel->r_offset, misc->contents);

      if ((switch_table_128 > 0) || (switch_table_256 > 0))
       /* If the index is greater than 0 then it has already been processed.  */
       continue;

      if (switch_table_128 == 0)
       {
         if (!ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc))
           return FALSE;

         continue;
       }

      if (switch_table_256 == 0)
       {
         if (!ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc))
           return FALSE;

         continue;
       }

      /* Simple relax.  */
      if (ip2k_test_page_insn (abfd, sec, irel, misc))
       {
         if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
           return FALSE;

         continue;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean ip2k_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 1403 of file elf32-ip2k.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  = ip2k_elf_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 = BASEADDR (sec) + sym->st_value;

         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 warned;
         bfd_boolean unresolved_reloc;

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

         name = h->root.root.string;
       }

      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;

      /* Finally, the sole IP2K-specific part.  */
      r = ip2k_final_link_relocate (howto, input_bfd, input_section,
                                 contents, rel, relocation);

      if (r != bfd_reloc_ok)
       {
         const char * msg = 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;

             /* This is how ip2k_final_link_relocate tells us of a non-kosher
                 reference between insn & data address spaces.  */
           case bfd_reloc_notsupported:
              if (sym != NULL) /* Only if it's not an unresolved symbol.  */
                msg = _("unsupported relocation between data/insn address spaces");
             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_reloc_status_type ip2k_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 1274 of file elf32-ip2k.c.

{
  static bfd_vma page_addr = 0;

  bfd_reloc_status_type r = bfd_reloc_ok;
  switch (howto->type)
    {
      /* Handle data space relocations.  */
    case R_IP2K_FR9:
    case R_IP2K_BANK:
      if ((relocation & IP2K_DATA_MASK) == IP2K_DATA_VALUE)
       relocation &= ~IP2K_DATA_MASK;
      else
       r = bfd_reloc_notsupported;
      break;

    case R_IP2K_LO8DATA:
    case R_IP2K_HI8DATA:
    case R_IP2K_EX8DATA:
      break;

      /* Handle insn space relocations.  */
    case R_IP2K_PAGE3:
      page_addr = BASEADDR (input_section) + rel->r_offset;
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
       relocation &= ~IP2K_INSN_MASK;
      else
       r = bfd_reloc_notsupported;
      break;

    case R_IP2K_ADDR16CJP:
      if (BASEADDR (input_section) + rel->r_offset != page_addr + 2)
       {
         /* No preceding page instruction, verify that it isn't needed.  */
         if (PAGENO (relocation + rel->r_addend) !=
             ip2k_nominal_page_bits (input_bfd, input_section,
                                  rel->r_offset, contents))
           _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."),
                            BASEADDR (input_section) + rel->r_offset,
                            relocation + rel->r_addend);
        }
      else if (ip2k_relaxed)
        {
          /* Preceding page instruction. Verify that the page instruction is
             really needed. One reason for the relaxation to miss a page is if
             the section is not marked as executable.  */
         if (!ip2k_is_switch_table_128 (input_bfd, input_section,
                                    rel->r_offset - 2, contents)
             && !ip2k_is_switch_table_256 (input_bfd, input_section,
                                       rel->r_offset - 2, contents)
             && (PAGENO (relocation + rel->r_addend) ==
                ip2k_nominal_page_bits (input_bfd, input_section,
                                     rel->r_offset - 2, contents)))
           _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."),
                            page_addr,
                            relocation + rel->r_addend);
        }
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
       relocation &= ~IP2K_INSN_MASK;
      else
       r = bfd_reloc_notsupported;
      break;

    case R_IP2K_LO8INSN:
    case R_IP2K_HI8INSN:
    case R_IP2K_PC_SKIP:
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
       relocation &= ~IP2K_INSN_MASK;
      else
       r = bfd_reloc_notsupported;
      break;

    case R_IP2K_16:
      /* If this is a relocation involving a TEXT
        symbol, reduce it to a word address.  */
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
       howto = &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
      break;

      /* Pass others through.  */
    default:
      break;
    }

  /* Only install relocation if above tests did not disqualify it.  */
  if (r == bfd_reloc_ok)
    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 ip2k_get_mem ( bfd *abfd  ATTRIBUTE_UNUSED,
bfd_byte addr,
int  length,
bfd_byte ptr 
) [static]

Definition at line 242 of file elf32-ip2k.c.

{
  while (length --)
    * ptr ++ = bfd_get_8 (abfd, addr ++);
}

Here is the caller graph for this function:

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

Definition at line 1260 of file elf32-ip2k.c.

{
  unsigned int r_type;

  r_type = ELF32_R_TYPE (dst->r_info);
  cache_ptr->howto = & ip2k_elf_howto_table [r_type];
}
static bfd_boolean ip2k_is_opcode ( bfd_byte code,
const struct ip2k_opcode opcodes 
) [static]

Definition at line 252 of file elf32-ip2k.c.

{
  unsigned short insn = (code[0] << 8) | code[1];

  while (opcodes->mask != 0)
    {
      if ((insn & opcodes->mask) == opcodes->opcode)
       return TRUE;

      opcodes ++;
    }

  return FALSE;
}
static int ip2k_is_switch_table_128 ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
bfd_vma  addr,
bfd_byte contents 
) [static]

Definition at line 344 of file elf32-ip2k.c.

{
  bfd_byte code[4];
  int index = 0;
  
  /* Check current page-jmp.  */
  if (addr + 4 > sec->size)
    return -1;

  ip2k_get_mem (abfd, contents + addr, 4, code);

  if ((! IS_PAGE_OPCODE (code + 0))
      || (! IS_JMP_OPCODE (code + 2)))
    return -1;
  
  /* Search back.  */
  while (1)
    {
      if (addr < 4)
       return -1;

      /* Check previous 2 instructions.  */
      ip2k_get_mem (abfd, contents + addr - 4, 4, code);
      if ((IS_ADD_W_WREG_OPCODE (code + 0))
         && (IS_ADD_PCL_W_OPCODE (code + 2)))
       return index;

      if ((! IS_PAGE_OPCODE (code + 0))
         || (! IS_JMP_OPCODE (code + 2)))
       return -1;

      index++;
      addr -= 4;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ip2k_is_switch_table_256 ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
bfd_vma  addr,
bfd_byte contents 
) [static]

Definition at line 424 of file elf32-ip2k.c.

{
  bfd_byte code[16];
  int index = 0;
  
  /* Check current page-jmp.  */
  if (addr + 4 > sec->size)
    return -1;

  ip2k_get_mem (abfd, contents + addr, 4, code);
  if ((! IS_PAGE_OPCODE (code + 0))
      || (! IS_JMP_OPCODE (code + 2)))
    return -1;
  
  /* Search back.  */
  while (1)
    {
      if (addr < 16)
       return -1;

      /* Check previous 8 instructions.  */
      ip2k_get_mem (abfd, contents + addr - 16, 16, code);
      if ((IS_ADD_W_WREG_OPCODE (code + 0))
         && (IS_SNC_OPCODE (code + 2))
         && (IS_INC_1SP_OPCODE (code + 4))
         && (IS_ADD_2SP_W_OPCODE (code + 6))
         && (IS_SNC_OPCODE (code + 8))
         && (IS_INC_1SP_OPCODE (code + 10))
         && (IS_PAGE_OPCODE (code + 12))
         && (IS_JMP_OPCODE (code + 14)))
       return index;

      if ((IS_ADD_W_WREG_OPCODE (code + 2))
         && (IS_SNC_OPCODE (code + 4))
         && (IS_INC_1SP_OPCODE (code + 6))
         && (IS_ADD_2SP_W_OPCODE (code + 8))
         && (IS_SNC_OPCODE (code + 10))
         && (IS_INC_1SP_OPCODE (code + 12))
         && (IS_JMP_OPCODE (code + 14)))
       return index;
      
      if ((! IS_PAGE_OPCODE (code + 0))
         || (! IS_JMP_OPCODE (code + 2)))
       return -1;

      index++;
      addr -= 4;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_vma ip2k_nominal_page_bits ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
bfd_vma  addr,
bfd_byte contents 
) [static]

Definition at line 481 of file elf32-ip2k.c.

{
  bfd_vma page = PAGENO (BASEADDR (sec) + addr);

  /* Check if section flows into this page. If not then the page
     bits are assumed to match the PC. This will be true unless
     the user has a page instruction without a call/jump, in which
     case they are on their own.  */
  if (PAGENO (BASEADDR (sec)) == page)
    return page;

  /* Section flows across page boundary. The page bits should match
     the PC unless there is a possible flow from the previous page,
     in which case it is not possible to determine the value of the
     page bits.  */
  while (PAGENO (BASEADDR (sec) + addr - 2) == page)
    {
      bfd_byte code[2];

      addr -= 2;
      ip2k_get_mem (abfd, contents + addr, 2, code);
      if (!IS_PAGE_OPCODE (code))
       continue;

      /* Found a page instruction, check if jump table.  */
      if (ip2k_is_switch_table_128 (abfd, sec, addr, contents) != -1)
       /* Jump table => page is conditional.  */
       continue;

      if (ip2k_is_switch_table_256 (abfd, sec, addr, contents) != -1)
       /* Jump table => page is conditional.  */
       continue;

      /* Found a page instruction, check if conditional.  */
      if (addr >= 2)
        {
         ip2k_get_mem (abfd, contents + addr - 2, 2, code);
          if (IS_SKIP_OPCODE (code))
           /* Page is conditional.  */
           continue;
        }

      /* Unconditional page instruction => page bits should be correct.  */
      return page;
    }

  /* Flow from previous page => page bits are impossible to determine.  */
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean ip2k_relax_switch_table_128 ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
Elf_Internal_Rela irel,
bfd_boolean again,
struct misc misc 
) [static]

Definition at line 841 of file elf32-ip2k.c.

{
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
  Elf_Internal_Rela *ireltest = irel;
  bfd_byte code[4];
  bfd_vma addr;
  
  /* Test all page instructions.  */
  addr = irel->r_offset;
  while (1)
    {
      if (addr + 4 > sec->size)
       break;

      ip2k_get_mem (abfd, misc->contents + addr, 4, code);
      if ((! IS_PAGE_OPCODE (code + 0))
         || (! IS_JMP_OPCODE (code + 2)))
       break;

      /* Validate relocation entry (every entry should have a matching
          relocation entry).  */
      if (ireltest >= irelend)
        {
         _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
          return FALSE;
        }

      if (ireltest->r_offset != addr)
        {
         _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
          return FALSE;
        }

      if (! ip2k_test_page_insn (abfd, sec, ireltest, misc))
       /* Un-removable page insn => nothing can be done.  */
       return TRUE;

      addr += 4;
      ireltest += 2;
    }

  /* Relaxable. Adjust table header.  */
  ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 4, code);
  if ((! IS_ADD_W_WREG_OPCODE (code + 0))
      || (! IS_ADD_PCL_W_OPCODE (code + 2)))
    {
      _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
      return FALSE;
    }

  if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset - 4, 2))
    return FALSE;

  *again = TRUE;

  /* Delete all page instructions in table.  */
  while (irel < ireltest)
    {
      if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
       return FALSE;
      irel += 2;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean ip2k_relax_switch_table_256 ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
Elf_Internal_Rela irel,
bfd_boolean again,
struct misc misc 
) [static]

Definition at line 912 of file elf32-ip2k.c.

{
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
  Elf_Internal_Rela *ireltest = irel;
  bfd_byte code[12];
  bfd_vma addr;
  
  /* Test all page instructions.  */
  addr = irel->r_offset;

  while (1)
    {
      if (addr + 4 > sec->size)
       break;

      ip2k_get_mem (abfd, misc->contents + addr, 4, code);

      if ((! IS_PAGE_OPCODE (code + 0))
         || (! IS_JMP_OPCODE (code + 2)))
       break;

      /* Validate relocation entry (every entry should have a matching
          relocation entry).  */
      if (ireltest >= irelend)
        {
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
          return FALSE;
        }

      if (ireltest->r_offset != addr)
        {
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
          return FALSE;
        }

      if (!ip2k_test_page_insn (abfd, sec, ireltest, misc))
       /* Un-removable page insn => nothing can be done.  */
       return TRUE;

      addr += 4;
      ireltest += 2;
    }

  /* Relaxable. Adjust table header.  */
  ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 2, code);
  if (IS_PAGE_OPCODE (code))
    addr = irel->r_offset - 16;
  else
    addr = irel->r_offset - 14;

  ip2k_get_mem (abfd, misc->contents + addr, 12, code);
  if ((!IS_ADD_W_WREG_OPCODE (code + 0))
      || (!IS_SNC_OPCODE (code + 2))
      || (!IS_INC_1SP_OPCODE (code + 4))
      || (!IS_ADD_2SP_W_OPCODE (code + 6))
      || (!IS_SNC_OPCODE (code + 8))
      || (!IS_INC_1SP_OPCODE (code + 10)))
    {
      _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
      return FALSE;
    }

  /* Delete first 3 opcodes.  */
  if (!ip2k_elf_relax_delete_bytes (abfd, sec, addr + 0, 6))
    return FALSE;

  *again = TRUE;

  /* Delete all page instructions in table.  */
  while (irel < ireltest)
    {
      if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
       return FALSE;
      irel += 2;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 227 of file elf32-ip2k.c.

{
  unsigned int i;

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

  return NULL;
}

Here is the call graph for this function:

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

Definition at line 179 of file elf32-ip2k.c.

{
  /* Note that the ip2k_elf_howto_table is indxed by the R_
     constants.  Thus, the order that the howto records appear in the
     table *must* match the order of the relocation types defined in
     include/elf/ip2k.h.  */

  switch (code)
    {
    case BFD_RELOC_NONE:
      return &ip2k_elf_howto_table[ (int) R_IP2K_NONE];
    case BFD_RELOC_16:
      return &ip2k_elf_howto_table[ (int) R_IP2K_16];
    case BFD_RELOC_32:
      return &ip2k_elf_howto_table[ (int) R_IP2K_32];
    case BFD_RELOC_IP2K_FR9:
      return &ip2k_elf_howto_table[ (int) R_IP2K_FR9];
    case BFD_RELOC_IP2K_BANK:
      return &ip2k_elf_howto_table[ (int) R_IP2K_BANK];
    case BFD_RELOC_IP2K_ADDR16CJP:
      return &ip2k_elf_howto_table[ (int) R_IP2K_ADDR16CJP];
    case BFD_RELOC_IP2K_PAGE3:
      return &ip2k_elf_howto_table[ (int) R_IP2K_PAGE3];
    case BFD_RELOC_IP2K_LO8DATA:
      return &ip2k_elf_howto_table[ (int) R_IP2K_LO8DATA];
    case BFD_RELOC_IP2K_HI8DATA:
      return &ip2k_elf_howto_table[ (int) R_IP2K_HI8DATA];
    case BFD_RELOC_IP2K_LO8INSN:
      return &ip2k_elf_howto_table[ (int) R_IP2K_LO8INSN];
    case BFD_RELOC_IP2K_HI8INSN:
      return &ip2k_elf_howto_table[ (int) R_IP2K_HI8INSN];
    case BFD_RELOC_IP2K_PC_SKIP:
      return &ip2k_elf_howto_table[ (int) R_IP2K_PC_SKIP];
    case BFD_RELOC_IP2K_TEXT:
      return &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
    case BFD_RELOC_IP2K_FR_OFFSET:
      return &ip2k_elf_howto_table[ (int) R_IP2K_FR_OFFSET];
    case BFD_RELOC_IP2K_EX8DATA:
      return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];
    default:
      /* Pacify gcc -Wall.  */
      return NULL;
    }
  return NULL;
}
static bfd_boolean ip2k_test_page_insn ( bfd *abfd  ATTRIBUTE_UNUSED,
asection sec,
Elf_Internal_Rela irel,
struct misc misc 
) [static]

Definition at line 535 of file elf32-ip2k.c.

{
  bfd_vma symval;

  /* Get the value of the symbol referred to by the reloc.  */
  symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, irel);
  if (symval == UNDEFINED_SYMBOL)
    /* This appears to be a reference to an undefined
       symbol.  Just ignore it--it will be caught by the
       regular reloc processing.  */
    return FALSE;

  /* Test if we can delete this page instruction.  */
  if (PAGENO (symval + irel->r_addend) !=
      ip2k_nominal_page_bits (abfd, sec, irel->r_offset, misc->contents))
    return FALSE;

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_vma symbol_value ( bfd abfd,
Elf_Internal_Shdr symtab_hdr,
Elf_Internal_Sym *  isymbuf,
Elf_Internal_Rela irel 
) [static]

Definition at line 275 of file elf32-ip2k.c.

{
  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
    {
      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);

      return isym->st_value + BASEADDR (sym_sec);
    }
  else
    {
      unsigned long indx;
      struct elf_link_hash_entry *h;

      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)
       return UNDEFINED_SYMBOL;

      return (h->root.u.def.value + BASEADDR (h->root.u.def.section));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

reloc_howto_type ip2k_elf_howto_table[] [static]

Definition at line 127 of file elf32-ip2k.c.

static struct ip2k_opcode [static]
Initial value:
{
  {0x0010, 0xFFF8},  
  {0x0000, 0x0000},
}

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

Definition at line 44 of file elf32-ip2k.c.