Back to index

cell-binutils  2.17cvs20070401
Defines | Functions | Variables
nlm32-alpha.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "nlm/alpha-ext.h"
#include "libnlm.h"
#include "nlmswap.h"
#include "nlm-target.h"

Go to the source code of this file.

Defines

#define ARCH_SIZE   32
#define Nlm_External_Fixed_Header   Nlm32_alpha_External_Fixed_Header
#define ONES(n)   (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
#define TARGET_LITTLE_NAME   "nlm32-alpha"
#define TARGET_LITTLE_SYM   nlmNAME (alpha_vec)
#define TARGET_BACKEND_DATA   & nlm32_alpha_backend

Functions

static bfd_boolean nlm_alpha_backend_object_p (bfd *abfd)
static bfd_boolean nlm_alpha_write_prefix (bfd *abfd)
static bfd_boolean nlm_alpha_read_reloc (bfd *abfd, nlmNAME(symbol_type)*sym, asection **secp, arelent *rel)
static bfd_boolean nlm_alpha_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED, const void *data ATTRIBUTE_UNUSED, bfd_vma offset ATTRIBUTE_UNUSED, bfd_size_type count ATTRIBUTE_UNUSED)
static bfd_boolean nlm_alpha_read_import (bfd *abfd, nlmNAME(symbol_type)*sym)
static bfd_boolean nlm_alpha_write_import (bfd *abfd, asection *sec, arelent *rel)
static bfd_boolean nlm_alpha_set_public_section (bfd *abfd, nlmNAME(symbol_type)*sym)
static bfd_vma nlm_alpha_get_public_offset (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
static bfd_boolean nlm_alpha_write_external (bfd *abfd, bfd_size_type count, asymbol *sym, struct reloc_and_sec *relocs)

Variables

static reloc_howto_type nlm32_alpha_howto_table []
static reloc_howto_type nlm32_alpha_nw_howto
static struct nlm_backend_data

Define Documentation

#define ARCH_SIZE   32

Definition at line 30 of file nlm32-alpha.c.

Definition at line 33 of file nlm32-alpha.c.

#define ONES (   n)    (((bfd_vma) 1 << ((n) - 1) << 1) - 1)

Definition at line 79 of file nlm32-alpha.c.

#define TARGET_BACKEND_DATA   & nlm32_alpha_backend

Definition at line 856 of file nlm32-alpha.c.

#define TARGET_LITTLE_NAME   "nlm32-alpha"

Definition at line 854 of file nlm32-alpha.c.

#define TARGET_LITTLE_SYM   nlmNAME (alpha_vec)

Definition at line 855 of file nlm32-alpha.c.


Function Documentation

static bfd_boolean nlm_alpha_backend_object_p ( bfd abfd) [static]

Definition at line 42 of file nlm32-alpha.c.

{
  struct nlm32_alpha_external_prefix_header s;
  file_ptr size;

  if (bfd_bread (&s, (bfd_size_type) sizeof s, abfd) != sizeof s)
    return FALSE;

  if (H_GET_32 (abfd, s.magic) != NLM32_ALPHA_MAGIC)
    return FALSE;

  /* FIXME: Should we check the format number?  */

  /* Skip to the end of the header.  */
  size = H_GET_32 (abfd, s.size);
  if (bfd_seek (abfd, size, SEEK_SET) != 0)
    return FALSE;

  return TRUE;
}

Here is the call graph for this function:

static bfd_vma nlm_alpha_get_public_offset ( bfd *abfd  ATTRIBUTE_UNUSED,
asymbol sym 
) [static]

Definition at line 780 of file nlm32-alpha.c.

{
  return bfd_asymbol_value (sym);
}
static bfd_boolean nlm_alpha_mangle_relocs ( bfd *abfd  ATTRIBUTE_UNUSED,
asection *sec  ATTRIBUTE_UNUSED,
const void *data  ATTRIBUTE_UNUSED,
bfd_vma offset  ATTRIBUTE_UNUSED,
bfd_size_type count  ATTRIBUTE_UNUSED 
) [static]

Definition at line 586 of file nlm32-alpha.c.

{
  return TRUE;
}
static bfd_boolean nlm_alpha_read_import ( bfd abfd,
nlmNAME(symbol_type)*  sym 
) [static]

Definition at line 598 of file nlm32-alpha.c.

{
  struct nlm_relent *nlm_relocs;   /* Relocation records for symbol.  */
  bfd_size_type rcount;                   /* Number of relocs.  */
  bfd_byte temp[NLM_TARGET_LONG_SIZE];    /* Temporary 32-bit value.  */
  unsigned char symlength;         /* Length of symbol name.  */
  char *name;
  bfd_size_type amt;

  if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
      != sizeof (symlength))
    return FALSE;
  sym -> symbol.the_bfd = abfd;
  name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
  if (name == NULL)
    return FALSE;
  if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
    return FALSE;
  name[symlength] = '\0';
  sym -> symbol.name = name;
  sym -> symbol.flags = 0;
  sym -> symbol.value = 0;
  sym -> symbol.section = bfd_und_section_ptr;
  if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd)
      != sizeof (temp))
    return FALSE;
  rcount = H_GET_32 (abfd, temp);
  amt = rcount * sizeof (struct nlm_relent);
  nlm_relocs = bfd_alloc (abfd, amt);
  if (!nlm_relocs)
    return FALSE;
  sym -> relocs = nlm_relocs;
  sym -> rcnt = 0;
  while (sym -> rcnt < rcount)
    {
      asection *section;

      if (! nlm_alpha_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
       return FALSE;
      nlm_relocs -> section = section;
      nlm_relocs++;
      sym -> rcnt++;
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean nlm_alpha_read_reloc ( bfd abfd,
nlmNAME(symbol_type)*  sym,
asection **  secp,
arelent rel 
) [static]

Definition at line 391 of file nlm32-alpha.c.

{
  static bfd_vma gp_value;
  static bfd_vma lita_address;
  struct nlm32_alpha_external_reloc ext;
  bfd_vma r_vaddr;
  long r_symndx;
  int r_type, r_extern, r_offset, r_size;
  asection *code_sec, *data_sec;

  /* Read the reloc from the file.  */
  if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
    return FALSE;

  /* Swap in the reloc information.  */
  r_vaddr = H_GET_64 (abfd, ext.r_vaddr);
  r_symndx = H_GET_32 (abfd, ext.r_symndx);

  BFD_ASSERT (bfd_little_endian (abfd));

  r_type = ((ext.r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
           >> RELOC_BITS0_TYPE_SH_LITTLE);
  r_extern = (ext.r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
  r_offset = ((ext.r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
             >> RELOC_BITS1_OFFSET_SH_LITTLE);
  /* Ignore the reserved bits.  */
  r_size = ((ext.r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
           >> RELOC_BITS3_SIZE_SH_LITTLE);

  /* Fill in the BFD arelent structure.  */
  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  if (r_extern)
    {
      /* External relocations are only used for imports.  */
      BFD_ASSERT (sym != NULL);
      /* We don't need to set sym_ptr_ptr for this case.  It is set in
        nlm_canonicalize_reloc.  */
      rel->sym_ptr_ptr = NULL;
      rel->addend = 0;
    }
  else
    {
      /* Internal relocations are only used for local relocation
        fixups.  If they are not NW_RELOC or GPDISP or IGNORE, they
        must be against .text or .data.  */
      BFD_ASSERT (r_type == ALPHA_R_NW_RELOC || sym == NULL);
      if (r_type == ALPHA_R_NW_RELOC
         || r_type == ALPHA_R_GPDISP
         || r_type == ALPHA_R_IGNORE)
       {
         rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
         rel->addend = 0;
       }
      else if (r_symndx == ALPHA_RELOC_SECTION_TEXT)
       {
         rel->sym_ptr_ptr = code_sec->symbol_ptr_ptr;
         BFD_ASSERT (bfd_get_section_vma (abfd, code_sec) == 0);
         rel->addend = 0;
       }
      else if (r_symndx == ALPHA_RELOC_SECTION_DATA)
       {
         rel->sym_ptr_ptr = data_sec->symbol_ptr_ptr;
         rel->addend = - bfd_get_section_vma (abfd, data_sec);
       }
      else
       {
         BFD_ASSERT (0);
         rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
         rel->addend = 0;
       }
    }

  /* We use the address to determine whether the reloc is in the .text
     or .data section.  R_NW_RELOC relocs don't really have a section,
     so we put them in .text.  */
  if (r_type == ALPHA_R_NW_RELOC
      || r_vaddr < code_sec->size)
    {
      *secp = code_sec;
      rel->address = r_vaddr;
    }
  else
    {
      *secp = data_sec;
      rel->address = r_vaddr - code_sec->size;
    }

  /* We must adjust the addend based on the type.  */
  BFD_ASSERT ((r_type >= 0 && r_type <= ALPHA_R_GPVALUE)
             || r_type == ALPHA_R_NW_RELOC);

  switch (r_type)
    {
    case ALPHA_R_BRADDR:
    case ALPHA_R_SREL16:
    case ALPHA_R_SREL32:
    case ALPHA_R_SREL64:
      /* The PC relative relocs do not seem to use the section VMA as
        a negative addend.  */
      rel->addend = 0;
      break;

    case ALPHA_R_GPREL32:
      /* Copy the gp value for this object file into the addend, to
        ensure that we are not confused by the linker.  */
      if (! r_extern)
       rel->addend += gp_value;
      break;

    case ALPHA_R_LITERAL:
      BFD_ASSERT (! r_extern);
      rel->addend += lita_address;
      break;

    case ALPHA_R_LITUSE:
    case ALPHA_R_GPDISP:
      /* The LITUSE and GPDISP relocs do not use a symbol, or an
        addend, but they do use a special code.  Put this code in the
        addend field.  */
      rel->addend = r_symndx;
      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
      break;

    case ALPHA_R_OP_STORE:
      /* The STORE reloc needs the size and offset fields.  We store
        them in the addend.  */
      BFD_ASSERT (r_offset < 256 && r_size < 256);
      rel->addend = (r_offset << 8) + r_size;
      break;

    case ALPHA_R_OP_PUSH:
    case ALPHA_R_OP_PSUB:
    case ALPHA_R_OP_PRSHIFT:
      /* The PUSH, PSUB and PRSHIFT relocs do not actually use an
        address.  I believe that the address supplied is really an
        addend.  */
      rel->addend = r_vaddr;
      break;

    case ALPHA_R_GPVALUE:
      /* Record the new gp value.  */
      gp_value += r_symndx;
      rel->addend = gp_value;
      break;

    case ALPHA_R_IGNORE:
      /* If the type is ALPHA_R_IGNORE, make sure this is a reference
        to the absolute section so that the reloc is ignored.  For
        some reason the address of this reloc type is not adjusted by
        the section vma.  We record the gp value for this object file
        here, for convenience when doing the GPDISP relocation.  */
      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
      rel->address = r_vaddr;
      rel->addend = gp_value;
      break;

    case ALPHA_R_NW_RELOC:
      /* If this is SETGP, we set the addend to 0.  Otherwise we set
        the addend to the size of the .lita section (this is
        r_symndx) plus 1.  We have already set the address of the
        reloc to r_vaddr.  */
      if (r_size == ALPHA_R_NW_RELOC_SETGP)
       {
         gp_value = r_vaddr;
         rel->addend = 0;
       }
      else if (r_size == ALPHA_R_NW_RELOC_LITA)
       {
         lita_address = r_vaddr;
         rel->addend = r_symndx + 1;
       }
      else
       BFD_ASSERT (0);
      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
      break;

    default:
      break;
    }

  if (r_type == ALPHA_R_NW_RELOC)
    rel->howto = &nlm32_alpha_nw_howto;
  else
    rel->howto = &nlm32_alpha_howto_table[r_type];

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean nlm_alpha_set_public_section ( bfd abfd,
nlmNAME(symbol_type)*  sym 
) [static]

Definition at line 756 of file nlm32-alpha.c.

{
  asection *code_sec, *data_sec;

  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  if (sym->symbol.value < code_sec->size)
    {
      sym->symbol.section = code_sec;
      sym->symbol.flags |= BSF_FUNCTION;
    }
  else
    {
      sym->symbol.section = data_sec;
      sym->symbol.value -= code_sec->size;
      /* The data segment had better be aligned.  */
      BFD_ASSERT ((code_sec->size & 0xf) == 0);
    }
  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean nlm_alpha_write_external ( bfd abfd,
bfd_size_type  count,
asymbol sym,
struct reloc_and_sec relocs 
) [static]

Definition at line 788 of file nlm32-alpha.c.

{
  bfd_size_type i;
  bfd_byte len;
  unsigned char temp[NLM_TARGET_LONG_SIZE];
  arelent r;

  len = strlen (sym->name);
  if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
       != sizeof (bfd_byte))
      || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
    return FALSE;

  bfd_put_32 (abfd, count + 2, temp);
  if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
    return FALSE;

  /* The first two relocs for each external symbol are the .lita
     address and the GP value.  */
  r.sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  r.howto = &nlm32_alpha_nw_howto;

  r.address = nlm_alpha_backend_data (abfd)->lita_address;
  r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1;
  if (! nlm_alpha_write_import (abfd, NULL, &r))
    return FALSE;

  r.address = nlm_alpha_backend_data (abfd)->gp;
  r.addend = 0;
  if (! nlm_alpha_write_import (abfd, NULL, &r))
    return FALSE;

  for (i = 0; i < count; i++)
    if (! nlm_alpha_write_import (abfd, relocs[i].sec, relocs[i].rel))
      return FALSE;

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean nlm_alpha_write_import ( bfd abfd,
asection sec,
arelent rel 
) [static]

Definition at line 648 of file nlm32-alpha.c.

{
  asymbol *sym;
  bfd_vma r_vaddr;
  long r_symndx;
  int r_type, r_extern, r_offset, r_size;
  struct nlm32_alpha_external_reloc ext;

  sym = *rel->sym_ptr_ptr;

  /* Get values for the relocation fields.  */
  r_type = rel->howto->type;
  if (r_type != ALPHA_R_NW_RELOC)
    {
      r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address;
      if ((sec->flags & SEC_CODE) == 0)
       r_vaddr += bfd_get_section_by_name (abfd, NLM_CODE_NAME) -> size;
      if (bfd_is_und_section (bfd_get_section (sym)))
       {
         r_extern = 1;
         r_symndx = 0;
       }
      else
       {
         r_extern = 0;
         if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
           r_symndx = ALPHA_RELOC_SECTION_TEXT;
         else
           r_symndx = ALPHA_RELOC_SECTION_DATA;
       }
      r_offset = 0;
      r_size = 0;

      switch (r_type)
       {
       case ALPHA_R_LITUSE:
       case ALPHA_R_GPDISP:
         r_symndx = rel->addend;
         break;

       case ALPHA_R_OP_STORE:
         r_size = rel->addend & 0xff;
         r_offset = (rel->addend >> 8) & 0xff;
         break;

       case ALPHA_R_OP_PUSH:
       case ALPHA_R_OP_PSUB:
       case ALPHA_R_OP_PRSHIFT:
         r_vaddr = rel->addend;
         break;

       case ALPHA_R_IGNORE:
         r_vaddr = rel->address;
         break;

       default:
         break;
       }
    }
  else
    {
      /* r_type == ALPHA_R_NW_RELOC.  */
      r_vaddr = rel->address;
      if (rel->addend == 0)
       {
         r_symndx = 0;
         r_size = ALPHA_R_NW_RELOC_SETGP;
       }
      else
       {
         r_symndx = rel->addend - 1;
         r_size = ALPHA_R_NW_RELOC_LITA;
       }
      r_extern = 0;
      r_offset = 0;
    }

  /* Swap out the relocation fields.  */
  H_PUT_64 (abfd, r_vaddr, ext.r_vaddr);
  H_PUT_32 (abfd, r_symndx, ext.r_symndx);

  BFD_ASSERT (bfd_little_endian (abfd));

  ext.r_bits[0] = ((r_type << RELOC_BITS0_TYPE_SH_LITTLE)
                 & RELOC_BITS0_TYPE_LITTLE);
  ext.r_bits[1] = ((r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)
                 | ((r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)
                    & RELOC_BITS1_OFFSET_LITTLE));
  ext.r_bits[2] = 0;
  ext.r_bits[3] = ((r_size << RELOC_BITS3_SIZE_SH_LITTLE)
                 & RELOC_BITS3_SIZE_LITTLE);

  /* Write out the relocation.  */
  if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
    return FALSE;

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean nlm_alpha_write_prefix ( bfd abfd) [static]

Definition at line 66 of file nlm32-alpha.c.

{
  struct nlm32_alpha_external_prefix_header s;

  memset (&s, 0, sizeof s);
  H_PUT_32 (abfd, NLM32_ALPHA_MAGIC, s.magic);
  H_PUT_32 (abfd, 2, s.format);
  H_PUT_32 (abfd, sizeof s, s.size);
  if (bfd_bwrite (&s, (bfd_size_type) sizeof s, abfd) != sizeof s)
    return FALSE;
  return TRUE;
}

Here is the call graph for this function:


Variable Documentation

reloc_howto_type nlm32_alpha_howto_table[] [static]

Definition at line 83 of file nlm32-alpha.c.

reloc_howto_type nlm32_alpha_nw_howto [static]
Initial value:
  HOWTO (ALPHA_R_NW_RELOC,  
        0,                  
        0,                  
        0,                  
        FALSE,                     
        0,                  
        complain_overflow_dont, 
        0,                  
        "NW_RELOC",         
        FALSE,                     
        0,                  
        0,                  
        FALSE)

Definition at line 371 of file nlm32-alpha.c.