Back to index

cell-binutils  2.17cvs20070401
Defines | Functions | Variables
coff-or32.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "coff/or32.h"
#include "coff/internal.h"
#include "libcoff.h"
#include "coffcode.h"

Go to the source code of this file.

Defines

#define OR32   1
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER   (2)
#define INSERT_HWORD(WORD, HWORD)   (((WORD) & 0xffff0000) | ((HWORD)& 0x0000ffff))
#define EXTRACT_HWORD(WORD)   ((WORD) & 0x0000ffff)
#define SIGN_EXTEND_HWORD(HWORD)   ((HWORD) & 0x8000 ? (HWORD)|(~0xffffL) : (HWORD))
#define INSERT_JUMPTARG(WORD, JT)   (((WORD) & 0xfc000000) | ((JT)& 0x03ffffff))
#define EXTRACT_JUMPTARG(WORD)   ((WORD) & 0x03ffffff)
#define SIGN_EXTEND_JUMPTARG(JT)   ((JT) & 0x04000000 ? (JT)|(~0x03ffffffL) : (JT))
#define BADMAG(x)   OR32BADMAG (x)
#define RELOC_PROCESSING(relent, reloc, symbols, abfd, section)   reloc_processing (relent, reloc, symbols, abfd, section)
#define coff_relocate_section   coff_or32_relocate_section
#define coff_adjust_symndx   coff_or32_adjust_symndx

Functions

static long get_symbol_value PARAMS ((asymbol *))
static bfd_reloc_status_type
or32_reloc 
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **))
static bfd_boolean
coff_or32_relocate_section 
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **))
static bfd_boolean
coff_or32_adjust_symndx 
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, struct internal_reloc *, bfd_boolean *))
static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *))
static long get_symbol_value (asymbol *symbol)
static bfd_reloc_status_type or32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in, PTR data, asection *input_section, bfd *output_bfd, char **error_message)
static void reloc_processing (arelent *relent, struct internal_reloc *reloc, asymbol **symbols, bfd *abfd, asection *section)
static bfd_boolean coff_or32_relocate_section (output_bfd, struct bfd_link_info *info, bfd *input_bfd, asection *input_section, bfd_byte *contents, struct internal_reloc *relocs, struct internal_syment *syms, asection **sections)
static bfd_boolean coff_or32_adjust_symndx (obfd, info, ibfd, sec, struct internal_reloc *irel, bfd_boolean *adjustedp)

Variables

static reloc_howto_type howto_table []
const bfd_target or32coff_big_vec

Define Documentation

#define BADMAG (   x)    OR32BADMAG (x)

Definition at line 284 of file coff-or32.c.

Definition at line 570 of file coff-or32.c.

Definition at line 43 of file coff-or32.c.

Definition at line 549 of file coff-or32.c.

#define EXTRACT_HWORD (   WORD)    ((WORD) & 0x0000ffff)

Definition at line 47 of file coff-or32.c.

#define EXTRACT_JUMPTARG (   WORD)    ((WORD) & 0x03ffffff)

Definition at line 54 of file coff-or32.c.

#define INSERT_HWORD (   WORD,
  HWORD 
)    (((WORD) & 0xffff0000) | ((HWORD)& 0x0000ffff))

Definition at line 45 of file coff-or32.c.

#define INSERT_JUMPTARG (   WORD,
  JT 
)    (((WORD) & 0xfc000000) | ((JT)& 0x03ffffff))

Definition at line 52 of file coff-or32.c.

#define OR32   1

Definition at line 21 of file coff-or32.c.

#define RELOC_PROCESSING (   relent,
  reloc,
  symbols,
  abfd,
  section 
)    reloc_processing (relent, reloc, symbols, abfd, section)

Definition at line 286 of file coff-or32.c.

#define SIGN_EXTEND_HWORD (   HWORD)    ((HWORD) & 0x8000 ? (HWORD)|(~0xffffL) : (HWORD))

Definition at line 49 of file coff-or32.c.

#define SIGN_EXTEND_JUMPTARG (   JT)    ((JT) & 0x04000000 ? (JT)|(~0x03ffffffL) : (JT))

Definition at line 56 of file coff-or32.c.


Function Documentation

static bfd_boolean coff_or32_adjust_symndx ( obfd  ,
info  ,
ibfd  ,
sec  ,
struct internal_reloc irel,
bfd_boolean adjustedp 
) [static]

Definition at line 555 of file coff-or32.c.

