/* BFD back-end for National Semiconductor's CRX ELF
- Copyright 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004-2019 Free Software Foundation, Inc.
Written by Tomer Levi, NSC, Israel.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
static reloc_howto_type *elf_crx_reloc_type_lookup
(bfd *, bfd_reloc_code_real_type);
-static void elf_crx_info_to_howto
+static bfd_boolean elf_crx_info_to_howto
(bfd *, arelent *, Elf_Internal_Rela *);
static bfd_boolean elf32_crx_relax_delete_bytes
(struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
static bfd_boolean elf32_crx_relocate_section
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
-static asection * elf32_crx_gc_mark_hook
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *);
-static bfd_boolean elf32_crx_gc_sweep_hook
- (bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *);
static bfd_boolean elf32_crx_relax_section
(bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
static bfd_byte * elf32_crx_get_relocated_section_contents
{
HOWTO (R_CRX_NONE, /* type */
0, /* rightshift */
- 2, /* size */
- 32, /* bitsize */
+ 3, /* size */
+ 0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL4", /* name */
FALSE, /* partial_inplace */
- 0xf, /* src_mask */
+ 0x0, /* src_mask */
0xf, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL8", /* name */
FALSE, /* partial_inplace */
- 0xff, /* src_mask */
+ 0x0, /* src_mask */
0xff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL8_CMP", /* name */
FALSE, /* partial_inplace */
- 0xff, /* src_mask */
+ 0x0, /* src_mask */
0xff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL16", /* name */
FALSE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0x0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL24", /* name */
FALSE, /* partial_inplace */
- 0xffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REL32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REGREL12", /* name */
FALSE, /* partial_inplace */
- 0xfff, /* src_mask */
+ 0x0, /* src_mask */
0xfff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REGREL22", /* name */
FALSE, /* partial_inplace */
- 0x3fffff, /* src_mask */
+ 0x0, /* src_mask */
0x3fffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REGREL28", /* name */
FALSE, /* partial_inplace */
- 0xfffffff, /* src_mask */
+ 0x0, /* src_mask */
0xfffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_REGREL32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_ABS16", /* name */
FALSE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0x0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_ABS32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_NUM8", /* name */
FALSE, /* partial_inplace */
- 0xff, /* src_mask */
+ 0x0, /* src_mask */
0xff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_NUM16", /* name */
FALSE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0x0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_NUM32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_IMM16", /* name */
FALSE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0x0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_IMM32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
-
+
/* An 8 bit switch table entry. This is generated for an expression
such as ``.byte L1 - L2''. The offset holds the difference
between the reloc address and L2. */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_SWITCH8", /* name */
FALSE, /* partial_inplace */
- 0xff, /* src_mask */
+ 0x0, /* src_mask */
0xff, /* dst_mask */
TRUE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_SWITCH16", /* name */
FALSE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0x0, /* src_mask */
0xffff, /* dst_mask */
TRUE), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_CRX_SWITCH32", /* name */
FALSE, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x0, /* src_mask */
0xffffffff, /* dst_mask */
TRUE) /* pcrel_offset */
};
return 0;
}
+static reloc_howto_type *
+elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
+ i++)
+ if (crx_elf_howto_table[i].name != NULL
+ && strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
+ return &crx_elf_howto_table[i];
+
+ return NULL;
+}
+
/* Retrieve a howto ptr using an internal relocation entry. */
-static void
-elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+static bfd_boolean
+elf_crx_info_to_howto (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
unsigned int r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
+ if (r_type >= R_CRX_MAX)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
cache_ptr->howto = &crx_elf_howto_table[r_type];
+ return TRUE;
}
/* Perform a relocation as part of a final link. */
case R_CRX_SWITCH8:
case R_CRX_SWITCH16:
case R_CRX_SWITCH32:
- /* We only care about the addend, where the difference between
+ /* We only care about the addend, where the difference between
expressions is kept. */
Rvalue = 0;
-
+
default:
break;
}
/* Delete some bytes from a section while relaxing. */
static bfd_boolean
-elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
+elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
asection *sec, bfd_vma addr, int count)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned int sec_shndx;
bfd_byte *contents;
Elf_Internal_Rela *irel, *irelend;
- Elf_Internal_Rela *irelalign;
bfd_vma toaddr;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
contents = elf_section_data (sec)->this_hdr.contents;
- /* The deletion must stop at the next ALIGN reloc for an aligment
- power larger than the number of bytes we are deleting. */
-
- irelalign = NULL;
toaddr = sec->size;
irel = elf_section_data (sec)->relocs;
&& isym->st_value > addr
&& isym->st_value < toaddr)
{
- /* Adjust the addend of SWITCH relocations in this section,
+ /* Adjust the addend of SWITCH relocations in this section,
which reference this local symbol. */
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
{
{
struct elf_link_hash_entry *sym_hash = *sym_hashes;
- /* The '--wrap SYMBOL' option is causing a pain when the object file,
- containing the definition of __wrap_SYMBOL, includes a direct
- call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
- the same symbol (which is __wrap_SYMBOL), but still exist as two
- different symbols in 'sym_hashes', we don't want to adjust
- the global symbol __wrap_SYMBOL twice.
+ /* The '--wrap SYMBOL' option is causing a pain when the object file,
+ containing the definition of __wrap_SYMBOL, includes a direct
+ call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
+ the same symbol (which is __wrap_SYMBOL), but still exist as two
+ different symbols in 'sym_hashes', we don't want to adjust
+ the global symbol __wrap_SYMBOL twice.
This check is only relevant when symbols are being wrapped. */
if (link_info->wrap_hash != NULL)
{
struct elf_link_hash_entry **cur_sym_hashes;
-
+
/* Loop only over the symbols whom been already checked. */
- for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
+ for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
cur_sym_hashes++)
{
- /* If the current symbol is identical to 'sym_hash', that means
+ /* If the current symbol is identical to 'sym_hash', that means
the symbol was already adjusted (or at least checked). */
if (*cur_sym_hashes == sym_hash)
break;
bfd_size_type amt;
internal_relocs = (_bfd_elf_link_read_relocs
- (input_bfd, input_section, (PTR) NULL,
+ (input_bfd, input_section, NULL,
(Elf_Internal_Rela *) NULL, FALSE));
if (internal_relocs == NULL)
goto error_return;
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel, *relend;
- if (info->relocatable)
- return TRUE;
-
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
+
+ if (bfd_link_relocatable (info))
+ continue;
+
r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
input_section,
contents, rel->r_offset,
name = (bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name));
if (name == NULL || *name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ name = bfd_section_name (sec);
}
switch (r)
{
case bfd_reloc_overflow:
- if (!((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section,
- rel->r_offset)))
- return FALSE;
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
break;
case bfd_reloc_undefined:
- if (!((*info->callbacks->undefined_symbol)
- (info, name, input_bfd, input_section,
- rel->r_offset, TRUE)))
- return FALSE;
+ (*info->callbacks->undefined_symbol)
+ (info, name, input_bfd, input_section, rel->r_offset, TRUE);
break;
case bfd_reloc_outofrange:
/* Fall through. */
common_error:
- if (!((*info->callbacks->warning)
- (info, msg, name, input_bfd, input_section,
- rel->r_offset)))
- return FALSE;
+ (*info->callbacks->warning) (info, msg, name, input_bfd,
+ input_section, rel->r_offset);
break;
}
}
/* We don't have to do anything for a relocatable link, if
this section does not have relocs, or if this is not a
code section. */
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
|| (sec->flags & SEC_CODE) == 0)
/* Get a copy of the native relocations. */
internal_relocs = (_bfd_elf_link_read_relocs
- (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
link_info->keep_memory));
if (internal_relocs == NULL)
goto error_return;
return FALSE;
}
-static asection *
-elf32_crx_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym)
-{
- if (h == NULL)
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- return NULL;
- }
-}
-
-/* Update the got entry reference counts for the section being removed. */
-
-static bfd_boolean
-elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
-{
- /* We don't support garbage collection of GOT and PLT relocs yet. */
- return TRUE;
-}
-
/* Definitions for setting CRX target vector. */
-#define TARGET_LITTLE_SYM bfd_elf32_crx_vec
+#define TARGET_LITTLE_SYM crx_elf32_vec
#define TARGET_LITTLE_NAME "elf32-crx"
#define ELF_ARCH bfd_arch_crx
#define ELF_MACHINE_CODE EM_CRX
#define elf_symbol_leading_char '_'
#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup \
+ elf_crx_reloc_name_lookup
#define elf_info_to_howto elf_crx_info_to_howto
-#define elf_info_to_howto_rel 0
+#define elf_info_to_howto_rel NULL
#define elf_backend_relocate_section elf32_crx_relocate_section
#define bfd_elf32_bfd_relax_section elf32_crx_relax_section
#define bfd_elf32_bfd_get_relocated_section_contents \
elf32_crx_get_relocated_section_contents
-#define elf_backend_gc_mark_hook elf32_crx_gc_mark_hook
-#define elf_backend_gc_sweep_hook elf32_crx_gc_sweep_hook
#define elf_backend_can_gc_sections 1
#define elf_backend_rela_normal 1