Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Enumerations | Functions | Variables
coff-ppc.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "coff/powerpc.h"
#include "coff/internal.h"
#include "coff/pe.h"
#include "libcoff.h"
#include "coffcode.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  ppc_coff_link_hash_entry
struct  list_ele

Defines

#define BADMAG(x)   PPCBADMAG(x)
#define SET_UNALLOCATED(x)   ((x) = 1)
#define IS_UNALLOCATED(x)   ((x) == 1)
#define IS_WRITTEN(x)   ((x) & 1)
#define MARK_AS_WRITTEN(x)   ((x) |= 1)
#define MAKE_ADDR_AGAIN(x)   ((x) &= ~1)
#define HASH_CHECK_DCL
#define HASH_CHECK_INIT(ret)
#define HASH_CHECK(addr)
#define coff_bfd_link_hash_table_create   ppc_coff_link_hash_table_create
#define TOC_LOAD_ADJUSTMENT   (-32768)
#define TOC_SECTION_NAME   ".private.toc"
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER   (3)
#define MINUS_ONE   (((bfd_vma)0) - 1)
#define IMAGE_REL_PPC_ABSOLUTE   0x0000
#define IMAGE_REL_PPC_ADDR64   0x0001
#define IMAGE_REL_PPC_ADDR32   0x0002
#define IMAGE_REL_PPC_ADDR24   0x0003
#define IMAGE_REL_PPC_ADDR16   0x0004
#define IMAGE_REL_PPC_ADDR14   0x0005
#define IMAGE_REL_PPC_REL24   0x0006
#define IMAGE_REL_PPC_REL14   0x0007
#define IMAGE_REL_PPC_TOCREL16   0x0008
#define IMAGE_REL_PPC_TOCREL14   0x0009
#define IMAGE_REL_PPC_ADDR32NB   0x000A
#define IMAGE_REL_PPC_SECREL   0x000B
#define IMAGE_REL_PPC_SECTION   0x000C
#define IMAGE_REL_PPC_IFGLUE   0x000D
#define IMAGE_REL_PPC_IMGLUE   0x000E
#define IMAGE_REL_PPC_SECREL16   0x000F
#define IMAGE_REL_PPC_REFHI   0x0010
#define IMAGE_REL_PPC_REFLO   0x0011
#define IMAGE_REL_PPC_PAIR   0x0012
#define IMAGE_REL_PPC_TOCREL16_DEFN   0x0013
#define IMAGE_REL_PPC_NEG   0x0100
#define IMAGE_REL_PPC_BRTAKEN   0x0200
#define IMAGE_REL_PPC_BRNTAKEN   0x0400
#define IMAGE_REL_PPC_TOCDEFN   0x0800
#define IMAGE_REL_PPC_TYPEMASK   0x00FF
#define IMAGE_REL_PPC_FLAGMASK   0x0F00
#define EXTRACT_TYPE(x)   ((x) & IMAGE_REL_PPC_TYPEMASK)
#define EXTRACT_FLAGS(x)   ((x) & IMAGE_REL_PPC_FLAGMASK)
#define EXTRACT_JUNK(x)   ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
#define UN_IMPL(x)
#define DUMP_RELOC(n, r)
#define DUMP_RELOC2(n, r)
#define MAX_RELOC_INDEX   (sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]) - 1)
#define HOW2MAP(bfd_rtype, ppc_rtype)   case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
#define RTYPE2HOWTO(cache_ptr, dst)   ppc_coff_rtype2howto (cache_ptr, dst)
#define coff_bfd_reloc_type_lookup   ppc_coff_reloc_type_lookup
#define coff_bfd_reloc_name_lookup   ppc_coff_reloc_name_lookup
#define coff_rtype_to_howto   coff_ppc_rtype_to_howto
#define coff_relocate_section   coff_ppc_relocate_section
#define coff_bfd_final_link   ppc_bfd_coff_final_link
#define SELECT_RELOC(internal, howto)   {internal.r_type=howto->type;}
#define COFF_PAGE_SIZE   0x1000
#define POWERPC_LE_PE
#define COFF_SECTION_ALIGNMENT_ENTRIES

Enumerations

enum  toc_type { default_toc, toc_32, toc_64 }
enum  ref_category { priv, pub, tocdata }

Functions

bfd_boolean ppc_bfd_coff_final_link PARAMS ((bfd *, struct bfd_link_info *))
void dump_toc PARAMS ((PTR))
static struct bfd_hash_entry
*ppc_coff_link_hash_newfunc 
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *))
static struct
bfd_link_hash_table
*ppc_coff_link_hash_table_create 
PARAMS ((bfd *))
static bfd_boolean
coff_ppc_relocate_section 
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **))
static reloc_howto_type
*coff_ppc_rtype_to_howto 
PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *))
static struct bfd_hash_entryppc_coff_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string)
static bfd_boolean ppc_coff_link_hash_table_init (struct ppc_coff_link_hash_table *table, bfd *abfd, struct bfd_hash_entry *(*newfunc)(struct bfd_hash_entry *, struct bfd_hash_table *, const char *), unsigned int entsize)
static struct bfd_link_hash_tableppc_coff_link_hash_table_create (bfd *abfd)
static bfd_reloc_status_type
ppc_refhi_reloc 
PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data, asection *section, bfd *output_bfd, char **error))
static bfd_boolean in_reloc_p PARAMS ((bfd *abfd, reloc_howto_type *howto))
static void record_toc PARAMS ((asection *, bfd_signed_vma, enum ref_category, const char *))
static void record_toc (asection *toc_section, bfd_signed_vma our_toc_offset, enum ref_category cat, const char *name)
static bfd_boolean in_reloc_p (abfd, reloc_howto_type *howto)
static bfd_boolean coff_ppc_relocate_section (bfd *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_reloc_status_type ppc_refhi_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static bfd_reloc_status_type ppc_pair_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static bfd_reloc_status_type ppc_toc16_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static bfd_reloc_status_type ppc_secrel_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static bfd_reloc_status_type ppc_section_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static bfd_reloc_status_type ppc_imglue_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd, error_message)
static void ppc_coff_rtype2howto PARAMS ((arelent *, struct internal_reloc *))
static void ppc_coff_rtype2howto (arelent *relent, struct internal_reloc *internal)
static reloc_howto_type * coff_ppc_rtype_to_howto (abfd, asection *sec, struct internal_reloc *rel, h, sym, bfd_vma *addendp)
static reloc_howto_type
*ppc_coff_reloc_type_lookup 
PARAMS ((bfd *, bfd_reloc_code_real_type))
static reloc_howto_type * ppc_coff_reloc_type_lookup (abfd, bfd_reloc_code_real_type code)
static reloc_howto_type * ppc_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static bfd *ppc_get_last PARAMS ((void))
static bfd_boolean ppc_do_last (bfd *abfd)
static bfdppc_get_last ()
bfd_boolean ppc_bfd_coff_final_link (bfd *abfd, struct bfd_link_info *info)