{
  if (irel->r_type == R_IHCONST)
    *adjustedp = TRUE;
  else
    *adjustedp = FALSE;
  return TRUE;
}
static bfd_boolean coff_or32_relocate_section ( output_bfd  ,
struct bfd_link_info info,
bfd input_bfd,
asection input_section,
bfd_byte contents,
struct internal_reloc relocs,
struct internal_syment syms,
asection **  sections 
) [static]

Definition at line 334 of file coff-or32.c.

{
  struct internal_reloc *rel;
  struct internal_reloc *relend;
  bfd_boolean hihalf;
  bfd_vma hihalf_val;

  /* If we are performing a relocatable link, we don't need to do a
     thing.  The caller will take care of adjusting the reloc
     addresses and symbol indices.  */
  if (info->relocatable)
    return TRUE;

  hihalf = FALSE;
  hihalf_val = 0;

  rel = relocs;
  relend = rel + input_section->reloc_count;

  for (; rel < relend; rel++)
    {
      long symndx;
      bfd_byte *loc;
      struct coff_link_hash_entry *h;
      struct internal_syment *sym;
      asection *sec;
      bfd_vma val;
      bfd_boolean overflow;
      unsigned long insn;
      long signed_value;
      unsigned long unsigned_value;
      bfd_reloc_status_type rstat;

      symndx = rel->r_symndx;
      loc = contents + rel->r_vaddr - input_section->vma;

      if (symndx == -1 || rel->r_type == R_IHCONST)
        h = NULL;
      else
        h = obj_coff_sym_hashes (input_bfd)[symndx];

      sym = NULL;
      sec = NULL;
      val = 0;

      /* An R_IHCONST reloc does not have a symbol.  Instead, the
         symbol index is an addend.  R_IHCONST is always used in
         conjunction with R_IHHALF.  */
      if (rel->r_type != R_IHCONST)
        {
          if (h == NULL)
            {
              if (symndx == -1)
                sec = bfd_abs_section_ptr;
              else
                {
                  sym = syms + symndx;
                  sec = sections[symndx];
                  val = (sec->output_section->vma
                         + sec->output_offset
                         + sym->n_value
                         - sec->vma);
                }
            }
          else
            {
              if (h->root.type == bfd_link_hash_defined
                  || h->root.type == bfd_link_hash_defweak)
                {
                  sec = h->root.u.def.section;
                  val = (h->root.u.def.value
                         + sec->output_section->vma
                         + sec->output_offset);
                }
              else
                {
                  if (! ((*info->callbacks->undefined_symbol)
                         (info, h->root.root.string, input_bfd, input_section,
                          rel->r_vaddr - input_section->vma, TRUE)))
                    return FALSE;
                }
            }

          if (hihalf)
            {
              if (! ((*info->callbacks->reloc_dangerous)
                     (info, "missing IHCONST reloc", input_bfd,
                      input_section, rel->r_vaddr - input_section->vma)))
                return FALSE;
              hihalf = FALSE;
            }
        }

      overflow = FALSE;

      switch (rel->r_type)
        {
        default:
          bfd_set_error (bfd_error_bad_value);
          return FALSE;

        case R_IREL:
          insn = bfd_get_32 (input_bfd, loc);

          /* Extract the addend.  */
          signed_value = EXTRACT_JUMPTARG (insn);
          signed_value = SIGN_EXTEND_JUMPTARG (signed_value);
          signed_value <<= 2;

          /* Determine the destination of the jump.  */
          signed_value += val;

         /* Make the destination PC relative.  */
         signed_value -= (input_section->output_section->vma
                        + input_section->output_offset
                        + (rel->r_vaddr - input_section->vma));
         if (signed_value > 0x7ffffff || signed_value < - 0x8000000)
           {
             overflow = TRUE;
             signed_value = 0;
           }

          /* Put the adjusted value back into the instruction.  */
          signed_value >>= 2;
          insn = INSERT_JUMPTARG(insn, signed_value);

          bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
          break;

        case R_ILOHALF:
          insn = bfd_get_32 (input_bfd, loc);
          unsigned_value = EXTRACT_HWORD (insn);
          unsigned_value += val;
          insn = INSERT_HWORD (insn, unsigned_value);
          bfd_put_32 (input_bfd, insn, loc);
          break;

        case R_IHIHALF:
          /* Save the value for the R_IHCONST reloc.  */
          hihalf = TRUE;
          hihalf_val = val;
          break;

        case R_IHCONST:
          if (! hihalf)
            {
              if (! ((*info->callbacks->reloc_dangerous)
                     (info, "missing IHIHALF reloc", input_bfd,
                      input_section, rel->r_vaddr - input_section->vma)))
                return FALSE;
              hihalf_val = 0;
            }

          insn = bfd_get_32 (input_bfd, loc);
          unsigned_value = rel->r_symndx + hihalf_val;
          unsigned_value >>= 16;
          insn = INSERT_HWORD (insn, unsigned_value);
          bfd_put_32 (input_bfd, (bfd_vma) insn, loc);

          hihalf = FALSE;
          break;

        case R_BYTE:
        case R_HWORD:
        case R_WORD:
          rstat = _bfd_relocate_contents (howto_table + rel->r_type,
                                          input_bfd, val, loc);
          if (rstat == bfd_reloc_overflow)
            overflow = TRUE;
          else if (rstat != bfd_reloc_ok)
            abort ();
          break;
        }

      if (overflow)
        {
          const char *name;
          char buf[SYMNMLEN + 1];

          if (symndx == -1)
            name = "*ABS*";
          else if (h != NULL)
            name = NULL;
          else if (sym == NULL)
            name = "*unknown*";
          else if (sym->_n._n_n._n_zeroes == 0
                   && sym->_n._n_n._n_offset != 0)
            name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
          else
            {
              strncpy (buf, sym->_n._n_name, SYMNMLEN);
              buf[SYMNMLEN] = '\0';
              name = buf;
            }

          if (! ((*info->callbacks->reloc_overflow)
                 (info, (h ? &h->root : NULL), name,
                howto_table[rel->r_type].name, (bfd_vma) 0, input_bfd,
                input_section, rel->r_vaddr - input_section->vma)))
            return FALSE;
        }
    }

  return TRUE;
}

