/* PowerPC-specific support for 32-bit ELF
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file is based on a preliminary PowerPC ELF ABI. The
information may not match the final PowerPC ELF ABI. It includes
#include "elf-bfd.h"
#include "elf/ppc.h"
-#define USE_RELA /* we want RELA relocations, not REL */
+/* RELA relocations are used here. */
+static struct bfd_hash_entry *ppc_elf_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
+ const char *string));
+static struct bfd_link_hash_table *ppc_elf_link_hash_table_create
+ PARAMS ((bfd *abfd));
+static void ppc_elf_copy_indirect_symbol
+ PARAMS ((struct elf_backend_data *bed, struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind));
static reloc_howto_type *ppc_elf_reloc_type_lookup
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
static void ppc_elf_info_to_howto
- PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst));
-static void ppc_elf_howto_init PARAMS ((void));
-static int ppc_elf_sort_rela PARAMS ((const PTR, const PTR));
-static boolean ppc_elf_relax_section
- PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
+ PARAMS ((bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst));
+static void ppc_elf_howto_init
+ PARAMS ((void));
+static int ppc_elf_sort_rela
+ PARAMS ((const PTR, const PTR));
+static bfd_boolean ppc_elf_relax_section
+ PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
static bfd_reloc_status_type ppc_elf_addr16_ha_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword));
-static boolean ppc_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
-static boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
-
-static int ppc_elf_additional_program_headers PARAMS ((bfd *));
-static boolean ppc_elf_modify_segment_map PARAMS ((bfd *));
-
-static boolean ppc_elf_create_dynamic_sections
+static bfd_boolean ppc_elf_object_p
+ PARAMS ((bfd *));
+static bfd_boolean ppc_elf_set_private_flags
+ PARAMS ((bfd *, flagword));
+static bfd_boolean ppc_elf_merge_private_bfd_data
+ PARAMS ((bfd *, bfd *));
+static int ppc_elf_additional_program_headers
+ PARAMS ((bfd *));
+static bfd_boolean ppc_elf_modify_segment_map
+ PARAMS ((bfd *));
+static asection *ppc_elf_create_got
PARAMS ((bfd *, struct bfd_link_info *));
-
-static boolean ppc_elf_section_from_shdr PARAMS ((bfd *,
- Elf32_Internal_Shdr *,
- char *));
-static boolean ppc_elf_fake_sections
- PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
-
+static bfd_boolean ppc_elf_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean ppc_elf_section_from_shdr
+ PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
+static bfd_boolean ppc_elf_fake_sections
+ PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
static elf_linker_section_t *ppc_elf_create_linker_section
- PARAMS ((bfd *abfd,
- struct bfd_link_info *info,
+ PARAMS ((bfd *abfd, struct bfd_link_info *info,
enum elf_linker_section_enum));
-
-static boolean ppc_elf_check_relocs PARAMS ((bfd *,
- struct bfd_link_info *,
- asection *,
- const Elf_Internal_Rela *));
-
-static asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,
- struct bfd_link_info *info,
- Elf_Internal_Rela *rel,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym));
-
-static boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs));
-
-static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
- struct elf_link_hash_entry *));
-
-static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
-
-static boolean ppc_elf_relocate_section PARAMS ((bfd *,
- struct bfd_link_info *info,
- bfd *,
- asection *,
- bfd_byte *,
- Elf_Internal_Rela *relocs,
- Elf_Internal_Sym *local_syms,
- asection **));
-
-static boolean ppc_elf_add_symbol_hook PARAMS ((bfd *,
- struct bfd_link_info *,
- const Elf_Internal_Sym *,
- const char **,
- flagword *,
- asection **,
- bfd_vma *));
-
-static boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *,
- struct bfd_link_info *,
- struct elf_link_hash_entry *,
- Elf_Internal_Sym *));
-
-static boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
-static enum elf_reloc_type_class ppc_elf_reloc_type_class PARAMS ((int));
-static boolean ppc_elf_grok_prstatus
+static bfd_boolean ppc_elf_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static asection * ppc_elf_gc_mark_hook
+ PARAMS ((asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
+static bfd_boolean ppc_elf_gc_sweep_hook
+ PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
+ const Elf_Internal_Rela *relocs));
+static bfd_boolean ppc_elf_adjust_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static bfd_boolean allocate_dynrelocs
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static bfd_boolean readonly_dynrelocs
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static bfd_boolean ppc_elf_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean ppc_elf_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *info, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
+ asection **));
+static bfd_boolean ppc_elf_add_symbol_hook
+ PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ const char **, flagword *, asection **, bfd_vma *));
+static bfd_boolean ppc_elf_finish_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+static bfd_boolean ppc_elf_finish_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static enum elf_reloc_type_class ppc_elf_reloc_type_class
+ PARAMS ((const Elf_Internal_Rela *));
+static bfd_boolean ppc_elf_grok_prstatus
PARAMS ((bfd *abfd, Elf_Internal_Note *note));
-static boolean ppc_elf_grok_psinfo
+static bfd_boolean ppc_elf_grok_psinfo
PARAMS ((bfd *abfd, Elf_Internal_Note *note));
-#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */
-#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */
-#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */
+#define BRANCH_PREDICT_BIT 0x200000 /* Branch prediction bit for branch taken relocs. */
+#define RA_REGISTER_MASK 0x001f0000 /* Mask to set RA in memory instructions. */
+#define RA_REGISTER_SHIFT 16 /* Value to shift register by to insert RA. */
/* The name of the dynamic interpreter. This is put in the .interp
section. */
|| ELF_ST_VISIBILITY (H->other) != STV_DEFAULT) \
&& (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
\f
+/* The PPC linker needs to keep track of the number of relocs that it
+ decides to copy as dynamic relocs in check_relocs for each symbol.
+ This is so that it can later discard them if they are found to be
+ unnecessary. We store the information in a field extending the
+ regular ELF linker hash table. */
+
+struct ppc_elf_dyn_relocs
+{
+ struct ppc_elf_dyn_relocs *next;
+
+ /* The input section of the reloc. */
+ asection *sec;
+
+ /* Total number of relocs copied for the input section. */
+ bfd_size_type count;
+};
+
+/* PPC ELF linker hash entry. */
+
+struct ppc_elf_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+
+ /* Track dynamic relocs copied for this symbol. */
+ struct ppc_elf_dyn_relocs *dyn_relocs;
+};
+
+#define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent))
+
+/* PPC ELF linker hash table. */
+
+struct ppc_elf_link_hash_table
+{
+ struct elf_link_hash_table root;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
+};
+
+/* Get the PPC ELF linker hash table from a link_info structure. */
+
+#define ppc_elf_hash_table(p) \
+ ((struct ppc_elf_link_hash_table *) (p)->hash)
+
+/* Create an entry in a PPC ELF linker hash table. */
+
+static struct bfd_hash_entry *
+ppc_elf_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (entry == NULL)
+ {
+ entry = bfd_hash_allocate (table,
+ sizeof (struct ppc_elf_link_hash_entry));
+ if (entry == NULL)
+ return entry;
+ }
+
+ /* Call the allocation method of the superclass. */
+ entry = _bfd_elf_link_hash_newfunc (entry, table, string);
+ if (entry != NULL)
+ ppc_elf_hash_entry (entry)->dyn_relocs = NULL;
+
+ return entry;
+}
+
+/* Create a PPC ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+ppc_elf_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct ppc_elf_link_hash_table *ret;
+
+ ret = ((struct ppc_elf_link_hash_table *)
+ bfd_malloc (sizeof (struct ppc_elf_link_hash_table)));
+ if (ret == NULL)
+ return NULL;
+
+ if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+ ppc_elf_link_hash_newfunc))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ ret->sym_sec.abfd = NULL;
+
+ return &ret->root.root;
+}
+
+/* Copy the extra info we tack onto an elf_link_hash_entry. */
+
+static void
+ppc_elf_copy_indirect_symbol (bed, dir, ind)
+ struct elf_backend_data *bed;
+ struct elf_link_hash_entry *dir, *ind;
+{
+ struct ppc_elf_link_hash_entry *edir, *eind;
+
+ edir = (struct ppc_elf_link_hash_entry *) dir;
+ eind = (struct ppc_elf_link_hash_entry *) ind;
+
+ if (eind->dyn_relocs != NULL)
+ {
+ if (edir->dyn_relocs != NULL)
+ {
+ struct ppc_elf_dyn_relocs **pp;
+ struct ppc_elf_dyn_relocs *p;
+
+ if (ind->root.type == bfd_link_hash_indirect)
+ abort ();
+
+ /* Add reloc counts against the weak sym to the strong sym
+ list. Merge any entries against the same section. */
+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
+ {
+ struct ppc_elf_dyn_relocs *q;
+
+ for (q = edir->dyn_relocs; q != NULL; q = q->next)
+ if (q->sec == p->sec)
+ {
+ q->count += p->count;
+ *pp = p->next;
+ break;
+ }
+ if (q == NULL)
+ pp = &p->next;
+ }
+ *pp = edir->dyn_relocs;
+ }
+
+ edir->dyn_relocs = eind->dyn_relocs;
+ eind->dyn_relocs = NULL;
+ }
+
+ _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+}
+\f
static reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max];
static reloc_howto_type ppc_elf_howto_raw[] = {
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_NONE", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A standard 32 bit relocation. */
HOWTO (R_PPC_ADDR32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* An absolute 26 bit branch; the lower two bits must be zero.
FIXME: we don't check that, we just clear them. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR24", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0x3fffffc, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A standard 16 bit relocation. */
HOWTO (R_PPC_ADDR16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A 16 bit relocation without overflow. */
HOWTO (R_PPC_ADDR16_LO, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR16_LO", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* The high order 16 bits of an address. */
HOWTO (R_PPC_ADDR16_HI, /* type */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR16_HI", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* The high order 16 bits of an address, plus 1 if the contents of
the low 16 bits, treated as a signed number, is negative. */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_ADDR16_HA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* An absolute 16 bit branch; the lower two bits must be zero.
FIXME: we don't check that, we just clear them. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* An absolute 16 bit branch, for which bit 10 should be set to
indicate that the branch is expected to be taken. The lower two
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14_BRTAKEN",/* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* An absolute 16 bit branch, for which bit 10 should be set to
indicate that the branch is not expected to be taken. The lower
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14_BRNTAKEN",/* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A relative 26 bit branch; the lower two bits must be zero. */
HOWTO (R_PPC_REL24, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL24", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0x3fffffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* A relative 16 bit branch; the lower two bits must be zero. */
HOWTO (R_PPC_REL14, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL14", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* A relative 16 bit branch. Bit 10 should be set to indicate that
the branch is expected to be taken. The lower two bits must be
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL14_BRTAKEN", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* A relative 16 bit branch. Bit 10 should be set to indicate that
the branch is not expected to be taken. The lower two bits must
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL14_BRNTAKEN",/* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xfffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* Like R_PPC_ADDR16, but referring to the GOT table entry for the
symbol. */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GOT16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
the symbol. */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GOT16_LO", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
the symbol. */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GOT16_HI", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
the symbol. */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_GOT16_HA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_REL24, but referring to the procedure linkage table
entry for the symbol. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLTREL24", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0x3fffffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* This is used only by the dynamic linker. The symbol should exist
both in the object being run and in some shared library. The
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_COPY", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR32, but used when setting global offset table
entries. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GLOB_DAT", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Marks a procedure linkage table entry for a symbol. */
HOWTO (R_PPC_JMP_SLOT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_JMP_SLOT", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Used only by the dynamic linker. When the object is run, this
longword is set to the load address of the object, plus the
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_RELATIVE", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_REL24, but uses the value of the symbol within the
object rather than the final value. Normally used for
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_LOCAL24PC", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0x3fffffc, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* Like R_PPC_ADDR32, but may be unaligned. */
HOWTO (R_PPC_UADDR32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_UADDR32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16, but may be unaligned. */
HOWTO (R_PPC_UADDR16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_UADDR16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 32-bit PC relative */
HOWTO (R_PPC_REL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* 32-bit relocation to the symbol's procedure linkage table.
FIXME: not supported. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLT32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 32-bit PC relative relocation to the symbol's procedure linkage table.
FIXME: not supported. */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLTREL32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- true), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
/* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
the symbol. */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLT16_LO", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
the symbol. */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLT16_HI", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
the symbol. */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_PLT16_HA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
small data items. */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SDAREL16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* 32-bit section relative relocation. */
+ /* 16-bit section relative relocation. */
HOWTO (R_PPC_SECTOFF, /* type */
0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- true, /* pc_relative */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SECTOFF", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
- 0, /* dst_mask */
- true), /* pcrel_offset */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
/* 16-bit lower half section relative relocation. */
HOWTO (R_PPC_SECTOFF_LO, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SECTOFF_LO", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 16-bit upper half section relative relocation. */
HOWTO (R_PPC_SECTOFF_HI, /* type */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SECTOFF_HI", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 16-bit upper half adjusted section relative relocation. */
HOWTO (R_PPC_SECTOFF_HA, /* type */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_SECTOFF_HA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* The remaining relocs are from the Embedded ELF ABI, and are not
in the SVR4 ELF ABI. */
- /* 32 bit value resulting from the addend minus the symbol */
+ /* 32 bit value resulting from the addend minus the symbol. */
HOWTO (R_PPC_EMB_NADDR32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_NADDR32", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* 16 bit value resulting from the addend minus the symbol */
+ /* 16 bit value resulting from the addend minus the symbol. */
HOWTO (R_PPC_EMB_NADDR16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_NADDR16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* 16 bit value resulting from the addend minus the symbol */
+ /* 16 bit value resulting from the addend minus the symbol. */
HOWTO (R_PPC_EMB_NADDR16_LO, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_ADDR16_LO", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* The high order 16 bits of the addend minus the symbol */
+ /* The high order 16 bits of the addend minus the symbol. */
HOWTO (R_PPC_EMB_NADDR16_HI, /* type */
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_NADDR16_HI", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* The high order 16 bits of the result of the addend minus the address,
plus 1 if the contents of the low 16 bits, treated as a signed number,
16, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_EMB_NADDR16_HA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 16 bit value resulting from allocating a 4 byte word to hold an
address in the .sdata section, and returning the offset from
- _SDA_BASE_ for that relocation */
+ _SDA_BASE_ for that relocation. */
HOWTO (R_PPC_EMB_SDAI16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDAI16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* 16 bit value resulting from allocating a 4 byte word to hold an
address in the .sdata2 section, and returning the offset from
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDA2I16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
small data items. */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDA2REL", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
signed offset from the appropriate base, and filling in the register
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_SDA21", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
/* Relocation not handled: R_PPC_EMB_MRKREF */
/* Relocation not handled: R_PPC_EMB_RELSEC16 */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_RELSDA", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* GNU extension to record C++ vtable hierarchy */
+ /* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
NULL, /* special_function */
"R_PPC_GNU_VTINHERIT", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* GNU extension to record C++ vtable member usage */
+ /* GNU extension to record C++ vtable member usage. */
HOWTO (R_PPC_GNU_VTENTRY, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
NULL, /* special_function */
"R_PPC_GNU_VTENTRY", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
- /* Phony reloc to handle AIX style TOC entries */
+ /* Phony reloc to handle AIX style TOC entries. */
HOWTO (R_PPC_TOC16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_TOC16", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- false), /* pcrel_offset */
+ FALSE), /* pcrel_offset */
};
\f
/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */
3/ Conditional forward branches - Ensure that the "inverse prediction
bit" is set (ensure it is predicted taken).
4/ Conditional register branches - Ensure that the "y bit" is set
- (ensure it is predicted taken).
-*/
+ (ensure it is predicted taken). */
/* Sort sections by address. */
return ((*rela1)->r_offset - (*rela2)->r_offset);
}
-static boolean
+static bfd_boolean
ppc_elf_relax_section (abfd, isec, link_info, again)
bfd *abfd;
asection *isec;
struct bfd_link_info *link_info;
- boolean *again;
+ bfd_boolean *again;
{
#define PAGESIZE 0x1000
int comb_curr, comb_count;
/* We never have to do this more than once per input section. */
- *again = false;
+ *again = FALSE;
/* If needed, initialize this section's cooked size. */
if (isec->_cooked_size == 0)
if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size)
{
bfd_vma dot, end_page, end_section;
- boolean section_modified;
+ bfd_boolean section_modified;
/* Get the section contents. */
/* Get cached copy if it exists. */
The array rela_comb is built here for use in the EOP scan loop. */
switch (r_type)
{
- case R_PPC_ADDR14_BRNTAKEN: /* absolute, predicted not taken */
- case R_PPC_REL14: /* relative cond. br. */
- case R_PPC_REL14_BRNTAKEN: /* rel. cond. br., predicted not taken */
+ case R_PPC_ADDR14_BRNTAKEN: /* Absolute, predicted not taken */
+ case R_PPC_REL14: /* Relative cond. br. */
+ case R_PPC_REL14_BRNTAKEN: /* Rel. cond. br., predicted not taken */
/* We should check the instruction. */
break;
default:
end_section = isec->vma + isec->_cooked_size;
dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1;
dot -= link_info->mpc860c0;
- section_modified = false;
+ section_modified = FALSE;
if (dot < isec->vma) /* Increment the start position if this section */
dot = isec->vma; /* begins in the middle of its first EOP region. */
for (;
{
bfd_vma isec_offset;
unsigned long insn;
- boolean skip, modified;
+ bfd_boolean skip, modified;
/* Don't process this word if there is a relocation for it and
- the relocation indicates the word is not a conditional branch. */
- skip = false;
+ the relocation indicates the word is not a conditional branch. */
+ skip = FALSE;
isec_offset = dot - isec->vma;
for (; comb_curr<comb_count; ++comb_curr)
{
r_offset = rela_comb[comb_curr]->r_offset;
if (r_offset >= isec_offset)
{
- if (r_offset == isec_offset) skip = true;
+ if (r_offset == isec_offset) skip = TRUE;
break;
}
}
#define BO2(insn) ((insn) & 0x00800000)
#define BO4(insn) ((insn) & 0x00200000)
insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset);
- modified = false;
+ modified = FALSE;
if ((insn & 0xFc000000) == 0x40000000)
{
/* Instruction is BCx */
{
bfd_vma target;
/* This branch is predicted as "normal".
- If this is a forward branch, it is problematic. */
+ If this is a forward branch, it is problematic. */
target = insn & 0x0000Fffc; /*extract*/
target = (target ^ 0x8000) - 0x8000; /*sign extend*/
target += dot; /*convert to abs*/
if (target > dot)
{
- insn |= 0x00200000; /* set the prediction bit */
- modified = true;
+ insn |= 0x00200000; /* Set the prediction bit. */
+ modified = TRUE;
}
}
}
else if ((insn & 0xFc00Fffe) == 0x4c000420)
{
- /* Instruction is BCCTRx */
+ /* Instruction is BCCTRx. */
if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
{
/* This branch is predicted as not-taken.
- If this is a forward branch, it is problematic.
- Since we can't tell statically if it will branch forward,
- always set the prediction bit. */
- insn |= 0x00200000; /* set the prediction bit */
- modified = true;
+ If this is a forward branch, it is problematic.
+ Since we can't tell statically if it will branch forward,
+ always set the prediction bit. */
+ insn |= 0x00200000; /* Set the prediction bit. */
+ modified = TRUE;
}
}
else if ((insn & 0xFc00Fffe) == 0x4c000020)
if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
{
/* This branch is predicted as not-taken.
- If this is a forward branch, it is problematic.
- Since we can't tell statically if it will branch forward,
- always set the prediction bit. */
- insn |= 0x00200000; /* set the prediction bit */
- modified = true;
+ If this is a forward branch, it is problematic.
+ Since we can't tell statically if it will branch forward,
+ always set the prediction bit. */
+ insn |= 0x00200000; /* Set the prediction bit. */
+ modified = TRUE;
}
}
#undef BO0
if (modified)
{
bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset);
- section_modified = true;
+ section_modified = TRUE;
}
}
}
free_contents = NULL;
}
- return true;
+ return TRUE;
error_return:
if (rela_comb != NULL)
free (free_relocs);
if (free_contents != NULL)
free (free_contents);
- return false;
+ return FALSE;
}
\f
static reloc_howto_type *
case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break;
case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break;
case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break;
- case BFD_RELOC_32_BASEREL: ppc_reloc = R_PPC_SECTOFF; break;
+ case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC_SECTOFF; break;
case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break;
case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break;
case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break;
ppc_elf_info_to_howto (abfd, cache_ptr, dst)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *cache_ptr;
- Elf32_Internal_Rela *dst;
+ Elf_Internal_Rela *dst;
{
if (!ppc_elf_howto_table[R_PPC_ADDR32])
/* Initialize howto table if needed. */
return bfd_reloc_continue;
}
+/* Fix bad default arch selected for a 32 bit input bfd when the
+ default is 64 bit. */
+
+static bfd_boolean
+ppc_elf_object_p (abfd)
+ bfd *abfd;
+{
+ if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64)
+ {
+ Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
+
+ if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+ {
+ /* Relies on arch after 64 bit default being 32 bit default. */
+ abfd->arch_info = abfd->arch_info->next;
+ BFD_ASSERT (abfd->arch_info->bits_per_word == 32);
+ }
+ }
+ return TRUE;
+}
+
/* Function to set whether a module needs the -mrelocatable bit set. */
-static boolean
+static bfd_boolean
ppc_elf_set_private_flags (abfd, flags)
bfd *abfd;
flagword flags;
|| elf_elfheader (abfd)->e_flags == flags);
elf_elfheader (abfd)->e_flags = flags;
- elf_flags_init (abfd) = true;
- return true;
-}
-
-/* Copy backend specific data from one object module to another */
-static boolean
-ppc_elf_copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
-{
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = true;
- return true;
+ elf_flags_init (abfd) = TRUE;
+ return TRUE;
}
/* Merge backend specific data from an object file to the output
- object file when linking */
-static boolean
+ object file when linking. */
+
+static bfd_boolean
ppc_elf_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
flagword old_flags;
flagword new_flags;
- boolean error;
+ bfd_boolean error;
- /* Check if we have the same endianess */
- if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
- return false;
+ /* Check if we have the same endianess. */
+ if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+ return FALSE;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
+ return TRUE;
new_flags = elf_elfheader (ibfd)->e_flags;
old_flags = elf_elfheader (obfd)->e_flags;
- if (!elf_flags_init (obfd)) /* First call, no flags set */
+ if (!elf_flags_init (obfd)) /* First call, no flags set. */
{
- elf_flags_init (obfd) = true;
+ elf_flags_init (obfd) = TRUE;
elf_elfheader (obfd)->e_flags = new_flags;
}
- else if (new_flags == old_flags) /* Compatible flags are ok */
+ else if (new_flags == old_flags) /* Compatible flags are ok. */
;
- else /* Incompatible flags */
+ else /* Incompatible flags. */
{
/* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked
with either. */
- error = false;
+ error = FALSE;
if ((new_flags & EF_PPC_RELOCATABLE) != 0
&& (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
{
- error = true;
+ error = TRUE;
(*_bfd_error_handler)
(_("%s: compiled with -mrelocatable and linked with modules compiled normally"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
}
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
&& (old_flags & EF_PPC_RELOCATABLE) != 0)
{
- error = true;
+ error = TRUE;
(*_bfd_error_handler)
(_("%s: compiled normally and linked with modules compiled with -mrelocatable"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
}
/* The output is -mrelocatable-lib iff both the input files are. */
&& (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)))
elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE;
- /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */
+ /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it. */
elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
- /* Warn about any other mismatches */
+ /* Warn about any other mismatches. */
if (new_flags != old_flags)
{
- error = true;
+ error = TRUE;
(*_bfd_error_handler)
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
- bfd_get_filename (ibfd), (long) new_flags, (long) old_flags);
+ bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
}
if (error)
{
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
}
- return true;
+ return TRUE;
}
\f
/* Handle a PowerPC specific section when reading an object file. This
is called when elfcode.h finds a section with an unknown type. */
-static boolean
+static bfd_boolean
ppc_elf_section_from_shdr (abfd, hdr, name)
bfd *abfd;
- Elf32_Internal_Shdr *hdr;
- char *name;
+ Elf_Internal_Shdr *hdr;
+ const char *name;
{
asection *newsect;
flagword flags;
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
- return false;
+ return FALSE;
newsect = hdr->bfd_section;
flags = bfd_get_section_flags (abfd, newsect);
flags |= SEC_SORT_ENTRIES;
bfd_set_section_flags (abfd, newsect, flags);
- return true;
+ return TRUE;
}
\f
/* Set up any other section flags and such that may be necessary. */
-static boolean
+static bfd_boolean
ppc_elf_fake_sections (abfd, shdr, asect)
bfd *abfd ATTRIBUTE_UNUSED;
- Elf32_Internal_Shdr *shdr;
+ Elf_Internal_Shdr *shdr;
asection *asect;
{
if ((asect->flags & SEC_EXCLUDE) != 0)
if ((asect->flags & SEC_SORT_ENTRIES) != 0)
shdr->sh_type = SHT_ORDERED;
- return true;
+ return TRUE;
}
\f
/* Create a special linker section */
bfd *dynobj = elf_hash_table (info)->dynobj;
elf_linker_section_t *lsect;
- /* Record the first bfd section that needs the special section */
+ /* Record the first bfd section that needs the special section. */
if (!dynobj)
dynobj = elf_hash_table (info)->dynobj = abfd;
- /* If this is the first time, create the section */
+ /* If this is the first time, create the section. */
lsect = elf_linker_section (dynobj, which);
if (!lsect)
{
defaults = zero_section;
defaults.which = which;
- defaults.hole_written_p = false;
+ defaults.hole_written_p = FALSE;
defaults.alignment = 2;
/* Both of these sections are (technically) created by the user
/* Modify the segment map if needed. */
-static boolean
+static bfd_boolean
ppc_elf_modify_segment_map (abfd)
bfd *abfd ATTRIBUTE_UNUSED;
{
- return true;
+ return TRUE;
}
\f
+/* The powerpc .got has a blrl instruction in it. Mark it executable. */
+
+static asection *
+ppc_elf_create_got (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ register asection *s;
+ flagword flags;
+
+ if (!_bfd_elf_create_got_section (abfd, info))
+ return NULL;
+
+ s = bfd_get_section_by_name (abfd, ".got");
+ if (s == NULL)
+ abort ();
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+ if (!bfd_set_section_flags (abfd, s, flags))
+ return NULL;
+ return s;
+}
+
/* We have to create .dynsbss and .rela.sbss here so that they get mapped
to output sections (just like _bfd_elf_create_dynamic_sections has
to create .dynbss and .rela.bss). */
-static boolean
+static bfd_boolean
ppc_elf_create_dynamic_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
register asection *s;
flagword flags;
+ if (!ppc_elf_create_got (abfd, info))
+ return FALSE;
+
if (!_bfd_elf_create_dynamic_sections (abfd, info))
- return false;
+ return FALSE;
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
s = bfd_make_section (abfd, ".dynsbss");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
- return false;
+ return FALSE;
if (! info->shared)
{
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, 2))
- return false;
+ return FALSE;
}
- return true;
+
+ s = bfd_get_section_by_name (abfd, ".plt");
+ if (s == NULL)
+ abort ();
+
+ flags = SEC_ALLOC | SEC_CODE | SEC_IN_MEMORY | SEC_LINKER_CREATED;
+ return bfd_set_section_flags (abfd, s, flags);
}
/* Adjust a symbol defined by a dynamic object and referenced by a
change the definition to something the rest of the link can
understand. */
-static boolean
+static bfd_boolean
ppc_elf_adjust_dynamic_symbol (info, h)
struct bfd_link_info *info;
struct elf_link_hash_entry *h;
all uses of the symbol, not just those to the GOT or PLT. */
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- return true;
+ return TRUE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
+ return FALSE;
}
BFD_ASSERT (h->dynindx != -1);
BFD_ASSERT (s != NULL);
s->_raw_size += sizeof (Elf32_External_Rela);
- return true;
+ return TRUE;
}
+ else
+ h->plt.offset = (bfd_vma) -1;
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
|| h->weakdef->root.type == bfd_link_hash_defweak);
h->root.u.def.section = h->weakdef->root.u.def.section;
h->root.u.def.value = h->weakdef->root.u.def.value;
- return true;
+ return TRUE;
}
/* This is a reference to a symbol defined by a dynamic object which
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
if (info->shared)
- return true;
+ return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
if (power_of_two > bfd_get_section_alignment (dynobj, s))
{
if (! bfd_set_section_alignment (dynobj, s, power_of_two))
- return false;
+ return FALSE;
}
/* Define the symbol as being at this point in the section. */
/* Increment the section size to make room for the symbol. */
s->_raw_size += h->size;
- return true;
+ return TRUE;
}
\f
+/* Allocate space in associated reloc sections for dynamic relocs. */
+
+static bfd_boolean
+allocate_dynrelocs (h, info)
+ struct elf_link_hash_entry *h;
+ PTR info ATTRIBUTE_UNUSED;
+{
+ struct ppc_elf_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ /* When warning symbols are created, they **replace** the "real"
+ entry in the hash table, thus we never get to see the real
+ symbol in a hash traversal. So look at it now. */
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *sreloc = elf_section_data (p->sec)->sreloc;
+ sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ }
+
+ return TRUE;
+}
+
+/* Find any dynamic relocs that apply to read-only sections. */
+
+static bfd_boolean
+readonly_dynrelocs (h, info)
+ struct elf_link_hash_entry *h;
+ PTR info;
+{
+ struct ppc_elf_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL
+ && ((s->flags & (SEC_READONLY | SEC_ALLOC))
+ == (SEC_READONLY | SEC_ALLOC)))
+ {
+ ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/* Set the sizes of the dynamic sections. */
-static boolean
+static bfd_boolean
ppc_elf_size_dynamic_sections (output_bfd, info)
bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
bfd *dynobj;
asection *s;
- boolean plt;
- boolean relocs;
+ bfd_boolean plt;
+ bfd_boolean relocs;
+ bfd *ibfd;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
}
}
+ /* Allocate space for local sym dynamic relocs. */
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ {
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ continue;
+
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ {
+ struct ppc_elf_dyn_relocs *p;
+
+ for (p = ((struct ppc_elf_dyn_relocs *)
+ elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
+ {
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else if (p->count != 0)
+ {
+ elf_section_data (p->sec)->sreloc->_raw_size
+ += p->count * sizeof (Elf32_External_Rela);
+ if ((p->sec->output_section->flags
+ & (SEC_READONLY | SEC_ALLOC))
+ == (SEC_READONLY | SEC_ALLOC))
+ info->flags |= DF_TEXTREL;
+ }
+ }
+ }
+ }
+
+ /* Allocate space for global sym dynamic relocs. */
+ elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, NULL);
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
- plt = false;
- relocs = false;
+ plt = FALSE;
+ relocs = FALSE;
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
- boolean strip;
+ bfd_boolean strip;
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
- strip = false;
+ strip = FALSE;
if (strcmp (name, ".plt") == 0)
{
{
/* Strip this section if we don't need it; see the
comment below. */
- strip = true;
+ strip = TRUE;
}
else
{
/* Remember whether there is a PLT. */
- plt = true;
+ plt = TRUE;
}
}
else if (strncmp (name, ".rela", 5) == 0)
adjust_dynamic_symbol is called, and it is that
function which decides whether anything needs to go
into these sections. */
- strip = true;
+ strip = TRUE;
}
else
{
/* Remember whether there are any relocation sections. */
- relocs = true;
+ relocs = TRUE;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
/* Allocate memory for the section contents. */
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
- return false;
+ return FALSE;
}
if (elf_hash_table (info)->dynamic_sections_created)
if (!info->shared)
{
if (!add_dynamic_entry (DT_DEBUG, 0))
- return false;
+ return FALSE;
}
if (plt)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
|| !add_dynamic_entry (DT_PLTREL, DT_RELA)
|| !add_dynamic_entry (DT_JMPREL, 0))
- return false;
+ return FALSE;
}
if (relocs)
if (!add_dynamic_entry (DT_RELA, 0)
|| !add_dynamic_entry (DT_RELASZ, 0)
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
- return false;
+ return FALSE;
}
+ /* If any dynamic relocs apply to a read-only section, then we
+ need a DT_TEXTREL entry. */
+ if ((info->flags & DF_TEXTREL) == 0)
+ elf_link_hash_traverse (elf_hash_table (info), readonly_dynrelocs,
+ (PTR) info);
+
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
- return false;
- info->flags |= DF_TEXTREL;
+ return FALSE;
}
}
#undef add_dynamic_entry
- return true;
+ return TRUE;
}
\f
/* Look through the relocs for a section during the first phase, and
allocate space in the global offset table or procedure linkage
table. */
-static boolean
+static bfd_boolean
ppc_elf_check_relocs (abfd, info, sec, relocs)
bfd *abfd;
struct bfd_link_info *info;
asection *srelgot = NULL;
if (info->relocateable)
- return true;
+ return TRUE;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n",
bfd_get_section_name (abfd, sec),
- bfd_get_filename (abfd));
+ bfd_archive_filename (abfd));
#endif
/* Create the linker generated sections all the time so that the
{
sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
if (!sdata)
- return false;
+ return FALSE;
}
if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL)
{
sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2);
if (!sdata2)
- return false;
+ return FALSE;
}
dynobj = elf_hash_table (info)->dynobj;
{
if (dynobj == NULL)
elf_hash_table (info)->dynobj = dynobj = abfd;
- if (! _bfd_elf_create_got_section (dynobj, info))
- return false;
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
+ sgot = ppc_elf_create_got (dynobj, info);
+ if (sgot == NULL)
+ return FALSE;
}
}
{
if (dynobj == NULL)
elf_hash_table (info)->dynobj = dynobj = abfd;
- if (! _bfd_elf_create_got_section (dynobj, info))
- return false;
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
+ sgot = ppc_elf_create_got (dynobj, info);
+ if (sgot == NULL)
+ return FALSE;
}
if (srelgot == NULL
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
- return false;
+ return FALSE;
}
}
if (h != NULL)
{
- if (h->got.refcount == -1)
+ if (h->got.refcount == 0)
{
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
if (!bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
+ return FALSE;
/* Allocate space in the .got. */
sgot->_raw_size += 4;
/* Allocate relocation space. */
srelgot->_raw_size += sizeof (Elf32_External_Rela);
-
- h->got.refcount = 1;
}
- else
- h->got.refcount++;
+ h->got.refcount++;
}
else
{
size = symtab_hdr->sh_info;
size *= sizeof (bfd_signed_vma);
local_got_refcounts
- = (bfd_signed_vma *) bfd_alloc (abfd, size);
+ = (bfd_signed_vma *) bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
- return false;
+ return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
- memset (local_got_refcounts, -1, (size_t) size);
}
- if (local_got_refcounts[r_symndx] == -1)
+ if (local_got_refcounts[r_symndx] == 0)
{
sgot->_raw_size += 4;
dynamic linker can adjust this GOT entry. */
if (info->shared)
srelgot->_raw_size += sizeof (Elf32_External_Rela);
-
- local_got_refcounts[r_symndx] = 1;
}
- else
- local_got_refcounts[r_symndx]++;
+ local_got_refcounts[r_symndx]++;
}
break;
- /* Indirect .sdata relocation */
+ /* Indirect .sdata relocation. */
case R_PPC_EMB_SDAI16:
if (info->shared)
{
((*_bfd_error_handler)
(_("%s: relocation %s cannot be used when making a shared object"),
- bfd_get_filename (abfd), "R_PPC_EMB_SDAI16"));
- return false;
+ bfd_archive_filename (abfd), "R_PPC_EMB_SDAI16"));
+ return FALSE;
}
if (srelgot == NULL && (h != NULL || info->shared))
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
- return false;
+ return FALSE;
}
}
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel))
- return false;
+ return FALSE;
break;
- /* Indirect .sdata2 relocation */
+ /* Indirect .sdata2 relocation. */
case R_PPC_EMB_SDA2I16:
if (info->shared)
{
((*_bfd_error_handler)
(_("%s: relocation %s cannot be used when making a shared object"),
- bfd_get_filename (abfd), "R_PPC_EMB_SDA2I16"));
- return false;
+ bfd_archive_filename (abfd), "R_PPC_EMB_SDA2I16"));
+ return FALSE;
}
if (srelgot == NULL && (h != NULL || info->shared))
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
- return false;
+ return FALSE;
}
}
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel))
- return false;
+ return FALSE;
break;
{
((*_bfd_error_handler)
(_("%s: relocation %s cannot be used when making a shared object"),
- bfd_get_filename (abfd),
+ bfd_archive_filename (abfd),
ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name));
- return false;
+ return FALSE;
}
break;
/* It does not make sense to have a procedure linkage
table entry for a local symbol. */
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
- if (h->plt.refcount == -1)
- {
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->plt.refcount = 1;
+ return FALSE;
}
- else
- h->plt.refcount++;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->plt.refcount++;
break;
/* The following relocations don't need to propagate the
case R_PPC_SECTOFF_HA:
break;
- /* This refers only to functions defined in the shared library */
+ /* This refers only to functions defined in the shared library. */
case R_PPC_LOCAL24PC:
break;
Reconstruct it for later use during GC. */
case R_PPC_GNU_VTINHERIT:
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return false;
+ return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_PPC_GNU_VTENTRY:
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return false;
+ return FALSE;
break;
/* When creating a shared object, we must copy these
default:
if (info->shared)
{
+ struct ppc_elf_dyn_relocs *p;
+ struct ppc_elf_dyn_relocs **head;
+
#ifdef DEBUG
fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n",
(h && h->root.root.string) ? h->root.root.string : "<unknown>");
elf_elfheader (abfd)->e_shstrndx,
elf_section_data (sec)->rel_hdr.sh_name));
if (name == NULL)
- return false;
+ return FALSE;
BFD_ASSERT (strncmp (name, ".rela", 5) == 0
&& strcmp (bfd_get_section_name (abfd, sec),
if (sreloc == NULL
|| ! bfd_set_section_flags (dynobj, sreloc, flags)
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
- return false;
+ return FALSE;
}
- if (sec->flags & SEC_READONLY)
- info->flags |= DF_TEXTREL;
+ elf_section_data (sec)->sreloc = sreloc;
+ }
+
+ /* If this is a global symbol, we count the number of
+ relocations we need for this symbol. */
+ if (h != NULL)
+ {
+ head = &ppc_elf_hash_entry (h)->dyn_relocs;
+ }
+ else
+ {
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = (bfd_section_from_r_symndx
+ (abfd, &ppc_elf_hash_table (info)->sym_sec,
+ sec, r_symndx));
+ if (s == NULL)
+ return FALSE;
+
+ head = ((struct ppc_elf_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
}
- sreloc->_raw_size += sizeof (Elf32_External_Rela);
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ p = ((struct ppc_elf_dyn_relocs *)
+ bfd_alloc (elf_hash_table (info)->dynobj, sizeof *p));
+ if (p == NULL)
+ return FALSE;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ }
- /* FIXME: We should here do what the m68k and i386
- backends do: if the reloc is pc-relative, record it
- in case it turns out that the reloc is unnecessary
- because the symbol is forced local by versioning or
- we are linking with -Bdynamic. Fortunately this
- case is not frequent. */
+ p->count++;
}
break;
}
}
- return true;
+ return TRUE;
}
/* Return the section that should be marked against GC for a given
relocation. */
static asection *
-ppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+ppc_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- if (!(elf_bad_symtab (abfd)
- && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
- && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
- && sym->st_shndx != SHN_COMMON))
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* Update the got entry reference counts for the section being removed. */
-static boolean
+static bfd_boolean
ppc_elf_gc_sweep_hook (abfd, info, sec, relocs)
bfd *abfd;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
+ elf_section_data (sec)->local_dynrel = NULL;
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
if (h->plt.refcount > 0)
h->plt.refcount--;
}
- break;
+ /* Fall through */
default:
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ struct ppc_elf_dyn_relocs **pp, *p;
+
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ for (pp = &ppc_elf_hash_entry (h)->dyn_relocs;
+ (p = *pp) != NULL;
+ pp = &p->next)
+ if (p->sec == sec)
+ {
+ if (--p->count == 0)
+ *pp = p->next;
+ break;
+ }
+ }
break;
}
- return true;
+ return TRUE;
}
\f
/* Hook called by the linker routine which adds symbols from an object
file. We use it to put .comm items in .sbss, and not .bss. */
-static boolean
+static bfd_boolean
ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
bfd *abfd;
struct bfd_link_info *info;
{
if (sym->st_shndx == SHN_COMMON
&& !info->relocateable
- && sym->st_size <= elf_gp_size (abfd))
+ && sym->st_size <= elf_gp_size (abfd)
+ && info->hash->creator->flavour == bfd_target_elf_flavour)
{
/* Common symbols less than or equal to -G nn bytes are automatically
put into .sdata. */
amt = sizeof (asection);
sdata->bss_section = (asection *) bfd_zalloc (abfd, amt);
if (sdata->bss_section == NULL)
- return false;
+ return FALSE;
sdata->bss_section->name = sdata->bss_name;
sdata->bss_section->flags = SEC_IS_COMMON;
sdata->bss_section->output_section = sdata->bss_section;
(asymbol **) bfd_zalloc (abfd, amt);
if (sdata->bss_section->symbol == NULL
|| sdata->bss_section->symbol_ptr_ptr == NULL)
- return false;
+ return FALSE;
sdata->bss_section->symbol->name = sdata->bss_name;
sdata->bss_section->symbol->flags = BSF_SECTION_SYM;
sdata->bss_section->symbol->section = sdata->bss_section;
*valp = sym->st_size;
}
- return true;
+ return TRUE;
}
\f
/* Finish up dynamic symbol handling. We set the contents of various
dynamic sections here. */
-static boolean
+static bfd_boolean
ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
bfd *output_bfd;
struct bfd_link_info *info;
asection *splt;
asection *srela;
Elf_Internal_Rela rela;
+ bfd_byte *loc;
bfd_vma reloc_index;
#ifdef DEBUG
reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE;
if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
- bfd_elf32_swap_reloca_out (output_bfd, &rela,
- ((Elf32_External_Rela *) srela->contents
- + reloc_index));
+ loc = srela->contents + reloc_index * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
asection *sgot;
asection *srela;
Elf_Internal_Rela rela;
+ bfd_byte *loc;
/* This symbol has an entry in the global offset table. Set it
up. */
else
{
BFD_ASSERT ((h->got.offset & 1) == 0);
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT);
rela.r_addend = 0;
}
- bfd_elf32_swap_reloca_out (output_bfd, &rela,
- ((Elf32_External_Rela *) srela->contents
- + srela->reloc_count));
- ++srela->reloc_count;
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+ loc = srela->contents;
+ loc += srela->reloc_count++ * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
{
asection *s;
Elf_Internal_Rela rela;
+ bfd_byte *loc;
/* This symbols needs a copy reloc. Set it up. */
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
rela.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &rela,
- ((Elf32_External_Rela *) s->contents
- + s->reloc_count));
- ++s->reloc_count;
+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
#ifdef DEBUG
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
sym->st_shndx = SHN_ABS;
- return true;
+ return TRUE;
}
\f
/* Finish up the dynamic sections. */
-static boolean
+static bfd_boolean
ppc_elf_finish_dynamic_sections (output_bfd, info)
bfd *output_bfd;
struct bfd_link_info *info;
{
Elf_Internal_Dyn dyn;
const char *name;
- boolean size;
+ bfd_boolean size;
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
switch (dyn.d_tag)
{
- case DT_PLTGOT: name = ".plt"; size = false; break;
- case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
- case DT_JMPREL: name = ".rela.plt"; size = false; break;
- default: name = NULL; size = false; break;
+ case DT_PLTGOT: name = ".plt"; size = FALSE; break;
+ case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
+ case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
+ default: name = NULL; size = FALSE; break;
}
if (name != NULL)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
}
- return true;
+ return TRUE;
}
\f
/* The RELOCATE_SECTION function is called by the ELF backend linker
section, which means that the addend must be adjusted
accordingly. */
-static boolean
+static bfd_boolean
ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
contents, relocs, local_syms, local_sections)
bfd *output_bfd;
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
- Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
- bfd *dynobj = elf_hash_table (info)->dynobj;
- elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL;
- elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
- Elf_Internal_Rela *rel = relocs;
- Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
- asection *sreloc = NULL;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *sdata = NULL;
+ elf_linker_section_t *sdata2 = NULL;
+ Elf_Internal_Rela *rel = relocs;
+ Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
+ asection *sreloc = NULL;
asection *splt;
asection *sgot;
bfd_vma *local_got_offsets;
- boolean ret = true;
+ bfd_boolean ret = TRUE;
long insn;
+ if (dynobj)
+ {
+ sdata = elf_linker_section (dynobj, LINKER_SECTION_SDATA);
+ sdata2 = elf_linker_section (dynobj, LINKER_SECTION_SDATA2);
+ }
+
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n",
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
bfd_section_name(input_bfd, input_section),
(long) input_section->reloc_count,
(info->relocateable) ? " (relocatable)" : "");
#endif
+ if (info->relocateable)
+ return TRUE;
+
if (!ppc_elf_howto_table[R_PPC_ADDR32])
/* Initialize howto table if needed. */
ppc_elf_howto_init ();
|| !ppc_elf_howto_table[(int) r_type])
{
(*_bfd_error_handler) (_("%s: unknown relocation type %d"),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
(int) r_type);
bfd_set_error (bfd_error_bad_value);
- ret = false;
+ ret = FALSE;
continue;
}
howto = ppc_elf_howto_table[(int) r_type];
r_symndx = ELF32_R_SYM (rel->r_info);
- if (info->relocateable)
- {
- /* This is a relocateable link. We don't have to change
- anything, unless the reloc is against a section symbol,
- in which case we have to adjust according to where the
- section symbol winds up in the output section. */
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- sec = local_sections[r_symndx];
- addend = rel->r_addend += sec->output_offset + sym->st_value;
- }
- }
-
-#ifdef DEBUG
- fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
- howto->name,
- (int) r_type,
- r_symndx,
- (long) offset,
- (long) addend);
-#endif
- continue;
- }
-
- /* This is a final link. */
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
sym_name = "<local symbol>";
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ addend = rel->r_addend;
/* Relocs to local symbols are always resolved. */
will_become_local = 1;
}
{
(*_bfd_error_handler)
(_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
- bfd_get_filename (input_bfd), h->root.root.string,
+ bfd_archive_filename (input_bfd), h->root.root.string,
bfd_get_section_name (input_bfd, input_section));
relocation = 0;
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
else if (info->shared
- && (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
(!info->shared
|| info->no_undefined
|| ELF_ST_VISIBILITY (h->other))))
- return false;
+ return FALSE;
relocation = 0;
}
}
{
default:
(*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
(int) r_type, sym_name);
bfd_set_error (bfd_error_bad_value);
- ret = false;
+ ret = FALSE;
+ continue;
+
+ case (int) R_PPC_NONE:
continue;
/* Relocations that need no special processing. */
input_bfd,
input_section,
rel->r_offset,
- true))
- return false;
+ TRUE))
+ return FALSE;
continue;
}
break;
/* Relocations that always need to be propagated if this is a shared
object. */
- case (int) R_PPC_NONE:
case (int) R_PPC_ADDR32:
case (int) R_PPC_ADDR24:
case (int) R_PPC_ADDR16:
case (int) R_PPC_ADDR14:
case (int) R_PPC_UADDR32:
case (int) R_PPC_UADDR16:
- if (info->shared)
+ if (info->shared && r_symndx != 0)
{
Elf_Internal_Rela outrel;
- boolean skip;
+ bfd_byte *loc;
+ int skip;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n",
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
-
if (sreloc == NULL)
{
const char *name;
elf_elfheader (input_bfd)->e_shstrndx,
elf_section_data (input_section)->rel_hdr.sh_name));
if (name == NULL)
- return false;
+ return FALSE;
BFD_ASSERT (strncmp (name, ".rela", 5) == 0
&& strcmp (bfd_get_section_name (input_bfd,
BFD_ASSERT (sreloc != NULL);
}
- skip = false;
-
- if (elf_section_data (input_section)->stab_info == NULL)
- outrel.r_offset = rel->r_offset;
- else
- {
- bfd_vma off;
-
- off = (_bfd_stab_section_offset
- (output_bfd, &elf_hash_table (info)->stab_info,
- input_section,
- &elf_section_data (input_section)->stab_info,
- rel->r_offset));
- if (off == (bfd_vma) -1)
- skip = true;
- outrel.r_offset = off;
- }
+ skip = 0;
+ outrel.r_offset =
+ _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset);
+ if (outrel.r_offset == (bfd_vma) -1
+ || outrel.r_offset == (bfd_vma) -2)
+ skip = (int) outrel.r_offset;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
}
else
{
+ outrel.r_addend = relocation + rel->r_addend;
+
if (r_type == R_PPC_ADDR32)
- {
- outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
- outrel.r_addend = relocation + rel->r_addend;
- }
+ outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
else
{
long indx;
== bfd_link_hash_defweak));
sec = h->root.u.def.section;
}
- if (sec != NULL && bfd_is_abs_section (sec))
+
+ if (bfd_is_abs_section (sec))
indx = 0;
else if (sec == NULL || sec->owner == NULL)
{
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
else
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
BFD_ASSERT (indx > 0);
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
}
}
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- (((Elf32_External_Rela *)
- sreloc->contents)
- + sreloc->reloc_count));
- ++sreloc->reloc_count;
-
- /* This reloc will be computed at runtime, so there's no
- need to do anything now, unless this is a RELATIVE
- reloc in an unallocated section. */
- if (skip
- || (input_section->flags & SEC_ALLOC) != 0
- || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)
+ loc = sreloc->contents;
+ loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+
+ if (skip == -1)
continue;
+
+ /* This reloc will be computed at runtime. We clear the memory
+ so that it contains predictable value. */
+ if (! skip
+ && ((input_section->flags & SEC_ALLOC) != 0
+ || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE))
+ {
+ relocation = howto->pc_relative ? outrel.r_offset : 0;
+ addend = 0;
+ break;
+ }
}
/* Arithmetic adjust relocations that aren't going into a
}
break;
- /* branch taken prediction relocations */
+ /* Branch taken prediction relocations. */
case (int) R_PPC_ADDR14_BRTAKEN:
case (int) R_PPC_REL14_BRTAKEN:
insn = bfd_get_32 (output_bfd, contents + offset);
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
break;
- /* branch not taken predicition relocations */
+ /* Branch not taken predicition relocations. */
case (int) R_PPC_ADDR14_BRNTAKEN:
case (int) R_PPC_REL14_BRNTAKEN:
insn = bfd_get_32 (output_bfd, contents + offset);
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
break;
- /* GOT16 relocations */
+ /* GOT16 relocations. */
case (int) R_PPC_GOT16:
case (int) R_PPC_GOT16_LO:
case (int) R_PPC_GOT16_HI:
off &= ~1;
else
{
- bfd_put_32 (output_bfd, relocation, sgot->contents + off);
if (info->shared)
{
asection *srelgot;
Elf_Internal_Rela outrel;
+ bfd_byte *loc;
/* We need to generate a R_PPC_RELATIVE reloc
for the dynamic linker. */
+ off);
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
outrel.r_addend = relocation;
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- (((Elf32_External_Rela *)
- srelgot->contents)
- + srelgot->reloc_count));
- ++srelgot->reloc_count;
+ loc = srelgot->contents;
+ loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+ relocation = 0;
}
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
local_got_offsets[r_symndx] |= 1;
}
relocation = sgot->output_offset + off - 4;
}
+ if (r_type == R_PPC_GOT16_HA)
+ addend += ((relocation + addend) & 0x8000) << 1;
break;
- /* Indirect .sdata relocation */
+ /* Indirect .sdata relocation. */
case (int) R_PPC_EMB_SDAI16:
BFD_ASSERT (sdata != NULL);
relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
R_PPC_RELATIVE);
break;
- /* Indirect .sdata2 relocation */
+ /* Indirect .sdata2 relocation. */
case (int) R_PPC_EMB_SDA2I16:
BFD_ASSERT (sdata2 != NULL);
relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
+ h->plt.offset);
break;
- /* relocate against _SDA_BASE_ */
+ /* Relocate against _SDA_BASE_. */
case (int) R_PPC_SDAREL16:
{
const char *name;
BFD_ASSERT (sec != (asection *) 0);
name = bfd_get_section_name (abfd, sec->output_section);
- if (strcmp (name, ".sdata") != 0
- && strcmp (name, ".sbss") != 0)
+ if (! ((strncmp (name, ".sdata", 6) == 0
+ && (name[6] == 0 || name[6] == '.'))
+ || (strncmp (name, ".sbss", 5) == 0
+ && (name[5] == 0 || name[5] == '.'))))
{
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
sym_name,
ppc_elf_howto_table[(int) r_type]->name,
name);
BFD_ASSERT (sec != (asection *) 0);
name = bfd_get_section_name (abfd, sec->output_section);
- if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0)
+ if (! (strncmp (name, ".sdata2", 7) == 0
+ || strncmp (name, ".sbss2", 6) == 0))
{
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
sym_name,
ppc_elf_howto_table[(int) r_type]->name,
name);
bfd_set_error (bfd_error_bad_value);
- ret = false;
+ ret = FALSE;
continue;
}
addend -= (sdata2->sym_hash->root.u.def.value
}
break;
- /* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */
+ /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
case (int) R_PPC_EMB_SDA21:
case (int) R_PPC_EMB_RELSDA:
{
BFD_ASSERT (sec != (asection *) 0);
name = bfd_get_section_name (abfd, sec->output_section);
- if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
+ if (((strncmp (name, ".sdata", 6) == 0
+ && (name[6] == 0 || name[6] == '.'))
+ || (strncmp (name, ".sbss", 5) == 0
+ && (name[5] == 0 || name[5] == '.'))))
{
reg = 13;
addend -= (sdata->sym_hash->root.u.def.value
+ sdata->sym_hash->root.u.def.section->output_offset);
}
- else if (strcmp (name, ".sdata2") == 0
- || strcmp (name, ".sbss2") == 0)
+ else if (strncmp (name, ".sdata2", 7) == 0
+ || strncmp (name, ".sbss2", 6) == 0)
{
reg = 2;
addend -= (sdata2->sym_hash->root.u.def.value
else
{
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
sym_name,
ppc_elf_howto_table[(int) r_type]->name,
name);
bfd_set_error (bfd_error_bad_value);
- ret = false;
+ ret = FALSE;
continue;
}
}
break;
- /* Relocate against the beginning of the section */
+ /* Relocate against the beginning of the section. */
case (int) R_PPC_SECTOFF:
case (int) R_PPC_SECTOFF_LO:
case (int) R_PPC_SECTOFF_HI:
case (int) R_PPC_EMB_RELST_HA:
case (int) R_PPC_EMB_BIT_FLD:
(*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."),
- bfd_get_filename (input_bfd),
+ bfd_archive_filename (input_bfd),
ppc_elf_howto_table[(int) r_type]->name,
sym_name);
bfd_set_error (bfd_error_invalid_operation);
- ret = false;
+ ret = FALSE;
continue;
case (int) R_PPC_GNU_VTINHERIT:
input_bfd,
input_section,
offset))
- return false;
+ return FALSE;
}
else
- ret = false;
+ ret = FALSE;
}
#ifdef DEBUG
}
static enum elf_reloc_type_class
-ppc_elf_reloc_type_class (type)
- int type;
+ppc_elf_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
{
- switch (type)
+ switch ((int) ELF32_R_TYPE (rela->r_info))
{
case R_PPC_RELATIVE:
return reloc_class_relative;
}
}
\f
-/* Support for core dump NOTE sections */
-static boolean
+/* Support for core dump NOTE sections. */
+
+static bfd_boolean
ppc_elf_grok_prstatus (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
switch (note->descsz)
{
default:
- return false;
+ return FALSE;
- case 268: /* Linux/PPC */
+ case 268: /* Linux/PPC. */
/* pr_cursig */
elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
raw_size, note->descpos + offset);
}
-static boolean
+static bfd_boolean
ppc_elf_grok_psinfo (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
switch (note->descsz)
{
default:
- return false;
+ return FALSE;
- case 128: /* Linux/PPC elf_prpsinfo */
+ case 128: /* Linux/PPC elf_prpsinfo. */
elf_tdata (abfd)->core_program
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
elf_tdata (abfd)->core_command
command[n - 1] = '\0';
}
- return true;
+ return TRUE;
+}
+\f
+/* Very simple linked list structure for recording apuinfo values. */
+typedef struct apuinfo_list
+{
+ struct apuinfo_list * next;
+ unsigned long value;
+}
+apuinfo_list;
+
+static apuinfo_list * head;
+
+static void apuinfo_list_init PARAMS ((void));
+static void apuinfo_list_add PARAMS ((unsigned long));
+static unsigned apuinfo_list_length PARAMS ((void));
+static unsigned long apuinfo_list_element PARAMS ((unsigned long));
+static void apuinfo_list_finish PARAMS ((void));
+
+extern void ppc_elf_begin_write_processing
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern void ppc_elf_final_write_processing
+ PARAMS ((bfd *, bfd_boolean));
+extern bfd_boolean ppc_elf_write_section
+ PARAMS ((bfd *, asection *, bfd_byte *));
+
+
+
+static void
+apuinfo_list_init PARAMS ((void))
+{
+ head = NULL;
+}
+
+static void
+apuinfo_list_add (value)
+ unsigned long value;
+{
+ apuinfo_list * entry = head;
+
+ while (entry != NULL)
+ {
+ if (entry->value == value)
+ return;
+ entry = entry->next;
+ }
+
+ entry = bfd_malloc (sizeof (* entry));
+ if (entry == NULL)
+ return;
+
+ entry->value = value;
+ entry->next = head;
+ head = entry;
+}
+
+static unsigned
+apuinfo_list_length PARAMS ((void))
+{
+ apuinfo_list * entry;
+ unsigned long count;
+
+ for (entry = head, count = 0;
+ entry;
+ entry = entry->next)
+ ++ count;
+
+ return count;
+}
+
+static inline unsigned long
+apuinfo_list_element (number)
+ unsigned long number;
+{
+ apuinfo_list * entry;
+
+ for (entry = head;
+ entry && number --;
+ entry = entry->next)
+ ;
+
+ return entry ? entry->value : 0;
+}
+
+static void
+apuinfo_list_finish PARAMS ((void))
+{
+ apuinfo_list * entry;
+
+ for (entry = head; entry;)
+ {
+ apuinfo_list * next = entry->next;
+ free (entry);
+ entry = next;
+ }
+
+ head = NULL;
+}
+
+#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo"
+#define APUINFO_LABEL "APUinfo"
+
+/* Scan the input BFDs and create a linked list of
+ the APUinfo values that will need to be emitted. */
+
+void
+ppc_elf_begin_write_processing (abfd, link_info)
+ bfd *abfd;
+ struct bfd_link_info *link_info;
+{
+ bfd * ibfd;
+ asection * asec;
+ char * buffer;
+ unsigned num_input_sections;
+ bfd_size_type output_section_size;
+ unsigned i;
+ unsigned num_entries;
+ unsigned long offset;
+ unsigned long length;
+ const char * error_message = NULL;
+
+ if (link_info == NULL)
+ return;
+
+ /* Scan the input bfds, looking for apuinfo sections. */
+ num_input_sections = 0;
+ output_section_size = 0;
+
+ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
+ {
+ asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
+ if (asec)
+ {
+ ++ num_input_sections;
+ output_section_size += asec->_raw_size;
+ }
+ }
+
+ /* We need at least one input sections
+ in order to make merging worthwhile. */
+ if (num_input_sections < 1)
+ return;
+
+ /* Just make sure that the output section exists as well. */
+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+ if (asec == NULL)
+ return;
+
+ /* Allocate a buffer for the contents of the input sections. */
+ buffer = bfd_malloc (output_section_size);
+ if (buffer == NULL)
+ return;
+
+ offset = 0;
+ apuinfo_list_init ();
+
+ /* Read in the input sections contents. */
+ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
+ {
+ unsigned long datum;
+ char * ptr;
+
+
+ asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
+ if (asec == NULL)
+ continue;
+
+ length = asec->_raw_size;
+ if (length < 24)
+ {
+ error_message = _("corrupt or empty %s section in %s");
+ goto fail;
+ }
+
+ if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
+ || (bfd_bread (buffer + offset, length, ibfd) != length))
+ {
+ error_message = _("unable to read in %s section from %s");
+ goto fail;
+ }
+
+ /* Process the contents of the section. */
+ ptr = buffer + offset;
+ error_message = _("corrupt %s section in %s");
+
+ /* Verify the contents of the header. Note - we have to
+ extract the values this way in order to allow for a
+ host whose endian-ness is different from the target. */
+ datum = bfd_get_32 (ibfd, ptr);
+ if (datum != sizeof APUINFO_LABEL)
+ goto fail;
+
+ datum = bfd_get_32 (ibfd, ptr + 8);
+ if (datum != 0x2)
+ goto fail;
+
+ if (strcmp (ptr + 12, APUINFO_LABEL) != 0)
+ goto fail;
+
+ /* Get the number of apuinfo entries. */
+ datum = bfd_get_32 (ibfd, ptr + 4);
+ if ((datum * 4 + 20) != length)
+ goto fail;
+
+ /* Make sure that we do not run off the end of the section. */
+ if (offset + length > output_section_size)
+ goto fail;
+
+ /* Scan the apuinfo section, building a list of apuinfo numbers. */
+ for (i = 0; i < datum; i++)
+ apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + (i * 4)));
+
+ /* Update the offset. */
+ offset += length;
+ }
+
+ error_message = NULL;
+
+ /* Compute the size of the output section. */
+ num_entries = apuinfo_list_length ();
+ output_section_size = 20 + num_entries * 4;
+
+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+
+ if (! bfd_set_section_size (abfd, asec, output_section_size))
+ ibfd = abfd,
+ error_message = _("warning: unable to set size of %s section in %s");
+
+ fail:
+ free (buffer);
+
+ if (error_message)
+ _bfd_error_handler (error_message, APUINFO_SECTION_NAME,
+ bfd_archive_filename (ibfd));
+}
+
+
+/* Prevent the output section from accumulating the input sections'
+ contents. We have already stored this in our linked list structure. */
+
+bfd_boolean
+ppc_elf_write_section (abfd, asec, contents)
+ bfd * abfd ATTRIBUTE_UNUSED;
+ asection * asec;
+ bfd_byte * contents ATTRIBUTE_UNUSED;
+{
+ return apuinfo_list_length () && strcmp (asec->name, APUINFO_SECTION_NAME) == 0;
+}
+
+
+/* Finally we can generate the output section. */
+
+void
+ppc_elf_final_write_processing (abfd, linker)
+ bfd * abfd;
+ bfd_boolean linker ATTRIBUTE_UNUSED;
+{
+ bfd_byte * buffer;
+ asection * asec;
+ unsigned i;
+ unsigned num_entries;
+ bfd_size_type length;
+
+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+ if (asec == NULL)
+ return;
+
+ if (apuinfo_list_length () == 0)
+ return;
+
+ length = asec->_raw_size;
+ if (length < 20)
+ return;
+
+ buffer = bfd_malloc (length);
+ if (buffer == NULL)
+ {
+ _bfd_error_handler (_("failed to allocate space for new APUinfo section."));
+ return;
+ }
+
+ /* Create the apuinfo header. */
+ num_entries = apuinfo_list_length ();
+ bfd_put_32 (abfd, sizeof APUINFO_LABEL, buffer);
+ bfd_put_32 (abfd, num_entries, buffer + 4);
+ bfd_put_32 (abfd, 0x2, buffer + 8);
+ strcpy (buffer + 12, APUINFO_LABEL);
+
+ length = 20;
+ for (i = 0; i < num_entries; i++)
+ {
+ bfd_put_32 (abfd, apuinfo_list_element (i), buffer + length);
+ length += 4;
+ }
+
+ if (length != asec->_raw_size)
+ _bfd_error_handler (_("failed to compute new APUinfo section."));
+
+ if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length))
+ _bfd_error_handler (_("failed to install new APUinfo section."));
+
+ free (buffer);
+
+ apuinfo_list_finish ();
}
\f
#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec
#define elf_backend_plt_not_loaded 1
#define elf_backend_got_symbol_offset 4
#define elf_backend_can_gc_sections 1
+#define elf_backend_can_refcount 1
#define elf_backend_got_header_size 12
#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE
+#define elf_backend_rela_normal 1
-#define bfd_elf32_bfd_copy_private_bfd_data ppc_elf_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data
#define bfd_elf32_bfd_relax_section ppc_elf_relax_section
#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup
#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags
#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link
+#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create
+#define elf_backend_object_p ppc_elf_object_p
#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook
#define elf_backend_section_from_shdr ppc_elf_section_from_shdr
#define elf_backend_relocate_section ppc_elf_relocate_section
#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections
#define elf_backend_check_relocs ppc_elf_check_relocs
+#define elf_backend_copy_indirect_symbol ppc_elf_copy_indirect_symbol
#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol
#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook
#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class
+#define elf_backend_begin_write_processing ppc_elf_begin_write_processing
+#define elf_backend_final_write_processing ppc_elf_final_write_processing
+#define elf_backend_write_section ppc_elf_write_section
#include "elf32-target.h"