Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Typedefs | Functions | Variables
elf32-xtensa.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include <stdarg.h>
#include <strings.h>
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/xtensa.h"
#include "xtensa-isa.h"
#include "xtensa-config.h"
#include "elf32-target.h"

Go to the source code of this file.

Classes

struct  string_pair
struct  r_reloc_struct
struct  source_reloc_struct
struct  literal_value_struct
struct  value_map_struct
struct  value_map_hash_table_struct

Defines

#define XTENSA_NO_NOP_REMOVAL   0
#define TRACE(str)
#define ELF_DYNAMIC_INTERPRETER   "/lib/ld.so"
#define PLT_ENTRY_SIZE   16
#define PLT_ENTRIES_PER_CHUNK   254
#define elf_xtensa_hash_table(p)   ((struct elf_xtensa_link_hash_table *) ((p)->hash))
#define add_dynamic_entry(TAG, VAL)   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
#define CALL_SEGMENT_BITS   (30)
#define CALL_SEGMENT_SIZE   (1 << CALL_SEGMENT_BITS)
#define MIN_INSN_LENGTH   2
#define L32R_TARGET_REG_OPERAND   0
#define CONST16_TARGET_REG_OPERAND   0
#define CALLN_SOURCE_OPERAND   0
#define INITIAL_HASH_RELOC_BUCKET_COUNT   1024
#define TARGET_LITTLE_SYM   bfd_elf32_xtensa_le_vec
#define TARGET_LITTLE_NAME   "elf32-xtensa-le"
#define TARGET_BIG_SYM   bfd_elf32_xtensa_be_vec
#define TARGET_BIG_NAME   "elf32-xtensa-be"
#define ELF_ARCH   bfd_arch_xtensa
#define ELF_MACHINE_CODE   EM_XTENSA
#define ELF_MACHINE_ALT1   EM_XTENSA_OLD
#define ELF_MAXPAGESIZE   1
#define elf_backend_can_gc_sections   1
#define elf_backend_can_refcount   1
#define elf_backend_plt_readonly   1
#define elf_backend_got_header_size   4
#define elf_backend_want_dynbss   0
#define elf_backend_want_got_plt   1
#define elf_info_to_howto   elf_xtensa_info_to_howto_rela
#define bfd_elf32_bfd_merge_private_bfd_data   elf_xtensa_merge_private_bfd_data
#define bfd_elf32_new_section_hook   elf_xtensa_new_section_hook
#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
#define elf_backend_create_dynamic_sections   elf_xtensa_create_dynamic_sections
#define elf_backend_discard_info   elf_xtensa_discard_info
#define elf_backend_ignore_discarded_relocs   elf_xtensa_ignore_discarded_relocs
#define elf_backend_final_write_processing   elf_xtensa_final_write_processing
#define elf_backend_finish_dynamic_sections   elf_xtensa_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol   elf_xtensa_finish_dynamic_symbol
#define elf_backend_gc_mark_hook   elf_xtensa_gc_mark_hook
#define elf_backend_gc_sweep_hook   elf_xtensa_gc_sweep_hook
#define elf_backend_grok_prstatus   elf_xtensa_grok_prstatus
#define elf_backend_grok_psinfo   elf_xtensa_grok_psinfo
#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

Typedefs

typedef struct r_reloc_struct
typedef struct source_reloc_struct
typedef struct literal_value_struct
typedef struct value_map_struct
typedef struct value_map_hash_table_struct
typedef struct text_action_struct
typedef struct text_action_list_struct

Functions

static bfd_boolean add_extra_plt_sections (struct bfd_link_info *, int)
static char * vsprint_msg (const char *, const char *, static xtensa_opcode get_expanded_call_opcode(bfd_byte int,...)
static reloc_howto_type * elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * elf_xtensa_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst)
static struct bfd_link_hash_tableelf_xtensa_link_hash_table_create (bfd *abfd)
static bfd_boolean elf_xtensa_dynamic_symbol_p (struct elf_link_hash_entry *h, struct bfd_link_info *info)
static int property_table_compare (const void *ap, const void *bp)
static int property_table_matches (const void *ap, const void *bp)
static int xtensa_read_table_entries (bfd *abfd, asection *section, property_table_entry **table_p, const char *sec_name, bfd_boolean output_addr)
static property_table_entryelf_xtensa_find_property_entry (property_table_entry *property_table, int property_table_size, bfd_vma addr)
static bfd_boolean elf_xtensa_in_literal_pool (property_table_entry *lit_table, int lit_table_size, bfd_vma addr)
static bfd_boolean elf_xtensa_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs)
static asectionelf_xtensa_gc_mark_hook (asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
static bfd_boolean elf_xtensa_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED, asection *sec, const Elf_Internal_Rela *relocs)
static bfd_boolean elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
static bfd_boolean elf_xtensa_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, struct elf_link_hash_entry *h)
static bfd_boolean elf_xtensa_allocate_dynrelocs (struct elf_link_hash_entry *h, void *arg)
static void elf_xtensa_allocate_local_got_size (struct bfd_link_info *info)
static bfd_boolean elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
static bfd_reloc_status_type elf_xtensa_do_reloc (reloc_howto_type *howto, bfd *abfd, asection *input_section, bfd_vma relocation, bfd_byte *contents, bfd_vma address, bfd_boolean is_weak_undef, char **error_message)
static char * vsprint_msg (const char *origmsg, const char *fmt, int arglen,...)
static bfd_reloc_status_type bfd_elf_xtensa_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message)
static bfd_vma elf_xtensa_create_plt_entry (struct bfd_link_info *info, bfd *output_bfd, unsigned reloc_index)
static bfd_boolean elf_xtensa_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, asection *input_section, bfd_byte *contents, Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, asection **local_sections)
static bfd_boolean elf_xtensa_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info ATTRIBUTE_UNUSED, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
static int elf_xtensa_combine_prop_entries (bfd *output_bfd, asection *sxtlit, asection *sgotloc)
static bfd_boolean elf_xtensa_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
static bfd_boolean elf_xtensa_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
static bfd_boolean elf_xtensa_set_private_flags (bfd *abfd, flagword flags)
static bfd_boolean elf_xtensa_print_private_bfd_data (bfd *abfd, void *farg)
static bfd_boolean elf_xtensa_object_p (bfd *abfd)
static void elf_xtensa_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
static enum elf_reloc_type_class elf_xtensa_reloc_type_class (const Elf_Internal_Rela *rela)
static bfd_boolean elf_xtensa_discard_info_for_section (bfd *abfd, struct elf_reloc_cookie *cookie, struct bfd_link_info *info, asection *sec)
static bfd_boolean elf_xtensa_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, struct bfd_link_info *info)
static bfd_boolean elf_xtensa_ignore_discarded_relocs (asection *sec)
static unsigned int elf_xtensa_action_discarded (asection *sec)
static bfd_boolean elf_xtensa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
static bfd_boolean elf_xtensa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
static void init_call_opcodes (void)
static bfd_boolean is_indirect_call_opcode (xtensa_opcode opcode)
static bfd_boolean is_direct_call_opcode (xtensa_opcode opcode)
static bfd_boolean is_windowed_call_opcode (xtensa_opcode opcode)
static xtensa_opcode get_const16_opcode (void)
static xtensa_opcode get_l32r_opcode (void)
static bfd_vma l32r_offset (bfd_vma addr, bfd_vma pc)
static int get_relocation_opnd (xtensa_opcode opcode, int r_type)
int get_relocation_slot (int r_type)
static xtensa_opcode get_relocation_opcode (bfd *abfd, asection *sec, bfd_byte *contents, Elf_Internal_Rela *irel)
bfd_boolean is_l32r_relocation (bfd *abfd, asection *sec, bfd_byte *contents, Elf_Internal_Rela *irel)
static bfd_size_type get_asm_simplify_size (bfd_byte *contents, bfd_size_type content_len, bfd_size_type offset)
bfd_boolean is_alt_relocation (int r_type)
bfd_boolean is_operand_relocation (int r_type)
bfd_size_type insn_decode_len (bfd_byte *contents, bfd_size_type content_len, bfd_size_type offset)
xtensa_opcode insn_decode_opcode (bfd_byte *contents, bfd_size_type content_len, bfd_size_type offset, int slot)
static bfd_boolean check_branch_target_aligned (bfd_byte *contents, bfd_size_type content_length, bfd_vma offset, bfd_vma address)
static bfd_boolean check_loop_aligned (bfd_byte *contents, bfd_size_type content_length, bfd_vma offset, bfd_vma address)
static bfd_boolean check_branch_target_aligned_address (bfd_vma addr, int len)
static void init_op_single_format_table (void)
static xtensa_format get_single_format (xtensa_opcode opcode)
static xtensa_insnbuf can_narrow_instruction (xtensa_insnbuf slotbuf, xtensa_format fmt, xtensa_opcode opcode)
static bfd_boolean narrow_instruction (bfd_byte *contents, bfd_size_type content_length, bfd_size_type offset)
static xtensa_insnbuf can_widen_instruction (xtensa_insnbuf slotbuf, xtensa_format fmt, xtensa_opcode opcode)
static bfd_boolean widen_instruction (bfd_byte *contents, bfd_size_type content_length, bfd_size_type offset)
static bfd_reloc_status_type elf_xtensa_do_asm_simplify (bfd_byte *contents, bfd_vma address, bfd_vma content_length, char **error_message)
static bfd_reloc_status_type contract_asm_expansion (bfd_byte *contents, bfd_vma content_length, Elf_Internal_Rela *irel, char **error_message)
static xtensa_opcode swap_callx_for_call_opcode (xtensa_opcode opcode)
static xtensa_opcode get_expanded_call_opcode (bfd_byte *buf, int bufsize, bfd_boolean *p_uses_l32r)
static bfd_boolean r_reloc_is_const (const r_reloc *r_rel)
static bfd_vma r_reloc_get_target_offset (const r_reloc *r_rel)
static struct elf_link_hash_entryr_reloc_get_hash_entry (const r_reloc *r_rel)
static asectionr_reloc_get_section (const r_reloc *r_rel)
static bfd_boolean r_reloc_is_defined (const r_reloc *r_rel)
static void r_reloc_init (r_reloc *r_rel, bfd *abfd, Elf_Internal_Rela *irel, bfd_byte *contents, bfd_size_type content_length)
static void init_source_reloc (source_reloc *reloc, asection *source_sec, const r_reloc *r_rel, xtensa_opcode opcode, int opnd, bfd_boolean is_abs_literal)
static source_reloc * find_source_reloc (source_reloc *src_relocs, int src_count, asection *sec, Elf_Internal_Rela *irel)
static int source_reloc_compare (const void *ap, const void *bp)
static void init_literal_value (literal_value *lit, const r_reloc *r_rel, unsigned long value, bfd_boolean is_abs_literal)
static bfd_boolean literal_value_equal (const literal_value *src1, const literal_value *src2, bfd_boolean final_static_link)
static value_map_hash_table * value_map_hash_table_init (void)
static void value_map_hash_table_delete (value_map_hash_table *table)
static unsigned hash_bfd_vma (bfd_vma val)
static unsigned literal_value_hash (const literal_value *src)
static value_map * value_map_get_cached_value (value_map_hash_table *map, const literal_value *val, bfd_boolean final_static_link)
static value_map * add_value_map (value_map_hash_table *map, const literal_value *val, const r_reloc *loc, bfd_boolean final_static_link)

Variables

static const bfd_byte elf_xtensa_be_plt_entry [PLT_ENTRY_SIZE]
static const bfd_byte elf_xtensa_le_plt_entry [PLT_ENTRY_SIZE]
static xtensa_opcode callx0_op = XTENSA_UNDEFINED
static xtensa_opcode callx4_op = XTENSA_UNDEFINED
static xtensa_opcode callx8_op = XTENSA_UNDEFINED
static xtensa_opcode callx12_op = XTENSA_UNDEFINED
static xtensa_opcode call0_op = XTENSA_UNDEFINED
static xtensa_opcode call4_op = XTENSA_UNDEFINED
static xtensa_opcode call8_op = XTENSA_UNDEFINED
static xtensa_opcode call12_op = XTENSA_UNDEFINED
static xtensa_formatop_single_fmt_table = NULL

Class Documentation

struct elf_xtensa_link_hash_table

Definition at line 474 of file elf32-xtensa.c.

Collaboration diagram for elf_xtensa_link_hash_table:
Class Members
int plt_reloc_count
asection * sgot
asection * sgotloc
asection * sgotplt
asection * splt
asection * spltlittbl
asection * srelgot
asection * srelplt
struct string_pair

Definition at line 3487 of file elf32-xtensa.c.

Class Members
const char * narrow
const char * wide
struct r_reloc_struct

Definition at line 4077 of file elf32-xtensa.c.

Collaboration diagram for r_reloc_struct:
Class Members
bfd * abfd
Elf_Internal_Rela rela
bfd_vma target_offset
bfd_vma virtual_offset
struct source_reloc_struct

Definition at line 4223 of file elf32-xtensa.c.

Collaboration diagram for source_reloc_struct:
Class Members
bfd_boolean is_abs_literal
bfd_boolean is_null
xtensa_opcode opcode
int opnd
r_reloc r_rel
asection * source_sec
struct literal_value_struct

Definition at line 4315 of file elf32-xtensa.c.

Class Members
bfd_boolean is_abs_literal
r_reloc r_rel
unsigned long value
struct value_map_struct

Definition at line 4322 of file elf32-xtensa.c.

Class Members
r_reloc loc
value_map * next
literal_value val
struct value_map_hash_table_struct

Definition at line 4329 of file elf32-xtensa.c.

Class Members
unsigned bucket_count
value_map ** buckets
unsigned count
bfd_boolean has_last_loc
r_reloc last_loc

Define Documentation

#define add_dynamic_entry (   TAG,
  VAL 
)    _bfd_elf_add_dynamic_entry (info, TAG, VAL)
#define bfd_elf32_bfd_relax_section   elf_xtensa_relax_section
#define bfd_elf32_new_section_hook   elf_xtensa_new_section_hook
#define CALL_SEGMENT_BITS   (30)

Definition at line 1505 of file elf32-xtensa.c.

#define CALL_SEGMENT_SIZE   (1 << CALL_SEGMENT_BITS)

Definition at line 1506 of file elf32-xtensa.c.

#define CALLN_SOURCE_OPERAND   0

Definition at line 3961 of file elf32-xtensa.c.

Definition at line 3960 of file elf32-xtensa.c.

#define ELF_ARCH   bfd_arch_xtensa
#define elf_backend_can_refcount   1
#define elf_backend_plt_readonly   1
#define elf_backend_special_sections   elf_xtensa_special_sections
#define elf_backend_want_dynbss   0
#define elf_backend_want_got_plt   1
#define ELF_DYNAMIC_INTERPRETER   "/lib/ld.so"

Definition at line 427 of file elf32-xtensa.c.

#define ELF_MAXPAGESIZE   1
#define elf_xtensa_hash_table (   p)    ((struct elf_xtensa_link_hash_table *) ((p)->hash))

Definition at line 498 of file elf32-xtensa.c.

Definition at line 4405 of file elf32-xtensa.c.

#define L32R_TARGET_REG_OPERAND   0