Here is the call graph for this function:

static long get_symbol_value ( asymbol symbol) [static]

Definition at line 62 of file coff-or32.c.

{
  long relocation = 0;

  if (bfd_is_com_section (symbol->section))
    relocation = 0;
  else
    relocation = symbol->value +
      symbol->section->output_section->vma +
      symbol->section->output_offset;

  return relocation;
}

Here is the caller graph for this function:

static bfd_reloc_status_type or32_reloc ( bfd abfd,
arelent reloc_entry,
asymbol symbol_in,
PTR  data,
asection input_section,
bfd output_bfd,
char **  error_message 
) [static]

Definition at line 80 of file coff-or32.c.

{
  /* The consth relocation comes in two parts, we have to remember
     the state between calls, in these variables.  */
  static bfd_boolean part1_consth_active = FALSE;
  static unsigned long part1_consth_value;

  unsigned long insn;
  unsigned long sym_value;
  unsigned long unsigned_value;
  unsigned short r_type;
  long signed_value;

  unsigned long addr = reloc_entry->address ;   /*+ input_section->vma*/
  bfd_byte *hit_data =addr + (bfd_byte *)(data);

  r_type = reloc_entry->howto->type;

  if (output_bfd)
    {
      /* Partial linking - do nothing.  */
      reloc_entry->address += input_section->output_offset;
      return bfd_reloc_ok;
    }

  if (symbol_in != NULL
      && bfd_is_und_section (symbol_in->section))
    {
      /* Keep the state machine happy in case we're called again.  */
      if (r_type == R_IHIHALF)
        {
          part1_consth_active = TRUE;
          part1_consth_value  = 0;
        }

      return bfd_reloc_undefined;
    }

  if ((part1_consth_active) && (r_type != R_IHCONST))
    {
      part1_consth_active = FALSE;
      *error_message = (char *) "Missing IHCONST";

      return bfd_reloc_dangerous;
    }

  sym_value = get_symbol_value (symbol_in);

  switch (r_type)
    {
    case R_IREL:
      insn = bfd_get_32(abfd, hit_data);

      /* Take the value in the field and sign extend it.  */
      signed_value = EXTRACT_JUMPTARG (insn);
      signed_value = SIGN_EXTEND_JUMPTARG (signed_value);
      signed_value <<= 2;

      /* See the note on the R_IREL reloc in coff_or32_relocate_section.  */
      if (signed_value == - (long) reloc_entry->address)
        signed_value = 0;

      signed_value += sym_value + reloc_entry->addend;
      /* Relative jmp/call, so subtract from the value the
        address of the place we're coming from.  */
      signed_value -= (reloc_entry->address
                     + input_section->output_section->vma
                     + input_section->output_offset);
      if (signed_value > 0x7ffffff || signed_value < -0x8000000)
       return bfd_reloc_overflow;

      signed_value >>= 2;
      insn = INSERT_JUMPTARG (insn, signed_value);
      bfd_put_32 (abfd, insn, hit_data);
      break;

    case R_ILOHALF:
      insn = bfd_get_32 (abfd, hit_data);
      unsigned_value = EXTRACT_HWORD (insn);
      unsigned_value +=  sym_value + reloc_entry->addend;
      insn = INSERT_HWORD (insn, unsigned_value);
      bfd_put_32 (abfd, insn, hit_data);
      break;

    case R_IHIHALF:
      insn = bfd_get_32 (abfd, hit_data);

      /* consth, part 1
         Just get the symbol value that is referenced.  */
      part1_consth_active = TRUE;
      part1_consth_value = sym_value + reloc_entry->addend;

      /* Don't modify insn until R_IHCONST.  */
      break;

    case R_IHCONST:
      insn = bfd_get_32 (abfd, hit_data);

      /* consth, part 2
         Now relocate the reference.  */
      if (! part1_consth_active)
        {
          *error_message = (char *) "Missing IHIHALF";
          return bfd_reloc_dangerous;
        }

      /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
      unsigned_value = 0;   /*EXTRACT_HWORD(insn) << 16;*/
      unsigned_value += reloc_entry->addend; /* r_symndx */
      unsigned_value += part1_consth_value;
      unsigned_value = unsigned_value >> 16;
      insn = INSERT_HWORD (insn, unsigned_value);
      part1_consth_active = FALSE;
      bfd_put_32 (abfd, insn, hit_data);
      break;

    case R_BYTE:
      insn = bfd_get_8 (abfd, hit_data);
      unsigned_value = insn + sym_value + reloc_entry->addend;
      if (unsigned_value & 0xffffff00)
        return bfd_reloc_overflow;
      bfd_put_8 (abfd, unsigned_value, hit_data);
      break;

    case R_HWORD:
      insn = bfd_get_16 (abfd, hit_data);
      unsigned_value = insn + sym_value + reloc_entry->addend;
      if (unsigned_value & 0xffff0000)
        return bfd_reloc_overflow;
      bfd_put_16 (abfd, insn, hit_data);
      break;

    case R_WORD:
      insn = bfd_get_32 (abfd, hit_data);
      insn += sym_value + reloc_entry->addend;
      bfd_put_32 (abfd, insn, hit_data);
      break;

    default:
      *error_message = _("Unrecognized reloc");
      return bfd_reloc_dangerous;
    }

  return bfd_reloc_ok;
}

