/* Xtensa-specific support for 32-bit ELF.
- Copyright (C) 2003-2019 Free Software Foundation, Inc.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "xtensa-isa.h"
#include "xtensa-config.h"
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
#define XTENSA_NO_NOP_REMOVAL 0
/* Local helper functions. */
HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
FALSE, 0, 0, FALSE),
+
+ HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
+ HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
+ HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
+
+ HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
+ HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
+ HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
};
#if DEBUG_GEN_RELOC
TRACE ("BFD_RELOC_XTENSA_DIFF32");
return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
+ case BFD_RELOC_XTENSA_PDIFF8:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF8");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
+
+ case BFD_RELOC_XTENSA_PDIFF16:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF16");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
+
+ case BFD_RELOC_XTENSA_PDIFF32:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF32");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
+
+ case BFD_RELOC_XTENSA_NDIFF8:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF8");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
+
+ case BFD_RELOC_XTENSA_NDIFF16:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF16");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
+
+ case BFD_RELOC_XTENSA_NDIFF32:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF32");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
+
case BFD_RELOC_XTENSA_RTLD:
TRACE ("BFD_RELOC_XTENSA_RTLD");
return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
{
struct elf_link_hash_entry *tlsbase;
struct elf_xtensa_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct elf_xtensa_link_hash_table);
+ size_t amt = sizeof (struct elf_xtensa_link_hash_table);
ret = bfd_zmalloc (amt);
if (ret == NULL)
case R_XTENSA_DIFF8:
case R_XTENSA_DIFF16:
case R_XTENSA_DIFF32:
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF8:
+ case R_XTENSA_NDIFF16:
+ case R_XTENSA_NDIFF32:
case R_XTENSA_TLS_FUNC:
case R_XTENSA_TLS_ARG:
case R_XTENSA_TLS_CALL:
bfd_vma relocation;
bfd_reloc_status_type flag;
bfd_size_type octets = (reloc_entry->address
- * bfd_octets_per_byte (abfd, NULL));
+ * OCTETS_PER_BYTE (abfd, input_section));
bfd_vma output_base = 0;
reloc_howto_type *howto = reloc_entry->howto;
asection *reloc_target_output_section;
}
}
- if (lit_table)
- free (lit_table);
-
+ free (lit_table);
input_section->reloc_done = TRUE;
return TRUE;
if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
{
- if (contents != 0)
- free (contents);
+ free (contents);
free (table);
return -1;
}
if (!sec->used_by_bfd)
{
struct elf_xtensa_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ size_t amt = sizeof (*sdata);
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
{
release_contents (sec_cache->sec, sec_cache->contents);
release_internal_relocs (sec_cache->sec, sec_cache->relocs);
- if (sec_cache->ptbl)
- free (sec_cache->ptbl);
+ free (sec_cache->ptbl);
}
}
err:
release_contents (sec, contents);
release_internal_relocs (sec, internal_relocs);
- if (prop_table)
- free (prop_table);
+ free (prop_table);
return FALSE;
}
static void
free_ebb_constraint (ebb_constraint *c)
{
- if (c->actions)
- free (c->actions);
+ free (c->actions);
}
for (i = 0; i < c->action_count; i++)
new_actions[i] = c->actions[i];
- if (c->actions)
- free (c->actions);
+ free (c->actions);
c->actions = new_actions;
c->action_allocated = new_allocated;
}
static void
release_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
{
- if (internal_relocs
- && elf_section_data (sec)->relocs != internal_relocs)
+ if (elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
}
{
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
{
- if (contents)
- free (contents);
+ free (contents);
return NULL;
}
if (keep_memory)
static void
release_contents (asection *sec, bfd_byte *contents)
{
- if (contents && elf_section_data (sec)->this_hdr.contents != contents)
+ if (elf_section_data (sec)->this_hdr.contents != contents)
free (contents);
}
print_action_list (stderr, &relax_info->action_list);
#endif
-error_return:
+ error_return:
release_contents (sec, contents);
release_internal_relocs (sec, internal_relocs);
- if (prop_table)
- free (prop_table);
- if (reloc_opcodes)
- free (reloc_opcodes);
+ free (prop_table);
+ free (reloc_opcodes);
return ok;
}
static void
free_xlate_map (xlate_map_t *map)
{
- if (map && map->entry)
- free (map->entry);
if (map)
- free (map);
+ {
+ free (map->entry);
+ free (map);
+ }
}
}
}
- if (xmap)
- free_xlate_map (xmap);
+ free_xlate_map (xmap);
return ok;
}
print_action_list (stderr, &relax_info->action_list);
#endif /* DEBUG */
-error_return:
- if (prop_table)
- free (prop_table);
+ error_return:
+ free (prop_table);
free_section_cache (&target_sec_cache);
release_contents (sec, contents);
if (r_type == R_XTENSA_DIFF8
|| r_type == R_XTENSA_DIFF16
- || r_type == R_XTENSA_DIFF32)
+ || r_type == R_XTENSA_DIFF32
+ || r_type == R_XTENSA_PDIFF8
+ || r_type == R_XTENSA_PDIFF16
+ || r_type == R_XTENSA_PDIFF32
+ || r_type == R_XTENSA_NDIFF8
+ || r_type == R_XTENSA_NDIFF16
+ || r_type == R_XTENSA_NDIFF32)
{
bfd_signed_vma diff_value = 0;
bfd_vma new_end_offset, diff_mask = 0;
switch (r_type)
{
case R_XTENSA_DIFF8:
+ diff_mask = 0x7f;
diff_value =
bfd_get_signed_8 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
+ diff_mask = 0x7fff;
diff_value =
bfd_get_signed_16 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
+ diff_mask = 0x7fffffff;
diff_value =
bfd_get_signed_32 (abfd, &contents[old_source_offset]);
break;
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_NDIFF8:
+ diff_mask = 0xff;
+ diff_value =
+ bfd_get_8 (abfd, &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_NDIFF16:
+ diff_mask = 0xffff;
+ diff_value =
+ bfd_get_16 (abfd, &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF32:
+ diff_mask = 0xffffffff;
+ diff_value =
+ bfd_get_32 (abfd, &contents[old_source_offset]);
+ break;
}
+ if (r_type >= R_XTENSA_NDIFF8
+ && r_type <= R_XTENSA_NDIFF32
+ && diff_value)
+ diff_value |= ~diff_mask;
+
new_end_offset = offset_with_removed_text_map
(&target_relax_info->action_list,
r_rel.target_offset + diff_value);
switch (r_type)
{
case R_XTENSA_DIFF8:
- diff_mask = 0x7f;
bfd_put_signed_8 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
- diff_mask = 0x7fff;
bfd_put_signed_16 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
- diff_mask = 0x7fffffff;
bfd_put_signed_32 (abfd, diff_value,
&contents[old_source_offset]);
break;
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_NDIFF8:
+ bfd_put_8 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_NDIFF16:
+ bfd_put_16 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF32:
+ bfd_put_32 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
}
- /* Check for overflow. Sign bits must be all zeroes or all ones */
- if ((diff_value & ~diff_mask) != 0 &&
- (diff_value & ~diff_mask) != (-1 & ~diff_mask))
+ /* Check for overflow. Sign bits must be all zeroes or
+ all ones. When sign bits are all ones diff_value
+ may not be zero. */
+ if (((diff_value & ~diff_mask) != 0
+ && (diff_value & ~diff_mask) != ~diff_mask)
+ || (diff_value && (bfd_vma) diff_value == ~diff_mask))
{
(*link_info->callbacks->reloc_dangerous)
(link_info, _("overflow after relaxation"),
if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
&& (input_section->flags & SEC_ALLOC) != 0
- && (dynamic_symbol || bfd_link_pic (info))
- && (!h || h->root.type != bfd_link_hash_undefweak
- || (dynamic_symbol
- && (bfd_link_dll (info) || info->export_dynamic))))
+ && (dynamic_symbol
+ || (bfd_link_pic (info)
+ && (!h || h->root.type != bfd_link_hash_undefweak))))
{
asection *srel;
bfd_boolean is_plt = FALSE;