Variables

static reloc_howto_type ppc_coff_howto_table []
bfdbfd_of_toc_owner
long int global_toc_size
long int import_table_size
long int first_thunk_address
long int thunk_size
struct list_elehead
struct list_eletail

Class Documentation

struct ppc_coff_link_hash_entry

Definition at line 107 of file coff-ppc.c.

Class Members
unsigned long int glue_insn
int symbol_is_glue
bfd_vma toc_offset
struct ppc_coff_link_hash_table

Definition at line 122 of file coff-ppc.c.

struct list_ele

Definition at line 808 of file coff-ppc.c.

Collaboration diagram for list_ele:
Class Members
bfd_vma addr
struct list_ele * next

Define Documentation

#define BADMAG (   x)    PPCBADMAG(x)

Definition at line 50 of file coff-ppc.c.

Definition at line 1992 of file coff-ppc.c.

Definition at line 216 of file coff-ppc.c.

Definition at line 1989 of file coff-ppc.c.

Definition at line 1988 of file coff-ppc.c.

Definition at line 226 of file coff-ppc.c.

#define COFF_PAGE_SIZE   0x1000

Definition at line 1999 of file coff-ppc.c.

Definition at line 1991 of file coff-ppc.c.

Definition at line 1990 of file coff-ppc.c.

Value:
{ COFF_SECTION_NAME_EXACT_MATCH (".idata$2"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".idata$3"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".idata$4"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".idata$5"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".idata$6"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".reloc"), \
  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }

Definition at line 2006 of file coff-ppc.c.

#define DUMP_RELOC (   n,
  r 
)

Definition at line 779 of file coff-ppc.c.

#define DUMP_RELOC2 (   n,
  r 
)

Definition at line 780 of file coff-ppc.c.

#define EXTRACT_FLAGS (   x)    ((x) & IMAGE_REL_PPC_FLAGMASK)

Definition at line 311 of file coff-ppc.c.

Definition at line 312 of file coff-ppc.c.

#define EXTRACT_TYPE (   x)    ((x) & IMAGE_REL_PPC_TYPEMASK)

Definition at line 310 of file coff-ppc.c.

#define HASH_CHECK (   addr)

Definition at line 98 of file coff-ppc.c.

#define HASH_CHECK_DCL

Definition at line 96 of file coff-ppc.c.

#define HASH_CHECK_INIT (   ret)

Definition at line 97 of file coff-ppc.c.

#define HOW2MAP (   bfd_rtype,
  ppc_rtype 
)    case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]

Definition at line 1938 of file coff-ppc.c.

#define IMAGE_REL_PPC_ABSOLUTE   0x0000

Definition at line 235 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR14   0x0005

Definition at line 250 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR16   0x0004

Definition at line 247 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR24   0x0003

Definition at line 244 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR32   0x0002

Definition at line 241 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR32NB   0x000A

Definition at line 265 of file coff-ppc.c.

#define IMAGE_REL_PPC_ADDR64   0x0001

Definition at line 238 of file coff-ppc.c.

#define IMAGE_REL_PPC_BRNTAKEN   0x0400

Definition at line 301 of file coff-ppc.c.

#define IMAGE_REL_PPC_BRTAKEN   0x0200

Definition at line 298 of file coff-ppc.c.

#define IMAGE_REL_PPC_FLAGMASK   0x0F00

Definition at line 308 of file coff-ppc.c.

#define IMAGE_REL_PPC_IFGLUE   0x000D

Definition at line 274 of file coff-ppc.c.

#define IMAGE_REL_PPC_IMGLUE   0x000E

Definition at line 277 of file coff-ppc.c.

#define IMAGE_REL_PPC_NEG   0x0100

Definition at line 295 of file coff-ppc.c.

#define IMAGE_REL_PPC_PAIR   0x0012

Definition at line 287 of file coff-ppc.c.

#define IMAGE_REL_PPC_REFHI   0x0010

Definition at line 285 of file coff-ppc.c.

#define IMAGE_REL_PPC_REFLO   0x0011

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

#define IMAGE_REL_PPC_REL14   0x0007

Definition at line 256 of file coff-ppc.c.

#define IMAGE_REL_PPC_REL24   0x0006

Definition at line 253 of file coff-ppc.c.

#define IMAGE_REL_PPC_SECREL   0x000B

Definition at line 268 of file coff-ppc.c.

#define IMAGE_REL_PPC_SECREL16   0x000F

Definition at line 280 of file coff-ppc.c.

#define IMAGE_REL_PPC_SECTION   0x000C

Definition at line 271 of file coff-ppc.c.

#define IMAGE_REL_PPC_TOCDEFN   0x0800

Definition at line 304 of file coff-ppc.c.

#define IMAGE_REL_PPC_TOCREL14   0x0009

Definition at line 262 of file coff-ppc.c.

#define IMAGE_REL_PPC_TOCREL16   0x0008

Definition at line 259 of file coff-ppc.c.

#define IMAGE_REL_PPC_TOCREL16_DEFN   0x0013

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

#define IMAGE_REL_PPC_TYPEMASK   0x00FF

Definition at line 307 of file coff-ppc.c.

#define IS_UNALLOCATED (   x)    ((x) == 1)

Definition at line 71 of file coff-ppc.c.

#define IS_WRITTEN (   x)    ((x) & 1)

Definition at line 73 of file coff-ppc.c.

#define MAKE_ADDR_AGAIN (   x)    ((x) &= ~1)

Definition at line 75 of file coff-ppc.c.

#define MARK_AS_WRITTEN (   x)    ((x) |= 1)

Definition at line 74 of file coff-ppc.c.

#define MAX_RELOC_INDEX   (sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]) - 1)

Definition at line 1793 of file coff-ppc.c.

#define MINUS_ONE   (((bfd_vma)0) - 1)

Definition at line 230 of file coff-ppc.c.

#define POWERPC_LE_PE

Definition at line 2004 of file coff-ppc.c.

#define RTYPE2HOWTO (   cache_ptr,
  dst 
)    ppc_coff_rtype2howto (cache_ptr, dst)

Definition at line 1984 of file coff-ppc.c.