Here is the call graph for this function:

static long get_symbol_value PARAMS ( (asymbol *)  ) [static]
static bfd_reloc_status_type or32_reloc PARAMS ( (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)  ) [static]
static void reloc_processing PARAMS ( (arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)  ) [static]
static void reloc_processing ( arelent relent,
struct internal_reloc reloc,
asymbol **  symbols,
bfd abfd,
asection section 
) [static]

Definition at line 290 of file coff-or32.c.

{
  static bfd_vma ihihalf_vaddr = (bfd_vma) -1;

  relent->address = reloc->r_vaddr;
  relent->howto = howto_table + reloc->r_type;

  if (reloc->r_type == R_IHCONST)
    {
      /* The address of an R_IHCONST should always be the address of
        the immediately preceding R_IHIHALF.  relocs generated by gas
        are correct, but relocs generated by High C are different (I
        can't figure out what the address means for High C).  We can
        handle both gas and High C by ignoring the address here, and
        simply reusing the address saved for R_IHIHALF.  */
      if (ihihalf_vaddr == (bfd_vma) -1)
       abort ();

      relent->address = ihihalf_vaddr;
      ihihalf_vaddr = (bfd_vma) -1;
      relent->addend = reloc->r_symndx;
      relent->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
    }
  else
    {
      relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
      relent->addend = 0;
      relent->address-= section->vma;

      if (reloc->r_type == R_IHIHALF)
       ihihalf_vaddr = relent->address;
      else if (ihihalf_vaddr != (bfd_vma) -1)
       abort ();
    }
}

Variable Documentation

reloc_howto_type howto_table[] [static]

Definition at line 248 of file coff-or32.c.

Definition at line 574 of file coff-or32.c.