Definition at line 3959 of file elf32-xtensa.c.

#define MIN_INSN_LENGTH   2

Definition at line 3303 of file elf32-xtensa.c.

#define PLT_ENTRIES_PER_CHUNK   254

Definition at line 445 of file elf32-xtensa.c.

#define PLT_ENTRY_SIZE   16

Definition at line 433 of file elf32-xtensa.c.

#define TARGET_BIG_NAME   "elf32-xtensa-be"
#define TARGET_LITTLE_NAME   "elf32-xtensa-le"
#define TRACE (   str)

Definition at line 291 of file elf32-xtensa.c.

#define XTENSA_NO_NOP_REMOVAL   0

Definition at line 34 of file elf32-xtensa.c.


Typedef Documentation

Definition at line 4311 of file elf32-xtensa.c.

Definition at line 4075 of file elf32-xtensa.c.

Definition at line 4221 of file elf32-xtensa.c.

Definition at line 4556 of file elf32-xtensa.c.

Definition at line 4555 of file elf32-xtensa.c.

Definition at line 4313 of file elf32-xtensa.c.

Definition at line 4312 of file elf32-xtensa.c.


Function Documentation

static bfd_boolean add_extra_plt_sections ( struct bfd_link_info info,
int  count 
) [static]

Definition at line 1108 of file elf32-xtensa.c.

{
  bfd *dynobj = elf_hash_table (info)->dynobj;
  int chunk;

  /* Iterate over all chunks except 0 which uses the standard ".plt" and
     ".got.plt" sections.  */
  for (chunk = count / PLT_ENTRIES_PER_CHUNK; chunk > 0; chunk--)
    {
      char *sname;
      flagword flags;
      asection *s;

      /* Stop when we find a section has already been created.  */
      if (elf_xtensa_get_plt_section (info, chunk))
       break;

      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
              | SEC_LINKER_CREATED | SEC_READONLY);

      sname = (char *) bfd_malloc (10);
      sprintf (sname, ".plt.%u", chunk);
      s = bfd_make_section_with_flags (dynobj, sname, flags | SEC_CODE);
      if (s == NULL
         || ! bfd_set_section_alignment (dynobj, s, 2))
       return FALSE;

      sname = (char *) bfd_malloc (14);
      sprintf (sname, ".got.plt.%u", chunk);
      s = bfd_make_section_with_flags (dynobj, sname, flags);
      if (s == NULL
         || ! bfd_set_section_alignment (dynobj, s, 2))
       return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static value_map* add_value_map ( value_map_hash_table *  map,
const literal_value *  val,
const r_reloc *  loc,
bfd_boolean  final_static_link 
) [static]

Definition at line 4496 of file elf32-xtensa.c.

{
  value_map **bucket_p;
  unsigned idx;

  value_map *val_e = (value_map *) bfd_zmalloc (sizeof (value_map));
  if (val_e == NULL)
    {
      bfd_set_error (bfd_error_no_memory);
      return NULL;
    }

  BFD_ASSERT (!value_map_get_cached_value (map, val, final_static_link));
  val_e->val = *val;
  val_e->loc = *loc;

  idx = literal_value_hash (val);
  idx = idx & (map->bucket_count - 1);
  bucket_p = &map->buckets[idx];

  val_e->next = *bucket_p;
  *bucket_p = val_e;
  map->count++;
  /* FIXME: Consider resizing the hash table if we get too many entries.  */
  
  return val_e;
}

Here is the call graph for this function:

static bfd_reloc_status_type bfd_elf_xtensa_reloc ( bfd abfd,
arelent reloc_entry,
asymbol symbol,
void *  data,
asection input_section,
bfd output_bfd,
char **  error_message 
) [static]

Definition at line 1777 of file elf32-xtensa.c.

{
  bfd_vma relocation;
  bfd_reloc_status_type flag;
  bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
  bfd_vma output_base = 0;
  reloc_howto_type *howto = reloc_entry->howto;
  asection *reloc_target_output_section;
  bfd_boolean is_weak_undef;

  if (!xtensa_default_isa)
    xtensa_default_isa = xtensa_isa_init (0, 0);

  /* ELF relocs are against symbols.  If we are producing relocatable
     output, and the reloc is against an external symbol, the resulting
     reloc will also be against the same symbol.  In such a case, we
     don't want to change anything about the way the reloc is handled,
     since it will all be done at final link time.  This test is similar
     to what bfd_elf_generic_reloc does except that it lets relocs with
     howto->partial_inplace go through even if the addend is non-zero.
     (The real problem is that partial_inplace is set for XTENSA_32
     relocs to begin with, but that's a long story and there's little we
     can do about it now....)  */

  if (output_bfd && (symbol->flags & BSF_SECTION_SYM) == 0)
    {
      reloc_entry->address += input_section->output_offset;
      return bfd_reloc_ok;
    }

  /* Is the address of the relocation really within the section?  */
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
    return bfd_reloc_outofrange;

  /* Work out which section the relocation is targeted at and the
     initial relocation command value.  */

  /* Get symbol value.  (Common symbols are special.)  */
  if (bfd_is_com_section (symbol->section))
    relocation = 0;
  else
    relocation = symbol->value;

  reloc_target_output_section = symbol->section->output_section;

  /* Convert input-section-relative symbol value to absolute.  */
  if ((output_bfd && !howto->partial_inplace)
      || reloc_target_output_section == NULL)
    output_base = 0;
  else
    output_base = reloc_target_output_section->vma;

  relocation += output_base + symbol->section->output_offset;

  /* Add in supplied addend.  */
  relocation += reloc_entry->addend;

  /* Here the variable relocation holds the final address of the
     symbol we are relocating against, plus any addend.  */
  if (output_bfd)
    {
      if (!howto->partial_inplace)
       {
         /* This is a partial relocation, and we want to apply the relocation
            to the reloc entry rather than the raw data.  Everything except
            relocations against section symbols has already been handled
            above.  */

         BFD_ASSERT (symbol->flags & BSF_SECTION_SYM);
         reloc_entry->addend = relocation;
         reloc_entry->address += input_section->output_offset;
         return bfd_reloc_ok;
       }
      else
       {
         reloc_entry->address += input_section->output_offset;
         reloc_entry->addend = 0;
       }
    }

  is_weak_undef = (bfd_is_und_section (symbol->section)
                 && (symbol->flags & BSF_WEAK) != 0);
  flag = elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
                           (bfd_byte *) data, (bfd_vma) octets,
                           is_weak_undef, error_message);

  if (flag == bfd_reloc_dangerous)
    {
      /* Add the symbol name to the error message.  */
      if (! *error_message)
       *error_message = "";
      *error_message = vsprint_msg (*error_message, ": (%s + 0x%lx)",
                                strlen (symbol->name) + 17,
                                symbol->name,
                                (unsigned long) reloc_entry->addend);
    }

  return flag;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static xtensa_insnbuf can_narrow_instruction ( xtensa_insnbuf  slotbuf,
xtensa_format  fmt,
xtensa_opcode  opcode 
) [static]

Definition at line 3529 of file elf32-xtensa.c.

{
  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 (narrowable)/sizeof (struct string_pair)); opi++)
    {
      bfd_boolean is_or = (strcmp ("or", narrowable[opi].wide) == 0);

      if (opcode == xtensa_opcode_lookup (isa, narrowable[opi].wide))
       {
         uint32 value, newval;
         int i, operand_count, o_operand_count;
         xtensa_opcode o_opcode;

         /* Address does not matter in this case.  We might need to
            fix it to handle branches/jumps.  */
         bfd_vma self_address = 0;

         o_opcode = xtensa_opcode_lookup (isa, narrowable[opi].narrow);
         if (o_opcode == XTENSA_UNDEFINED)
           return 0;
         o_fmt = get_single_format (o_opcode);
         if (o_fmt == XTENSA_UNDEFINED)
           return 0;

         if (xtensa_format_length (isa, fmt) != 3
             || xtensa_format_length (isa, o_fmt) != 2)
           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 0;

         if (!is_or)
           {
             if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
              return 0;
           }
         else
           {
             uint32 rawval0, rawval1, rawval2;

             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)
           {
             if (xtensa_operand_get_field (isa, opcode, i, fmt, 0,
                                       slotbuf, &value)
                || xtensa_operand_decode (isa, opcode, i, &value))
              return 0;

             /* PC-relative branches need adjustment, but
               the PC-rel operand will always have a relocation.  */
             newval = value;
             if (xtensa_operand_do_reloc (isa, o_opcode, i, &newval,
                                      self_address)
                || xtensa_operand_encode (isa, o_opcode, i, &newval)
                || xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
                                          o_slotbuf, newval))
              return 0;
           }

         if (xtensa_format_set_slot (isa, o_fmt, 0, o_insnbuf, o_slotbuf))
           return 0;

         return o_insnbuf;
       }
    }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static xtensa_insnbuf can_widen_instruction ( xtensa_insnbuf  slotbuf,
xtensa_format  fmt,
xtensa_opcode  opcode 
) [static]

Definition at line 3693 of file elf32-xtensa.c.

{
  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
                            || strcmp ("bnez", widenable[opi].wide) == 0);

      if (opcode == xtensa_opcode_lookup (isa, widenable[opi].narrow))
       {
         uint32 value, newval;
         int i, operand_count, o_operand_count, check_operand_count;
         xtensa_opcode o_opcode;

         /* Address does not matter in this case.  We might need to fix it
            to handle branches/jumps.  */
         bfd_vma self_address = 0;

         o_opcode = xtensa_opcode_lookup (isa, widenable[opi].wide);
         if (o_opcode == XTENSA_UNDEFINED)
           return 0;
         o_fmt = get_single_format (o_opcode);
         if (o_fmt == XTENSA_UNDEFINED)
           return 0;

         if (xtensa_format_length (isa, fmt) != 2
             || xtensa_format_length (isa, o_fmt) != 3)
           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);
         check_operand_count = o_operand_count;

         if (xtensa_opcode_encode (isa, o_fmt, 0, o_slotbuf, o_opcode) != 0)
           return 0;

         if (!is_or)
           {
             if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
              return 0;
           }
         else
           {
             uint32 rawval0, rawval1;

             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++)
           {
             int new_i = i;
             if (is_or && i == o_operand_count - 1)
              new_i = i - 1;
             if (xtensa_operand_get_field (isa, opcode, new_i, fmt, 0,
                                       slotbuf, &value)
                || xtensa_operand_decode (isa, opcode, new_i, &value))
              return 0;

             /* PC-relative branches need adjustment, but
               the PC-rel operand will always have a relocation.  */
             newval = value;
             if (xtensa_operand_do_reloc (isa, o_opcode, i, &newval,
                                      self_address)
                || xtensa_operand_encode (isa, o_opcode, i, &newval)
                || xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
                                          o_slotbuf, newval))
              return 0;
           }

         if (xtensa_format_set_slot (isa, o_fmt, 0, o_insnbuf, o_slotbuf))
           return 0;

         return o_insnbuf;
       }
    }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean check_branch_target_aligned ( bfd_byte contents,
bfd_size_type  content_length,
bfd_vma  offset,
bfd_vma  address 
) [static]

Definition at line 3375 of file elf32-xtensa.c.

{
  bfd_size_type insn_len = insn_decode_len (contents, content_length, offset);
  if (insn_len == 0)
    return FALSE;
  return check_branch_target_aligned_address (address, insn_len);
}

Here is the call graph for this function:

static bfd_boolean check_branch_target_aligned_address ( bfd_vma  addr,
int  len 
) [static]

Definition at line 3417 of file elf32-xtensa.c.

{
  if (len == 8)
    return (addr % 8 == 0);
  return ((addr >> 2) == ((addr + len - 1) >> 2));
}

Here is the caller graph for this function:

static bfd_boolean check_loop_aligned ( bfd_byte contents,
bfd_size_type  content_length,
bfd_vma  offset,
bfd_vma  address 
) [static]

Definition at line 3388 of file elf32-xtensa.c.

{
  bfd_size_type loop_len, insn_len;
  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);
  insn_len = insn_decode_len (contents, content_length, offset + loop_len);
  if (loop_len == 0 || insn_len == 0)
    {
      BFD_ASSERT (FALSE);
      return FALSE;
    }

  return check_branch_target_aligned_address (address + loop_len, insn_len);
}

Here is the call graph for this function:

static bfd_reloc_status_type contract_asm_expansion ( bfd_byte contents,
bfd_vma  content_length,
Elf_Internal_Rela irel,
char **  error_message 
) [static]

Definition at line 3920 of file elf32-xtensa.c.

{
  bfd_reloc_status_type retval =
    elf_xtensa_do_asm_simplify (contents, irel->r_offset, content_length,
                            error_message);

  if (retval != bfd_reloc_ok)
    return bfd_reloc_dangerous;

  /* Update the irel->r_offset field so that the right immediate and
     the right instruction are modified during the relocation.  */
  irel->r_offset += 3;
  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_XTENSA_SLOT0_OP);
  return bfd_reloc_ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned int elf_xtensa_action_discarded ( asection sec) [static]

Definition at line 2958 of file elf32-xtensa.c.

{
  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);
}

Here is the call graph for this function:

Definition at line 1154 of file elf32-xtensa.c.

{
  /* If this is a weak symbol, and there is a real definition, the
     processor independent code will have arranged for us to see the
     real definition first, and we can just use the same value.  */
  if (h->u.weakdef)
    {
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
                || h->u.weakdef->root.type == bfd_link_hash_defweak);
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
      return TRUE;
    }

  /* This is a reference to a symbol defined by a dynamic object.  The
     reference must go through the GOT, so there's no need for COPY relocs,
     .dynbss, etc.  */

  return TRUE;
}
static bfd_boolean elf_xtensa_allocate_dynrelocs ( struct elf_link_hash_entry h,
void *  arg 
) [static]

Definition at line 1178 of file elf32-xtensa.c.

{
  struct bfd_link_info *info;
  struct elf_xtensa_link_hash_table *htab;
  bfd_boolean is_dynamic;

  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;

  info = (struct bfd_link_info *) arg;
  htab = elf_xtensa_hash_table (info);

  is_dynamic = elf_xtensa_dynamic_symbol_p (h, info);

  if (! is_dynamic)
    {
      if (info->shared)
       {
         /* For shared objects, there's no need for PLT entries for local
            symbols (use RELATIVE relocs instead of JMP_SLOT relocs).  */
         if (h->plt.refcount > 0)
           {
             if (h->got.refcount < 0)
              h->got.refcount = 0;
             h->got.refcount += h->plt.refcount;
             h->plt.refcount = 0;
           }
       }
      else
       {
         /* Don't need any dynamic relocations at all.  */
         h->plt.refcount = 0;
         h->got.refcount = 0;
       }
    }

  if (h->plt.refcount > 0)
    htab->srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));

  if (h->got.refcount > 0)
    htab->srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela));

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void elf_xtensa_allocate_local_got_size ( struct bfd_link_info info) [static]

Definition at line 1228 of file elf32-xtensa.c.