#define SELECT_RELOC (   internal,
  howto 
)    {internal.r_type=howto->type;}

Definition at line 1997 of file coff-ppc.c.

#define SET_UNALLOCATED (   x)    ((x) = 1)

Definition at line 70 of file coff-ppc.c.

#define TOC_LOAD_ADJUSTMENT   (-32768)

Definition at line 221 of file coff-ppc.c.

#define TOC_SECTION_NAME   ".private.toc"

Definition at line 222 of file coff-ppc.c.

#define UN_IMPL (   x)

Definition at line 778 of file coff-ppc.c.


Enumeration Type Documentation

Enumerator:
priv 
pub 
tocdata 

Definition at line 801 of file coff-ppc.c.

{
  priv,
  pub,
  tocdata
};
enum toc_type
Enumerator:
default_toc 
toc_32 
toc_64 

Definition at line 794 of file coff-ppc.c.


Function Documentation

static bfd_boolean coff_ppc_relocate_section ( bfd 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 989 of file coff-ppc.c.

{
  struct internal_reloc *rel;
  struct internal_reloc *relend;
  bfd_boolean hihalf;
  bfd_vma hihalf_val;
  asection *toc_section = 0;
  bfd_vma relocation;
  reloc_howto_type *howto = 0;

  /* 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;
      struct ppc_coff_link_hash_entry *h;
      struct internal_syment *sym;
      bfd_vma val;

      asection *sec;
      bfd_reloc_status_type rstat;
      bfd_byte *loc;

      unsigned short r_type  = EXTRACT_TYPE (rel->r_type);
      unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);

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

      /* FIXME: check bounds on r_type */
      howto = ppc_coff_howto_table + r_type;

      if (symndx == -1)
       {
         h = NULL;
         sym = NULL;
       }
      else
       {
         h = (struct ppc_coff_link_hash_entry *)
           (obj_coff_sym_hashes (input_bfd)[symndx]);
         if (h != 0)
           {
             HASH_CHECK(h);
           }

         sym = syms + symndx;
       }

      if (r_type == IMAGE_REL_PPC_IMGLUE && h == 0)
       {
         /* An IMGLUE reloc must have a name. Something is very wrong.  */
         abort ();
       }

      sec = NULL;
      val = 0;

      /* FIXME: PAIR unsupported in the following code.  */
      if (h == NULL)
       {
         if (symndx == -1)
           sec = bfd_abs_section_ptr;
         else
           {
             sec = sections[symndx];
             val = (sec->output_section->vma
                   + sec->output_offset
                   + sym->n_value);
             if (! obj_pe (output_bfd))
              val -= sec->vma;
           }
       }
      else
       {
         HASH_CHECK(h);

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

      rstat = bfd_reloc_ok;

      /* Each case must do its own relocation, setting rstat appropriately.  */
      switch (r_type)
       {
       default:
         (*_bfd_error_handler)
           (_("%B: unsupported relocation type 0x%02x"), input_bfd, r_type);
         bfd_set_error (bfd_error_bad_value);
         return FALSE;
       case IMAGE_REL_PPC_TOCREL16:
         {
           bfd_signed_vma our_toc_offset;
           int fixit;

           DUMP_RELOC2(howto->name, rel);

           if (toc_section == 0)
             {
              toc_section = bfd_get_section_by_name (bfd_of_toc_owner,
                                                 TOC_SECTION_NAME);

              if ( toc_section == NULL )
                {
                  /* There is no toc section. Something is very wrong.  */
                  abort ();
                }
             }

           /* Amazing bit tricks present. As we may have seen earlier, we
              use the 1 bit to tell us whether or not a toc offset has been
              allocated. Now that they've all been allocated, we will use
              the 1 bit to tell us if we've written this particular toc
              entry out.  */
           fixit = FALSE;
           if (h == 0)
             {
              /* It is a file local symbol.  */
              int *local_toc_table;
              const char *name;

              sym = syms + symndx;
              name = sym->_n._n_name;

              local_toc_table = obj_coff_local_toc_table(input_bfd);
              our_toc_offset = local_toc_table[symndx];

              if (IS_WRITTEN(our_toc_offset))
                {
                  /* If it has been written out, it is marked with the
                     1 bit. Fix up our offset, but do not write it out
                     again.  */
                  MAKE_ADDR_AGAIN(our_toc_offset);
                }
              else
                {
                  /* Write out the toc entry.  */
                  record_toc (toc_section, our_toc_offset, priv,
                            strdup (name));

                  bfd_put_32 (output_bfd, val,
                            toc_section->contents + our_toc_offset);

                  MARK_AS_WRITTEN(local_toc_table[symndx]);
                  fixit = TRUE;
                }
             }
           else
             {
              const char *name = h->root.root.root.string;
              our_toc_offset = h->toc_offset;

              if ((r_flags & IMAGE_REL_PPC_TOCDEFN)
                  == IMAGE_REL_PPC_TOCDEFN )
                {
                  /* This is unbelievable cheese. Some knowledgable asm
                     hacker has decided to use r2 as a base for loading
                     a value. He/She does this by setting the tocdefn bit,
                     and not supplying a toc definition. The behaviour is
                     then to use the difference between the value of the
                     symbol and the actual location of the toc as the toc
                     index.

                     In fact, what is usually happening is, because the
                     Import Address Table is mapped immediately following
                     the toc, some trippy library code trying for speed on
                     dll linkage, takes advantage of that and considers
                     the IAT to be part of the toc, thus saving a load.  */

                  our_toc_offset = val - (toc_section->output_section->vma
                                       + toc_section->output_offset);

                  /* The size must still fit in a 16-bit displacement.  */
                  if ((bfd_vma) our_toc_offset >= 65535)
                    {
                     (*_bfd_error_handler)
                       (_("%B: Relocation for %s of %lx exceeds Toc size limit"),
                        input_bfd, name,
                        (unsigned long) our_toc_offset);
                     bfd_set_error (bfd_error_bad_value);
                     return FALSE;
                    }

                  record_toc (toc_section, our_toc_offset, pub,
                            strdup (name));
                }
              else if (IS_WRITTEN (our_toc_offset))
                {
                  /* If it has been written out, it is marked with the
                     1 bit. Fix up our offset, but do not write it out
                     again.  */
                  MAKE_ADDR_AGAIN(our_toc_offset);
                }
              else
                {
                  record_toc(toc_section, our_toc_offset, pub,
                            strdup (name));

                  /* Write out the toc entry.  */
                  bfd_put_32 (output_bfd, val,
                            toc_section->contents + our_toc_offset);

                  MARK_AS_WRITTEN(h->toc_offset);
                  /* The tricky part is that this is the address that
                     needs a .reloc entry for it.  */
                  fixit = TRUE;
                }
             }

           if (fixit && info->base_file)
             {
              /* So if this is non pcrelative, and is referenced
                 to a section or a common symbol, then it needs a reloc.  */

              /* Relocation to a symbol in a section which
                 isn't absolute - we output the address here
                 to a file.  */
              bfd_vma addr = (toc_section->output_section->vma
                            + toc_section->output_offset + our_toc_offset);

              if (coff_data (output_bfd)->pe)
                addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;

              fwrite (&addr, 1,4, (FILE *) info->base_file);
             }

           /* FIXME: this test is conservative.  */
           if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN
              && (bfd_vma) our_toc_offset > toc_section->size)
             {
              (*_bfd_error_handler)
                (_("%B: Relocation exceeds allocated TOC (%lx)"),
                 input_bfd, (unsigned long) toc_section->size);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
             }

           /* Now we know the relocation for this toc reference.  */
           relocation =  our_toc_offset + TOC_LOAD_ADJUSTMENT;
           rstat = _bfd_relocate_contents (howto, input_bfd, relocation, loc);
         }
         break;
       case IMAGE_REL_PPC_IFGLUE:
         {
           /* To solve this, we need to know whether or not the symbol
              appearing on the call instruction is a glue function or not.
              A glue function must announce itself via a IMGLUE reloc, and 
              the reloc contains the required toc restore instruction.  */
           bfd_vma x;
           const char *my_name;
           
           DUMP_RELOC2 (howto->name, rel);

           if (h != 0)
             {
              my_name = h->root.root.root.string;
              if (h->symbol_is_glue == 1)
                {
                  x = bfd_get_32 (input_bfd, loc);
                  bfd_put_32 (input_bfd, (bfd_vma) h->glue_insn, loc);
                }
             }
         }
         break;
       case IMAGE_REL_PPC_SECREL:
         /* Unimplemented: codeview debugging information.  */
         /* For fast access to the header of the section
            containing the item.  */
         break;
       case IMAGE_REL_PPC_SECTION:
         /* Unimplemented: codeview debugging information.  */
         /* Is used to indicate that the value should be relative
            to the beginning of the section that contains the
            symbol.  */
         break;
       case IMAGE_REL_PPC_ABSOLUTE:
         {
           const char *my_name;

           if (h == 0)
             my_name = (syms+symndx)->_n._n_name;
           else
             my_name = h->root.root.root.string;

           (*_bfd_error_handler)
             (_("Warning: unsupported reloc %s <file %B, section %A>\n"
               "sym %ld (%s), r_vaddr %ld (%lx)"),
              input_bfd, input_section, howto->name,
              rel->r_symndx, my_name, (long) rel->r_vaddr,
              (unsigned long) rel->r_vaddr);
         }
         break;
       case IMAGE_REL_PPC_IMGLUE:
         {
           /* There is nothing to do now. This reloc was noted in the first
              pass over the relocs, and the glue instruction extracted.  */
           const char *my_name;

           if (h->symbol_is_glue == 1)
             break;
           my_name = h->root.root.root.string;

           (*_bfd_error_handler)
             (_("%B: Out of order IMGLUE reloc for %s"), input_bfd, my_name);
           bfd_set_error (bfd_error_bad_value);
           return FALSE;
         }

       case IMAGE_REL_PPC_ADDR32NB:
         {
           const char *name = 0;

           DUMP_RELOC2 (howto->name, rel);

           if (CONST_STRNEQ (input_section->name, ".idata$2") && first_thunk_address == 0)
             {
              /* Set magic values.  */
              int idata5offset;
              struct coff_link_hash_entry *myh;

              myh = coff_link_hash_lookup (coff_hash_table (info),
                                        "__idata5_magic__",
                                        FALSE, FALSE, TRUE);
              first_thunk_address = myh->root.u.def.value +
                sec->output_section->vma +
                  sec->output_offset -
                    pe_data(output_bfd)->pe_opthdr.ImageBase;

              idata5offset = myh->root.u.def.value;
              myh = coff_link_hash_lookup (coff_hash_table (info),
                                        "__idata6_magic__",
                                        FALSE, FALSE, TRUE);

              thunk_size = myh->root.u.def.value - idata5offset;
              myh = coff_link_hash_lookup (coff_hash_table (info),
                                        "__idata4_magic__",
                                        FALSE, FALSE, TRUE);
              import_table_size = myh->root.u.def.value;
             }

           if (h == 0)
             {
              /* It is a file local symbol.  */
              sym = syms + symndx;
              name = sym->_n._n_name;
             }
           else
             {
              char *target = 0;

              name = h->root.root.root.string;
              if (strcmp (".idata$2", name) == 0)
                target = "__idata2_magic__";
              else if (strcmp (".idata$4", name) == 0)
                target = "__idata4_magic__";
              else if (strcmp (".idata$5", name) == 0)
                target = "__idata5_magic__";

              if (target != 0)
                {
                  struct coff_link_hash_entry *myh;

                  myh = coff_link_hash_lookup (coff_hash_table (info),
                                           target,
                                           FALSE, FALSE, TRUE);
                  if (myh == 0)
                    {
                     /* Missing magic cookies. Something is very wrong.  */
                     abort ();
                    }

                  val = myh->root.u.def.value +
                    sec->output_section->vma + sec->output_offset;
                  if (first_thunk_address == 0)
                    {
                     int idata5offset;
                     myh = coff_link_hash_lookup (coff_hash_table (info),
                                               "__idata5_magic__",
                                               FALSE, FALSE, TRUE);
                     first_thunk_address = myh->root.u.def.value +
                       sec->output_section->vma +
                         sec->output_offset -
                           pe_data(output_bfd)->pe_opthdr.ImageBase;

                     idata5offset = myh->root.u.def.value;
                     myh = coff_link_hash_lookup (coff_hash_table (info),
                                               "__idata6_magic__",
                                               FALSE, FALSE, TRUE);

                     thunk_size = myh->root.u.def.value - idata5offset;
                     myh = coff_link_hash_lookup (coff_hash_table (info),
                                               "__idata4_magic__",
                                               FALSE, FALSE, TRUE);
                     import_table_size = myh->root.u.def.value;
                    }
                }
             }

           rstat = _bfd_relocate_contents (howto,
                                       input_bfd,
                                       val -
                                       pe_data (output_bfd)->pe_opthdr.ImageBase,
                                       loc);
         }
         break;

       case IMAGE_REL_PPC_REL24:
         DUMP_RELOC2(howto->name, rel);
         val -= (input_section->output_section->vma
                + input_section->output_offset);

         rstat = _bfd_relocate_contents (howto,
                                     input_bfd,
                                     val,
                                     loc);
         break;
       case IMAGE_REL_PPC_ADDR16:
       case IMAGE_REL_PPC_ADDR24:
       case IMAGE_REL_PPC_ADDR32:
         DUMP_RELOC2(howto->name, rel);
         rstat = _bfd_relocate_contents (howto,
                                     input_bfd,
                                     val,
                                     loc);
         break;
       }

      if (info->base_file)
       {
         /* So if this is non pcrelative, and is referenced
            to a section or a common symbol, then it needs a reloc.  */
         if (sym && pe_data(output_bfd)->in_reloc_p (output_bfd, howto))
           {
             /* Relocation to a symbol in a section which
               isn't absolute - we output the address here
               to a file.  */
             bfd_vma addr = rel->r_vaddr
              - input_section->vma
              + input_section->output_offset
                + input_section->output_section->vma;

             if (coff_data (output_bfd)->pe)
              addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;

             fwrite (&addr, 1,4, (FILE *) info->base_file);
           }
       }

      switch (rstat)
       {
       default:
         abort ();
       case bfd_reloc_ok:
         break;
       case bfd_reloc_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.root : NULL), name, howto->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 reloc_howto_type* coff_ppc_rtype_to_howto ( abfd  ,
asection sec,
struct internal_reloc rel,
,
sym  ,
bfd_vma addendp 
) [static]

Definition at line 1865 of file coff-ppc.c.

{
  reloc_howto_type *howto;

  /* We can encode one of three things in the type field, aside from the
     type:
     1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
        value, rather than an addition value
     2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
        the branch is expected to be taken or not.
     3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
     For now, we just strip this stuff to find the type, and ignore it other
     than that.  */

  unsigned short r_type  = EXTRACT_TYPE  (rel->r_type);
  unsigned short r_flags = EXTRACT_FLAGS (rel->r_type);
  unsigned short junk    = EXTRACT_JUNK  (rel->r_type);

  /* The masking process only slices off the bottom byte for r_type.  */
  if (r_type > MAX_RELOC_INDEX)
    abort ();

  /* Check for absolute crap.  */
  if (junk != 0)
    abort ();

  switch(r_type)
    {
    case IMAGE_REL_PPC_ADDR32NB:
      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
      howto = ppc_coff_howto_table + r_type;
      break;
    case IMAGE_REL_PPC_TOCREL16:
      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
      else
       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
      break;
    case IMAGE_REL_PPC_ADDR16:
    case IMAGE_REL_PPC_REL24:
    case IMAGE_REL_PPC_ADDR24:
    case IMAGE_REL_PPC_ADDR32:
    case IMAGE_REL_PPC_IFGLUE:
    case IMAGE_REL_PPC_SECTION:
    case IMAGE_REL_PPC_SECREL:
      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
      howto = ppc_coff_howto_table + r_type;
      break;
    case IMAGE_REL_PPC_IMGLUE:
      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
      howto = ppc_coff_howto_table + r_type;
      break;
    default:
      fprintf (stderr,
             _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
             ppc_coff_howto_table[r_type].name,
             r_type);
      howto = ppc_coff_howto_table + r_type;
      break;
    }

  return howto;
}

Here is the call graph for this function:

static bfd_boolean in_reloc_p ( abfd  ,
reloc_howto_type *  howto 
) [static]

Definition at line 967 of file coff-ppc.c.

{
  return
    (! howto->pc_relative)
      && (howto->type != IMAGE_REL_PPC_ADDR32NB)
      && (howto->type != IMAGE_REL_PPC_TOCREL16)
      && (howto->type != IMAGE_REL_PPC_IMGLUE)
      && (howto->type != IMAGE_REL_PPC_IFGLUE)
      && (howto->type != IMAGE_REL_PPC_SECREL)
      && (howto->type != IMAGE_REL_PPC_SECTION)
      && (howto->type != IMAGE_REL_PPC_SECREL16)
      && (howto->type != IMAGE_REL_PPC_REFHI)
      && (howto->type != IMAGE_REL_PPC_REFLO)
      && (howto->type != IMAGE_REL_PPC_PAIR)
      && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ;
}

Here is the caller graph for this function:

void dump_toc PARAMS ( (PTR )
static bfd_boolean in_reloc_p PARAMS ( (bfd *abfd, reloc_howto_type *howto)  ) [static]
static void record_toc PARAMS ( (asection *, bfd_signed_vma, enum ref_category, const char *)  ) [static]
static void ppc_coff_rtype2howto PARAMS ( (arelent *, struct internal_reloc *)  ) [static]
static reloc_howto_type* ppc_coff_reloc_type_lookup PARAMS ( (bfd *, bfd_reloc_code_real_type ) [static]
static bfd* ppc_get_last PARAMS ( (void)  ) [static]

Definition at line 2057 of file coff-ppc.c.

{
  bfd_size_type symesz;
  struct coff_final_link_info finfo;
  bfd_boolean debug_merge_allocated;
  asection *o;
  struct bfd_link_order *p;
  bfd_size_type max_sym_count;
  bfd_size_type max_lineno_count;
  bfd_size_type max_reloc_count;
  bfd_size_type max_output_reloc_count;
  bfd_size_type max_contents_size;
  file_ptr rel_filepos;
  unsigned int relsz;
  file_ptr line_filepos;
  unsigned int linesz;
  bfd *sub;
  bfd_byte *external_relocs = NULL;
  char strbuf[STRING_SIZE_SIZE];
  bfd_size_type amt;

  symesz = bfd_coff_symesz (abfd);

  finfo.info = info;
  finfo.output_bfd = abfd;
  finfo.strtab = NULL;
  finfo.section_info = NULL;
  finfo.last_file_index = -1;
  finfo.last_bf_index = -1;
  finfo.internal_syms = NULL;
  finfo.sec_ptrs = NULL;
  finfo.sym_indices = NULL;
  finfo.outsyms = NULL;
  finfo.linenos = NULL;
  finfo.contents = NULL;
  finfo.external_relocs = NULL;
  finfo.internal_relocs = NULL;
  debug_merge_allocated = FALSE;

  coff_data (abfd)->link_info = info;

  finfo.strtab = _bfd_stringtab_init ();
  if (finfo.strtab == NULL)
    goto error_return;

  if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
    goto error_return;
  debug_merge_allocated = TRUE;

  /* Compute the file positions for all the sections.  */
  if (! abfd->output_has_begun)
    {
      if (! bfd_coff_compute_section_file_positions (abfd))
       return FALSE;
    }

  /* Count the line numbers and relocation entries required for the
     output file.  Set the file positions for the relocs.  */
  rel_filepos = obj_relocbase (abfd);
  relsz = bfd_coff_relsz (abfd);
  max_contents_size = 0;
  max_lineno_count = 0;
  max_reloc_count = 0;

  for (o = abfd->sections; o != NULL; o = o->next)
    {
      o->reloc_count = 0;
      o->lineno_count = 0;

      for (p = o->map_head.link_order; p != NULL; p = p->next)
       {
         if (p->type == bfd_indirect_link_order)
           {
             asection *sec;

             sec = p->u.indirect.section;

             /* Mark all sections which are to be included in the
               link.  This will normally be every section.  We need
               to do this so that we can identify any sections which
               the linker has decided to not include.  */
             sec->linker_mark = TRUE;

             if (info->strip == strip_none
                || info->strip == strip_some)
              o->lineno_count += sec->lineno_count;

             if (info->relocatable)
              o->reloc_count += sec->reloc_count;

             if (sec->rawsize > max_contents_size)
              max_contents_size = sec->rawsize;
             if (sec->size > max_contents_size)
              max_contents_size = sec->size;
             if (sec->lineno_count > max_lineno_count)
              max_lineno_count = sec->lineno_count;
             if (sec->reloc_count > max_reloc_count)
              max_reloc_count = sec->reloc_count;
           }
         else if (info->relocatable
                 && (p->type == bfd_section_reloc_link_order
                     || p->type == bfd_symbol_reloc_link_order))
           ++o->reloc_count;
       }
      if (o->reloc_count == 0)
       o->rel_filepos = 0;
      else
       {
         o->flags |= SEC_RELOC;
         o->rel_filepos = rel_filepos;
         rel_filepos += o->reloc_count * relsz;
       }
    }

  /* If doing a relocatable link, allocate space for the pointers we
     need to keep.  */
  if (info->relocatable)
    {
      unsigned int i;

      /* We use section_count + 1, rather than section_count, because
         the target_index fields are 1 based.  */
      amt = abfd->section_count + 1;
      amt *= sizeof (struct coff_link_section_info);
      finfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);

      if (finfo.section_info == NULL)
       goto error_return;

      for (i = 0; i <= abfd->section_count; i++)
       {
         finfo.section_info[i].relocs = NULL;
         finfo.section_info[i].rel_hashes = NULL;
       }
    }

  /* We now know the size of the relocs, so we can determine the file
     positions of the line numbers.  */
  line_filepos = rel_filepos;
  linesz = bfd_coff_linesz (abfd);
  max_output_reloc_count = 0;

  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (o->lineno_count == 0)
       o->line_filepos = 0;
      else
       {
         o->line_filepos = line_filepos;
         line_filepos += o->lineno_count * linesz;
       }

      if (o->reloc_count != 0)
       {
         /* We don't know the indices of global symbols until we have
             written out all the local symbols.  For each section in
             the output file, we keep an array of pointers to hash
             table entries.  Each entry in the array corresponds to a
             reloc.  When we find a reloc against a global symbol, we
             set the corresponding entry in this array so that we can
             fix up the symbol index after we have written out all the
             local symbols.

            Because of this problem, we also keep the relocs in
            memory until the end of the link.  This wastes memory,
            but only when doing a relocatable link, which is not the
            common case.  */
         BFD_ASSERT (info->relocatable);
         amt = o->reloc_count;
         amt *= sizeof (struct internal_reloc);
         finfo.section_info[o->target_index].relocs =
           (struct internal_reloc *) bfd_malloc (amt);
         amt = o->reloc_count;
         amt *= sizeof (struct coff_link_hash_entry *);
         finfo.section_info[o->target_index].rel_hashes =
           (struct coff_link_hash_entry **) bfd_malloc (amt);
         if (finfo.section_info[o->target_index].relocs == NULL
             || finfo.section_info[o->target_index].rel_hashes == NULL)
           goto error_return;

         if (o->reloc_count > max_output_reloc_count)
           max_output_reloc_count = o->reloc_count;
       }

      /* Reset the reloc and lineno counts, so that we can use them to
        count the number of entries we have output so far.  */
      o->reloc_count = 0;
      o->lineno_count = 0;
    }

  obj_sym_filepos (abfd) = line_filepos;

  /* Figure out the largest number of symbols in an input BFD.  Take
     the opportunity to clear the output_has_begun fields of all the
     input BFD's.  */
  max_sym_count = 0;
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
    {
      bfd_size_type sz;

      sub->output_has_begun = FALSE;
      sz = obj_raw_syment_count (sub);
      if (sz > max_sym_count)
       max_sym_count = sz;
    }

  /* Allocate some buffers used while linking.  */
  amt = max_sym_count * sizeof (struct internal_syment);
  finfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
  amt = max_sym_count * sizeof (asection *);
  finfo.sec_ptrs = (asection **) bfd_malloc (amt);
  amt = max_sym_count * sizeof (long);
  finfo.sym_indices = (long *) bfd_malloc (amt);
  amt = (max_sym_count + 1) * symesz;
  finfo.outsyms = (bfd_byte *) bfd_malloc (amt);
  amt = max_lineno_count * bfd_coff_linesz (abfd);
  finfo.linenos = (bfd_byte *) bfd_malloc (amt);
  finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
  finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
  if (! info->relocatable)
    {
      amt = max_reloc_count * sizeof (struct internal_reloc);
      finfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
    }
  if ((finfo.internal_syms == NULL && max_sym_count > 0)
      || (finfo.sec_ptrs == NULL && max_sym_count > 0)
      || (finfo.sym_indices == NULL && max_sym_count > 0)
      || finfo.outsyms == NULL
      || (finfo.linenos == NULL && max_lineno_count > 0)
      || (finfo.contents == NULL && max_contents_size > 0)
      || (finfo.external_relocs == NULL && max_reloc_count > 0)
      || (! info->relocatable
         && finfo.internal_relocs == NULL
         && max_reloc_count > 0))
    goto error_return;

  /* We now know the position of everything in the file, except that
     we don't know the size of the symbol table and therefore we don't
     know where the string table starts.  We just build the string
     table in memory as we go along.  We process all the relocations
     for a single input file at once.  */
  obj_raw_syment_count (abfd) = 0;

  if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
    {
      if (! bfd_coff_start_final_link (abfd, info))
       goto error_return;
    }

  for (o = abfd->sections; o != NULL; o = o->next)
    {
      for (p = o->map_head.link_order; p != NULL; p = p->next)
       {
         if (p->type == bfd_indirect_link_order
             && (bfd_get_flavour (p->u.indirect.section->owner)
                == bfd_target_coff_flavour))
           {
             sub = p->u.indirect.section->owner;
#ifdef POWERPC_LE_PE
             if (! sub->output_has_begun && !ppc_do_last(sub))
#else
             if (! sub->output_has_begun)
#endif
              {
                if (! _bfd_coff_link_input_bfd (&finfo, sub))
                  goto error_return;
                sub->output_has_begun = TRUE;
              }
           }
         else if (p->type == bfd_section_reloc_link_order
                 || p->type == bfd_symbol_reloc_link_order)
           {
             if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
              goto error_return;
           }
         else
           {
             if (! _bfd_default_link_order (abfd, info, o, p))
              goto error_return;
           }
       }
    }

#ifdef POWERPC_LE_PE
  {
    bfd* last_one = ppc_get_last();
    if (last_one)
      {
       if (! _bfd_coff_link_input_bfd (&finfo, last_one))
         goto error_return;
      }
    last_one->output_has_begun = TRUE;
  }
#endif

  /* Free up the buffers used by _bfd_coff_link_input_bfd.  */
  coff_debug_merge_hash_table_free (&finfo.debug_merge);
  debug_merge_allocated = FALSE;

  if (finfo.internal_syms != NULL)
    {
      free (finfo.internal_syms);
      finfo.internal_syms = NULL;
    }
  if (finfo.sec_ptrs != NULL)
    {
      free (finfo.sec_ptrs);
      finfo.sec_ptrs = NULL;
    }
  if (finfo.sym_indices != NULL)
    {
      free (finfo.sym_indices);
      finfo.sym_indices = NULL;
    }
  if (finfo.linenos != NULL)
    {
      free (finfo.linenos);
      finfo.linenos = NULL;
    }
  if (finfo.contents != NULL)
    {
      free (finfo.contents);
      finfo.contents = NULL;
    }
  if (finfo.external_relocs != NULL)
    {
      free (finfo.external_relocs);
      finfo.external_relocs = NULL;
    }
  if (finfo.internal_relocs != NULL)
    {
      free (finfo.internal_relocs);
      finfo.internal_relocs = NULL;
    }

  /* The value of the last C_FILE symbol is supposed to be the symbol
     index of the first external symbol.  Write it out again if
     necessary.  */
  if (finfo.last_file_index != -1
      && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
    {
      file_ptr pos;

      finfo.last_file.n_value = obj_raw_syment_count (abfd);
      bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
                          (PTR) finfo.outsyms);
      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0
         || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
       return FALSE;
    }

  /* Write out the global symbols.  */
  finfo.failed = FALSE;
  coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
                        (PTR) &finfo);
  if (finfo.failed)
    goto error_return;

  /* The outsyms buffer is used by _bfd_coff_write_global_sym.  */
  if (finfo.outsyms != NULL)
    {
      free (finfo.outsyms);
      finfo.outsyms = NULL;
    }

  if (info->relocatable)
    {
      /* Now that we have written out all the global symbols, we know
        the symbol indices to use for relocs against them, and we can
        finally write out the relocs.  */
      amt = max_output_reloc_count * relsz;
      external_relocs = (bfd_byte *) bfd_malloc (amt);
      if (external_relocs == NULL)
       goto error_return;

      for (o = abfd->sections; o != NULL; o = o->next)
       {
         struct internal_reloc *irel;
         struct internal_reloc *irelend;
         struct coff_link_hash_entry **rel_hash;
         bfd_byte *erel;

         if (o->reloc_count == 0)
           continue;

         irel = finfo.section_info[o->target_index].relocs;
         irelend = irel + o->reloc_count;
         rel_hash = finfo.section_info[o->target_index].rel_hashes;
         erel = external_relocs;
         for (; irel < irelend; irel++, rel_hash++, erel += relsz)
           {
             if (*rel_hash != NULL)
              {
                BFD_ASSERT ((*rel_hash)->indx >= 0);
                irel->r_symndx = (*rel_hash)->indx;
              }
             bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
           }

         amt = relsz * o->reloc_count;
         if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
             || bfd_bwrite ((PTR) external_relocs, amt, abfd) != amt)
           goto error_return;
       }

      free (external_relocs);
      external_relocs = NULL;
    }

  /* Free up the section information.  */
  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
      finfo.section_info = NULL;
    }

  /* If we have optimized stabs strings, output them.  */
  if (coff_hash_table (info)->stab_info.stabstr != NULL)
    {
      if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
       return FALSE;
    }

  /* Write out the string table.  */
  if (obj_raw_syment_count (abfd) != 0)
    {
      file_ptr pos;

      pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
       return FALSE;

#if STRING_SIZE_SIZE == 4
      H_PUT_32 (abfd,
              _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
              strbuf);
#else
 #error Change H_PUT_32 above
#endif

      if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd)
         != STRING_SIZE_SIZE)
       return FALSE;

      if (! _bfd_stringtab_emit (abfd, finfo.strtab))
       return FALSE;
    }

  _bfd_stringtab_free (finfo.strtab);

  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
     not try to write out the symbols.  */
  bfd_get_symcount (abfd) = 0;

  return TRUE;

 error_return:
  if (debug_merge_allocated)
    coff_debug_merge_hash_table_free (&finfo.debug_merge);
  if (finfo.strtab != NULL)
    _bfd_stringtab_free (finfo.strtab);
  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
    }
  if (finfo.internal_syms != NULL)
    free (finfo.internal_syms);
  if (finfo.sec_ptrs != NULL)
    free (finfo.sec_ptrs);
  if (finfo.sym_indices != NULL)
    free (finfo.sym_indices);
  if (finfo.outsyms != NULL)
    free (finfo.outsyms);
  if (finfo.linenos != NULL)
    free (finfo.linenos);
  if (finfo.contents != NULL)
    free (finfo.contents);
  if (finfo.external_relocs != NULL)
    free (finfo.external_relocs);
  if (finfo.internal_relocs != NULL)
    free (finfo.internal_relocs);
  if (external_relocs != NULL)
    free (external_relocs);
  return FALSE;
}

