aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-xtensa.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-xtensa.c')
-rw-r--r--bfd/elf32-xtensa.c1745
1 files changed, 953 insertions, 792 deletions
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 7a41d6285771..a8ec37e5298d 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -1,5 +1,5 @@
/* Xtensa-specific support for 32-bit ELF.
- Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -18,8 +18,8 @@
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include <stdarg.h>
#include <strings.h>
@@ -35,7 +35,7 @@
/* Local helper functions. */
-static bfd_boolean add_extra_plt_sections (bfd *, int);
+static bfd_boolean add_extra_plt_sections (struct bfd_link_info *, int);
static char *vsprint_msg (const char *, const char *, int, ...) ATTRIBUTE_PRINTF(2,4);
static bfd_reloc_status_type bfd_elf_xtensa_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
@@ -94,8 +94,8 @@ static Elf_Internal_Sym *retrieve_local_syms (bfd *);
/* Miscellaneous utility functions. */
-static asection *elf_xtensa_get_plt_section (bfd *, int);
-static asection *elf_xtensa_get_gotplt_section (bfd *, int);
+static asection *elf_xtensa_get_plt_section (struct bfd_link_info *, int);
+static asection *elf_xtensa_get_gotplt_section (struct bfd_link_info *, int);
static asection *get_elf_r_symndx_section (bfd *, unsigned long);
static struct elf_link_hash_entry *get_elf_r_symndx_hash_entry
(bfd *, unsigned long);
@@ -103,10 +103,12 @@ static bfd_vma get_elf_r_symndx_offset (bfd *, unsigned long);
static bfd_boolean is_reloc_sym_weak (bfd *, Elf_Internal_Rela *);
static bfd_boolean pcrel_reloc_fits (xtensa_opcode, int, bfd_vma, bfd_vma);
static bfd_boolean xtensa_is_property_section (asection *);
+static bfd_boolean xtensa_is_insntable_section (asection *);
static bfd_boolean xtensa_is_littable_section (asection *);
+static bfd_boolean xtensa_is_proptable_section (asection *);
static int internal_reloc_compare (const void *, const void *);
static int internal_reloc_matches (const void *, const void *);
-extern char *xtensa_get_property_section_name (asection *, const char *);
+extern asection *xtensa_get_property_section (asection *, const char *);
static flagword xtensa_get_property_predef_flags (asection *);
/* Other functions called directly by the linker. */
@@ -132,16 +134,6 @@ int elf32xtensa_size_opt;
typedef struct xtensa_relax_info_struct xtensa_relax_info;
-/* Total count of PLT relocations seen during check_relocs.
- The actual PLT code must be split into multiple sections and all
- the sections have to be created before size_dynamic_sections,
- where we figure out the exact number of PLT entries that will be
- needed. It is OK if this count is an overestimate, e.g., some
- relocations may be removed by GC. */
-
-static int plt_reloc_count = 0;
-
-
/* The GNU tools do not easily allow extending interfaces to pass around
the pointer to the Xtensa ISA information, so instead we add a global
variable here (in BFD) that can be used by any of the tools that need
@@ -166,163 +158,132 @@ static reloc_howto_type elf_howto_table[] =
{
HOWTO (R_XTENSA_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_xtensa_reloc, "R_XTENSA_NONE",
- FALSE, 0x00000000, 0x00000000, FALSE),
+ FALSE, 0, 0, FALSE),
HOWTO (R_XTENSA_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_xtensa_reloc, "R_XTENSA_32",
TRUE, 0xffffffff, 0xffffffff, FALSE),
+
/* Replace a 32-bit value with a value from the runtime linker (only
used by linker-generated stub functions). The r_addend value is
special: 1 means to substitute a pointer to the runtime linker's
dynamic resolver function; 2 means to substitute the link map for
the shared object. */
HOWTO (R_XTENSA_RTLD, 0, 2, 32, FALSE, 0, complain_overflow_dont,
- NULL, "R_XTENSA_RTLD",
- FALSE, 0x00000000, 0x00000000, FALSE),
+ NULL, "R_XTENSA_RTLD", FALSE, 0, 0, FALSE),
+
HOWTO (R_XTENSA_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_XTENSA_GLOB_DAT",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ FALSE, 0, 0xffffffff, FALSE),
HOWTO (R_XTENSA_JMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_XTENSA_JMP_SLOT",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ FALSE, 0, 0xffffffff, FALSE),
HOWTO (R_XTENSA_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_XTENSA_RELATIVE",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ FALSE, 0, 0xffffffff, FALSE),
HOWTO (R_XTENSA_PLT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_xtensa_reloc, "R_XTENSA_PLT",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ FALSE, 0, 0xffffffff, FALSE),
+
EMPTY_HOWTO (7),
+
+ /* Old relocations for backward compatibility. */
HOWTO (R_XTENSA_OP0, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_OP0",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_OP0", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_OP1, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_OP1",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_OP1", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_OP2, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_OP2",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_OP2", FALSE, 0, 0, TRUE),
+
/* Assembly auto-expansion. */
HOWTO (R_XTENSA_ASM_EXPAND, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_ASM_EXPAND",
- FALSE, 0x00000000, 0x00000000, FALSE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_ASM_EXPAND", FALSE, 0, 0, TRUE),
/* Relax assembly auto-expansion. */
HOWTO (R_XTENSA_ASM_SIMPLIFY, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_ASM_SIMPLIFY",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_ASM_SIMPLIFY", FALSE, 0, 0, TRUE),
+
EMPTY_HOWTO (13),
EMPTY_HOWTO (14),
+
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_XTENSA_GNU_VTINHERIT, 0, 2, 0, FALSE, 0, complain_overflow_dont,
NULL, "R_XTENSA_GNU_VTINHERIT",
- FALSE, 0x00000000, 0x00000000, FALSE),
+ FALSE, 0, 0, FALSE),
/* GNU extension to record C++ vtable member usage. */
HOWTO (R_XTENSA_GNU_VTENTRY, 0, 2, 0, FALSE, 0, complain_overflow_dont,
_bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY",
- FALSE, 0x00000000, 0x00000000, FALSE),
+ FALSE, 0, 0, FALSE),
/* Relocations for supporting difference of symbols. */
HOWTO (R_XTENSA_DIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
- bfd_elf_xtensa_reloc, "R_XTENSA_DIFF8",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_DIFF8", FALSE, 0, 0xff, FALSE),
HOWTO (R_XTENSA_DIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
- bfd_elf_xtensa_reloc, "R_XTENSA_DIFF16",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_DIFF16", FALSE, 0, 0xffff, FALSE),
HOWTO (R_XTENSA_DIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
- bfd_elf_xtensa_reloc, "R_XTENSA_DIFF32",
- FALSE, 0xffffffff, 0xffffffff, FALSE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_DIFF32", FALSE, 0, 0xffffffff, FALSE),
/* General immediate operand relocations. */
HOWTO (R_XTENSA_SLOT0_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT1_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT2_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT3_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT4_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT5_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT6_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT7_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT8_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT9_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT10_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT11_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT12_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT13_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_OP", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT14_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_OP",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_OP", FALSE, 0, 0, TRUE),
/* "Alternate" relocations. The meaning of these is opcode-specific. */
HOWTO (R_XTENSA_SLOT0_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT1_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT2_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT3_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT4_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT5_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT6_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT7_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT8_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT9_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT10_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT11_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT12_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT13_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE),
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_ALT", FALSE, 0, 0, TRUE),
HOWTO (R_XTENSA_SLOT14_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
- bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_ALT",
- FALSE, 0x00000000, 0x00000000, TRUE)
+ bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_ALT", FALSE, 0, 0, TRUE),
};
#if DEBUG_GEN_RELOC
@@ -430,6 +391,20 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
return NULL;
}
+static reloc_howto_type *
+elf_xtensa_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
+ if (elf_howto_table[i].name != NULL
+ && strcasecmp (elf_howto_table[i].name, r_name) == 0)
+ return &elf_howto_table[i];
+
+ return NULL;
+}
+
/* Given an ELF "rela" relocation, find the corresponding howto and record
it in the BFD internal arelent representation of the relocation. */
@@ -496,9 +471,70 @@ static const bfd_byte elf_xtensa_le_plt_entry[PLT_ENTRY_SIZE] =
0 /* unused */
};
+/* Xtensa ELF linker hash table. */
+
+struct elf_xtensa_link_hash_table
+{
+ struct elf_link_hash_table elf;
+
+ /* Short-cuts to get to dynamic linker sections. */
+ asection *sgot;
+ asection *sgotplt;
+ asection *srelgot;
+ asection *splt;
+ asection *srelplt;
+ asection *sgotloc;
+ asection *spltlittbl;
+
+ /* Total count of PLT relocations seen during check_relocs.
+ The actual PLT code must be split into multiple sections and all
+ the sections have to be created before size_dynamic_sections,
+ where we figure out the exact number of PLT entries that will be
+ needed. It is OK if this count is an overestimate, e.g., some
+ relocations may be removed by GC. */
+ int plt_reloc_count;
+};
+
+/* Get the Xtensa ELF linker hash table from a link_info structure. */
+
+#define elf_xtensa_hash_table(p) \
+ ((struct elf_xtensa_link_hash_table *) ((p)->hash))
+
+/* Create an Xtensa ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+elf_xtensa_link_hash_table_create (bfd *abfd)
+{
+ struct elf_xtensa_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct elf_xtensa_link_hash_table);
+
+ ret = bfd_malloc (amt);
+ if (ret == NULL)
+ return NULL;
+
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ ret->sgot = NULL;
+ ret->sgotplt = NULL;
+ ret->srelgot = NULL;
+ ret->splt = NULL;
+ ret->srelplt = NULL;
+ ret->sgotloc = NULL;
+ ret->spltlittbl = NULL;
+
+ ret->plt_reloc_count = 0;
+
+ return &ret->elf.root;
+}
static inline bfd_boolean
-xtensa_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
+elf_xtensa_dynamic_symbol_p (struct elf_link_hash_entry *h,
struct bfd_link_info *info)
{
/* Check if we should do dynamic things to this symbol. The
@@ -571,16 +607,15 @@ xtensa_read_table_entries (bfd *abfd,
bfd_boolean output_addr)
{
asection *table_section;
- char *table_section_name;
bfd_size_type table_size = 0;
bfd_byte *table_data;
property_table_entry *blocks;
int blk, block_count;
bfd_size_type num_records;
- Elf_Internal_Rela *internal_relocs;
- bfd_vma section_addr;
+ Elf_Internal_Rela *internal_relocs, *irel, *rel_end;
+ bfd_vma section_addr, off;
flagword predef_flags;
- bfd_size_type table_entry_size;
+ bfd_size_type table_entry_size, section_limit;
if (!section
|| !(section->flags & SEC_ALLOC)
@@ -590,9 +625,7 @@ xtensa_read_table_entries (bfd *abfd,
return 0;
}
- table_section_name = xtensa_get_property_section_name (section, sec_name);
- table_section = bfd_get_section_by_name (abfd, table_section_name);
- free (table_section_name);
+ table_section = xtensa_get_property_section (section, sec_name);
if (table_section)
table_size = table_section->size;
@@ -618,67 +651,63 @@ xtensa_read_table_entries (bfd *abfd,
else
section_addr = section->vma;
- /* If the file has not yet been relocated, process the relocations
- and sort out the table entries that apply to the specified section. */
internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE);
if (internal_relocs && !table_section->reloc_done)
{
- unsigned i;
-
- for (i = 0; i < table_section->reloc_count; i++)
- {
- Elf_Internal_Rela *rel = &internal_relocs[i];
- unsigned long r_symndx;
+ qsort (internal_relocs, table_section->reloc_count,
+ sizeof (Elf_Internal_Rela), internal_reloc_compare);
+ irel = internal_relocs;
+ }
+ else
+ irel = NULL;
- if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE)
- continue;
+ section_limit = bfd_get_section_limit (abfd, section);
+ rel_end = internal_relocs + table_section->reloc_count;
- BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32);
- r_symndx = ELF32_R_SYM (rel->r_info);
+ for (off = 0; off < table_size; off += table_entry_size)
+ {
+ bfd_vma address = bfd_get_32 (abfd, table_data + off);
- if (get_elf_r_symndx_section (abfd, r_symndx) == section)
- {
- bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
- BFD_ASSERT (sym_off == 0);
- blocks[block_count].address =
- (section_addr + sym_off + rel->r_addend
- + bfd_get_32 (abfd, table_data + rel->r_offset));
- blocks[block_count].size =
- bfd_get_32 (abfd, table_data + rel->r_offset + 4);
- if (predef_flags)
- blocks[block_count].flags = predef_flags;
- else
- blocks[block_count].flags =
- bfd_get_32 (abfd, table_data + rel->r_offset + 8);
- block_count++;
- }
+ /* Skip any relocations before the current offset. This should help
+ avoid confusion caused by unexpected relocations for the preceding
+ table entry. */
+ while (irel &&
+ (irel->r_offset < off
+ || (irel->r_offset == off
+ && ELF32_R_TYPE (irel->r_info) == R_XTENSA_NONE)))
+ {
+ irel += 1;
+ if (irel >= rel_end)
+ irel = 0;
}
- }
- else
- {
- /* The file has already been relocated and the addresses are
- already in the table. */
- bfd_vma off;
- bfd_size_type section_limit = bfd_get_section_limit (abfd, section);
- for (off = 0; off < table_size; off += table_entry_size)
+ if (irel && irel->r_offset == off)
{
- bfd_vma address = bfd_get_32 (abfd, table_data + off);
+ bfd_vma sym_off;
+ unsigned long r_symndx = ELF32_R_SYM (irel->r_info);
+ BFD_ASSERT (ELF32_R_TYPE (irel->r_info) == R_XTENSA_32);
- if (address >= section_addr
- && address < section_addr + section_limit)
- {
- blocks[block_count].address = address;
- blocks[block_count].size =
- bfd_get_32 (abfd, table_data + off + 4);
- if (predef_flags)
- blocks[block_count].flags = predef_flags;
- else
- blocks[block_count].flags =
- bfd_get_32 (abfd, table_data + off + 8);
- block_count++;
- }
+ if (get_elf_r_symndx_section (abfd, r_symndx) != section)
+ continue;
+
+ sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
+ BFD_ASSERT (sym_off == 0);
+ address += (section_addr + sym_off + irel->r_addend);
}
+ else
+ {
+ if (address < section_addr
+ || address >= section_addr + section_limit)
+ continue;
+ }
+
+ blocks[block_count].address = address;
+ blocks[block_count].size = bfd_get_32 (abfd, table_data + off + 4);
+ if (predef_flags)
+ blocks[block_count].flags = predef_flags;
+ else
+ blocks[block_count].flags = bfd_get_32 (abfd, table_data + off + 8);
+ block_count++;
}
release_contents (table_section, table_data);
@@ -757,6 +786,7 @@ elf_xtensa_check_relocs (bfd *abfd,
asection *sec,
const Elf_Internal_Rela *relocs)
{
+ struct elf_xtensa_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
@@ -765,6 +795,7 @@ elf_xtensa_check_relocs (bfd *abfd,
if (info->relocatable)
return TRUE;
+ htab = elf_xtensa_hash_table (info);
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
@@ -829,12 +860,11 @@ elf_xtensa_check_relocs (bfd *abfd,
/* Keep track of the total PLT relocation count even if we
don't yet know whether the dynamic sections will be
created. */
- plt_reloc_count += 1;
+ htab->plt_reloc_count += 1;
if (elf_hash_table (info)->dynamic_sections_created)
{
- if (!add_extra_plt_sections (elf_hash_table (info)->dynobj,
- plt_reloc_count))
+ if (! add_extra_plt_sections (info, htab->plt_reloc_count))
return FALSE;
}
}
@@ -929,18 +959,19 @@ elf_xtensa_check_relocs (bfd *abfd,
static void
elf_xtensa_make_sym_local (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ struct elf_link_hash_entry *h)
{
if (info->shared)
{
if (h->plt.refcount > 0)
- {
- /* Will use RELATIVE relocs instead of JMP_SLOT relocs. */
- if (h->got.refcount < 0)
- h->got.refcount = 0;
- h->got.refcount += h->plt.refcount;
- h->plt.refcount = 0;
- }
+ {
+ /* For shared objects, there's no need for PLT entries for local
+ symbols (use RELATIVE relocs instead of JMP_SLOT relocs). */
+ if (h->got.refcount < 0)
+ h->got.refcount = 0;
+ h->got.refcount += h->plt.refcount;
+ h->plt.refcount = 0;
+ }
}
else
{
@@ -953,8 +984,8 @@ elf_xtensa_make_sym_local (struct bfd_link_info *info,
static void
elf_xtensa_hide_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h,
- bfd_boolean force_local)
+ struct elf_link_hash_entry *h,
+ bfd_boolean force_local)
{
/* For a shared link, move the plt refcount to the got refcount to leave
space for RELATIVE relocs. */
@@ -969,38 +1000,33 @@ elf_xtensa_hide_symbol (struct bfd_link_info *info,
static asection *
elf_xtensa_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
Elf_Internal_Rela *rel,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- if (h)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_XTENSA_GNU_VTINHERIT:
- case R_XTENSA_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
+ /* Property sections are marked "KEEP" in the linker scripts, but they
+ should not cause other sections to be marked. (This approach relies
+ on elf_xtensa_discard_info to remove property table entries that
+ describe discarded sections. Alternatively, it might be more
+ efficient to avoid using "KEEP" in the linker scripts and instead use
+ the gc_mark_extra_sections hook to mark only the property sections
+ that describe marked sections. That alternative does not work well
+ with the current property table sections, which do not correspond
+ one-to-one with the sections they describe, but that should be fixed
+ someday.) */
+ if (xtensa_is_property_section (sec))
+ return NULL;
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+ if (h != NULL)
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_XTENSA_GNU_VTINHERIT:
+ case R_XTENSA_GNU_VTENTRY:
+ return NULL;
+ }
- return NULL;
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
@@ -1077,16 +1103,22 @@ elf_xtensa_gc_sweep_hook (bfd *abfd,
static bfd_boolean
elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
{
+ struct elf_xtensa_link_hash_table *htab;
flagword flags, noalloc_flags;
- asection *s;
+
+ htab = elf_xtensa_hash_table (info);
/* First do all the standard stuff. */
if (! _bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
+ htab->splt = bfd_get_section_by_name (dynobj, ".plt");
+ htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+ htab->sgot = bfd_get_section_by_name (dynobj, ".got");
+ htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
/* Create any extra PLT sections in case check_relocs has already
been called on all the non-dynamic input files. */
- if (!add_extra_plt_sections (dynobj, plt_reloc_count))
+ if (! add_extra_plt_sections (info, htab->plt_reloc_count))
return FALSE;
noalloc_flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -1094,28 +1126,27 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
flags = noalloc_flags | SEC_ALLOC | SEC_LOAD;
/* Mark the ".got.plt" section READONLY. */
- s = bfd_get_section_by_name (dynobj, ".got.plt");
- if (s == NULL
- || ! bfd_set_section_flags (dynobj, s, flags))
+ if (htab->sgotplt == NULL
+ || ! bfd_set_section_flags (dynobj, htab->sgotplt, flags))
return FALSE;
/* Create ".rela.got". */
- s = bfd_make_section_with_flags (dynobj, ".rela.got", flags);
- if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got", flags);
+ if (htab->srelgot == NULL
+ || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
return FALSE;
/* Create ".got.loc" (literal tables for use by dynamic linker). */
- s = bfd_make_section_with_flags (dynobj, ".got.loc", flags);
- if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ htab->sgotloc = bfd_make_section_with_flags (dynobj, ".got.loc", flags);
+ if (htab->sgotloc == NULL
+ || ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2))
return FALSE;
/* Create ".xt.lit.plt" (literal table for ".got.plt*"). */
- s = bfd_make_section_with_flags (dynobj, ".xt.lit.plt",
- noalloc_flags);
- if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ htab->spltlittbl = bfd_make_section_with_flags (dynobj, ".xt.lit.plt",
+ noalloc_flags);
+ if (htab->spltlittbl == NULL
+ || ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2))
return FALSE;
return TRUE;
@@ -1123,8 +1154,9 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
static bfd_boolean
-add_extra_plt_sections (bfd *dynobj, int count)
+add_extra_plt_sections (struct bfd_link_info *info, int count)
{
+ bfd *dynobj = elf_hash_table (info)->dynobj;
int chunk;
/* Iterate over all chunks except 0 which uses the standard ".plt" and
@@ -1136,7 +1168,7 @@ add_extra_plt_sections (bfd *dynobj, int count)
asection *s;
/* Stop when we find a section has already been created. */
- if (elf_xtensa_get_plt_section (dynobj, chunk))
+ if (elf_xtensa_get_plt_section (info, chunk))
break;
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -1144,8 +1176,7 @@ add_extra_plt_sections (bfd *dynobj, int count)
sname = (char *) bfd_malloc (10);
sprintf (sname, ".plt.%u", chunk);
- s = bfd_make_section_with_flags (dynobj, sname,
- flags | SEC_CODE);
+ s = bfd_make_section_with_flags (dynobj, sname, flags | SEC_CODE);
if (s == NULL
|| ! bfd_set_section_alignment (dynobj, s, 2))
return FALSE;
@@ -1193,56 +1224,44 @@ elf_xtensa_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
static bfd_boolean
-elf_xtensa_fix_refcounts (struct elf_link_hash_entry *h, void *arg)
+elf_xtensa_allocate_dynrelocs (struct elf_link_hash_entry *h, void *arg)
{
- struct bfd_link_info *info = (struct bfd_link_info *) arg;
-
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- if (! xtensa_elf_dynamic_symbol_p (h, info))
- elf_xtensa_make_sym_local (info, h);
-
- return TRUE;
-}
+ struct bfd_link_info *info;
+ struct elf_xtensa_link_hash_table *htab;
+ bfd_boolean is_dynamic;
-
-static bfd_boolean
-elf_xtensa_allocate_plt_size (struct elf_link_hash_entry *h, void *arg)
-{
- asection *srelplt = (asection *) arg;
+ 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;
- if (h->plt.refcount > 0)
- srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
-
- return TRUE;
-}
+ info = (struct bfd_link_info *) arg;
+ htab = elf_xtensa_hash_table (info);
+ is_dynamic = elf_xtensa_dynamic_symbol_p (h, info);
-static bfd_boolean
-elf_xtensa_allocate_got_size (struct elf_link_hash_entry *h, void *arg)
-{
- asection *srelgot = (asection *) arg;
+ if (! is_dynamic)
+ elf_xtensa_make_sym_local (info, h);
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->plt.refcount > 0)
+ htab->srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
if (h->got.refcount > 0)
- srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela));
+ htab->srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela));
return TRUE;
}
static void
-elf_xtensa_allocate_local_got_size (struct bfd_link_info *info,
- asection *srelgot)
+elf_xtensa_allocate_local_got_size (struct bfd_link_info *info)
{
+ struct elf_xtensa_link_hash_table *htab;
bfd *i;
+ htab = elf_xtensa_hash_table (info);
+
for (i = info->input_bfds; i; i = i->link_next)
{
bfd_signed_vma *local_got_refcounts;
@@ -1259,8 +1278,8 @@ elf_xtensa_allocate_local_got_size (struct bfd_link_info *info,
for (j = 0; j < cnt; ++j)
{
if (local_got_refcounts[j] > 0)
- srelgot->size += (local_got_refcounts[j]
- * sizeof (Elf32_External_Rela));
+ htab->srelgot->size += (local_got_refcounts[j]
+ * sizeof (Elf32_External_Rela));
}
}
}
@@ -1272,6 +1291,7 @@ static bfd_boolean
elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info)
{
+ struct elf_xtensa_link_hash_table *htab;
bfd *dynobj, *abfd;
asection *s, *srelplt, *splt, *sgotplt, *srelgot, *spltlittbl, *sgotloc;
bfd_boolean relplt, relgot;
@@ -1279,14 +1299,22 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
plt_entries = 0;
plt_chunks = 0;
- srelgot = 0;
+ htab = elf_xtensa_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
if (dynobj == NULL)
abort ();
+ srelgot = htab->srelgot;
+ srelplt = htab->srelplt;
if (elf_hash_table (info)->dynamic_sections_created)
{
+ BFD_ASSERT (htab->srelgot != NULL
+ && htab->srelplt != NULL
+ && htab->sgot != NULL
+ && htab->spltlittbl != NULL
+ && htab->sgotloc != NULL);
+
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
@@ -1298,48 +1326,27 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
/* Allocate room for one word in ".got". */
- s = bfd_get_section_by_name (dynobj, ".got");
- if (s == NULL)
- abort ();
- s->size = 4;
+ htab->sgot->size = 4;
- /* Adjust refcounts for symbols that we now know are not "dynamic". */
+ /* Allocate space in ".rela.got" for literals that reference global
+ symbols and space in ".rela.plt" for literals that have PLT
+ entries. */
elf_link_hash_traverse (elf_hash_table (info),
- elf_xtensa_fix_refcounts,
+ elf_xtensa_allocate_dynrelocs,
(void *) info);
- /* Allocate space in ".rela.got" for literals that reference
- global symbols. */
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- if (srelgot == NULL)
- abort ();
- elf_link_hash_traverse (elf_hash_table (info),
- elf_xtensa_allocate_got_size,
- (void *) srelgot);
-
/* If we are generating a shared object, we also need space in
".rela.got" for R_XTENSA_RELATIVE relocs for literals that
reference local symbols. */
if (info->shared)
- elf_xtensa_allocate_local_got_size (info, srelgot);
-
- /* Allocate space in ".rela.plt" for literals that have PLT entries. */
- srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- if (srelplt == NULL)
- abort ();
- elf_link_hash_traverse (elf_hash_table (info),
- elf_xtensa_allocate_plt_size,
- (void *) srelplt);
+ elf_xtensa_allocate_local_got_size (info);
/* Allocate space in ".plt" to match the size of ".rela.plt". For
each PLT entry, we need the PLT code plus a 4-byte literal.
For each chunk of ".plt", we also need two more 4-byte
literals, two corresponding entries in ".rela.got", and an
8-byte entry in ".xt.lit.plt". */
- spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
- if (spltlittbl == NULL)
- abort ();
-
+ spltlittbl = htab->spltlittbl;
plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
plt_chunks =
(plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
@@ -1348,14 +1355,13 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
created earlier because the initial count of PLT relocations
was an overestimate. */
for (chunk = 0;
- (splt = elf_xtensa_get_plt_section (dynobj, chunk)) != NULL;
+ (splt = elf_xtensa_get_plt_section (info, chunk)) != NULL;
chunk++)
{
int chunk_entries;
- sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
- if (sgotplt == NULL)
- abort ();
+ sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
+ BFD_ASSERT (sgotplt != NULL);
if (chunk < plt_chunks - 1)
chunk_entries = PLT_ENTRIES_PER_CHUNK;
@@ -1380,9 +1386,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
/* Allocate space in ".got.loc" to match the total size of all the
literal tables. */
- sgotloc = bfd_get_section_by_name (dynobj, ".got.loc");
- if (sgotloc == NULL)
- abort ();
+ sgotloc = htab->sgotloc;
sgotloc->size = spltlittbl->size;
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
{
@@ -1412,7 +1416,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
- if (strncmp (name, ".rela", 5) == 0)
+ if (CONST_STRNEQ (name, ".rela"))
{
if (s->size != 0)
{
@@ -1426,8 +1430,8 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
s->reloc_count = 0;
}
}
- else if (strncmp (name, ".plt.", 5) != 0
- && strncmp (name, ".got.plt.", 9) != 0
+ else if (! CONST_STRNEQ (name, ".plt.")
+ && ! CONST_STRNEQ (name, ".got.plt.")
&& strcmp (name, ".got") != 0
&& strcmp (name, ".plt") != 0
&& strcmp (name, ".got.plt") != 0
@@ -1465,8 +1469,6 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
/* Add the special XTENSA_RTLD relocations now. The offsets won't be
known until finish_dynamic_sections, but we need to get the relocs
in place before they are sorted. */
- if (srelgot == NULL)
- abort ();
for (chunk = 0; chunk < plt_chunks; chunk++)
{
Elf_Internal_Rela irela;
@@ -1492,7 +1494,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (! info->shared)
+ if (info->executable)
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
@@ -1525,31 +1527,6 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
-/* Remove any PT_LOAD segments with no allocated sections. Prior to
- binutils 2.13, this function used to remove the non-SEC_ALLOC
- sections from PT_LOAD segments, but that task has now been moved
- into elf.c. We still need this function to remove any empty
- segments that result, but there's nothing Xtensa-specific about
- this and it probably ought to be moved into elf.c as well. */
-
-static bfd_boolean
-elf_xtensa_modify_segment_map (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED)
-{
- struct elf_segment_map **m_p;
-
- m_p = &elf_tdata (abfd)->segment_map;
- while (*m_p)
- {
- if ((*m_p)->p_type == PT_LOAD && (*m_p)->count == 0)
- *m_p = (*m_p)->next;
- else
- m_p = &(*m_p)->next;
- }
- return TRUE;
-}
-
-
/* Perform the specified relocation. The instruction at (contents + address)
is modified to set one operand to represent the value in "relocation". The
operand position is determined by the relocation type recorded in the
@@ -1937,7 +1914,7 @@ bfd_elf_xtensa_reloc (bfd *abfd,
/* Set up an entry in the procedure linkage table. */
static bfd_vma
-elf_xtensa_create_plt_entry (bfd *dynobj,
+elf_xtensa_create_plt_entry (struct bfd_link_info *info,
bfd *output_bfd,
unsigned reloc_index)
{
@@ -1947,8 +1924,8 @@ elf_xtensa_create_plt_entry (bfd *dynobj,
int chunk;
chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
- splt = elf_xtensa_get_plt_section (dynobj, chunk);
- sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+ splt = elf_xtensa_get_plt_section (info, chunk);
+ sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
BFD_ASSERT (splt != NULL && sgotplt != NULL);
plt_base = splt->output_section->vma + splt->output_offset;
@@ -1995,12 +1972,11 @@ elf_xtensa_relocate_section (bfd *output_bfd,
Elf_Internal_Sym *local_syms,
asection **local_sections)
{
+ struct elf_xtensa_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
struct elf_link_hash_entry **sym_hashes;
- asection *srelgot, *srelplt;
- bfd *dynobj;
property_table_entry *lit_table = 0;
int ltblsize = 0;
char *error_message = NULL;
@@ -2009,18 +1985,10 @@ elf_xtensa_relocate_section (bfd *output_bfd,
if (!xtensa_default_isa)
xtensa_default_isa = xtensa_isa_init (0, 0);
- dynobj = elf_hash_table (info)->dynobj;
+ htab = elf_xtensa_hash_table (info);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
- srelgot = NULL;
- srelplt = NULL;
- if (dynobj)
- {
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
- srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- }
-
if (elf_hash_table (info)->dynamic_sections_created)
{
ltblsize = xtensa_read_table_entries (input_bfd, input_section,
@@ -2062,6 +2030,53 @@ elf_xtensa_relocate_section (bfd *output_bfd,
r_symndx = ELF32_R_SYM (rel->r_info);
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ is_weak_undef = FALSE;
+ unresolved_reloc = FALSE;
+ warned = FALSE;
+
+ if (howto->partial_inplace && !info->relocatable)
+ {
+ /* Because R_XTENSA_32 was made partial_inplace to fix some
+ problems with DWARF info in partial links, there may be
+ an addend stored in the contents. Take it out of there
+ and move it back into the addend field of the reloc. */
+ rel->r_addend += bfd_get_32 (input_bfd, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, 0, contents + rel->r_offset);
+ }
+
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+ }
+ else
+ {
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
+
+ if (relocation == 0
+ && !unresolved_reloc
+ && h->root.type == bfd_link_hash_undefweak)
+ is_weak_undef = TRUE;
+ }
+
+ if (sec != NULL && elf_discarded_section (sec))
+ {
+ /* For relocs against symbols from removed linkonce sections,
+ or sections discarded by a linker script, we just want the
+ section contents zeroed. Avoid any special processing. */
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
+ }
+
if (info->relocatable)
{
/* This is a relocatable link.
@@ -2143,42 +2158,6 @@ elf_xtensa_relocate_section (bfd *output_bfd,
/* This is a final link. */
- h = NULL;
- sym = NULL;
- sec = NULL;
- is_weak_undef = FALSE;
- unresolved_reloc = FALSE;
- warned = FALSE;
-
- if (howto->partial_inplace)
- {
- /* Because R_XTENSA_32 was made partial_inplace to fix some
- problems with DWARF info in partial links, there may be
- an addend stored in the contents. Take it out of there
- and move it back into the addend field of the reloc. */
- rel->r_addend += bfd_get_32 (input_bfd, contents + rel->r_offset);
- bfd_put_32 (input_bfd, 0, contents + rel->r_offset);
- }
-
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
- }
- else
- {
- RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
- r_symndx, symtab_hdr, sym_hashes,
- h, sec, relocation,
- unresolved_reloc, warned);
-
- if (relocation == 0
- && !unresolved_reloc
- && h->root.type == bfd_link_hash_undefweak)
- is_weak_undef = TRUE;
- }
-
if (relaxing_section)
{
/* Check if this references a section in another input file. */
@@ -2204,7 +2183,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
/* Generate dynamic relocations. */
if (elf_hash_table (info)->dynamic_sections_created)
{
- bfd_boolean dynamic_symbol = xtensa_elf_dynamic_symbol_p (h, info);
+ bfd_boolean dynamic_symbol = elf_xtensa_dynamic_symbol_p (h, info);
if (dynamic_symbol && is_operand_relocation (r_type))
{
@@ -2228,9 +2207,9 @@ elf_xtensa_relocate_section (bfd *output_bfd,
asection *srel;
if (dynamic_symbol && r_type == R_XTENSA_PLT)
- srel = srelplt;
+ srel = htab->srelplt;
else
- srel = srelgot;
+ srel = htab->srelgot;
BFD_ASSERT (srel != NULL);
@@ -2279,7 +2258,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
contents of the literal entry to the address of
the PLT entry. */
relocation =
- elf_xtensa_create_plt_entry (dynobj, output_bfd,
+ elf_xtensa_create_plt_entry (info, output_bfd,
srel->reloc_count);
}
unresolved_reloc = FALSE;
@@ -2306,13 +2285,16 @@ elf_xtensa_relocate_section (bfd *output_bfd,
if (unresolved_reloc
&& !((input_section->flags & SEC_DEBUGGING) != 0
&& h->def_dynamic))
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
- input_bfd,
- input_section,
- (long) rel->r_offset,
- howto->name,
- h->root.root.string);
+ {
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+ input_bfd,
+ input_section,
+ (long) rel->r_offset,
+ howto->name,
+ h->root.root.string);
+ return FALSE;
+ }
/* There's no point in calling bfd_perform_relocation here.
Just go directly to our "special function". */
@@ -2373,12 +2355,17 @@ elf_xtensa_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- if (h->needs_plt
- && !h->def_regular)
+ if (h->needs_plt && !h->def_regular)
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. */
sym->st_shndx = SHN_UNDEF;
+ /* If the symbol is weak, we do need to clear the value.
+ Otherwise, the PLT entry would provide a definition for
+ the symbol even if the symbol wasn't defined anywhere,
+ and so the symbol would never be NULL. */
+ if (!h->ref_regular_nonweak)
+ sym->st_value = 0;
}
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
@@ -2509,6 +2496,7 @@ static bfd_boolean
elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
+ struct elf_xtensa_link_hash_table *htab;
bfd *dynobj;
asection *sdyn, *srelplt, *sgot, *sxtlit, *sgotloc;
Elf32_External_Dyn *dyncon, *dynconend;
@@ -2517,13 +2505,14 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
if (! elf_hash_table (info)->dynamic_sections_created)
return TRUE;
+ htab = elf_xtensa_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
BFD_ASSERT (sdyn != NULL);
/* Set the first entry in the global offset table to the address of
the dynamic section. */
- sgot = bfd_get_section_by_name (dynobj, ".got");
+ sgot = htab->sgot;
if (sgot)
{
BFD_ASSERT (sgot->size == 4);
@@ -2535,7 +2524,7 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
sgot->contents);
}
- srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+ srelplt = htab->srelplt;
if (srelplt && srelplt->size != 0)
{
asection *sgotplt, *srelgot, *spltlittbl;
@@ -2544,11 +2533,9 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
bfd_byte *loc;
unsigned rtld_reloc;
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
- BFD_ASSERT (srelgot != NULL);
-
- spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
- BFD_ASSERT (spltlittbl != NULL);
+ srelgot = htab->srelgot;
+ spltlittbl = htab->spltlittbl;
+ BFD_ASSERT (srelgot != NULL && spltlittbl != NULL);
/* Find the first XTENSA_RTLD relocation. Presumably the rest
of them follow immediately after.... */
@@ -2569,7 +2556,7 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
{
int chunk_entries = 0;
- sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+ sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
BFD_ASSERT (sgotplt != NULL);
/* Emit special RTLD relocations for the first two entries in
@@ -2637,7 +2624,7 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
/* Combine adjacent literal table entries. */
BFD_ASSERT (! info->relocatable);
sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit");
- sgotloc = bfd_get_section_by_name (dynobj, ".got.loc");
+ sgotloc = htab->sgotloc;
BFD_ASSERT (sxtlit && sgotloc);
num_xtlit_entries =
elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc);
@@ -2649,8 +2636,6 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
- const char *name;
- asection *s;
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
@@ -2664,23 +2649,19 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
break;
case DT_XTENSA_GOT_LOC_OFF:
- name = ".got.loc";
- goto get_vma;
+ dyn.d_un.d_ptr = htab->sgotloc->vma;
+ break;
+
case DT_PLTGOT:
- name = ".got";
- goto get_vma;
+ dyn.d_un.d_ptr = htab->sgot->vma;
+ break;
+
case DT_JMPREL:
- name = ".rela.plt";
- get_vma:
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s);
- dyn.d_un.d_ptr = s->vma;
+ dyn.d_un.d_ptr = htab->srelplt->vma;
break;
case DT_PLTRELSZ:
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
- BFD_ASSERT (s);
- dyn.d_un.d_val = s->size;
+ dyn.d_un.d_val = htab->srelplt->size;
break;
case DT_RELASZ:
@@ -2690,9 +2671,8 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
seems to be unresolved. Since the linker script arranges
for .rela.plt to follow all other relocation sections, we
don't have to worry about changing the DT_RELA entry. */
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
- if (s)
- dyn.d_un.d_val -= s->size;
+ if (htab->srelplt)
+ dyn.d_un.d_val -= htab->srelplt->size;
break;
}
@@ -2866,16 +2846,22 @@ elf_xtensa_discard_info_for_section (bfd *abfd,
bfd_byte *contents;
bfd_vma section_size;
bfd_vma offset, actual_offset;
- size_t removed_bytes = 0;
-
- section_size = sec->size;
- if (section_size == 0 || section_size % 8 != 0)
- return FALSE;
+ bfd_size_type removed_bytes = 0;
+ bfd_size_type entry_size;
if (sec->output_section
&& bfd_is_abs_section (sec->output_section))
return FALSE;
+ if (xtensa_is_proptable_section (sec))
+ entry_size = 12;
+ else
+ entry_size = 8;
+
+ section_size = sec->size;
+ if (section_size == 0 || section_size % entry_size != 0)
+ return FALSE;
+
contents = retrieve_contents (abfd, sec, info->keep_memory);
if (!contents)
return FALSE;
@@ -2887,10 +2873,15 @@ elf_xtensa_discard_info_for_section (bfd *abfd,
return FALSE;
}
+ /* Sort the relocations. They should already be in order when
+ relaxation is enabled, but it might not be. */
+ qsort (cookie->rels, sec->reloc_count, sizeof (Elf_Internal_Rela),
+ internal_reloc_compare);
+
cookie->rel = cookie->rels;
cookie->relend = cookie->rels + sec->reloc_count;
- for (offset = 0; offset < section_size; offset += 8)
+ for (offset = 0; offset < section_size; offset += entry_size)
{
actual_offset = offset - removed_bytes;
@@ -2914,11 +2905,11 @@ elf_xtensa_discard_info_for_section (bfd *abfd,
if (ELF32_R_TYPE (cookie->rel->r_info) != R_XTENSA_NONE)
{
/* Shift the contents up. */
- if (offset + 8 < section_size)
+ if (offset + entry_size < section_size)
memmove (&contents[actual_offset],
- &contents[actual_offset+8],
- section_size - offset - 8);
- removed_bytes += 8;
+ &contents[actual_offset + entry_size],
+ section_size - offset - entry_size);
+ removed_bytes += entry_size;
}
/* Remove this relocation. */
@@ -2961,14 +2952,9 @@ elf_xtensa_discard_info_for_section (bfd *abfd,
if (xtensa_is_littable_section (sec))
{
- bfd *dynobj = elf_hash_table (info)->dynobj;
- if (dynobj)
- {
- asection *sgotloc =
- bfd_get_section_by_name (dynobj, ".got.loc");
- if (sgotloc)
- sgotloc->size -= removed_bytes;
- }
+ asection *sgotloc = elf_xtensa_hash_table (info)->sgotloc;
+ if (sgotloc)
+ sgotloc->size -= removed_bytes;
}
}
else
@@ -3008,6 +2994,19 @@ elf_xtensa_ignore_discarded_relocs (asection *sec)
return xtensa_is_property_section (sec);
}
+
+static unsigned int
+elf_xtensa_action_discarded (asection *sec)
+{
+ if (strcmp (".xt_except_table", sec->name) == 0)
+ return 0;
+
+ if (strcmp (".xt_except_desc", sec->name) == 0)
+ return 0;
+
+ return _bfd_elf_default_action_discarded (sec);
+}
+
/* Support for core dump NOTE sections. */
@@ -3433,24 +3432,23 @@ check_loop_aligned (bfd_byte *contents,
bfd_vma address)
{
bfd_size_type loop_len, insn_len;
- xtensa_opcode opcode =
- insn_decode_opcode (contents, content_length, offset, 0);
- BFD_ASSERT (opcode != XTENSA_UNDEFINED);
- if (opcode != XTENSA_UNDEFINED)
- return FALSE;
- BFD_ASSERT (xtensa_opcode_is_loop (xtensa_default_isa, opcode));
- if (!xtensa_opcode_is_loop (xtensa_default_isa, opcode))
- return FALSE;
+ xtensa_opcode opcode;
+ opcode = insn_decode_opcode (contents, content_length, offset, 0);
+ if (opcode == XTENSA_UNDEFINED
+ || xtensa_opcode_is_loop (xtensa_default_isa, opcode) != 1)
+ {
+ BFD_ASSERT (FALSE);
+ return FALSE;
+ }
+
loop_len = insn_decode_len (contents, content_length, offset);
- BFD_ASSERT (loop_len != 0);
- if (loop_len == 0)
- return FALSE;
-
insn_len = insn_decode_len (contents, content_length, offset + loop_len);
- BFD_ASSERT (insn_len != 0);
- if (insn_len == 0)
- return FALSE;
+ if (loop_len == 0 || insn_len == 0)
+ {
+ BFD_ASSERT (FALSE);
+ return FALSE;
+ }
return check_branch_target_aligned_address (address + loop_len, insn_len);
}
@@ -3562,60 +3560,31 @@ struct string_pair widenable[] =
};
-/* Attempt to narrow an instruction. Return true if the narrowing is
- valid. If the do_it parameter is non-zero, then perform the action
- in-place directly into the contents. Otherwise, do not modify the
- contents. The set of valid narrowing are specified by a string table
+/* Check if an instruction can be "narrowed", i.e., changed from a standard
+ 3-byte instruction to a 2-byte "density" instruction. If it is valid,
+ return the instruction buffer holding the narrow instruction. Otherwise,
+ return 0. The set of valid narrowing are specified by a string table
but require some special case operand checks in some cases. */
-static bfd_boolean
-narrow_instruction (bfd_byte *contents,
- bfd_size_type content_length,
- bfd_size_type offset,
- bfd_boolean do_it)
+static xtensa_insnbuf
+can_narrow_instruction (xtensa_insnbuf slotbuf,
+ xtensa_format fmt,
+ xtensa_opcode opcode)
{
- xtensa_opcode opcode;
- bfd_size_type insn_len, opi;
xtensa_isa isa = xtensa_default_isa;
- xtensa_format fmt, o_fmt;
+ xtensa_format o_fmt;
+ unsigned opi;
- static xtensa_insnbuf insnbuf = NULL;
- static xtensa_insnbuf slotbuf = NULL;
static xtensa_insnbuf o_insnbuf = NULL;
static xtensa_insnbuf o_slotbuf = NULL;
- if (insnbuf == NULL)
+ if (o_insnbuf == NULL)
{
- insnbuf = xtensa_insnbuf_alloc (isa);
- slotbuf = xtensa_insnbuf_alloc (isa);
o_insnbuf = xtensa_insnbuf_alloc (isa);
o_slotbuf = xtensa_insnbuf_alloc (isa);
}
- BFD_ASSERT (offset < content_length);
-
- if (content_length < 2)
- return FALSE;
-
- /* We will hand-code a few of these for a little while.
- These have all been specified in the assembler aleady. */
- xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
- content_length - offset);
- fmt = xtensa_format_decode (isa, insnbuf);
- if (xtensa_format_num_slots (isa, fmt) != 1)
- return FALSE;
-
- if (xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf) != 0)
- return FALSE;
-
- opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
- if (opcode == XTENSA_UNDEFINED)
- return FALSE;
- insn_len = xtensa_format_length (isa, fmt);
- if (insn_len > content_length)
- return FALSE;
-
- for (opi = 0; opi < (sizeof (narrowable)/sizeof (struct string_pair)); ++opi)
+ for (opi = 0; opi < (sizeof (narrowable)/sizeof (struct string_pair)); opi++)
{
bfd_boolean is_or = (strcmp ("or", narrowable[opi].wide) == 0);
@@ -3631,47 +3600,41 @@ narrow_instruction (bfd_byte *contents,
o_opcode = xtensa_opcode_lookup (isa, narrowable[opi].narrow);
if (o_opcode == XTENSA_UNDEFINED)
- return FALSE;
+ return 0;
o_fmt = get_single_format (o_opcode);
if (o_fmt == XTENSA_UNDEFINED)
- return FALSE;
+ return 0;
if (xtensa_format_length (isa, fmt) != 3
|| xtensa_format_length (isa, o_fmt) != 2)
- return FALSE;
+ return 0;
xtensa_format_encode (isa, o_fmt, o_insnbuf);
operand_count = xtensa_opcode_num_operands (isa, opcode);
o_operand_count = xtensa_opcode_num_operands (isa, o_opcode);
if (xtensa_opcode_encode (isa, o_fmt, 0, o_slotbuf, o_opcode) != 0)
- return FALSE;
+ return 0;
if (!is_or)
{
if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
- return FALSE;
+ return 0;
}
else
{
uint32 rawval0, rawval1, rawval2;
- if (o_operand_count + 1 != operand_count)
- return FALSE;
- if (xtensa_operand_get_field (isa, opcode, 0,
- fmt, 0, slotbuf, &rawval0) != 0)
- return FALSE;
- if (xtensa_operand_get_field (isa, opcode, 1,
- fmt, 0, slotbuf, &rawval1) != 0)
- return FALSE;
- if (xtensa_operand_get_field (isa, opcode, 2,
- fmt, 0, slotbuf, &rawval2) != 0)
- return FALSE;
-
- if (rawval1 != rawval2)
- return FALSE;
- if (rawval0 == rawval1) /* it is a nop */
- return FALSE;
+ if (o_operand_count + 1 != operand_count
+ || xtensa_operand_get_field (isa, opcode, 0,
+ fmt, 0, slotbuf, &rawval0) != 0
+ || xtensa_operand_get_field (isa, opcode, 1,
+ fmt, 0, slotbuf, &rawval1) != 0
+ || xtensa_operand_get_field (isa, opcode, 2,
+ fmt, 0, slotbuf, &rawval2) != 0
+ || rawval1 != rawval2
+ || rawval0 == rawval1 /* it is a nop */)
+ return 0;
}
for (i = 0; i < o_operand_count; ++i)
@@ -3679,7 +3642,7 @@ narrow_instruction (bfd_byte *contents,
if (xtensa_operand_get_field (isa, opcode, i, fmt, 0,
slotbuf, &value)
|| xtensa_operand_decode (isa, opcode, i, &value))
- return FALSE;
+ return 0;
/* PC-relative branches need adjustment, but
the PC-rel operand will always have a relocation. */
@@ -3689,52 +3652,41 @@ narrow_instruction (bfd_byte *contents,
|| xtensa_operand_encode (isa, o_opcode, i, &newval)
|| xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
o_slotbuf, newval))
- return FALSE;
+ return 0;
}
- if (xtensa_format_set_slot (isa, o_fmt, 0,
- o_insnbuf, o_slotbuf) != 0)
- return FALSE;
+ if (xtensa_format_set_slot (isa, o_fmt, 0, o_insnbuf, o_slotbuf))
+ return 0;
- if (do_it)
- xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
- content_length - offset);
- return TRUE;
+ return o_insnbuf;
}
}
- return FALSE;
+ return 0;
}
-/* Attempt to widen an instruction. Return true if the widening is
- valid. If the do_it parameter is non-zero, then the action should
- be performed inplace into the contents. Otherwise, do not modify
- the contents. The set of valid widenings are specified by a string
- table but require some special case operand checks in some
- cases. */
+/* Attempt to narrow an instruction. If the narrowing is valid, perform
+ the action in-place directly into the contents and return TRUE. Otherwise,
+ the return value is FALSE and the contents are not modified. */
static bfd_boolean
-widen_instruction (bfd_byte *contents,
- bfd_size_type content_length,
- bfd_size_type offset,
- bfd_boolean do_it)
+narrow_instruction (bfd_byte *contents,
+ bfd_size_type content_length,
+ bfd_size_type offset)
{
xtensa_opcode opcode;
- bfd_size_type insn_len, opi;
+ bfd_size_type insn_len;
xtensa_isa isa = xtensa_default_isa;
- xtensa_format fmt, o_fmt;
+ xtensa_format fmt;
+ xtensa_insnbuf o_insnbuf;
static xtensa_insnbuf insnbuf = NULL;
static xtensa_insnbuf slotbuf = NULL;
- static xtensa_insnbuf o_insnbuf = NULL;
- static xtensa_insnbuf o_slotbuf = NULL;
if (insnbuf == NULL)
{
insnbuf = xtensa_insnbuf_alloc (isa);
slotbuf = xtensa_insnbuf_alloc (isa);
- o_insnbuf = xtensa_insnbuf_alloc (isa);
- o_slotbuf = xtensa_insnbuf_alloc (isa);
}
BFD_ASSERT (offset < content_length);
@@ -3742,7 +3694,7 @@ widen_instruction (bfd_byte *contents,
if (content_length < 2)
return FALSE;
- /* We will hand code a few of these for a little while.
+ /* We will hand-code a few of these for a little while.
These have all been specified in the assembler aleady. */
xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
content_length - offset);
@@ -3760,7 +3712,43 @@ widen_instruction (bfd_byte *contents,
if (insn_len > content_length)
return FALSE;
- for (opi = 0; opi < (sizeof (widenable)/sizeof (struct string_pair)); ++opi)
+ o_insnbuf = can_narrow_instruction (slotbuf, fmt, opcode);
+ if (o_insnbuf)
+ {
+ xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
+ content_length - offset);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* Check if an instruction can be "widened", i.e., changed from a 2-byte
+ "density" instruction to a standard 3-byte instruction. If it is valid,
+ return the instruction buffer holding the wide instruction. Otherwise,
+ return 0. The set of valid widenings are specified by a string table
+ but require some special case operand checks in some cases. */
+
+static xtensa_insnbuf
+can_widen_instruction (xtensa_insnbuf slotbuf,
+ xtensa_format fmt,
+ xtensa_opcode opcode)
+{
+ xtensa_isa isa = xtensa_default_isa;
+ xtensa_format o_fmt;
+ unsigned opi;
+
+ static xtensa_insnbuf o_insnbuf = NULL;
+ static xtensa_insnbuf o_slotbuf = NULL;
+
+ if (o_insnbuf == NULL)
+ {
+ o_insnbuf = xtensa_insnbuf_alloc (isa);
+ o_slotbuf = xtensa_insnbuf_alloc (isa);
+ }
+
+ for (opi = 0; opi < (sizeof (widenable)/sizeof (struct string_pair)); opi++)
{
bfd_boolean is_or = (strcmp ("or", widenable[opi].wide) == 0);
bfd_boolean is_branch = (strcmp ("beqz", widenable[opi].wide) == 0
@@ -3778,14 +3766,14 @@ widen_instruction (bfd_byte *contents,
o_opcode = xtensa_opcode_lookup (isa, widenable[opi].wide);
if (o_opcode == XTENSA_UNDEFINED)
- return FALSE;
+ return 0;
o_fmt = get_single_format (o_opcode);
if (o_fmt == XTENSA_UNDEFINED)
- return FALSE;
+ return 0;
if (xtensa_format_length (isa, fmt) != 2
|| xtensa_format_length (isa, o_fmt) != 3)
- return FALSE;
+ return 0;
xtensa_format_encode (isa, o_fmt, o_insnbuf);
operand_count = xtensa_opcode_num_operands (isa, opcode);
@@ -3793,32 +3781,29 @@ widen_instruction (bfd_byte *contents,
check_operand_count = o_operand_count;
if (xtensa_opcode_encode (isa, o_fmt, 0, o_slotbuf, o_opcode) != 0)
- return FALSE;
+ return 0;
if (!is_or)
{
if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
- return FALSE;
+ return 0;
}
else
{
uint32 rawval0, rawval1;
- if (o_operand_count != operand_count + 1)
- return FALSE;
- if (xtensa_operand_get_field (isa, opcode, 0,
- fmt, 0, slotbuf, &rawval0) != 0)
- return FALSE;
- if (xtensa_operand_get_field (isa, opcode, 1,
- fmt, 0, slotbuf, &rawval1) != 0)
- return FALSE;
- if (rawval0 == rawval1) /* it is a nop */
- return FALSE;
+ if (o_operand_count != operand_count + 1
+ || xtensa_operand_get_field (isa, opcode, 0,
+ fmt, 0, slotbuf, &rawval0) != 0
+ || xtensa_operand_get_field (isa, opcode, 1,
+ fmt, 0, slotbuf, &rawval1) != 0
+ || rawval0 == rawval1 /* it is a nop */)
+ return 0;
}
if (is_branch)
check_operand_count--;
- for (i = 0; i < check_operand_count; ++i)
+ for (i = 0; i < check_operand_count; i++)
{
int new_i = i;
if (is_or && i == o_operand_count - 1)
@@ -3826,7 +3811,7 @@ widen_instruction (bfd_byte *contents,
if (xtensa_operand_get_field (isa, opcode, new_i, fmt, 0,
slotbuf, &value)
|| xtensa_operand_decode (isa, opcode, new_i, &value))
- return FALSE;
+ return 0;
/* PC-relative branches need adjustment, but
the PC-rel operand will always have a relocation. */
@@ -3836,18 +3821,73 @@ widen_instruction (bfd_byte *contents,
|| xtensa_operand_encode (isa, o_opcode, i, &newval)
|| xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
o_slotbuf, newval))
- return FALSE;
+ return 0;
}
if (xtensa_format_set_slot (isa, o_fmt, 0, o_insnbuf, o_slotbuf))
- return FALSE;
+ return 0;
- if (do_it)
- xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
- content_length - offset);
- return TRUE;
+ return o_insnbuf;
}
}
+ return 0;
+}
+
+
+/* Attempt to widen an instruction. If the widening is valid, perform
+ the action in-place directly into the contents and return TRUE. Otherwise,
+ the return value is FALSE and the contents are not modified. */
+
+static bfd_boolean
+widen_instruction (bfd_byte *contents,
+ bfd_size_type content_length,
+ bfd_size_type offset)
+{
+ xtensa_opcode opcode;
+ bfd_size_type insn_len;
+ xtensa_isa isa = xtensa_default_isa;
+ xtensa_format fmt;
+ xtensa_insnbuf o_insnbuf;
+
+ static xtensa_insnbuf insnbuf = NULL;
+ static xtensa_insnbuf slotbuf = NULL;
+
+ if (insnbuf == NULL)
+ {
+ insnbuf = xtensa_insnbuf_alloc (isa);
+ slotbuf = xtensa_insnbuf_alloc (isa);
+ }
+
+ BFD_ASSERT (offset < content_length);
+
+ if (content_length < 2)
+ return FALSE;
+
+ /* We will hand-code a few of these for a little while.
+ These have all been specified in the assembler aleady. */
+ xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
+ content_length - offset);
+ fmt = xtensa_format_decode (isa, insnbuf);
+ if (xtensa_format_num_slots (isa, fmt) != 1)
+ return FALSE;
+
+ if (xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf) != 0)
+ return FALSE;
+
+ opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
+ if (opcode == XTENSA_UNDEFINED)
+ return FALSE;
+ insn_len = xtensa_format_length (isa, fmt);
+ if (insn_len > content_length)
+ return FALSE;
+
+ o_insnbuf = can_widen_instruction (slotbuf, fmt, opcode);
+ if (o_insnbuf)
+ {
+ xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
+ content_length - offset);
+ return TRUE;
+ }
return FALSE;
}
@@ -5007,13 +5047,16 @@ struct elf_xtensa_section_data
static bfd_boolean
elf_xtensa_new_section_hook (bfd *abfd, asection *sec)
{
- struct elf_xtensa_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ if (!sec->used_by_bfd)
+ {
+ struct elf_xtensa_section_data *sdata;
+ bfd_size_type amt = sizeof (*sdata);
- sdata = (struct elf_xtensa_section_data *) bfd_zalloc (abfd, amt);
- if (sdata == NULL)
- return FALSE;
- sec->used_by_bfd = (void *) sdata;
+ sdata = bfd_zalloc (abfd, amt);
+ if (sdata == NULL)
+ return FALSE;
+ sec->used_by_bfd = sdata;
+ }
return _bfd_elf_new_section_hook (abfd, sec);
}
@@ -5498,7 +5541,7 @@ extend_ebb_bounds_forward (ebb_t *ebb)
new_entry = &ebb->ptbl[ebb->end_ptbl_idx + 1];
if (((new_entry->flags & XTENSA_PROP_INSN) == 0)
- || ((new_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) != 0)
+ || ((new_entry->flags & XTENSA_PROP_NO_TRANSFORM) != 0)
|| ((the_entry->flags & XTENSA_PROP_ALIGN) != 0))
break;
@@ -5571,7 +5614,7 @@ extend_ebb_bounds_backward (ebb_t *ebb)
new_entry = &ebb->ptbl[ebb->start_ptbl_idx - 1];
if ((new_entry->flags & XTENSA_PROP_INSN) == 0
- || ((new_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) != 0)
+ || ((new_entry->flags & XTENSA_PROP_NO_TRANSFORM) != 0)
|| ((new_entry->flags & XTENSA_PROP_ALIGN) != 0))
return TRUE;
if (new_entry->address + new_entry->size != the_entry->address)
@@ -5779,7 +5822,8 @@ static bfd_boolean compute_removed_literals
static Elf_Internal_Rela *get_irel_at_offset
(asection *, Elf_Internal_Rela *, bfd_vma);
static bfd_boolean is_removable_literal
- (const source_reloc *, int, const source_reloc *, int);
+ (const source_reloc *, int, const source_reloc *, int, asection *,
+ property_table_entry *, int);
static bfd_boolean remove_dead_literal
(bfd *, asection *, struct bfd_link_info *, Elf_Internal_Rela *,
Elf_Internal_Rela *, source_reloc *, property_table_entry *, int);
@@ -5926,6 +5970,8 @@ analyze_relocations (struct bfd_link_info *link_info)
relax_info->src_relocs = (source_reloc *)
bfd_malloc (relax_info->src_count * sizeof (source_reloc));
}
+ else
+ relax_info->src_count = 0;
}
/* Collect info on relocations against each relaxable section. */
@@ -5969,6 +6015,7 @@ find_relaxable_sections (bfd *abfd,
bfd_boolean ok = TRUE;
unsigned i;
xtensa_relax_info *source_relax_info;
+ bfd_boolean is_l32r_reloc;
internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
@@ -6019,13 +6066,21 @@ find_relaxable_sections (bfd *abfd,
/* Count PC-relative operand relocations against the target section.
Note: The conditions tested here must match the conditions under
which init_source_reloc is called in collect_source_relocs(). */
- if (is_operand_relocation (ELF32_R_TYPE (irel->r_info))
- && (!is_alt_relocation (ELF32_R_TYPE (irel->r_info))
- || is_l32r_relocation (abfd, sec, contents, irel)))
- target_relax_info->src_count++;
+ is_l32r_reloc = FALSE;
+ if (is_operand_relocation (ELF32_R_TYPE (irel->r_info)))
+ {
+ xtensa_opcode opcode =
+ get_relocation_opcode (abfd, sec, contents, irel);
+ if (opcode != XTENSA_UNDEFINED)
+ {
+ is_l32r_reloc = (opcode == get_l32r_opcode ());
+ if (!is_alt_relocation (ELF32_R_TYPE (irel->r_info))
+ || is_l32r_reloc)
+ target_relax_info->src_count++;
+ }
+ }
- if (is_l32r_relocation (abfd, sec, contents, irel)
- && r_reloc_is_defined (&r_rel))
+ if (is_l32r_reloc && r_reloc_is_defined (&r_rel))
{
/* Mark the target section as relaxable. */
target_relax_info->is_relaxable_literal_section = TRUE;
@@ -6346,14 +6401,12 @@ compute_text_actions (bfd *abfd,
property_table_entry *prop_table = 0;
int ptblsize = 0;
bfd_size_type sec_size;
- static bfd_boolean no_insn_move = FALSE;
-
- if (no_insn_move)
- return ok;
- /* Do nothing if the section contains no optimized longcalls. */
relax_info = get_xtensa_relax_info (sec);
BFD_ASSERT (relax_info);
+ BFD_ASSERT (relax_info->src_next == relax_info->src_count);
+
+ /* Do nothing if the section contains no optimized longcalls. */
if (!relax_info->is_relaxable_asm_section)
return ok;
@@ -6428,7 +6481,7 @@ compute_text_actions (bfd *abfd,
the_entry++;
}
- if (the_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM)
+ if (the_entry->flags & XTENSA_PROP_NO_TRANSFORM)
/* NO_REORDER is OK */
continue;
@@ -6492,6 +6545,23 @@ error_return:
}
+/* Do not widen an instruction if it is preceeded by a
+ loop opcode. It might cause misalignment. */
+
+static bfd_boolean
+prev_instr_is_a_loop (bfd_byte *contents,
+ bfd_size_type content_length,
+ bfd_size_type offset)
+{
+ xtensa_opcode prev_opcode;
+
+ if (offset < 3)
+ return FALSE;
+ prev_opcode = insn_decode_opcode (contents, content_length, offset-3, 0);
+ return (xtensa_opcode_is_loop (xtensa_default_isa, prev_opcode) == 1);
+}
+
+
/* Find all of the possible actions for an extended basic block. */
bfd_boolean
@@ -6500,13 +6570,24 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
const ebb_t *ebb = &ebb_table->ebb;
unsigned rel_idx = ebb->start_reloc_idx;
property_table_entry *entry, *start_entry, *end_entry;
+ bfd_vma offset = 0;
+ xtensa_isa isa = xtensa_default_isa;
+ xtensa_format fmt;
+ static xtensa_insnbuf insnbuf = NULL;
+ static xtensa_insnbuf slotbuf = NULL;
+
+ if (insnbuf == NULL)
+ {
+ insnbuf = xtensa_insnbuf_alloc (isa);
+ slotbuf = xtensa_insnbuf_alloc (isa);
+ }
start_entry = &ebb->ptbl[ebb->start_ptbl_idx];
end_entry = &ebb->ptbl[ebb->end_ptbl_idx];
for (entry = start_entry; entry <= end_entry; entry++)
{
- bfd_vma offset, start_offset, end_offset;
+ bfd_vma start_offset, end_offset;
bfd_size_type insn_len;
start_offset = entry->address - ebb->sec->vma;
@@ -6528,15 +6609,9 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
insn_len = insn_decode_len (ebb->contents, ebb->content_length,
offset);
-
- /* Propose no actions for a section with an undecodable offset. */
if (insn_len == 0)
- {
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, offset);
- return FALSE;
- }
+ goto decode_error;
+
if (check_branch_target_aligned_address (offset, insn_len))
align_type = EBB_REQUIRE_TGT_ALIGN;
@@ -6567,12 +6642,7 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
ebb->content_length,
irel->r_offset);
if (simplify_size == 0)
- {
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): could not decode instruction for XTENSA_ASM_SIMPLIFY relocation; possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, offset);
- return FALSE;
- }
+ goto decode_error;
ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
ta_convert_longcall, offset, 0, TRUE);
@@ -6581,47 +6651,50 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
continue;
}
- insn_len = insn_decode_len (ebb->contents, ebb->content_length,
- offset);
- /* If the instruction is undecodable, then report an error. */
- if (insn_len == 0)
+ if (offset + MIN_INSN_LENGTH > ebb->content_length)
+ goto decode_error;
+ xtensa_insnbuf_from_chars (isa, insnbuf, &ebb->contents[offset],
+ ebb->content_length - offset);
+ fmt = xtensa_format_decode (isa, insnbuf);
+ if (fmt == XTENSA_UNDEFINED)
+ goto decode_error;
+ insn_len = xtensa_format_length (isa, fmt);
+ if (insn_len == (bfd_size_type) XTENSA_UNDEFINED)
+ goto decode_error;
+
+ if (xtensa_format_num_slots (isa, fmt) != 1)
{
- (*_bfd_error_handler)
- (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, offset);
- return FALSE;
+ offset += insn_len;
+ continue;
}
-
+
+ xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf);
+ opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
+ if (opcode == XTENSA_UNDEFINED)
+ goto decode_error;
+
if ((entry->flags & XTENSA_PROP_INSN_NO_DENSITY) == 0
- && (entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) == 0
- && narrow_instruction (ebb->contents, ebb->content_length,
- offset, FALSE))
+ && (entry->flags & XTENSA_PROP_NO_TRANSFORM) == 0
+ && can_narrow_instruction (slotbuf, fmt, opcode) != 0)
{
/* Add an instruction narrow action. */
ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
ta_narrow_insn, offset, 0, FALSE);
- offset += insn_len;
- continue;
}
- if ((entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) == 0
- && widen_instruction (ebb->contents, ebb->content_length,
- offset, FALSE))
+ else if ((entry->flags & XTENSA_PROP_NO_TRANSFORM) == 0
+ && can_widen_instruction (slotbuf, fmt, opcode) != 0
+ && ! prev_instr_is_a_loop (ebb->contents,
+ ebb->content_length, offset))
{
/* Add an instruction widen action. */
ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
ta_widen_insn, offset, 0, FALSE);
- offset += insn_len;
- continue;
}
- opcode = insn_decode_opcode (ebb->contents, ebb->content_length,
- offset, 0);
- if (xtensa_opcode_is_loop (xtensa_default_isa, opcode))
+ else if (xtensa_opcode_is_loop (xtensa_default_isa, opcode) == 1)
{
/* Check for branch targets. */
ebb_propose_action (ebb_table, EBB_REQUIRE_LOOP_ALIGN, 0,
ta_none, offset, 0, TRUE);
- offset += insn_len;
- continue;
}
offset += insn_len;
@@ -6635,6 +6708,12 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
}
return TRUE;
+
+ decode_error:
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
+ ebb->sec->owner, ebb->sec, offset);
+ return FALSE;
}
@@ -7352,7 +7431,8 @@ compute_removed_literals (bfd *abfd,
/* Check if the relocation was from an L32R that is being removed
because a CALLX was converted to a direct CALL, and check if
there are no other relocations to the literal. */
- if (is_removable_literal (rel, i, src_relocs, relax_info->src_count))
+ if (is_removable_literal (rel, i, src_relocs, relax_info->src_count,
+ sec, prop_table, ptblsize))
{
if (!remove_dead_literal (abfd, sec, link_info, internal_relocs,
irel, rel, prop_table, ptblsize))
@@ -7436,12 +7516,22 @@ bfd_boolean
is_removable_literal (const source_reloc *rel,
int i,
const source_reloc *src_relocs,
- int src_count)
+ int src_count,
+ asection *sec,
+ property_table_entry *prop_table,
+ int ptblsize)
{
const source_reloc *curr_rel;
+ property_table_entry *entry;
+
if (!rel->is_null)
return FALSE;
+ entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
+ sec->vma + rel->r_rel.target_offset);
+ if (entry && (entry->flags & XTENSA_PROP_NO_TRANSFORM))
+ return FALSE;
+
for (++i; i < src_count; ++i)
{
curr_rel = &src_relocs[i];
@@ -7731,7 +7821,7 @@ coalesce_shared_literal (asection *sec,
entry = elf_xtensa_find_property_entry
(prop_table, ptblsize, sec->vma + rel->r_rel.target_offset);
- if (entry && (entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM))
+ if (entry && (entry->flags & XTENSA_PROP_NO_TRANSFORM))
return TRUE;
/* Mark that the literal will be coalesced. */
@@ -8247,7 +8337,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
copy_size = 2;
memmove (scratch, &contents[orig_dot], orig_insn_size);
BFD_ASSERT (action->removed_bytes == 1);
- rv = narrow_instruction (scratch, final_size, 0, TRUE);
+ rv = narrow_instruction (scratch, final_size, 0);
BFD_ASSERT (rv);
memmove (&dup_contents[dup_dot], scratch, copy_size);
orig_dot += orig_insn_size;
@@ -8280,7 +8370,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
copy_size = 3;
memmove (scratch, &contents[orig_dot], orig_insn_size);
BFD_ASSERT (action->removed_bytes == -1);
- rv = widen_instruction (scratch, final_size, 0, TRUE);
+ rv = widen_instruction (scratch, final_size, 0);
BFD_ASSERT (rv);
memmove (&dup_contents[dup_dot], scratch, copy_size);
orig_dot += orig_insn_size;
@@ -8557,6 +8647,7 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info,
asection *input_section,
Elf_Internal_Rela *rel)
{
+ struct elf_xtensa_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
unsigned long r_symndx;
@@ -8564,6 +8655,7 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info,
struct elf_link_hash_entry *h;
bfd_boolean dynamic_symbol;
+ htab = elf_xtensa_hash_table (info);
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
@@ -8575,30 +8667,24 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info,
else
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- dynamic_symbol = xtensa_elf_dynamic_symbol_p (h, info);
+ dynamic_symbol = elf_xtensa_dynamic_symbol_p (h, info);
if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
&& (input_section->flags & SEC_ALLOC) != 0
&& (dynamic_symbol || info->shared))
{
- bfd *dynobj;
- const char *srel_name;
asection *srel;
bfd_boolean is_plt = FALSE;
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
-
if (dynamic_symbol && r_type == R_XTENSA_PLT)
{
- srel_name = ".rela.plt";
+ srel = htab->srelplt;
is_plt = TRUE;
}
else
- srel_name = ".rela.got";
+ srel = htab->srelgot;
/* Reduce size of the .rela.* section by one reloc. */
- srel = bfd_get_section_by_name (dynobj, srel_name);
BFD_ASSERT (srel != NULL);
BFD_ASSERT (srel->size >= sizeof (Elf32_External_Rela));
srel->size -= sizeof (Elf32_External_Rela);
@@ -8617,15 +8703,15 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info,
reloc_index = srel->size / sizeof (Elf32_External_Rela);
chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
- splt = elf_xtensa_get_plt_section (dynobj, chunk);
- sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+ splt = elf_xtensa_get_plt_section (info, chunk);
+ sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
BFD_ASSERT (splt != NULL && sgotplt != NULL);
/* Check if an entire PLT chunk has just been eliminated. */
if (reloc_index % PLT_ENTRIES_PER_CHUNK == 0)
{
/* The two magic GOT entries for that chunk can go away. */
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = htab->srelgot;
BFD_ASSERT (srelgot != NULL);
srelgot->reloc_count -= 2;
srelgot->size -= 2 * sizeof (Elf32_External_Rela);
@@ -8794,12 +8880,13 @@ relax_property_section (bfd *abfd,
{
Elf_Internal_Rela *internal_relocs;
bfd_byte *contents;
- unsigned i, nexti;
+ unsigned i;
bfd_boolean ok = TRUE;
bfd_boolean is_full_prop_section;
size_t last_zfill_target_offset = 0;
asection *last_zfill_target_sec = NULL;
bfd_size_type sec_size;
+ bfd_size_type entry_size;
sec_size = bfd_get_section_limit (abfd, sec);
internal_relocs = retrieve_internal_relocs (abfd, sec,
@@ -8811,10 +8898,11 @@ relax_property_section (bfd *abfd,
goto error_return;
}
- is_full_prop_section =
- ((strcmp (sec->name, XTENSA_PROP_SEC_NAME) == 0)
- || (strncmp (sec->name, ".gnu.linkonce.prop.",
- sizeof ".gnu.linkonce.prop." - 1) == 0));
+ is_full_prop_section = xtensa_is_proptable_section (sec);
+ if (is_full_prop_section)
+ entry_size = 12;
+ else
+ entry_size = 8;
if (internal_relocs)
{
@@ -8843,12 +8931,8 @@ relax_property_section (bfd *abfd,
size_p = &contents[irel->r_offset + 4];
flags_p = NULL;
if (is_full_prop_section)
- {
- flags_p = &contents[irel->r_offset + 8];
- BFD_ASSERT (irel->r_offset + 12 <= sec_size);
- }
- else
- BFD_ASSERT (irel->r_offset + 8 <= sec_size);
+ flags_p = &contents[irel->r_offset + 8];
+ BFD_ASSERT (irel->r_offset + entry_size <= sec_size);
target_sec = r_reloc_get_section (&val.r_rel);
target_relax_info = get_xtensa_relax_info (target_sec);
@@ -8932,74 +9016,105 @@ relax_property_section (bfd *abfd,
reclaim the space in the output section, so we do this twice. */
if (internal_relocs && (!link_info->relocatable
- || strcmp (sec->name, XTENSA_LIT_SEC_NAME) == 0))
+ || xtensa_is_littable_section (sec)))
{
Elf_Internal_Rela *last_irel = NULL;
+ Elf_Internal_Rela *irel, *next_rel, *rel_end;
int removed_bytes = 0;
- bfd_vma offset, last_irel_offset;
+ bfd_vma offset;
bfd_vma section_size;
- bfd_size_type entry_size;
flagword predef_flags;
- if (is_full_prop_section)
- entry_size = 12;
- else
- entry_size = 8;
-
predef_flags = xtensa_get_property_predef_flags (sec);
- /* Walk over memory and irels at the same time.
+ /* Walk over memory and relocations at the same time.
This REQUIRES that the internal_relocs be sorted by offset. */
qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
internal_reloc_compare);
- nexti = 0; /* Index into internal_relocs. */
pin_internal_relocs (sec, internal_relocs);
pin_contents (sec, contents);
- last_irel_offset = (bfd_vma) -1;
+ next_rel = internal_relocs;
+ rel_end = internal_relocs + sec->reloc_count;
+
section_size = sec->size;
BFD_ASSERT (section_size % entry_size == 0);
for (offset = 0; offset < section_size; offset += entry_size)
{
- Elf_Internal_Rela *irel, *next_irel;
+ Elf_Internal_Rela *offset_rel, *extra_rel;
bfd_vma bytes_to_remove, size, actual_offset;
- bfd_boolean remove_this_irel;
+ bfd_boolean remove_this_rel;
flagword flags;
- irel = NULL;
- next_irel = NULL;
-
- /* Find the next two relocations (if there are that many left),
- skipping over any R_XTENSA_NONE relocs. On entry, "nexti" is
- the starting reloc index. After these two loops, "i"
- is the index of the first non-NONE reloc past that starting
- index, and "nexti" is the index for the next non-NONE reloc
- after "i". */
+ /* Find the first relocation for the entry at the current offset.
+ Adjust the offsets of any extra relocations for the previous
+ entry. */
+ offset_rel = NULL;
+ if (next_rel)
+ {
+ for (irel = next_rel; irel < rel_end; irel++)
+ {
+ if ((irel->r_offset == offset
+ && ELF32_R_TYPE (irel->r_info) != R_XTENSA_NONE)
+ || irel->r_offset > offset)
+ {
+ offset_rel = irel;
+ break;
+ }
+ irel->r_offset -= removed_bytes;
+ }
+ }
- for (i = nexti; i < sec->reloc_count; i++)
+ /* Find the next relocation (if there are any left). */
+ extra_rel = NULL;
+ if (offset_rel)
{
- if (ELF32_R_TYPE (internal_relocs[i].r_info) != R_XTENSA_NONE)
+ for (irel = offset_rel + 1; irel < rel_end; irel++)
{
- irel = &internal_relocs[i];
- break;
+ if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_NONE)
+ {
+ extra_rel = irel;
+ break;
+ }
}
- internal_relocs[i].r_offset -= removed_bytes;
}
- for (nexti = i + 1; nexti < sec->reloc_count; nexti++)
+ /* Check if there are relocations on the current entry. There
+ should usually be a relocation on the offset field. If there
+ are relocations on the size or flags, then we can't optimize
+ this entry. Also, find the next relocation to examine on the
+ next iteration. */
+ if (offset_rel)
{
- if (ELF32_R_TYPE (internal_relocs[nexti].r_info)
- != R_XTENSA_NONE)
+ if (offset_rel->r_offset >= offset + entry_size)
{
- next_irel = &internal_relocs[nexti];
- break;
+ next_rel = offset_rel;
+ /* There are no relocations on the current entry, but we
+ might still be able to remove it if the size is zero. */
+ offset_rel = NULL;
+ }
+ else if (offset_rel->r_offset > offset
+ || (extra_rel
+ && extra_rel->r_offset < offset + entry_size))
+ {
+ /* There is a relocation on the size or flags, so we can't
+ do anything with this entry. Continue with the next. */
+ next_rel = offset_rel;
+ continue;
+ }
+ else
+ {
+ BFD_ASSERT (offset_rel->r_offset == offset);
+ offset_rel->r_offset -= removed_bytes;
+ next_rel = offset_rel + 1;
}
- internal_relocs[nexti].r_offset -= removed_bytes;
}
+ else
+ next_rel = NULL;
- remove_this_irel = FALSE;
+ remove_this_rel = FALSE;
bytes_to_remove = 0;
actual_offset = offset - removed_bytes;
size = bfd_get_32 (abfd, &contents[actual_offset + 4]);
@@ -9009,90 +9124,64 @@ relax_property_section (bfd *abfd,
else
flags = predef_flags;
- /* Check that the irels are sorted by offset,
- with only one per address. */
- BFD_ASSERT (!irel || (int) irel->r_offset > (int) last_irel_offset);
- BFD_ASSERT (!next_irel || next_irel->r_offset > irel->r_offset);
-
- /* Make sure there aren't relocs on the size or flag fields. */
- if ((irel && irel->r_offset == offset + 4)
- || (is_full_prop_section
- && irel && irel->r_offset == offset + 8))
- {
- irel->r_offset -= removed_bytes;
- last_irel_offset = irel->r_offset;
- }
- else if (next_irel && (next_irel->r_offset == offset + 4
- || (is_full_prop_section
- && next_irel->r_offset == offset + 8)))
- {
- nexti += 1;
- irel->r_offset -= removed_bytes;
- next_irel->r_offset -= removed_bytes;
- last_irel_offset = next_irel->r_offset;
- }
- else if (size == 0 && (flags & XTENSA_PROP_ALIGN) == 0
- && (flags & XTENSA_PROP_UNREACHABLE) == 0)
+ if (size == 0
+ && (flags & XTENSA_PROP_ALIGN) == 0
+ && (flags & XTENSA_PROP_UNREACHABLE) == 0)
{
/* Always remove entries with zero size and no alignment. */
bytes_to_remove = entry_size;
- if (irel && irel->r_offset == offset)
- {
- remove_this_irel = TRUE;
-
- irel->r_offset -= removed_bytes;
- last_irel_offset = irel->r_offset;
- }
+ if (offset_rel)
+ remove_this_rel = TRUE;
}
- else if (irel && irel->r_offset == offset)
+ else if (offset_rel
+ && ELF32_R_TYPE (offset_rel->r_info) == R_XTENSA_32)
{
- if (ELF32_R_TYPE (irel->r_info) == R_XTENSA_32)
+ if (last_irel)
{
- if (last_irel)
+ flagword old_flags;
+ bfd_vma old_size =
+ bfd_get_32 (abfd, &contents[last_irel->r_offset + 4]);
+ bfd_vma old_address =
+ (last_irel->r_addend
+ + bfd_get_32 (abfd, &contents[last_irel->r_offset]));
+ bfd_vma new_address =
+ (offset_rel->r_addend
+ + bfd_get_32 (abfd, &contents[actual_offset]));
+ if (is_full_prop_section)
+ old_flags = bfd_get_32
+ (abfd, &contents[last_irel->r_offset + 8]);
+ else
+ old_flags = predef_flags;
+
+ if ((ELF32_R_SYM (offset_rel->r_info)
+ == ELF32_R_SYM (last_irel->r_info))
+ && old_address + old_size == new_address
+ && old_flags == flags
+ && (old_flags & XTENSA_PROP_INSN_BRANCH_TARGET) == 0
+ && (old_flags & XTENSA_PROP_INSN_LOOP_TARGET) == 0)
{
- flagword old_flags;
- bfd_vma old_size =
- bfd_get_32 (abfd, &contents[last_irel->r_offset + 4]);
- bfd_vma old_address =
- (last_irel->r_addend
- + bfd_get_32 (abfd, &contents[last_irel->r_offset]));
- bfd_vma new_address =
- (irel->r_addend
- + bfd_get_32 (abfd, &contents[actual_offset]));
- if (is_full_prop_section)
- old_flags = bfd_get_32
- (abfd, &contents[last_irel->r_offset + 8]);
- else
- old_flags = predef_flags;
-
- if ((ELF32_R_SYM (irel->r_info)
- == ELF32_R_SYM (last_irel->r_info))
- && old_address + old_size == new_address
- && old_flags == flags
- && (old_flags & XTENSA_PROP_INSN_BRANCH_TARGET) == 0
- && (old_flags & XTENSA_PROP_INSN_LOOP_TARGET) == 0)
- {
- /* Fix the old size. */
- bfd_put_32 (abfd, old_size + size,
- &contents[last_irel->r_offset + 4]);
- bytes_to_remove = entry_size;
- remove_this_irel = TRUE;
- }
- else
- last_irel = irel;
+ /* Fix the old size. */
+ bfd_put_32 (abfd, old_size + size,
+ &contents[last_irel->r_offset + 4]);
+ bytes_to_remove = entry_size;
+ remove_this_rel = TRUE;
}
else
- last_irel = irel;
+ last_irel = offset_rel;
}
-
- irel->r_offset -= removed_bytes;
- last_irel_offset = irel->r_offset;
+ else
+ last_irel = offset_rel;
}
- if (remove_this_irel)
+ if (remove_this_rel)
{
- irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
- irel->r_offset -= bytes_to_remove;
+ offset_rel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+ /* In case this is the last entry, move the relocation offset
+ to the previous entry, if there is one. */
+ if (offset_rel->r_offset >= bytes_to_remove)
+ offset_rel->r_offset -= bytes_to_remove;
+ else
+ offset_rel->r_offset = 0;
}
if (bytes_to_remove != 0)
@@ -9107,6 +9196,10 @@ relax_property_section (bfd *abfd,
if (removed_bytes)
{
+ /* Fix up any extra relocations on the last entry. */
+ for (irel = next_rel; irel < rel_end; irel++)
+ irel->r_offset -= removed_bytes;
+
/* Clear the removed bytes. */
memset (&contents[section_size - removed_bytes], 0, removed_bytes);
@@ -9114,14 +9207,9 @@ relax_property_section (bfd *abfd,
if (xtensa_is_littable_section (sec))
{
- bfd *dynobj = elf_hash_table (link_info)->dynobj;
- if (dynobj)
- {
- asection *sgotloc =
- bfd_get_section_by_name (dynobj, ".got.loc");
- if (sgotloc)
- sgotloc->size -= removed_bytes;
- }
+ asection *sgotloc = elf_xtensa_hash_table (link_info)->sgotloc;
+ if (sgotloc)
+ sgotloc->size -= removed_bytes;
}
}
}
@@ -9307,26 +9395,38 @@ do_fix_for_final_link (Elf_Internal_Rela *rel,
/* Miscellaneous utility functions.... */
static asection *
-elf_xtensa_get_plt_section (bfd *dynobj, int chunk)
+elf_xtensa_get_plt_section (struct bfd_link_info *info, int chunk)
{
+ struct elf_xtensa_link_hash_table *htab;
+ bfd *dynobj;
char plt_name[10];
if (chunk == 0)
- return bfd_get_section_by_name (dynobj, ".plt");
+ {
+ htab = elf_xtensa_hash_table (info);
+ return htab->splt;
+ }
+ dynobj = elf_hash_table (info)->dynobj;
sprintf (plt_name, ".plt.%u", chunk);
return bfd_get_section_by_name (dynobj, plt_name);
}
static asection *
-elf_xtensa_get_gotplt_section (bfd *dynobj, int chunk)
+elf_xtensa_get_gotplt_section (struct bfd_link_info *info, int chunk)
{
+ struct elf_xtensa_link_hash_table *htab;
+ bfd *dynobj;
char got_name[14];
if (chunk == 0)
- return bfd_get_section_by_name (dynobj, ".got.plt");
+ {
+ htab = elf_xtensa_hash_table (info);
+ return htab->sgotplt;
+ }
+ dynobj = elf_hash_table (info)->dynobj;
sprintf (got_name, ".got.plt.%u", chunk);
return bfd_get_section_by_name (dynobj, got_name);
}
@@ -9474,24 +9574,23 @@ pcrel_reloc_fits (xtensa_opcode opc,
}
-static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
-static int insn_sec_len = sizeof (XTENSA_INSN_SEC_NAME) - 1;
-static int lit_sec_len = sizeof (XTENSA_LIT_SEC_NAME) - 1;
-static int prop_sec_len = sizeof (XTENSA_PROP_SEC_NAME) - 1;
-
-
static bfd_boolean
xtensa_is_property_section (asection *sec)
{
- if (strncmp (XTENSA_INSN_SEC_NAME, sec->name, insn_sec_len) == 0
- || strncmp (XTENSA_LIT_SEC_NAME, sec->name, lit_sec_len) == 0
- || strncmp (XTENSA_PROP_SEC_NAME, sec->name, prop_sec_len) == 0)
+ if (xtensa_is_insntable_section (sec)
+ || xtensa_is_littable_section (sec)
+ || xtensa_is_proptable_section (sec))
return TRUE;
- if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0
- && (strncmp (&sec->name[linkonce_len], "x.", 2) == 0
- || strncmp (&sec->name[linkonce_len], "p.", 2) == 0
- || strncmp (&sec->name[linkonce_len], "prop.", 5) == 0))
+ return FALSE;
+}
+
+
+static bfd_boolean
+xtensa_is_insntable_section (asection *sec)
+{
+ if (CONST_STRNEQ (sec->name, XTENSA_INSN_SEC_NAME)
+ || CONST_STRNEQ (sec->name, ".gnu.linkonce.x."))
return TRUE;
return FALSE;
@@ -9501,12 +9600,19 @@ xtensa_is_property_section (asection *sec)
static bfd_boolean
xtensa_is_littable_section (asection *sec)
{
- if (strncmp (XTENSA_LIT_SEC_NAME, sec->name, lit_sec_len) == 0)
+ if (CONST_STRNEQ (sec->name, XTENSA_LIT_SEC_NAME)
+ || CONST_STRNEQ (sec->name, ".gnu.linkonce.p."))
return TRUE;
- if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0
- && sec->name[linkonce_len] == 'p'
- && sec->name[linkonce_len + 1] == '.')
+ return FALSE;
+}
+
+
+static bfd_boolean
+xtensa_is_proptable_section (asection *sec)
+{
+ if (CONST_STRNEQ (sec->name, XTENSA_PROP_SEC_NAME)
+ || CONST_STRNEQ (sec->name, ".gnu.linkonce.prop."))
return TRUE;
return FALSE;
@@ -9548,13 +9654,44 @@ internal_reloc_matches (const void *ap, const void *bp)
}
-char *
-xtensa_get_property_section_name (asection *sec, const char *base_name)
+/* Predicate function used to look up a section in a particular group. */
+
+static bfd_boolean
+match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
+{
+ const char *gname = inf;
+ const char *group_name = elf_group_name (sec);
+
+ return (group_name == gname
+ || (group_name != NULL
+ && gname != NULL
+ && strcmp (group_name, gname) == 0));
+}
+
+
+static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
+
+asection *
+xtensa_get_property_section (asection *sec, const char *base_name)
{
- if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
+ const char *suffix, *group_name;
+ char *prop_sec_name;
+ asection *prop_sec;
+
+ group_name = elf_group_name (sec);
+ if (group_name)
+ {
+ suffix = strrchr (sec->name, '.');
+ if (suffix == sec->name)
+ suffix = 0;
+ prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1
+ + (suffix ? strlen (suffix) : 0));
+ strcpy (prop_sec_name, base_name);
+ if (suffix)
+ strcat (prop_sec_name, suffix);
+ }
+ else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
{
- char *prop_sec_name;
- const char *suffix;
char *linkonce_kind = 0;
if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0)
@@ -9574,30 +9711,48 @@ xtensa_get_property_section_name (asection *sec, const char *base_name)
suffix = sec->name + linkonce_len;
/* For backward compatibility, replace "t." instead of inserting
the new linkonce_kind (but not for "prop" sections). */
- if (strncmp (suffix, "t.", 2) == 0 && linkonce_kind[1] == '.')
+ if (CONST_STRNEQ (suffix, "t.") && linkonce_kind[1] == '.')
suffix += 2;
strcat (prop_sec_name + linkonce_len, suffix);
+ }
+ else
+ prop_sec_name = strdup (base_name);
+
+ /* Check if the section already exists. */
+ prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name,
+ match_section_group,
+ (void *) group_name);
+ /* If not, create it. */
+ if (! prop_sec)
+ {
+ flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY);
+ flags |= (bfd_get_section_flags (sec->owner, sec)
+ & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES));
+
+ prop_sec = bfd_make_section_anyway_with_flags
+ (sec->owner, strdup (prop_sec_name), flags);
+ if (! prop_sec)
+ return 0;
- return prop_sec_name;
+ elf_group_name (prop_sec) = group_name;
}
- return strdup (base_name);
+ free (prop_sec_name);
+ return prop_sec;
}
flagword
xtensa_get_property_predef_flags (asection *sec)
{
- if (strcmp (sec->name, XTENSA_INSN_SEC_NAME) == 0
- || strncmp (sec->name, ".gnu.linkonce.x.",
- sizeof ".gnu.linkonce.x." - 1) == 0)
+ if (xtensa_is_insntable_section (sec))
return (XTENSA_PROP_INSN
- | XTENSA_PROP_INSN_NO_TRANSFORM
+ | XTENSA_PROP_NO_TRANSFORM
| XTENSA_PROP_INSN_NO_REORDER);
if (xtensa_is_littable_section (sec))
return (XTENSA_PROP_LITERAL
- | XTENSA_PROP_INSN_NO_TRANSFORM
+ | XTENSA_PROP_NO_TRANSFORM
| XTENSA_PROP_INSN_NO_REORDER);
return 0;
@@ -9624,7 +9779,7 @@ xtensa_callback_required_dependence (bfd *abfd,
/* ".plt*" sections have no explicit relocations but they contain L32R
instructions that reference the corresponding ".got.plt*" sections. */
if ((sec->flags & SEC_LINKER_CREATED) != 0
- && strncmp (sec->name, ".plt", 4) == 0)
+ && CONST_STRNEQ (sec->name, ".plt"))
{
asection *sgotplt;
@@ -9701,10 +9856,11 @@ xtensa_callback_required_dependence (bfd *abfd,
module loader so that the literals are not placed after the text. */
static const struct bfd_elf_special_section elf_xtensa_special_sections[] =
{
- { ".fini.literal", 13, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { ".init.literal", 13, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { ".literal", 8, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".fini.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".init.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".xtensa.info"), 0, SHT_NOTE, 0 },
+ { NULL, 0, 0, 0, 0 }
};
#ifndef ELF_ARCH
@@ -9738,7 +9894,10 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] =
#define bfd_elf32_bfd_print_private_bfd_data elf_xtensa_print_private_bfd_data
#define bfd_elf32_bfd_relax_section elf_xtensa_relax_section
#define bfd_elf32_bfd_reloc_type_lookup elf_xtensa_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup \
+ elf_xtensa_reloc_name_lookup
#define bfd_elf32_bfd_set_private_flags elf_xtensa_set_private_flags
+#define bfd_elf32_bfd_link_hash_table_create elf_xtensa_link_hash_table_create
#define elf_backend_adjust_dynamic_symbol elf_xtensa_adjust_dynamic_symbol
#define elf_backend_check_relocs elf_xtensa_check_relocs
@@ -9753,11 +9912,13 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] =
#define elf_backend_grok_prstatus elf_xtensa_grok_prstatus
#define elf_backend_grok_psinfo elf_xtensa_grok_psinfo
#define elf_backend_hide_symbol elf_xtensa_hide_symbol
-#define elf_backend_modify_segment_map elf_xtensa_modify_segment_map
#define elf_backend_object_p elf_xtensa_object_p
#define elf_backend_reloc_type_class elf_xtensa_reloc_type_class
#define elf_backend_relocate_section elf_xtensa_relocate_section
#define elf_backend_size_dynamic_sections elf_xtensa_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_special_sections elf_xtensa_special_sections
+#define elf_backend_action_discarded elf_xtensa_action_discarded
#include "elf32-target.h"