{
  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;
      bfd_size_type j, cnt;
      Elf_Internal_Shdr *symtab_hdr;

      local_got_refcounts = elf_local_got_refcounts (i);
      if (!local_got_refcounts)
       continue;

      symtab_hdr = &elf_tdata (i)->symtab_hdr;
      cnt = symtab_hdr->sh_info;

      for (j = 0; j < cnt; ++j)
       {
         if (local_got_refcounts[j] > 0)
           htab->srelgot->size += (local_got_refcounts[j]
                                * sizeof (Elf32_External_Rela));
       }
    }
}

Here is the caller graph for this function:

static bfd_boolean elf_xtensa_check_relocs ( bfd abfd,
struct bfd_link_info info,
asection sec,
const Elf_Internal_Rela relocs 
) [static]

Definition at line 786 of file elf32-xtensa.c.

{
  struct elf_xtensa_link_hash_table *htab;
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  const Elf_Internal_Rela *rel;
  const Elf_Internal_Rela *rel_end;

  if (info->relocatable)
    return TRUE;

  htab = elf_xtensa_hash_table (info);
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);

  rel_end = relocs + sec->reloc_count;
  for (rel = relocs; rel < rel_end; rel++)
    {
      unsigned int r_type;
      unsigned long r_symndx;
      struct elf_link_hash_entry *h;

      r_symndx = ELF32_R_SYM (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);

      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
       {
         (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
                             abfd, r_symndx);
         return FALSE;
       }

      if (r_symndx < symtab_hdr->sh_info)
       h = NULL;
      else
       {
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
         while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
           h = (struct elf_link_hash_entry *) h->root.u.i.link;
       }

      switch (r_type)
       {
       case R_XTENSA_32:
         if (h == NULL)
           goto local_literal;

         if ((sec->flags & SEC_ALLOC) != 0)
           {
             if (h->got.refcount <= 0)
              h->got.refcount = 1;
             else
              h->got.refcount += 1;
           }
         break;

       case R_XTENSA_PLT:
         /* If this relocation is against a local symbol, then it's
            exactly the same as a normal local GOT entry.  */
         if (h == NULL)
           goto local_literal;

         if ((sec->flags & SEC_ALLOC) != 0)
           {
             if (h->plt.refcount <= 0)
              {
                h->needs_plt = 1;
                h->plt.refcount = 1;
              }
             else
              h->plt.refcount += 1;

             /* Keep track of the total PLT relocation count even if we
               don't yet know whether the dynamic sections will be
               created.  */
             htab->plt_reloc_count += 1;

             if (elf_hash_table (info)->dynamic_sections_created)
              {
                if (! add_extra_plt_sections (info, htab->plt_reloc_count))
                  return FALSE;
              }
           }
         break;

       local_literal:
         if ((sec->flags & SEC_ALLOC) != 0)
           {
             bfd_signed_vma *local_got_refcounts;

             /* This is a global offset table entry for a local symbol.  */
             local_got_refcounts = elf_local_got_refcounts (abfd);
             if (local_got_refcounts == NULL)
              {
                bfd_size_type size;

                size = symtab_hdr->sh_info;
                size *= sizeof (bfd_signed_vma);
                local_got_refcounts =
                  (bfd_signed_vma *) bfd_zalloc (abfd, size);
                if (local_got_refcounts == NULL)
                  return FALSE;
                elf_local_got_refcounts (abfd) = local_got_refcounts;
              }
             local_got_refcounts[r_symndx] += 1;
           }
         break;

       case R_XTENSA_OP0:
       case R_XTENSA_OP1:
       case R_XTENSA_OP2:
       case R_XTENSA_SLOT0_OP:
       case R_XTENSA_SLOT1_OP:
       case R_XTENSA_SLOT2_OP:
       case R_XTENSA_SLOT3_OP:
       case R_XTENSA_SLOT4_OP:
       case R_XTENSA_SLOT5_OP:
       case R_XTENSA_SLOT6_OP:
       case R_XTENSA_SLOT7_OP:
       case R_XTENSA_SLOT8_OP:
       case R_XTENSA_SLOT9_OP:
       case R_XTENSA_SLOT10_OP:
       case R_XTENSA_SLOT11_OP:
       case R_XTENSA_SLOT12_OP:
       case R_XTENSA_SLOT13_OP:
       case R_XTENSA_SLOT14_OP:
       case R_XTENSA_SLOT0_ALT:
       case R_XTENSA_SLOT1_ALT:
       case R_XTENSA_SLOT2_ALT:
       case R_XTENSA_SLOT3_ALT:
       case R_XTENSA_SLOT4_ALT:
       case R_XTENSA_SLOT5_ALT:
       case R_XTENSA_SLOT6_ALT:
       case R_XTENSA_SLOT7_ALT:
       case R_XTENSA_SLOT8_ALT:
       case R_XTENSA_SLOT9_ALT:
       case R_XTENSA_SLOT10_ALT:
       case R_XTENSA_SLOT11_ALT:
       case R_XTENSA_SLOT12_ALT:
       case R_XTENSA_SLOT13_ALT:
       case R_XTENSA_SLOT14_ALT:
       case R_XTENSA_ASM_EXPAND:
       case R_XTENSA_ASM_SIMPLIFY:
       case R_XTENSA_DIFF8:
       case R_XTENSA_DIFF16:
       case R_XTENSA_DIFF32:
         /* Nothing to do for these.  */
         break;

       case R_XTENSA_GNU_VTINHERIT:
         /* This relocation describes the C++ object vtable hierarchy.
            Reconstruct it for later use during GC.  */
         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
           return FALSE;
         break;

       case R_XTENSA_GNU_VTENTRY:
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
           return FALSE;
         break;

       default:
         break;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

static int elf_xtensa_combine_prop_entries ( bfd output_bfd,
asection sxtlit,
asection sgotloc 
) [static]

Definition at line 2359 of file elf32-xtensa.c.

{
  bfd_byte *contents;
  property_table_entry *table;
  bfd_size_type section_size, sgotloc_size;
  bfd_vma offset;
  int n, m, num;

  section_size = sxtlit->size;
  BFD_ASSERT (section_size % 8 == 0);
  num = section_size / 8;

  sgotloc_size = sgotloc->size;
  if (sgotloc_size != section_size)
    {
      (*_bfd_error_handler)
       (_("internal inconsistency in size of .got.loc section"));
      return -1;
    }

  table = bfd_malloc (num * sizeof (property_table_entry));
  if (table == 0)
    return -1;

  /* The ".xt.lit.plt" section has the SEC_IN_MEMORY flag set and this
     propagates to the output section, where it doesn't really apply and
     where it breaks the following call to bfd_malloc_and_get_section.  */
  sxtlit->flags &= ~SEC_IN_MEMORY;

  if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
    {
      if (contents != 0)
       free (contents);
      free (table);
      return -1;
    }

  /* There should never be any relocations left at this point, so this
     is quite a bit easier than what is done during relaxation.  */

  /* Copy the raw contents into a property table array and sort it.  */
  offset = 0;
  for (n = 0; n < num; n++)
    {
      table[n].address = bfd_get_32 (output_bfd, &contents[offset]);
      table[n].size = bfd_get_32 (output_bfd, &contents[offset + 4]);
      offset += 8;
    }
  qsort (table, num, sizeof (property_table_entry), property_table_compare);

  for (n = 0; n < num; n++)
    {
      bfd_boolean remove = FALSE;

      if (table[n].size == 0)
       remove = TRUE;
      else if (n > 0 &&
              (table[n-1].address + table[n-1].size == table[n].address))
       {
         table[n-1].size += table[n].size;
         remove = TRUE;
       }

      if (remove)
       {
         for (m = n; m < num - 1; m++)
           {
             table[m].address = table[m+1].address;
             table[m].size = table[m+1].size;
           }

         n--;
         num--;
       }
    }

  /* Copy the data back to the raw contents.  */
  offset = 0;
  for (n = 0; n < num; n++)
    {
      bfd_put_32 (output_bfd, table[n].address, &contents[offset]);
      bfd_put_32 (output_bfd, table[n].size, &contents[offset + 4]);
      offset += 8;
    }

  /* Clear the removed bytes.  */
  if ((bfd_size_type) (num * 8) < section_size)
    memset (&contents[num * 8], 0, section_size - num * 8);

  if (! bfd_set_section_contents (output_bfd, sxtlit, contents, 0,
                              section_size))
    return -1;

  /* Copy the contents to ".got.loc".  */
  memcpy (sgotloc->contents, contents, section_size);

  free (contents);
  free (table);
  return num;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf_xtensa_create_dynamic_sections ( bfd dynobj,
struct bfd_link_info info 
) [static]

Definition at line 1055 of file elf32-xtensa.c.

{
  struct elf_xtensa_link_hash_table *htab;
  flagword flags, noalloc_flags;

  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 (info, htab->plt_reloc_count))
    return FALSE;

  noalloc_flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
                 | SEC_LINKER_CREATED | SEC_READONLY);
  flags = noalloc_flags | SEC_ALLOC | SEC_LOAD;

  /* Mark the ".got.plt" section READONLY.  */
  if (htab->sgotplt == NULL
      || ! bfd_set_section_flags (dynobj, htab->sgotplt, flags))
    return FALSE;

  /* Create ".rela.got".  */
  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).  */
  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*").  */
  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;
}

Here is the call graph for this function:

static bfd_vma elf_xtensa_create_plt_entry ( struct bfd_link_info info,
bfd output_bfd,
unsigned  reloc_index 
) [static]

Definition at line 1887 of file elf32-xtensa.c.