Here is the call graph for this function:

static struct bfd_hash_entry* ppc_coff_link_hash_newfunc ( struct bfd_hash_entry entry,
struct bfd_hash_table table,
const char *  string 
) [static, read]

Definition at line 143 of file coff-ppc.c.

{
  struct ppc_coff_link_hash_entry *ret =
    (struct ppc_coff_link_hash_entry *) entry;

  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
    ret = (struct ppc_coff_link_hash_entry *)
      bfd_hash_allocate (table,
                      sizeof (struct ppc_coff_link_hash_entry));

  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
    return NULL;

  /* Call the allocation method of the superclass.  */
  ret = ((struct ppc_coff_link_hash_entry *)
        _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                                  table, string));

  if (ret)
    {
      /* Initialize the local fields.  */
      SET_UNALLOCATED (ret->toc_offset);
      ret->symbol_is_glue = 0;
      ret->glue_insn = 0;

      HASH_CHECK_INIT (ret);
    }

  return (struct bfd_hash_entry *) ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct bfd_link_hash_table* ppc_coff_link_hash_table_create ( bfd abfd) [static, read]

Definition at line 195 of file coff-ppc.c.

{
  struct ppc_coff_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct ppc_coff_link_hash_table);

  ret = (struct ppc_coff_link_hash_table *) bfd_malloc (amt);
  if (ret == NULL)
    return NULL;
  if (!ppc_coff_link_hash_table_init (ret, abfd,
                                  ppc_coff_link_hash_newfunc,
                                  sizeof (struct ppc_coff_link_hash_entry)))
    {
      free (ret);
      return (struct bfd_link_hash_table *) NULL;
    }
  return &ret->root.root;
}