{
  asection *splt, *sgotplt;
  bfd_vma plt_base, got_base;
  bfd_vma code_offset, lit_offset;
  int chunk;

  chunk = reloc_index / PLT_ENTRIES_PER_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;
  got_base = sgotplt->output_section->vma + sgotplt->output_offset;

  lit_offset = 8 + (reloc_index % PLT_ENTRIES_PER_CHUNK) * 4;
  code_offset = (reloc_index % PLT_ENTRIES_PER_CHUNK) * PLT_ENTRY_SIZE;

  /* Fill in the literal entry.  This is the offset of the dynamic
     relocation entry.  */
  bfd_put_32 (output_bfd, reloc_index * sizeof (Elf32_External_Rela),
             sgotplt->contents + lit_offset);

  /* Fill in the entry in the procedure linkage table.  */
  memcpy (splt->contents + code_offset,
         (bfd_big_endian (output_bfd)
          ? elf_xtensa_be_plt_entry
          : elf_xtensa_le_plt_entry),
         PLT_ENTRY_SIZE);
  bfd_put_16 (output_bfd, l32r_offset (got_base + 0,
                                   plt_base + code_offset + 3),
             splt->contents + code_offset + 4);
  bfd_put_16 (output_bfd, l32r_offset (got_base + 4,
                                   plt_base + code_offset + 6),
             splt->contents + code_offset + 7);
  bfd_put_16 (output_bfd, l32r_offset (got_base + lit_offset,
                                   plt_base + code_offset + 9),
             splt->contents + code_offset + 10);

  return plt_base + code_offset;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf_xtensa_discard_info ( bfd abfd,
struct elf_reloc_cookie cookie,
struct bfd_link_info info 
) [static]

Definition at line 2930 of file elf32-xtensa.c.

{
  asection *sec;
  bfd_boolean changed = FALSE;

  for (sec = abfd->sections; sec != NULL; sec = sec->next)
    {
      if (xtensa_is_property_section (sec))
       {
         if (elf_xtensa_discard_info_for_section (abfd, cookie, info, sec))
           changed = TRUE;
       }
    }

  return changed;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_discard_info_for_section ( bfd abfd,
struct elf_reloc_cookie cookie,
struct bfd_link_info info,
asection sec 
) [static]

Definition at line 2811 of file elf32-xtensa.c.

{
  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;

  if (sec->output_section
      && bfd_is_abs_section (sec->output_section))
    return FALSE;

  contents = retrieve_contents (abfd, sec, info->keep_memory);
  if (!contents)
    return FALSE;

  cookie->rels = retrieve_internal_relocs (abfd, sec, info->keep_memory);
  if (!cookie->rels)
    {
      release_contents (sec, contents);
      return FALSE;
    }

  cookie->rel = cookie->rels;
  cookie->relend = cookie->rels + sec->reloc_count;

  for (offset = 0; offset < section_size; offset += 8)
    {
      actual_offset = offset - removed_bytes;

      /* The ...symbol_deleted_p function will skip over relocs but it
        won't adjust their offsets, so do that here.  */
      while (cookie->rel < cookie->relend
            && cookie->rel->r_offset < offset)
       {
         cookie->rel->r_offset -= removed_bytes;
         cookie->rel++;
       }

      while (cookie->rel < cookie->relend
            && cookie->rel->r_offset == offset)
       {
         if (bfd_elf_reloc_symbol_deleted_p (offset, cookie))
           {
             /* Remove the table entry.  (If the reloc type is NONE, then
               the entry has already been merged with another and deleted
               during relaxation.)  */
             if (ELF32_R_TYPE (cookie->rel->r_info) != R_XTENSA_NONE)
              {
                /* Shift the contents up.  */
                if (offset + 8 < section_size)
                  memmove (&contents[actual_offset],
                          &contents[actual_offset+8],
                          section_size - offset - 8);
                removed_bytes += 8;
              }

             /* Remove this relocation.  */
             cookie->rel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
           }

         /* Adjust the relocation offset for previous removals.  This
            should not be done before calling ...symbol_deleted_p
            because it might mess up the offset comparisons there.
            Make sure the offset doesn't underflow in the case where
            the first entry is removed.  */
         if (cookie->rel->r_offset >= removed_bytes)
           cookie->rel->r_offset -= removed_bytes;
         else
           cookie->rel->r_offset = 0;

         cookie->rel++;
       }
    }

  if (removed_bytes != 0)
    {
      /* Adjust any remaining relocs (shouldn't be any).  */
      for (; cookie->rel < cookie->relend; cookie->rel++)
       {
         if (cookie->rel->r_offset >= removed_bytes)
           cookie->rel->r_offset -= removed_bytes;
         else
           cookie->rel->r_offset = 0;
       }

      /* Clear the removed bytes.  */
      memset (&contents[section_size - removed_bytes], 0, removed_bytes);

      pin_contents (sec, contents);
      pin_internal_relocs (sec, cookie->rels);

      /* Shrink size.  */
      sec->size = section_size - removed_bytes;

      if (xtensa_is_littable_section (sec))
       {
         asection *sgotloc = elf_xtensa_hash_table (info)->sgotloc;
         if (sgotloc)
           sgotloc->size -= removed_bytes;
       }
    }
  else
    {
      release_contents (sec, contents);
      release_internal_relocs (sec, cookie->rels);
    }

  return (removed_bytes != 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_reloc_status_type elf_xtensa_do_asm_simplify ( bfd_byte contents,
bfd_vma  address,
bfd_vma  content_length,
char **  error_message 
) [static]

Definition at line 3857 of file elf32-xtensa.c.

{
  static xtensa_insnbuf insnbuf = NULL;
  static xtensa_insnbuf slotbuf = NULL;
  xtensa_format core_format = XTENSA_UNDEFINED;
  xtensa_opcode opcode;
  xtensa_opcode direct_call_opcode;
  xtensa_isa isa = xtensa_default_isa;
  bfd_byte *chbuf = contents + address;
  int opn;

  if (insnbuf == NULL)
    {
      insnbuf = xtensa_insnbuf_alloc (isa);
      slotbuf = xtensa_insnbuf_alloc (isa);
    }

  if (content_length < address)
    {
      *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
      return bfd_reloc_other;
    }

  opcode = get_expanded_call_opcode (chbuf, content_length - address, 0);
  direct_call_opcode = swap_callx_for_call_opcode (opcode);
  if (direct_call_opcode == XTENSA_UNDEFINED)
    {
      *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
      return bfd_reloc_other;
    }
  
  /* Assemble a NOP ("or a1, a1, a1") into the 0 byte offset.  */
  core_format = xtensa_format_lookup (isa, "x24");
  opcode = xtensa_opcode_lookup (isa, "or");
  xtensa_opcode_encode (isa, core_format, 0, slotbuf, opcode);
  for (opn = 0; opn < 3; opn++) 
    {
      uint32 regno = 1;
      xtensa_operand_encode (isa, opcode, opn, &regno);
      xtensa_operand_set_field (isa, opcode, opn, core_format, 0,
                            slotbuf, regno);
    }
  xtensa_format_encode (isa, core_format, insnbuf);
  xtensa_format_set_slot (isa, core_format, 0, insnbuf, slotbuf);
  xtensa_insnbuf_to_chars (isa, insnbuf, chbuf, content_length - address);

  /* Assemble a CALL ("callN 0") into the 3 byte offset.  */
  xtensa_opcode_encode (isa, core_format, 0, slotbuf, direct_call_opcode);
  xtensa_operand_set_field (isa, opcode, 0, core_format, 0, slotbuf, 0);

  xtensa_format_encode (isa, core_format, insnbuf);
  xtensa_format_set_slot (isa, core_format, 0, insnbuf, slotbuf);
  xtensa_insnbuf_to_chars (isa, insnbuf, chbuf + 3,
                        content_length - address - 3);

  return bfd_reloc_ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_reloc_status_type elf_xtensa_do_reloc ( reloc_howto_type *  howto,
bfd abfd,
asection input_section,
bfd_vma  relocation,
bfd_byte contents,
bfd_vma  address,
bfd_boolean  is_weak_undef,
char **  error_message 
) [static]

Definition at line 1509 of file elf32-xtensa.c.

{
  xtensa_format fmt;
  xtensa_opcode opcode;
  xtensa_isa isa = xtensa_default_isa;
  static xtensa_insnbuf ibuff = NULL;
  static xtensa_insnbuf sbuff = NULL;
  bfd_vma self_address = 0;
  bfd_size_type input_size;
  int opnd, slot;
  uint32 newval;

  if (!ibuff)
    {
      ibuff = xtensa_insnbuf_alloc (isa);
      sbuff = xtensa_insnbuf_alloc (isa);
    }

  input_size = bfd_get_section_limit (abfd, input_section);

  switch (howto->type)
    {
    case R_XTENSA_NONE:
    case R_XTENSA_DIFF8:
    case R_XTENSA_DIFF16:
    case R_XTENSA_DIFF32:
      return bfd_reloc_ok;

    case R_XTENSA_ASM_EXPAND:
      if (!is_weak_undef)
       {
         /* Check for windowed CALL across a 1GB boundary.  */
         xtensa_opcode opcode =
           get_expanded_call_opcode (contents + address,
                                  input_size - address, 0);
         if (is_windowed_call_opcode (opcode))
           {
             self_address = (input_section->output_section->vma
                           + input_section->output_offset
                           + address);
             if ((self_address >> CALL_SEGMENT_BITS)
                != (relocation >> CALL_SEGMENT_BITS)) 
              {
                *error_message = "windowed longcall crosses 1GB boundary; "
                  "return may fail";
                return bfd_reloc_dangerous;
              }
           }
       }
      return bfd_reloc_ok;

    case R_XTENSA_ASM_SIMPLIFY:
      {
        /* Convert the L32R/CALLX to CALL.  */
       bfd_reloc_status_type retval =
         elf_xtensa_do_asm_simplify (contents, address, input_size,
                                  error_message);
       if (retval != bfd_reloc_ok)
         return bfd_reloc_dangerous;

       /* The CALL needs to be relocated.  Continue below for that part.  */
       address += 3;
       howto = &elf_howto_table[(unsigned) R_XTENSA_SLOT0_OP ];
      }
      break;

    case R_XTENSA_32:
    case R_XTENSA_PLT:
      {
       bfd_vma x;
       x = bfd_get_32 (abfd, contents + address);
       x = x + relocation;
       bfd_put_32 (abfd, x, contents + address);
      }
      return bfd_reloc_ok;
    }

  /* Only instruction slot-specific relocations handled below.... */
  slot = get_relocation_slot (howto->type);
  if (slot == XTENSA_UNDEFINED)
    {
      *error_message = "unexpected relocation";
      return bfd_reloc_dangerous;
    }

  /* Read the instruction into a buffer and decode the opcode.  */
  xtensa_insnbuf_from_chars (isa, ibuff, contents + address,
                          input_size - address);
  fmt = xtensa_format_decode (isa, ibuff);
  if (fmt == XTENSA_UNDEFINED)
    {
      *error_message = "cannot decode instruction format";
      return bfd_reloc_dangerous;
    }

  xtensa_format_get_slot (isa, fmt, slot, ibuff, sbuff);

  opcode = xtensa_opcode_decode (isa, fmt, slot, sbuff);
  if (opcode == XTENSA_UNDEFINED)
    {
      *error_message = "cannot decode instruction opcode";
      return bfd_reloc_dangerous;
    }

  /* Check for opcode-specific "alternate" relocations.  */
  if (is_alt_relocation (howto->type))
    {
      if (opcode == get_l32r_opcode ())
       {
         /* Handle the special-case of non-PC-relative L32R instructions.  */
         bfd *output_bfd = input_section->output_section->owner;
         asection *lit4_sec = bfd_get_section_by_name (output_bfd, ".lit4");
         if (!lit4_sec)
           {
             *error_message = "relocation references missing .lit4 section";
             return bfd_reloc_dangerous;
           }
         self_address = ((lit4_sec->vma & ~0xfff)
                       + 0x40000 - 3); /* -3 to compensate for do_reloc */
         newval = relocation;
         opnd = 1;
       }
      else if (opcode == get_const16_opcode ())
       {
         /* ALT used for high 16 bits.  */
         newval = relocation >> 16;
         opnd = 1;
       }
      else
       {
         /* No other "alternate" relocations currently defined.  */
         *error_message = "unexpected relocation";
         return bfd_reloc_dangerous;
       }
    }
  else /* Not an "alternate" relocation.... */
    {
      if (opcode == get_const16_opcode ())
       {
         newval = relocation & 0xffff;
         opnd = 1;
       }
      else
       {
         /* ...normal PC-relative relocation.... */

         /* Determine which operand is being relocated.  */
         opnd = get_relocation_opnd (opcode, howto->type);
         if (opnd == XTENSA_UNDEFINED)
           {
             *error_message = "unexpected relocation";
             return bfd_reloc_dangerous;
           }

         if (!howto->pc_relative)
           {
             *error_message = "expected PC-relative relocation";
             return bfd_reloc_dangerous;
           }

         /* Calculate the PC address for this instruction.  */
         self_address = (input_section->output_section->vma
                       + input_section->output_offset
                       + address);

         newval = relocation;
       }
    }

  /* Apply the relocation.  */
  if (xtensa_operand_do_reloc (isa, opcode, opnd, &newval, self_address)
      || xtensa_operand_encode (isa, opcode, opnd, &newval)
      || xtensa_operand_set_field (isa, opcode, opnd, fmt, slot,
                               sbuff, newval))
    {
      const char *opname = xtensa_opcode_name (isa, opcode);
      const char *msg;

      msg = "cannot encode";
      if (is_direct_call_opcode (opcode))
       {
         if ((relocation & 0x3) != 0)
           msg = "misaligned call target";
         else
           msg = "call target out of range";
       }
      else if (opcode == get_l32r_opcode ())
       {
         if ((relocation & 0x3) != 0)
           msg = "misaligned literal target";
         else if (is_alt_relocation (howto->type))
           msg = "literal target out of range (too many literals)";
         else if (self_address > relocation)
           msg = "literal target out of range (try using text-section-literals)";
         else
           msg = "literal placed after use";
       }

      *error_message = vsprint_msg (opname, ": %s", strlen (msg) + 2, msg);
      return bfd_reloc_dangerous;
    }

  /* Check for calls across 1GB boundaries.  */
  if (is_direct_call_opcode (opcode)
      && is_windowed_call_opcode (opcode))
    {
      if ((self_address >> CALL_SEGMENT_BITS)
         != (relocation >> CALL_SEGMENT_BITS)) 
       {
         *error_message =
           "windowed call crosses 1GB boundary; return may fail";
         return bfd_reloc_dangerous;
       }
    }

  /* Write the modified instruction back out of the buffer.  */
  xtensa_format_set_slot (isa, fmt, slot, ibuff, sbuff);
  xtensa_insnbuf_to_chars (isa, ibuff, contents + address,
                        input_size - address);
  return bfd_reloc_ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 535 of file elf32-xtensa.c.

{
  /* Check if we should do dynamic things to this symbol.  The
     "ignore_protected" argument need not be set, because Xtensa code
     does not require special handling of STV_PROTECTED to make function
     pointer comparisons work properly.  The PLT addresses are never
     used for function pointers.  */

  return _bfd_elf_dynamic_symbol_p (h, info, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void elf_xtensa_final_write_processing ( bfd abfd,
bfd_boolean linker  ATTRIBUTE_UNUSED 
) [static]

Definition at line 2775 of file elf32-xtensa.c.

{
  int mach;
  unsigned long val;

  switch (mach = bfd_get_mach (abfd))
    {
    case bfd_mach_xtensa:
      val = E_XTENSA_MACH;
      break;
    default:
      return;
    }

  elf_elfheader (abfd)->e_flags &=  (~ EF_XTENSA_MACH);
  elf_elfheader (abfd)->e_flags |= val;
}

Here is the call graph for this function:

static property_table_entry* elf_xtensa_find_property_entry ( property_table_entry property_table,
int  property_table_size,
bfd_vma  addr 
) [static]

Definition at line 750 of file elf32-xtensa.c.

{
  property_table_entry entry;
  property_table_entry *rv;

  if (property_table_size == 0)
    return NULL;

  entry.address = addr;
  entry.size = 1;
  entry.flags = 0;

  rv = bsearch (&entry, property_table, property_table_size,
              sizeof (property_table_entry), property_table_matches);
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf_xtensa_finish_dynamic_sections ( bfd output_bfd,
struct bfd_link_info info 
) [static]

Definition at line 2466 of file elf32-xtensa.c.

{
  struct elf_xtensa_link_hash_table *htab;
  bfd *dynobj;
  asection *sdyn, *srelplt, *sgot, *sxtlit, *sgotloc;
  Elf32_External_Dyn *dyncon, *dynconend;
  int num_xtlit_entries;

  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 = htab->sgot;
  if (sgot)
    {
      BFD_ASSERT (sgot->size == 4);
      if (sdyn == NULL)
       bfd_put_32 (output_bfd, 0, sgot->contents);
      else
       bfd_put_32 (output_bfd,
                  sdyn->output_section->vma + sdyn->output_offset,
                  sgot->contents);
    }

  srelplt = htab->srelplt;
  if (srelplt && srelplt->size != 0)
    {
      asection *sgotplt, *srelgot, *spltlittbl;
      int chunk, plt_chunks, plt_entries;
      Elf_Internal_Rela irela;
      bfd_byte *loc;
      unsigned rtld_reloc;

      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....  */
      for (rtld_reloc = 0; rtld_reloc < srelgot->reloc_count; rtld_reloc++)
       {
         loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
         if (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD)
           break;
       }
      BFD_ASSERT (rtld_reloc < srelgot->reloc_count);

      plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
      plt_chunks =
       (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;

      for (chunk = 0; chunk < plt_chunks; chunk++)
       {
         int chunk_entries = 0;

         sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
         BFD_ASSERT (sgotplt != NULL);

         /* Emit special RTLD relocations for the first two entries in
            each chunk of the .got.plt section.  */

         loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
         BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
         irela.r_offset = (sgotplt->output_section->vma
                         + sgotplt->output_offset);
         irela.r_addend = 1; /* tell rtld to set value to resolver function */
         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
         rtld_reloc += 1;
         BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);

         /* Next literal immediately follows the first.  */
         loc += sizeof (Elf32_External_Rela);
         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
         BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
         irela.r_offset = (sgotplt->output_section->vma
                         + sgotplt->output_offset + 4);
         /* Tell rtld to set value to object's link map.  */
         irela.r_addend = 2;
         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
         rtld_reloc += 1;
         BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);

         /* Fill in the literal table.  */
         if (chunk < plt_chunks - 1)
           chunk_entries = PLT_ENTRIES_PER_CHUNK;
         else
           chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);

         BFD_ASSERT ((unsigned) (chunk + 1) * 8 <= spltlittbl->size);
         bfd_put_32 (output_bfd,
                    sgotplt->output_section->vma + sgotplt->output_offset,
                    spltlittbl->contents + (chunk * 8) + 0);
         bfd_put_32 (output_bfd,
                    8 + (chunk_entries * 4),
                    spltlittbl->contents + (chunk * 8) + 4);
       }

      /* All the dynamic relocations have been emitted at this point.
        Make sure the relocation sections are the correct size.  */
      if (srelgot->size != (sizeof (Elf32_External_Rela)
                         * srelgot->reloc_count)
         || srelplt->size != (sizeof (Elf32_External_Rela)
                            * srelplt->reloc_count))
       abort ();

     /* The .xt.lit.plt section has just been modified.  This must
       happen before the code below which combines adjacent literal
       table entries, and the .xt.lit.plt contents have to be forced to
       the output here.  */
      if (! bfd_set_section_contents (output_bfd,
                                  spltlittbl->output_section,
                                  spltlittbl->contents,
                                  spltlittbl->output_offset,
                                  spltlittbl->size))
       return FALSE;
      /* Clear SEC_HAS_CONTENTS so the contents won't be output again.  */
      spltlittbl->flags &= ~SEC_HAS_CONTENTS;
    }

  /* Combine adjacent literal table entries.  */
  BFD_ASSERT (! info->relocatable);
  sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit");
  sgotloc = htab->sgotloc;
  BFD_ASSERT (sxtlit && sgotloc);
  num_xtlit_entries =
    elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc);
  if (num_xtlit_entries < 0)
    return FALSE;

  dyncon = (Elf32_External_Dyn *) sdyn->contents;
  dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
  for (; dyncon < dynconend; dyncon++)
    {
      Elf_Internal_Dyn dyn;

      bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);

      switch (dyn.d_tag)
       {
       default:
         break;

       case DT_XTENSA_GOT_LOC_SZ:
         dyn.d_un.d_val = num_xtlit_entries;
         break;

       case DT_XTENSA_GOT_LOC_OFF:
         dyn.d_un.d_ptr = htab->sgotloc->vma;
         break;

       case DT_PLTGOT:
         dyn.d_un.d_ptr = htab->sgot->vma;
         break;

       case DT_JMPREL:
         dyn.d_un.d_ptr = htab->srelplt->vma;
         break;

       case DT_PLTRELSZ:
         dyn.d_un.d_val = htab->srelplt->size;
         break;

       case DT_RELASZ:
         /* Adjust RELASZ to not include JMPREL.  This matches what
            glibc expects and what is done for several other ELF
            targets (e.g., i386, alpha), but the "correct" behavior
            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.  */
         if (htab->srelplt)
           dyn.d_un.d_val -= htab->srelplt->size;
         break;
       }

      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_finish_dynamic_symbol ( bfd *output_bfd  ATTRIBUTE_UNUSED,
struct bfd_link_info *info  ATTRIBUTE_UNUSED,
struct elf_link_hash_entry h,
Elf_Internal_Sym *  sym 
) [static]

Definition at line 2323 of file elf32-xtensa.c.

{
  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.  */
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
      || h == elf_hash_table (info)->hgot)
    sym->st_shndx = SHN_ABS;

  return TRUE;
}

Here is the call graph for this function:

static asection* elf_xtensa_gc_mark_hook ( asection sec,
struct bfd_link_info info,
Elf_Internal_Rela rel,
struct elf_link_hash_entry h,
Elf_Internal_Sym *  sym 
) [static]

Definition at line 966 of file elf32-xtensa.c.

{
  if (h != NULL)
    switch (ELF32_R_TYPE (rel->r_info))
      {
      case R_XTENSA_GNU_VTINHERIT:
      case R_XTENSA_GNU_VTENTRY:
       return NULL;
      }

  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_gc_sweep_hook ( bfd abfd,
struct bfd_link_info *info  ATTRIBUTE_UNUSED,
asection sec,
const Elf_Internal_Rela relocs 
) [static]

Definition at line 988 of file elf32-xtensa.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  bfd_signed_vma *local_got_refcounts;
  const Elf_Internal_Rela *rel, *relend;

  if ((sec->flags & SEC_ALLOC) == 0)
    return TRUE;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  local_got_refcounts = elf_local_got_refcounts (abfd);

  relend = relocs + sec->reloc_count;
  for (rel = relocs; rel < relend; rel++)
    {
      unsigned long r_symndx;
      unsigned int r_type;
      struct elf_link_hash_entry *h = NULL;

      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx >= symtab_hdr->sh_info)
       {
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
         while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
           h = (struct elf_link_hash_entry *) h->root.u.i.link;
       }

      r_type = ELF32_R_TYPE (rel->r_info);
      switch (r_type)
       {
       case R_XTENSA_32:
         if (h == NULL)
           goto local_literal;
         if (h->got.refcount > 0)
           h->got.refcount--;
         break;

       case R_XTENSA_PLT:
         if (h == NULL)
           goto local_literal;
         if (h->plt.refcount > 0)
           h->plt.refcount--;
         break;

       local_literal:
         if (local_got_refcounts[r_symndx] > 0)
           local_got_refcounts[r_symndx] -= 1;
         break;

       default:
         break;
       }
    }

  return TRUE;
}
static bfd_boolean elf_xtensa_grok_prstatus ( bfd abfd,
Elf_Internal_Note note 
) [static]

Definition at line 2973 of file elf32-xtensa.c.

{
  int offset;
  unsigned int size;

  /* The size for Xtensa is variable, so don't try to recognize the format
     based on the size.  Just assume this is GNU/Linux.  */

  /* pr_cursig */
  elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);

  /* pr_pid */
  elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);

  /* pr_reg */
  offset = 72;
  size = note->descsz - offset - 4;

  /* Make a ".reg/999" section.  */
  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
                                     size, note->descpos + offset);
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_grok_psinfo ( bfd abfd,
Elf_Internal_Note note 
) [static]

Definition at line 2998 of file elf32-xtensa.c.

{
  switch (note->descsz)
    {
      default:
       return FALSE;

      case 128:             /* GNU/Linux elf_prpsinfo */
       elf_tdata (abfd)->core_program
        = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
       elf_tdata (abfd)->core_command
        = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
    }

  /* Note that for some reason, a spurious space is tacked
     onto the end of the args in some (at least one anyway)
     implementations, so strip it off if it exists.  */

  {
    char *command = elf_tdata (abfd)->core_command;
    int n = strlen (command);

    if (0 < n && command[n - 1] == ' ')
      command[n - 1] = '\0';
  }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 2951 of file elf32-xtensa.c.

{
  return xtensa_is_property_section (sec);
}
static bfd_boolean elf_xtensa_in_literal_pool ( property_table_entry lit_table,
int  lit_table_size,
bfd_vma  addr 
) [static]

Definition at line 771 of file elf32-xtensa.c.

{
  if (elf_xtensa_find_property_entry (lit_table, lit_table_size, addr))
    return TRUE;

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void elf_xtensa_info_to_howto_rela ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent cache_ptr,
Elf_Internal_Rela dst 
) [static]

Definition at line 411 of file elf32-xtensa.c.

{
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);

  BFD_ASSERT (r_type < (unsigned int) R_XTENSA_max);
  cache_ptr->howto = &elf_howto_table[r_type];
}

Definition at line 504 of file elf32-xtensa.c.

{
  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;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_merge_private_bfd_data ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 2662 of file elf32-xtensa.c.

{
  unsigned out_mach, in_mach;
  flagword out_flag, in_flag;

  /* Check if we have the same endianess.  */
  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
    return FALSE;

  /* Don't even pretend to support mixed-format linking.  */
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return FALSE;

  out_flag = elf_elfheader (obfd)->e_flags;
  in_flag = elf_elfheader (ibfd)->e_flags;

  out_mach = out_flag & EF_XTENSA_MACH;
  in_mach = in_flag & EF_XTENSA_MACH;
  if (out_mach != in_mach)
    {
      (*_bfd_error_handler)
       (_("%B: incompatible machine type. Output is 0x%x. Input is 0x%x"),
        ibfd, out_mach, in_mach);
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
    }

  if (! elf_flags_init (obfd))
    {
      elf_flags_init (obfd) = TRUE;
      elf_elfheader (obfd)->e_flags = in_flag;

      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
         && bfd_get_arch_info (obfd)->the_default)
       return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
                              bfd_get_mach (ibfd));

      return TRUE;
    }

  if ((out_flag & EF_XTENSA_XT_INSN) != (in_flag & EF_XTENSA_XT_INSN)) 
    elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_INSN);

  if ((out_flag & EF_XTENSA_XT_LIT) != (in_flag & EF_XTENSA_XT_LIT)) 
    elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_LIT);

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_object_p ( bfd abfd) [static]

Definition at line 2751 of file elf32-xtensa.c.

{
  int mach;
  unsigned long arch = elf_elfheader (abfd)->e_flags & EF_XTENSA_MACH;

  switch (arch)
    {
    case E_XTENSA_MACH:
      mach = bfd_mach_xtensa;
      break;
    default:
      return FALSE;
    }

  (void) bfd_default_set_arch_mach (abfd, bfd_arch_xtensa, mach);
  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_print_private_bfd_data ( bfd abfd,
void *  farg 
) [static]

Definition at line 2727 of file elf32-xtensa.c.

{
  FILE *f = (FILE *) farg;
  flagword e_flags = elf_elfheader (abfd)->e_flags;

  fprintf (f, "\nXtensa header:\n");
  if ((e_flags & EF_XTENSA_MACH) == E_XTENSA_MACH)
    fprintf (f, "\nMachine     = Base\n");
  else
    fprintf (f, "\nMachine Id  = 0x%x\n", e_flags & EF_XTENSA_MACH);

  fprintf (f, "Insn tables = %s\n",
          (e_flags & EF_XTENSA_XT_INSN) ? "true" : "false");

  fprintf (f, "Literal tables = %s\n",
          (e_flags & EF_XTENSA_XT_LIT) ? "true" : "false");

  return _bfd_elf_print_private_bfd_data (abfd, farg);
}

Here is the call graph for this function:

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

Definition at line 393 of file elf32-xtensa.c.

{
  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;
}

Here is the call graph for this function:

Definition at line 2796 of file elf32-xtensa.c.

{
  switch ((int) ELF32_R_TYPE (rela->r_info))
    {
    case R_XTENSA_RELATIVE:
      return reloc_class_relative;
    case R_XTENSA_JMP_SLOT:
      return reloc_class_plt;
    default:
      return reloc_class_normal;
    }
}
static reloc_howto_type* elf_xtensa_reloc_type_lookup ( bfd *abfd  ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type  code 
) [static]

Definition at line 295 of file elf32-xtensa.c.

{
  switch (code)
    {
    case BFD_RELOC_NONE:
      TRACE ("BFD_RELOC_NONE");
      return &elf_howto_table[(unsigned) R_XTENSA_NONE ];

    case BFD_RELOC_32:
      TRACE ("BFD_RELOC_32");
      return &elf_howto_table[(unsigned) R_XTENSA_32 ];

    case BFD_RELOC_XTENSA_DIFF8:
      TRACE ("BFD_RELOC_XTENSA_DIFF8");
      return &elf_howto_table[(unsigned) R_XTENSA_DIFF8 ];

    case BFD_RELOC_XTENSA_DIFF16:
      TRACE ("BFD_RELOC_XTENSA_DIFF16");
      return &elf_howto_table[(unsigned) R_XTENSA_DIFF16 ];

    case BFD_RELOC_XTENSA_DIFF32:
      TRACE ("BFD_RELOC_XTENSA_DIFF32");
      return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];

    case BFD_RELOC_XTENSA_RTLD:
      TRACE ("BFD_RELOC_XTENSA_RTLD");
      return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];

    case BFD_RELOC_XTENSA_GLOB_DAT:
      TRACE ("BFD_RELOC_XTENSA_GLOB_DAT");
      return &elf_howto_table[(unsigned) R_XTENSA_GLOB_DAT ];

    case BFD_RELOC_XTENSA_JMP_SLOT:
      TRACE ("BFD_RELOC_XTENSA_JMP_SLOT");
      return &elf_howto_table[(unsigned) R_XTENSA_JMP_SLOT ];

    case BFD_RELOC_XTENSA_RELATIVE:
      TRACE ("BFD_RELOC_XTENSA_RELATIVE");
      return &elf_howto_table[(unsigned) R_XTENSA_RELATIVE ];

    case BFD_RELOC_XTENSA_PLT:
      TRACE ("BFD_RELOC_XTENSA_PLT");
      return &elf_howto_table[(unsigned) R_XTENSA_PLT ];

    case BFD_RELOC_XTENSA_OP0:
      TRACE ("BFD_RELOC_XTENSA_OP0");
      return &elf_howto_table[(unsigned) R_XTENSA_OP0 ];

    case BFD_RELOC_XTENSA_OP1:
      TRACE ("BFD_RELOC_XTENSA_OP1");
      return &elf_howto_table[(unsigned) R_XTENSA_OP1 ];

    case BFD_RELOC_XTENSA_OP2:
      TRACE ("BFD_RELOC_XTENSA_OP2");
      return &elf_howto_table[(unsigned) R_XTENSA_OP2 ];

    case BFD_RELOC_XTENSA_ASM_EXPAND:
      TRACE ("BFD_RELOC_XTENSA_ASM_EXPAND");
      return &elf_howto_table[(unsigned) R_XTENSA_ASM_EXPAND ];

    case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
      TRACE ("BFD_RELOC_XTENSA_ASM_SIMPLIFY");
      return &elf_howto_table[(unsigned) R_XTENSA_ASM_SIMPLIFY ];

    case BFD_RELOC_VTABLE_INHERIT:
      TRACE ("BFD_RELOC_VTABLE_INHERIT");
      return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTINHERIT ];

    case BFD_RELOC_VTABLE_ENTRY:
      TRACE ("BFD_RELOC_VTABLE_ENTRY");
      return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTENTRY ];

    default:
      if (code >= BFD_RELOC_XTENSA_SLOT0_OP
         && code <= BFD_RELOC_XTENSA_SLOT14_OP)
       {
         unsigned n = (R_XTENSA_SLOT0_OP +
                     (code - BFD_RELOC_XTENSA_SLOT0_OP));
         return &elf_howto_table[n];
       }

      if (code >= BFD_RELOC_XTENSA_SLOT0_ALT
         && code <= BFD_RELOC_XTENSA_SLOT14_ALT)
       {
         unsigned n = (R_XTENSA_SLOT0_ALT +
                     (code - BFD_RELOC_XTENSA_SLOT0_ALT));
         return &elf_howto_table[n];
       }

      break;
    }

  TRACE ("Unknown");
  return NULL;
}
static bfd_boolean elf_xtensa_relocate_section ( bfd output_bfd,
struct bfd_link_info info,
bfd input_bfd,
asection input_section,
bfd_byte contents,
Elf_Internal_Rela relocs,
Elf_Internal_Sym *  local_syms,
asection **  local_sections 
) [static]

Definition at line 1936 of file elf32-xtensa.c.

{
  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;
  property_table_entry *lit_table = 0;
  int ltblsize = 0;
  char *error_message = NULL;
  bfd_size_type input_size;

  if (!xtensa_default_isa)
    xtensa_default_isa = xtensa_isa_init (0, 0);

  htab = elf_xtensa_hash_table (info);
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      ltblsize = xtensa_read_table_entries (input_bfd, input_section,
                                       &lit_table, XTENSA_LIT_SEC_NAME,
                                       TRUE);
      if (ltblsize < 0)
       return FALSE;
    }

  input_size = bfd_get_section_limit (input_bfd, input_section);

  rel = relocs;
  relend = relocs + input_section->reloc_count;
  for (; rel < relend; rel++)
    {
      int r_type;
      reloc_howto_type *howto;
      unsigned long r_symndx;
      struct elf_link_hash_entry *h;
      Elf_Internal_Sym *sym;
      asection *sec;
      bfd_vma relocation;
      bfd_reloc_status_type r;
      bfd_boolean is_weak_undef;
      bfd_boolean unresolved_reloc;
      bfd_boolean warned;

      r_type = ELF32_R_TYPE (rel->r_info);
      if (r_type == (int) R_XTENSA_GNU_VTINHERIT
         || r_type == (int) R_XTENSA_GNU_VTENTRY)
       continue;

      if (r_type < 0 || r_type >= (int) R_XTENSA_max)
       {
         bfd_set_error (bfd_error_bad_value);
         return FALSE;
       }
      howto = &elf_howto_table[r_type];

      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.
            1) If the reloc is against a section symbol, adjust
            according to the output section.
            2) If there is a new target for this relocation,
            the new target will be in the same output section.
            We adjust the relocation by the output section
            difference.  */

         if (relaxing_section)
           {
             /* Check if this references a section in another input file.  */
             if (!do_fix_for_relocatable_link (rel, input_bfd, input_section,
                                          contents))
              return FALSE;
             r_type = ELF32_R_TYPE (rel->r_info);
           }

         if (r_type == R_XTENSA_ASM_SIMPLIFY)
           {
             char *error_message = NULL;
             /* Convert ASM_SIMPLIFY into the simpler relocation
               so that they never escape a relaxing link.  */
             r = contract_asm_expansion (contents, input_size, rel,
                                     &error_message);
             if (r != bfd_reloc_ok)
              {
                if (!((*info->callbacks->reloc_dangerous)
                     (info, error_message, input_bfd, input_section,
                      rel->r_offset)))
                  return FALSE;
              }
             r_type = ELF32_R_TYPE (rel->r_info);
           }

         /* This is a relocatable link, so we don't have to change
            anything unless the reloc is against a section symbol,
            in which case we have to adjust according to where the
            section symbol winds up in the output section.  */
         if (r_symndx < symtab_hdr->sh_info)
           {
             sym = local_syms + r_symndx;
             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
              {
                sec = local_sections[r_symndx];
                rel->r_addend += sec->output_offset + sym->st_value;
              }
           }

         /* If there is an addend with a partial_inplace howto,
            then move the addend to the contents.  This is a hack
            to work around problems with DWARF in relocatable links
            with some previous version of BFD.  Now we can't easily get
            rid of the hack without breaking backward compatibility.... */
         if (rel->r_addend)
           {
             howto = &elf_howto_table[r_type];
             if (howto->partial_inplace)
              {
                r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
                                      rel->r_addend, contents,
                                      rel->r_offset, FALSE,
                                      &error_message);
                if (r != bfd_reloc_ok)
                  {
                    if (!((*info->callbacks->reloc_dangerous)
                         (info, error_message, input_bfd, input_section,
                          rel->r_offset)))
                     return FALSE;
                  }
                rel->r_addend = 0;
              }
           }

         /* Done with work for relocatable link; continue with next reloc.  */
         continue;
       }

      /* This is a final link.  */

      if (relaxing_section)
       {
         /* Check if this references a section in another input file.  */
         do_fix_for_final_link (rel, input_bfd, input_section, contents,
                             &relocation);

         /* Update some already cached values.  */
         r_type = ELF32_R_TYPE (rel->r_info);
         howto = &elf_howto_table[r_type];
       }

      /* Sanity check the address.  */
      if (rel->r_offset >= input_size
         && ELF32_R_TYPE (rel->r_info) != R_XTENSA_NONE)
       {
         (*_bfd_error_handler)
           (_("%B(%A+0x%lx): relocation offset out of range (size=0x%x)"),
            input_bfd, input_section, rel->r_offset, input_size);
         bfd_set_error (bfd_error_bad_value);
         return FALSE;
       }

      /* Generate dynamic relocations.  */
      if (elf_hash_table (info)->dynamic_sections_created)
       {
         bfd_boolean dynamic_symbol = elf_xtensa_dynamic_symbol_p (h, info);

         if (dynamic_symbol && is_operand_relocation (r_type))
           {
             /* This is an error.  The symbol's real value won't be known
               until runtime and it's likely to be out of range anyway.  */
             const char *name = h->root.root.string;
             error_message = vsprint_msg ("invalid relocation for dynamic "
                                      "symbol", ": %s",
                                      strlen (name) + 2, name);
             if (!((*info->callbacks->reloc_dangerous)
                  (info, error_message, input_bfd, input_section,
                   rel->r_offset)))
              return FALSE;
           }
         else if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
                 && (input_section->flags & SEC_ALLOC) != 0
                 && (dynamic_symbol || info->shared))
           {
             Elf_Internal_Rela outrel;
             bfd_byte *loc;
             asection *srel;

             if (dynamic_symbol && r_type == R_XTENSA_PLT)
              srel = htab->srelplt;
             else
              srel = htab->srelgot;

             BFD_ASSERT (srel != NULL);

             outrel.r_offset =
              _bfd_elf_section_offset (output_bfd, info,
                                    input_section, rel->r_offset);

             if ((outrel.r_offset | 1) == (bfd_vma) -1)
              memset (&outrel, 0, sizeof outrel);
             else
              {
                outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);

                /* Complain if the relocation is in a read-only section
                   and not in a literal pool.  */
                if ((input_section->flags & SEC_READONLY) != 0
                    && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
                                                outrel.r_offset))
                  {
                    error_message =
                     _("dynamic relocation in read-only section");
                    if (!((*info->callbacks->reloc_dangerous)
                         (info, error_message, input_bfd, input_section,
                          rel->r_offset)))
                     return FALSE;
                  }

                if (dynamic_symbol)
                  {
                    outrel.r_addend = rel->r_addend;
                    rel->r_addend = 0;

                    if (r_type == R_XTENSA_32)
                     {
                       outrel.r_info =
                         ELF32_R_INFO (h->dynindx, R_XTENSA_GLOB_DAT);
                       relocation = 0;
                     }
                    else /* r_type == R_XTENSA_PLT */
                     {
                       outrel.r_info =
                         ELF32_R_INFO (h->dynindx, R_XTENSA_JMP_SLOT);

                       /* Create the PLT entry and set the initial
                          contents of the literal entry to the address of
                          the PLT entry.  */
                       relocation =
                         elf_xtensa_create_plt_entry (info, output_bfd,
                                                  srel->reloc_count);
                     }
                    unresolved_reloc = FALSE;
                  }
                else
                  {
                    /* Generate a RELATIVE relocation.  */
                    outrel.r_info = ELF32_R_INFO (0, R_XTENSA_RELATIVE);
                    outrel.r_addend = 0;
                  }
              }

             loc = (srel->contents
                   + srel->reloc_count++ * sizeof (Elf32_External_Rela));
             bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
             BFD_ASSERT (sizeof (Elf32_External_Rela) * srel->reloc_count
                       <= srel->size);
           }
       }

      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
        because such sections are not SEC_ALLOC and thus ld.so will
        not process them.  */
      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);
         return FALSE;
       }

      /* There's no point in calling bfd_perform_relocation here.
        Just go directly to our "special function".  */
      r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
                            relocation + rel->r_addend,
                            contents, rel->r_offset, is_weak_undef,
                            &error_message);

      if (r != bfd_reloc_ok && !warned)
       {
         const char *name;

         BFD_ASSERT (r == bfd_reloc_dangerous || r == bfd_reloc_other);
         BFD_ASSERT (error_message != NULL);

         if (h)
           name = h->root.root.string;
         else
           {
             name = bfd_elf_string_from_elf_section
              (input_bfd, symtab_hdr->sh_link, sym->st_name);
             if (name && *name == '\0')
              name = bfd_section_name (input_bfd, sec);
           }
         if (name)
           {
             if (rel->r_addend == 0)
              error_message = vsprint_msg (error_message, ": %s",
                                        strlen (name) + 2, name);
             else
              error_message = vsprint_msg (error_message, ": (%s+0x%x)",
                                        strlen (name) + 22,
                                        name, (int)rel->r_addend);
           }

         if (!((*info->callbacks->reloc_dangerous)
              (info, error_message, input_bfd, input_section,
               rel->r_offset)))
           return FALSE;
       }
    }

  if (lit_table)
    free (lit_table);

  input_section->reloc_done = TRUE;

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf_xtensa_set_private_flags ( bfd abfd,
flagword  flags 
) [static]