Here is the call graph for this function:

Definition at line 182 of file coff-ppc.c.

{
  return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1967 of file coff-ppc.c.

{
  unsigned int i;

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

  return NULL;
}

Here is the call graph for this function:

static reloc_howto_type* ppc_coff_reloc_type_lookup ( abfd  ,
bfd_reloc_code_real_type  code 
) [static]
static void ppc_coff_rtype2howto ( arelent relent,
struct internal_reloc internal 
) [static]

Definition at line 1802 of file coff-ppc.c.

{
  /* We can encode one of three things in the type field, aside from the
     type:
     1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
        value, rather than an addition value
     2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
        the branch is expected to be taken or not.
     3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
     For now, we just strip this stuff to find the type, and ignore it other
     than that.  */
  reloc_howto_type *howto;
  unsigned short r_type  = EXTRACT_TYPE (internal->r_type);
  unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
  unsigned short junk    = EXTRACT_JUNK (internal->r_type);

  /* The masking process only slices off the bottom byte for r_type.  */
  if ( r_type > MAX_RELOC_INDEX )
    abort ();

  /* Check for absolute crap.  */
  if (junk != 0)
    abort ();

  switch(r_type)
    {
    case IMAGE_REL_PPC_ADDR16:
    case IMAGE_REL_PPC_REL24:
    case IMAGE_REL_PPC_ADDR24:
    case IMAGE_REL_PPC_ADDR32:
    case IMAGE_REL_PPC_IFGLUE:
    case IMAGE_REL_PPC_ADDR32NB:
    case IMAGE_REL_PPC_SECTION:
    case IMAGE_REL_PPC_SECREL:
      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
      howto = ppc_coff_howto_table + r_type;
      break;
    case IMAGE_REL_PPC_IMGLUE:
      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
      howto = ppc_coff_howto_table + r_type;
      break;
    case IMAGE_REL_PPC_TOCREL16:
      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
      else
       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
      break;
    default:
      fprintf (stderr,
             _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
             ppc_coff_howto_table[r_type].name,
             r_type);
      howto = ppc_coff_howto_table + r_type;
      break;
    }

  relent->howto = howto;
}

Here is the call graph for this function:

static bfd_boolean ppc_do_last ( bfd abfd) [static]

Definition at line 2028 of file coff-ppc.c.

{
  if (abfd == bfd_of_toc_owner)
    return TRUE;
  else
    return FALSE;
}

Here is the caller graph for this function:

static bfd* ppc_get_last ( ) [static]

Definition at line 2038 of file coff-ppc.c.

{
  return bfd_of_toc_owner;
}

Here is the caller graph for this function:

static bfd_reloc_status_type ppc_imglue_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1774 of file coff-ppc.c.

{
  UN_IMPL("IMGLUE");
  DUMP_RELOC("IMGLUE",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_ok;
}
static bfd_reloc_status_type ppc_pair_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1694 of file coff-ppc.c.

{
  UN_IMPL("PAIR");
  DUMP_RELOC("PAIR",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_undefined;
}
static bfd_reloc_status_type ppc_refhi_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1674 of file coff-ppc.c.

{
  UN_IMPL("REFHI");
  DUMP_RELOC("REFHI",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_undefined;
}
static bfd_reloc_status_type ppc_secrel_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1734 of file coff-ppc.c.

{
  UN_IMPL("SECREL");
  DUMP_RELOC("SECREL",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_ok;
}
static bfd_reloc_status_type ppc_section_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1754 of file coff-ppc.c.

{
  UN_IMPL("SECTION");
  DUMP_RELOC("SECTION",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_ok;
}
static bfd_reloc_status_type ppc_toc16_reloc ( abfd  ,
reloc_entry  ,
symbol  ,
data  ,
input_section  ,
bfd output_bfd,
error_message   
) [static]

Definition at line 1714 of file coff-ppc.c.

{
  UN_IMPL ("TOCREL16");
  DUMP_RELOC ("TOCREL16",reloc_entry);

  if (output_bfd == (bfd *) NULL)
    return bfd_reloc_continue;

  return bfd_reloc_ok;
}
static void record_toc ( asection toc_section,
bfd_signed_vma  our_toc_offset,
enum ref_category  cat,
const char *  name 
) [static]

Definition at line 824 of file coff-ppc.c.

{
  /* Add this entry to our toc addr-offset-name list.  */
  bfd_size_type amt = sizeof (struct list_ele);
  struct list_ele *t = (struct list_ele *) bfd_malloc (amt);

  if (t == NULL)
    abort ();
  t->next = 0;
  t->offset = our_toc_offset;
  t->name = name;
  t->cat = cat;
  t->addr = toc_section->output_offset + our_toc_offset;

  if (head == 0)
    {
      head = t;
      tail = t;
    }
  else
    {
      tail->next = t;
      tail = t;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

reloc_howto_type ppc_coff_howto_table[] [static]

Definition at line 400 of file coff-ppc.c.