Definition at line 2714 of file elf32-xtensa.c.

{
  BFD_ASSERT (!elf_flags_init (abfd)
             || elf_elfheader (abfd)->e_flags == flags);

  elf_elfheader (abfd)->e_flags |= flags;
  elf_flags_init (abfd) = TRUE;

  return TRUE;
}
static bfd_boolean elf_xtensa_size_dynamic_sections ( bfd *output_bfd  ATTRIBUTE_UNUSED,
struct bfd_link_info info 
) [static]

Definition at line 1261 of file elf32-xtensa.c.

{
  struct elf_xtensa_link_hash_table *htab;
  bfd *dynobj, *abfd;
  asection *s, *srelplt, *splt, *sgotplt, *srelgot, *spltlittbl, *sgotloc;
  bfd_boolean relplt, relgot;
  int plt_entries, plt_chunks, chunk;

  plt_entries = 0;
  plt_chunks = 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)
       {
         s = bfd_get_section_by_name (dynobj, ".interp");
         if (s == NULL)
           abort ();
         s->size = sizeof ELF_DYNAMIC_INTERPRETER;
         s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
       }

      /* Allocate room for one word in ".got".  */
      htab->sgot->size = 4;

      /* 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_allocate_dynrelocs,
                           (void *) info);

      /* 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);

      /* 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 = htab->spltlittbl;
      plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
      plt_chunks =
       (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;

      /* Iterate over all the PLT chunks, including any extra sections
        created earlier because the initial count of PLT relocations
        was an overestimate.  */
      for (chunk = 0;
          (splt = elf_xtensa_get_plt_section (info, chunk)) != NULL;
          chunk++)
       {
         int chunk_entries;

         sgotplt = elf_xtensa_get_gotplt_section (info, chunk);
         BFD_ASSERT (sgotplt != NULL);

         if (chunk < plt_chunks - 1)
           chunk_entries = PLT_ENTRIES_PER_CHUNK;
         else if (chunk == plt_chunks - 1)
           chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
         else
           chunk_entries = 0;

         if (chunk_entries != 0)
           {
             sgotplt->size = 4 * (chunk_entries + 2);
             splt->size = PLT_ENTRY_SIZE * chunk_entries;
             srelgot->size += 2 * sizeof (Elf32_External_Rela);
             spltlittbl->size += 8;
           }
         else
           {
             sgotplt->size = 0;
             splt->size = 0;
           }
       }

      /* Allocate space in ".got.loc" to match the total size of all the
        literal tables.  */
      sgotloc = htab->sgotloc;
      sgotloc->size = spltlittbl->size;
      for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
       {
         if (abfd->flags & DYNAMIC)
           continue;
         for (s = abfd->sections; s != NULL; s = s->next)
           {
             if (! elf_discarded_section (s)
                && xtensa_is_littable_section (s)
                && s != spltlittbl)
              sgotloc->size += s->size;
           }
       }
    }

  /* Allocate memory for dynamic sections.  */
  relplt = FALSE;
  relgot = FALSE;
  for (s = dynobj->sections; s != NULL; s = s->next)
    {
      const char *name;

      if ((s->flags & SEC_LINKER_CREATED) == 0)
       continue;

      /* It's OK to base decisions on the section name, because none
        of the dynobj section names depend upon the input files.  */
      name = bfd_get_section_name (dynobj, s);

      if (CONST_STRNEQ (name, ".rela"))
       {
         if (s->size != 0)
           {
             if (strcmp (name, ".rela.plt") == 0)
              relplt = TRUE;
             else if (strcmp (name, ".rela.got") == 0)
              relgot = TRUE;

             /* We use the reloc_count field as a counter if we need
               to copy relocs into the output file.  */
             s->reloc_count = 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
              && strcmp (name, ".xt.lit.plt") != 0
              && strcmp (name, ".got.loc") != 0)
       {
         /* It's not one of our sections, so don't allocate space.  */
         continue;
       }

      if (s->size == 0)
       {
         /* If we don't need this section, strip it from the output
            file.  We must create the ".plt*" and ".got.plt*"
            sections in create_dynamic_sections and/or check_relocs
            based on a conservative estimate of the PLT relocation
            count, because the sections must be created before the
            linker maps input sections to output sections.  The
            linker does that before size_dynamic_sections, where we
            compute the exact size of the PLT, so there may be more
            of these sections than are actually needed.  */
         s->flags |= SEC_EXCLUDE;
       }
      else if ((s->flags & SEC_HAS_CONTENTS) != 0)
       {
         /* Allocate memory for the section contents.  */
         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
         if (s->contents == NULL)
           return FALSE;
       }
    }

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      /* 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.  */
      for (chunk = 0; chunk < plt_chunks; chunk++)
       {
         Elf_Internal_Rela irela;
         bfd_byte *loc;

         irela.r_offset = 0;
         irela.r_info = ELF32_R_INFO (0, R_XTENSA_RTLD);
         irela.r_addend = 0;

         loc = (srelgot->contents
               + srelgot->reloc_count * sizeof (Elf32_External_Rela));
         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
         bfd_elf32_swap_reloca_out (output_bfd, &irela,
                                 loc + sizeof (Elf32_External_Rela));
         srelgot->reloc_count += 2;
       }

      /* Add some entries to the .dynamic section.  We fill in the
        values later, in elf_xtensa_finish_dynamic_sections, but we
        must add the entries now so that we get the correct size for
        the .dynamic section.  The DT_DEBUG entry is filled in by the
        dynamic linker and used by the debugger.  */
#define add_dynamic_entry(TAG, VAL) \
  _bfd_elf_add_dynamic_entry (info, TAG, VAL)

      if (info->executable)
       {
         if (!add_dynamic_entry (DT_DEBUG, 0))
           return FALSE;
       }

      if (relplt)
       {
         if (!add_dynamic_entry (DT_PLTGOT, 0)
             || !add_dynamic_entry (DT_PLTRELSZ, 0)
             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
             || !add_dynamic_entry (DT_JMPREL, 0))
           return FALSE;
       }

      if (relgot)
       {
         if (!add_dynamic_entry (DT_RELA, 0)
             || !add_dynamic_entry (DT_RELASZ, 0)
             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
           return FALSE;
       }

      if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
         || !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
       return FALSE;
    }
#undef add_dynamic_entry

  return TRUE;
}

Here is the call graph for this function:

static source_reloc* find_source_reloc ( source_reloc *  src_relocs,
int  src_count,
asection sec,
Elf_Internal_Rela irel 
) [static]

Definition at line 4256 of file elf32-xtensa.c.

{
  int i;

  for (i = 0; i < src_count; i++)
    {
      if (src_relocs[i].source_sec == sec
         && src_relocs[i].r_rel.rela.r_offset == irel->r_offset
         && (ELF32_R_TYPE (src_relocs[i].r_rel.rela.r_info)
             == ELF32_R_TYPE (irel->r_info)))
       return &src_relocs[i];
    }

  return NULL;
}
static bfd_size_type get_asm_simplify_size ( bfd_byte contents,
bfd_size_type  content_len,
bfd_size_type  offset 
) [static]

Definition at line 3251 of file elf32-xtensa.c.

{
  bfd_size_type insnlen, size = 0;

  /* Decode the size of the next two instructions.  */
  insnlen = insn_decode_len (contents, content_len, offset);
  if (insnlen == 0)
    return 0;

  size += insnlen;
  
  insnlen = insn_decode_len (contents, content_len, offset + size);
  if (insnlen == 0)
    return 0;

  size += insnlen;
  return size;
}

Here is the call graph for this function:

static xtensa_opcode get_const16_opcode ( void  ) [static]

Definition at line 3092 of file elf32-xtensa.c.

{
  static bfd_boolean done_lookup = FALSE;
  static xtensa_opcode const16_opcode = XTENSA_UNDEFINED;
  if (!done_lookup)
    {
      const16_opcode = xtensa_opcode_lookup (xtensa_default_isa, "const16");
      done_lookup = TRUE;
    }
  return const16_opcode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static xtensa_opcode get_expanded_call_opcode ( bfd_byte buf,
int  bufsize,
bfd_boolean p_uses_l32r 
) [static]

Definition at line 3964 of file elf32-xtensa.c.

{
  static xtensa_insnbuf insnbuf = NULL;
  static xtensa_insnbuf slotbuf = NULL;
  xtensa_format fmt;
  xtensa_opcode opcode;
  xtensa_isa isa = xtensa_default_isa;
  uint32 regno, const16_regno, call_regno;
  int offset = 0;

  if (insnbuf == NULL)
    {
      insnbuf = xtensa_insnbuf_alloc (isa);
      slotbuf = xtensa_insnbuf_alloc (isa);
    }

  xtensa_insnbuf_from_chars (isa, insnbuf, buf, bufsize);
  fmt = xtensa_format_decode (isa, insnbuf);
  if (fmt == XTENSA_UNDEFINED
      || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
    return XTENSA_UNDEFINED;

  opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
  if (opcode == XTENSA_UNDEFINED)
    return XTENSA_UNDEFINED;

  if (opcode == get_l32r_opcode ())
    {
      if (p_uses_l32r)
       *p_uses_l32r = TRUE;
      if (xtensa_operand_get_field (isa, opcode, L32R_TARGET_REG_OPERAND,
                                fmt, 0, slotbuf, &regno)
         || xtensa_operand_decode (isa, opcode, L32R_TARGET_REG_OPERAND,
                                &regno))
       return XTENSA_UNDEFINED;
    }
  else if (opcode == get_const16_opcode ())
    {
      if (p_uses_l32r)
       *p_uses_l32r = FALSE;
      if (xtensa_operand_get_field (isa, opcode, CONST16_TARGET_REG_OPERAND,
                                fmt, 0, slotbuf, &regno)
         || xtensa_operand_decode (isa, opcode, CONST16_TARGET_REG_OPERAND,
                                &regno))
       return XTENSA_UNDEFINED;

      /* Check that the next instruction is also CONST16.  */
      offset += xtensa_format_length (isa, fmt);
      xtensa_insnbuf_from_chars (isa, insnbuf, buf + offset, bufsize - offset);
      fmt = xtensa_format_decode (isa, insnbuf);
      if (fmt == XTENSA_UNDEFINED
         || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
       return XTENSA_UNDEFINED;
      opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
      if (opcode != get_const16_opcode ())
       return XTENSA_UNDEFINED;

      if (xtensa_operand_get_field (isa, opcode, CONST16_TARGET_REG_OPERAND,
                                fmt, 0, slotbuf, &const16_regno)
         || xtensa_operand_decode (isa, opcode, CONST16_TARGET_REG_OPERAND,
                                &const16_regno)
         || const16_regno != regno)
       return XTENSA_UNDEFINED;
    }
  else
    return XTENSA_UNDEFINED;

  /* Next instruction should be an CALLXn with operand 0 == regno.  */
  offset += xtensa_format_length (isa, fmt);
  xtensa_insnbuf_from_chars (isa, insnbuf, buf + offset, bufsize - offset);
  fmt = xtensa_format_decode (isa, insnbuf);
  if (fmt == XTENSA_UNDEFINED
      || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
    return XTENSA_UNDEFINED;
  opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
  if (opcode == XTENSA_UNDEFINED 
      || !is_indirect_call_opcode (opcode))
    return XTENSA_UNDEFINED;

  if (xtensa_operand_get_field (isa, opcode, CALLN_SOURCE_OPERAND,
                            fmt, 0, slotbuf, &call_regno)
      || xtensa_operand_decode (isa, opcode, CALLN_SOURCE_OPERAND,
                            &call_regno))
    return XTENSA_UNDEFINED;

  if (call_regno != regno)
    return XTENSA_UNDEFINED;

  return opcode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static xtensa_opcode get_l32r_opcode ( void  ) [static]

Definition at line 3106 of file elf32-xtensa.c.

{
  static xtensa_opcode l32r_opcode = XTENSA_UNDEFINED;
  static bfd_boolean done_lookup = FALSE;

  if (!done_lookup)
    {
      l32r_opcode = xtensa_opcode_lookup (xtensa_default_isa, "l32r");
      done_lookup = TRUE;
    }
  return l32r_opcode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static xtensa_opcode get_relocation_opcode ( bfd abfd,
asection sec,
bfd_byte contents,
Elf_Internal_Rela irel 
) [static]

Definition at line 3201 of file elf32-xtensa.c.

{
  static xtensa_insnbuf ibuff = NULL;
  static xtensa_insnbuf sbuff = NULL;
  xtensa_isa isa = xtensa_default_isa;
  xtensa_format fmt;
  int slot;

  if (contents == NULL)
    return XTENSA_UNDEFINED;

  if (bfd_get_section_limit (abfd, sec) <= irel->r_offset)
    return XTENSA_UNDEFINED;

  if (ibuff == NULL)
    {
      ibuff = xtensa_insnbuf_alloc (isa);
      sbuff = xtensa_insnbuf_alloc (isa);
    }

  /* Decode the instruction.  */
  xtensa_insnbuf_from_chars (isa, ibuff, &contents[irel->r_offset],
                          sec->size - irel->r_offset);
  fmt = xtensa_format_decode (isa, ibuff);
  slot = get_relocation_slot (ELF32_R_TYPE (irel->r_info));
  if (slot == XTENSA_UNDEFINED)
    return XTENSA_UNDEFINED;
  xtensa_format_get_slot (isa, fmt, slot, ibuff, sbuff);
  return xtensa_opcode_decode (isa, fmt, slot, sbuff);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_relocation_opnd ( xtensa_opcode  opcode,
int  r_type 
) [static]

Definition at line 3134 of file elf32-xtensa.c.

{
  xtensa_isa isa = xtensa_default_isa;
  int last_immed, last_opnd, opi;

  if (opcode == XTENSA_UNDEFINED)
    return XTENSA_UNDEFINED;

  /* Find the last visible PC-relative immediate operand for the opcode.
     If there are no PC-relative immediates, then choose the last visible
     immediate; otherwise, fail and return XTENSA_UNDEFINED.  */
  last_immed = XTENSA_UNDEFINED;
  last_opnd = xtensa_opcode_num_operands (isa, opcode);
  for (opi = last_opnd - 1; opi >= 0; opi--)
    {
      if (xtensa_operand_is_visible (isa, opcode, opi) == 0)
       continue;
      if (xtensa_operand_is_PCrelative (isa, opcode, opi) == 1)
       {
         last_immed = opi;
         break;
       }
      if (last_immed == XTENSA_UNDEFINED
         && xtensa_operand_is_register (isa, opcode, opi) == 0)
       last_immed = opi;
    }
  if (last_immed < 0)
    return XTENSA_UNDEFINED;

  /* If the operand number was specified in an old-style relocation,
     check for consistency with the operand computed above.  */
  if (r_type >= R_XTENSA_OP0 && r_type <= R_XTENSA_OP2)
    {
      int reloc_opnd = r_type - R_XTENSA_OP0;
      if (reloc_opnd != last_immed)
       return XTENSA_UNDEFINED;
    }

  return last_immed;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3177 of file elf32-xtensa.c.

{
  switch (r_type)
    {
    case R_XTENSA_OP0:
    case R_XTENSA_OP1:
    case R_XTENSA_OP2:
      return 0;

    default:
      if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP)
       return r_type - R_XTENSA_SLOT0_OP;
      if (r_type >= R_XTENSA_SLOT0_ALT && r_type <= R_XTENSA_SLOT14_ALT)
       return r_type - R_XTENSA_SLOT0_ALT;
      break;
    }

  return XTENSA_UNDEFINED;
}

Here is the caller graph for this function:

static xtensa_format get_single_format ( xtensa_opcode  opcode) [static]

Definition at line 3474 of file elf32-xtensa.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned hash_bfd_vma ( bfd_vma  val) [static]

Definition at line 4438 of file elf32-xtensa.c.

{
  return (val >> 2) + (val >> 10);
}

Here is the caller graph for this function:

static void init_call_opcodes ( void  ) [static]

Definition at line 3040 of file elf32-xtensa.c.

{
  if (callx0_op == XTENSA_UNDEFINED)
    {
      callx0_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx0");
      callx4_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx4");
      callx8_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx8");
      callx12_op = xtensa_opcode_lookup (xtensa_default_isa, "callx12");
      call0_op   = xtensa_opcode_lookup (xtensa_default_isa, "call0");
      call4_op   = xtensa_opcode_lookup (xtensa_default_isa, "call4");
      call8_op   = xtensa_opcode_lookup (xtensa_default_isa, "call8");
      call12_op  = xtensa_opcode_lookup (xtensa_default_isa, "call12");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_literal_value ( literal_value *  lit,
const r_reloc *  r_rel,
unsigned long  value,
bfd_boolean  is_abs_literal 
) [static]

Definition at line 4340 of file elf32-xtensa.c.

{
  lit->r_rel = *r_rel;
  lit->value = value;
  lit->is_abs_literal = is_abs_literal;
}
static void init_op_single_format_table ( void  ) [static]

Definition at line 3437 of file elf32-xtensa.c.

{
  xtensa_isa isa = xtensa_default_isa;
  xtensa_insnbuf ibuf;
  xtensa_opcode opcode;
  xtensa_format fmt;
  int num_opcodes;

  if (op_single_fmt_table)
    return;

  ibuf = xtensa_insnbuf_alloc (isa);
  num_opcodes = xtensa_isa_num_opcodes (isa);

  op_single_fmt_table = (xtensa_format *)
    bfd_malloc (sizeof (xtensa_format) * num_opcodes);
  for (opcode = 0; opcode < num_opcodes; opcode++)
    {
      op_single_fmt_table[opcode] = XTENSA_UNDEFINED;
      for (fmt = 0; fmt < xtensa_isa_num_formats (isa); fmt++)
       {
         if (xtensa_format_num_slots (isa, fmt) == 1
             && xtensa_opcode_encode (isa, fmt, 0, ibuf, opcode) == 0)
           {
             xtensa_opcode old_fmt = op_single_fmt_table[opcode];
             int fmt_length = xtensa_format_length (isa, fmt);
             if (old_fmt == XTENSA_UNDEFINED
                || fmt_length < xtensa_format_length (isa, old_fmt))
              op_single_fmt_table[opcode] = fmt;
           }
       }
    }
  xtensa_insnbuf_free (isa, ibuf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_source_reloc ( source_reloc *  reloc,
asection source_sec,
const r_reloc *  r_rel,
xtensa_opcode  opcode,
int  opnd,
bfd_boolean  is_abs_literal 
) [static]

Definition at line 4235 of file elf32-xtensa.c.

{
  reloc->source_sec = source_sec;
  reloc->r_rel = *r_rel;
  reloc->opcode = opcode;
  reloc->opnd = opnd;
  reloc->is_null = FALSE;
  reloc->is_abs_literal = is_abs_literal;
}
bfd_size_type insn_decode_len ( bfd_byte contents,
bfd_size_type  content_len,
bfd_size_type  offset 
)

Definition at line 3308 of file elf32-xtensa.c.

{
  int insn_len;
  xtensa_isa isa = xtensa_default_isa;
  xtensa_format fmt;
  static xtensa_insnbuf ibuff = NULL;

  if (offset + MIN_INSN_LENGTH > content_len)
    return 0;

  if (ibuff == NULL)
    ibuff = xtensa_insnbuf_alloc (isa);
  xtensa_insnbuf_from_chars (isa, ibuff, &contents[offset],
                          content_len - offset);
  fmt = xtensa_format_decode (isa, ibuff);
  if (fmt == XTENSA_UNDEFINED)
    return 0;
  insn_len = xtensa_format_length (isa, fmt);
  if (insn_len ==  XTENSA_UNDEFINED)
    return 0;
  return insn_len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

xtensa_opcode insn_decode_opcode ( bfd_byte contents,
bfd_size_type  content_len,
bfd_size_type  offset,
int  slot 
)

Definition at line 3338 of file elf32-xtensa.c.

{
  xtensa_isa isa = xtensa_default_isa;
  xtensa_format fmt;
  static xtensa_insnbuf insnbuf = NULL;
  static xtensa_insnbuf slotbuf = NULL;

  if (offset + MIN_INSN_LENGTH > content_len)
    return XTENSA_UNDEFINED;

  if (insnbuf == NULL)
    {
      insnbuf = xtensa_insnbuf_alloc (isa);
      slotbuf = xtensa_insnbuf_alloc (isa);
    }

  xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
                          content_len - offset);
  fmt = xtensa_format_decode (isa, insnbuf);
  if (fmt == XTENSA_UNDEFINED)
    return XTENSA_UNDEFINED;

  if (slot >= xtensa_format_num_slots (isa, fmt))
    return XTENSA_UNDEFINED;

  xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
  return xtensa_opcode_decode (isa, fmt, slot, slotbuf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3274 of file elf32-xtensa.c.

{
  return (r_type >= R_XTENSA_SLOT0_ALT
         && r_type <= R_XTENSA_SLOT14_ALT);
}

Here is the caller graph for this function:

static bfd_boolean is_direct_call_opcode ( xtensa_opcode  opcode) [static]

Definition at line 3068 of file elf32-xtensa.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean is_indirect_call_opcode ( xtensa_opcode  opcode) [static]

Definition at line 3057 of file elf32-xtensa.c.

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean is_l32r_relocation ( bfd abfd,
asection sec,
bfd_byte contents,
Elf_Internal_Rela irel 
)

Definition at line 3237 of file elf32-xtensa.c.

{
  xtensa_opcode opcode;
  if (!is_operand_relocation (ELF32_R_TYPE (irel->r_info)))
    return FALSE;
  opcode = get_relocation_opcode (abfd, sec, contents, irel);
  return (opcode == get_l32r_opcode ());
}

Here is the call graph for this function:

Definition at line 3282 of file elf32-xtensa.c.

{
  switch (r_type)
    {
    case R_XTENSA_OP0:
    case R_XTENSA_OP1:
    case R_XTENSA_OP2:
      return TRUE;

    default:
      if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP)
       return TRUE;
      if (r_type >= R_XTENSA_SLOT0_ALT && r_type <= R_XTENSA_SLOT14_ALT)
       return TRUE;
      break;
    }

  return FALSE;
}

Here is the caller graph for this function:

static bfd_boolean is_windowed_call_opcode ( xtensa_opcode  opcode) [static]

Definition at line 3079 of file elf32-xtensa.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_vma l32r_offset ( bfd_vma  addr,
bfd_vma  pc 
) [static]

Definition at line 3121 of file elf32-xtensa.c.

{
  bfd_vma offset;

  offset = addr - ((pc+3) & -4);
  BFD_ASSERT ((offset & ((1 << 2) - 1)) == 0);
  offset = (signed int) offset >> 2;
  BFD_ASSERT ((signed int) offset >> 16 == -1);
  return offset;
}

Here is the caller graph for this function:

static bfd_boolean literal_value_equal ( const literal_value *  src1,
const literal_value *  src2,
bfd_boolean  final_static_link 
) [static]

Definition at line 4352 of file elf32-xtensa.c.

{
  struct elf_link_hash_entry *h1, *h2;

  if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel)) 
    return FALSE;

  if (r_reloc_is_const (&src1->r_rel))
    return (src1->value == src2->value);

  if (ELF32_R_TYPE (src1->r_rel.rela.r_info)
      != ELF32_R_TYPE (src2->r_rel.rela.r_info))
    return FALSE;

  if (src1->r_rel.target_offset != src2->r_rel.target_offset)
    return FALSE;
   
  if (src1->r_rel.virtual_offset != src2->r_rel.virtual_offset)
    return FALSE;

  if (src1->value != src2->value)
    return FALSE;
  
  /* Now check for the same section (if defined) or the same elf_hash
     (if undefined or weak).  */
  h1 = r_reloc_get_hash_entry (&src1->r_rel);
  h2 = r_reloc_get_hash_entry (&src2->r_rel);
  if (r_reloc_is_defined (&src1->r_rel)
      && (final_static_link
         || ((!h1 || h1->root.type != bfd_link_hash_defweak)
             && (!h2 || h2->root.type != bfd_link_hash_defweak))))
    {
      if (r_reloc_get_section (&src1->r_rel)
         != r_reloc_get_section (&src2->r_rel))
       return FALSE;
    }
  else
    {
      /* Require that the hash entries (i.e., symbols) be identical.  */
      if (h1 != h2 || h1 == 0)
       return FALSE;
    }

  if (src1->is_abs_literal != src2->is_abs_literal)
    return FALSE;

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned literal_value_hash ( const literal_value *  src) [static]

Definition at line 4445 of file elf32-xtensa.c.

{
  unsigned hash_val;

  hash_val = hash_bfd_vma (src->value);
  if (!r_reloc_is_const (&src->r_rel))
    {
      void *sec_or_hash;

      hash_val += hash_bfd_vma (src->is_abs_literal * 1000);
      hash_val += hash_bfd_vma (src->r_rel.target_offset);
      hash_val += hash_bfd_vma (src->r_rel.virtual_offset);
  
      /* Now check for the same section and the same elf_hash.  */
      if (r_reloc_is_defined (&src->r_rel))
       sec_or_hash = r_reloc_get_section (&src->r_rel);
      else
       sec_or_hash = r_reloc_get_hash_entry (&src->r_rel);
      hash_val += hash_bfd_vma ((bfd_vma) (size_t) sec_or_hash);
    }
  return hash_val;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean narrow_instruction ( bfd_byte contents,
bfd_size_type  content_length,
bfd_size_type  offset 
) [static]

Definition at line 3632 of file elf32-xtensa.c.

{
  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_narrow_instruction (slotbuf, fmt, opcode);
  if (o_insnbuf)
    {
      xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
                            content_length - offset);
      return TRUE;
    }

  return FALSE;
}

Here is the call graph for this function:

static int property_table_compare ( const void *  ap,
const void *  bp 
) [static]

Definition at line 549 of file elf32-xtensa.c.

{
  const property_table_entry *a = (const property_table_entry *) ap;
  const property_table_entry *b = (const property_table_entry *) bp;

  if (a->address == b->address)
    {
      if (a->size != b->size)
       return (a->size - b->size);

      if ((a->flags & XTENSA_PROP_ALIGN) != (b->flags & XTENSA_PROP_ALIGN))
       return ((b->flags & XTENSA_PROP_ALIGN)
              - (a->flags & XTENSA_PROP_ALIGN));

      if ((a->flags & XTENSA_PROP_ALIGN)
         && (GET_XTENSA_PROP_ALIGNMENT (a->flags)
             != GET_XTENSA_PROP_ALIGNMENT (b->flags)))
       return (GET_XTENSA_PROP_ALIGNMENT (a->flags)
              - GET_XTENSA_PROP_ALIGNMENT (b->flags));
      
      if ((a->flags & XTENSA_PROP_UNREACHABLE)
         != (b->flags & XTENSA_PROP_UNREACHABLE))
       return ((b->flags & XTENSA_PROP_UNREACHABLE)
              - (a->flags & XTENSA_PROP_UNREACHABLE));

      return (a->flags - b->flags);
    }

  return (a->address - b->address);
}

Here is the caller graph for this function:

static int property_table_matches ( const void *  ap,
const void *  bp 
) [static]

Definition at line 582 of file elf32-xtensa.c.

{
  const property_table_entry *a = (const property_table_entry *) ap;
  const property_table_entry *b = (const property_table_entry *) bp;

  /* Check if one entry overlaps with the other.  */
  if ((b->address >= a->address && b->address < (a->address + a->size))
      || (a->address >= b->address && a->address < (b->address + b->size)))
    return 0;

  return (a->address - b->address);
}

Here is the caller graph for this function:

static struct elf_link_hash_entry* r_reloc_get_hash_entry ( const r_reloc *  r_rel) [static, read]

Definition at line 4113 of file elf32-xtensa.c.

{
  unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
  return get_elf_r_symndx_hash_entry (r_rel->abfd, r_symndx);
}

Here is the caller graph for this function:

static asection* r_reloc_get_section ( const r_reloc *  r_rel) [static]

Definition at line 4121 of file elf32-xtensa.c.

{
  unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
  return get_elf_r_symndx_section (r_rel->abfd, r_symndx);
}

Here is the caller graph for this function:

static bfd_vma r_reloc_get_target_offset ( const r_reloc *  r_rel) [static]

Definition at line 4100 of file elf32-xtensa.c.

{
  bfd_vma target_offset;
  unsigned long r_symndx;

  BFD_ASSERT (!r_reloc_is_const (r_rel));
  r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
  target_offset = get_elf_r_symndx_offset (r_rel->abfd, r_symndx);
  return (target_offset + r_rel->rela.r_addend);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void r_reloc_init ( r_reloc *  r_rel,
bfd abfd,
Elf_Internal_Rela irel,
bfd_byte contents,
bfd_size_type  content_length 
) [static]

Definition at line 4145 of file elf32-xtensa.c.

{
  int r_type;
  reloc_howto_type *howto;

  if (irel)
    {
      r_rel->rela = *irel;
      r_rel->abfd = abfd;
      r_rel->target_offset = r_reloc_get_target_offset (r_rel);
      r_rel->virtual_offset = 0;
      r_type = ELF32_R_TYPE (r_rel->rela.r_info);
      howto = &elf_howto_table[r_type];
      if (howto->partial_inplace)
       {
         bfd_vma inplace_val;
         BFD_ASSERT (r_rel->rela.r_offset < content_length);

         inplace_val = bfd_get_32 (abfd, &contents[r_rel->rela.r_offset]);
         r_rel->target_offset += inplace_val;
       }
    }
  else
    memset (r_rel, 0, sizeof (r_reloc));
}

Here is the call graph for this function:

static bfd_boolean r_reloc_is_const ( const r_reloc *  r_rel) [static]

Definition at line 4093 of file elf32-xtensa.c.

{
  return (r_rel->abfd == NULL);
}

Here is the caller graph for this function:

static bfd_boolean r_reloc_is_defined ( const r_reloc *  r_rel) [static]

Definition at line 4129 of file elf32-xtensa.c.

{
  asection *sec;
  if (r_rel == NULL)
    return FALSE;

  sec = r_reloc_get_section (r_rel);
  if (sec == bfd_abs_section_ptr
      || sec == bfd_com_section_ptr
      || sec == bfd_und_section_ptr)
    return FALSE;
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int source_reloc_compare ( const void *  ap,
const void *  bp 
) [static]

Definition at line 4277 of file elf32-xtensa.c.

{
  const source_reloc *a = (const source_reloc *) ap;
  const source_reloc *b = (const source_reloc *) bp;

  if (a->r_rel.target_offset != b->r_rel.target_offset)
    return (a->r_rel.target_offset - b->r_rel.target_offset);

  /* We don't need to sort on these criteria for correctness,
     but enforcing a more strict ordering prevents unstable qsort
     from behaving differently with different implementations.
     Without the code below we get correct but different results
     on Solaris 2.7 and 2.8.  We would like to always produce the
     same results no matter the host. */

  if ((!a->is_null) - (!b->is_null))
    return ((!a->is_null) - (!b->is_null));
  return internal_reloc_compare (&a->r_rel.rela, &b->r_rel.rela);
}

Definition at line 3941 of file elf32-xtensa.c.

{
  init_call_opcodes ();

  if (opcode == callx0_op) return call0_op;
  if (opcode == callx4_op) return call4_op;
  if (opcode == callx8_op) return call8_op;
  if (opcode == callx12_op) return call12_op;

  /* Return XTENSA_UNDEFINED if the opcode is not an indirect call.  */
  return XTENSA_UNDEFINED;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static value_map* value_map_get_cached_value ( value_map_hash_table *  map,
const literal_value *  val,
bfd_boolean  final_static_link 
) [static]

Definition at line 4472 of file elf32-xtensa.c.

{
  value_map *map_e;
  value_map *bucket;
  unsigned idx;

  idx = literal_value_hash (val);
  idx = idx & (map->bucket_count - 1);
  bucket = map->buckets[idx];
  for (map_e = bucket; map_e; map_e = map_e->next)
    {
      if (literal_value_equal (&map_e->val, val, final_static_link))
       return map_e;
    }
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void value_map_hash_table_delete ( value_map_hash_table *  table) [static]

Definition at line 4430 of file elf32-xtensa.c.

{
  free (table->buckets);
  free (table);
}

Here is the call graph for this function:

static value_map_hash_table* value_map_hash_table_init ( void  ) [static]

Definition at line 4408 of file elf32-xtensa.c.

{
  value_map_hash_table *values;

  values = (value_map_hash_table *)
    bfd_zmalloc (sizeof (value_map_hash_table));
  values->bucket_count = INITIAL_HASH_RELOC_BUCKET_COUNT;
  values->count = 0;
  values->buckets = (value_map **)
    bfd_zmalloc (sizeof (value_map *) * values->bucket_count);
  if (values->buckets == NULL) 
    {
      free (values);
      return NULL;
    }
  values->has_last_loc = FALSE;

  return values;
}

Here is the call graph for this function:

static char* vsprint_msg ( const char *  ,
const char *  ,
static xtensa_opcode get_expanded_call_opcode (bfd_byte  int,
  ... 
) [static]

Definition at line 39 of file elf32-xtensa.c.

{
  HOWTO (R_XTENSA_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
        bfd_elf_xtensa_reloc, "R_XTENSA_NONE",
        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, 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, 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, 0, 0xffffffff, FALSE),
  HOWTO (R_XTENSA_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_XTENSA_RELATIVE",
        FALSE, 0, 0xffffffff, FALSE),
  HOWTO (R_XTENSA_PLT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_xtensa_reloc, "R_XTENSA_PLT",
        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, 0, 0, TRUE),
  HOWTO (R_XTENSA_OP1, 0, 0, 0, TRUE, 0, complain_overflow_dont,
        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, 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, 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, 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, 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, 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, 0, 0xff, FALSE),
  HOWTO (R_XTENSA_DIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
        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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, TRUE),
};

Here is the call graph for this function:

Here is the caller graph for this function:

static char* vsprint_msg ( const char *  origmsg,
const char *  fmt,
int  arglen,
  ... 
) [static]

Definition at line 1740 of file elf32-xtensa.c.

{
  /* To reduce the size of the memory leak,
     we only use a single message buffer.  */
  static bfd_size_type alloc_size = 0;
  static char *message = NULL;
  bfd_size_type orig_len, len = 0;
  bfd_boolean is_append;

  VA_OPEN (ap, arglen);
  VA_FIXEDARG (ap, const char *, origmsg);
  
  is_append = (origmsg == message);  

  orig_len = strlen (origmsg);
  len = orig_len + strlen (fmt) + arglen + 20;
  if (len > alloc_size)
    {
      message = (char *) bfd_realloc (message, len);
      alloc_size = len;
    }
  if (!is_append)
    memcpy (message, origmsg, orig_len);
  vsprintf (message + orig_len, fmt, ap);
  VA_CLOSE (ap);
  return message;
}

Here is the call graph for this function:

static bfd_boolean widen_instruction ( bfd_byte contents,
bfd_size_type  content_length,
bfd_size_type  offset 
) [static]

Definition at line 3801 of file elf32-xtensa.c.

{
  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;
}

Here is the call graph for this function:

static int xtensa_read_table_entries ( bfd abfd,
asection section,
property_table_entry **  table_p,
const char *  sec_name,
bfd_boolean  output_addr 
) [static]

Definition at line 601 of file elf32-xtensa.c.

{
  asection *table_section;
  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;
  flagword predef_flags;
  bfd_size_type table_entry_size;

  if (!section
      || !(section->flags & SEC_ALLOC)
      || (section->flags & SEC_DEBUGGING))
    {
      *table_p = NULL;
      return 0;
    }

  table_section = xtensa_get_property_section (section, sec_name);
  if (table_section)
    table_size = table_section->size;

  if (table_size == 0) 
    {
      *table_p = NULL;
      return 0;
    }

  predef_flags = xtensa_get_property_predef_flags (table_section);
  table_entry_size = 12;
  if (predef_flags)
    table_entry_size -= 4;

  num_records = table_size / table_entry_size;
  table_data = retrieve_contents (abfd, table_section, TRUE);
  blocks = (property_table_entry *)
    bfd_malloc (num_records * sizeof (property_table_entry));
  block_count = 0;

  if (output_addr)
    section_addr = section->output_section->vma + section->output_offset;
  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;

         if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE)
           continue;

         BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32);
         r_symndx = ELF32_R_SYM (rel->r_info);

         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++;
           }
       }
    }
  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) 
       {
         bfd_vma address = bfd_get_32 (abfd, table_data + off);

         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++;
           }
       }
    }

  release_contents (table_section, table_data);
  release_internal_relocs (table_section, internal_relocs);

  if (block_count > 0)
    {
      /* Now sort them into address order for easy reference.  */
      qsort (blocks, block_count, sizeof (property_table_entry),
            property_table_compare);

      /* Check that the table contents are valid.  Problems may occur,
         for example, if an unrelocated object file is stripped.  */
      for (blk = 1; blk < block_count; blk++)
       {
         /* The only circumstance where two entries may legitimately
            have the same address is when one of them is a zero-size
            placeholder to mark a place where fill can be inserted.
            The zero-size entry should come first.  */
         if (blocks[blk - 1].address == blocks[blk].address &&
             blocks[blk - 1].size != 0)
           {
             (*_bfd_error_handler) (_("%B(%A): invalid property table"),
                                 abfd, section);
             bfd_set_error (bfd_error_bad_value);
             free (blocks);
             return -1;
           }
       }
    }

  *table_p = blocks;
  return block_count;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 3034 of file elf32-xtensa.c.

Definition at line 3037 of file elf32-xtensa.c.

Definition at line 3035 of file elf32-xtensa.c.

Definition at line 3036 of file elf32-xtensa.c.

Definition at line 3030 of file elf32-xtensa.c.

Definition at line 3033 of file elf32-xtensa.c.

Definition at line 3031 of file elf32-xtensa.c.

Definition at line 3032 of file elf32-xtensa.c.

Initial value:
{
  0x6c, 0x10, 0x04,  
  0x18, 0x00, 0x00,  
  0x1a, 0x00, 0x00,  
  0x1b, 0x00, 0x00,  
  0x0a, 0x80, 0x00,  
  0                  
}

Definition at line 452 of file elf32-xtensa.c.

Initial value:
{
  0x36, 0x41, 0x00,  
  0x81, 0x00, 0x00,  
  0xa1, 0x00, 0x00,  
  0xb1, 0x00, 0x00,  
  0xa0, 0x08, 0x00,  
  0                  
}

Definition at line 462 of file elf32-xtensa.c.

Definition at line 3433 of file elf32-xtensa.c.