/* BFD back-end for National Semiconductor's CR16 ELF
- Copyright 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
Written by M R Swami Reddy.
This file is part of BFD, the Binary File Descriptor library.
{
HOWTO (R_CR16_NONE, /* type */
0, /* rightshift */
- 2, /* size */
- 32, /* bitsize */
+ 3, /* size */
+ 0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
{
unsigned int r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
+ if (r_type >= R_CR16_MAX)
+ {
+ (*_bfd_error_handler) (_("%B: unrecognised CR16 reloc number: %d"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ r_type = R_CR16_NONE;
+ }
cache_ptr->howto = cr16_elf_howto_table + r_type;
}
srelgot = NULL;
bfd_boolean result = FALSE;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
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;
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
}
/* Some relocs require a global offset table. */
}
if (srelgot == NULL
- && (h != NULL || info->executable))
+ && (h != NULL || bfd_link_executable (info)))
{
srelgot = bfd_get_linker_section (dynobj, ".rela.got");
if (srelgot == NULL)
- {
+ {
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
| SEC_IN_MEMORY | SEC_LINKER_CREATED
| SEC_READONLY);
local_got_offsets[r_symndx] = sgot->size;
- if (info->executable)
+ if (bfd_link_executable (info))
/* If we are generating a shared object, we need to
output a R_CR16_RELATIVE reloc so that the dynamic
linker can adjust this GOT entry. */
/* We only care about the addend, where the difference between
expressions is kept. */
Rvalue = 0;
-
+
default:
break;
}
| ((Rvalue >> 16) & 0xf)), hit_data);
bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
}
- else if (r_type == R_CR16_GOT_REGREL20)
+ else if (r_type == R_CR16_GOT_REGREL20)
{
asection * sgot = bfd_get_linker_section (dynobj, ".got");
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
because of a version file. We must initialize
- this entry in the global offset table.
+ this entry in the global offset table.
When doing a dynamic link, we create a .rela.got
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
Rvalue += addend;
- /* REVISIT: if ((long) Rvalue > 0xffffff ||
+ /* REVISIT: if ((long) Rvalue > 0xffffff ||
(long) Rvalue < -0x800000). */
if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
return bfd_reloc_overflow;
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
because of a version file. We must initialize
- this entry in the global offset table.
+ this entry in the global offset table.
When doing a dynamic link, we create a .rela.got
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
Rvalue += Rvalue1;
/* Check for range. */
- /* REVISIT: if ((long) Rvalue > 0xffffff
+ /* REVISIT: if ((long) Rvalue > 0xffffff
|| (long) Rvalue < -0x800000). */
if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
return bfd_reloc_overflow;
}
else if (r_type == R_CR16_NUM32)
{
- Rvalue1 = (bfd_get_32 (input_bfd, hit_data));
+ Rvalue1 = (bfd_get_32 (input_bfd, hit_data));
/* Add or subtract the offset value */
if (Rvalue1 & 0x80000000)
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
continue;
-
+
r_symndx = ELF32_R_SYM (irel->r_info);
rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
}
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 (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
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;
}
}
struct elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_link_hash_table);
- ret = (struct elf_link_hash_table *) bfd_malloc (amt);
+ ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
if (ret == (struct elf_link_hash_table *) NULL)
return NULL;
return &ret->root;
}
-/* Free an cr16 ELF linker hash table. */
-
-static void
-elf32_cr16_link_hash_table_free (struct bfd_link_hash_table *hash)
-{
- struct elf_link_hash_table *ret
- = (struct elf_link_hash_table *) hash;
-
- _bfd_generic_link_hash_table_free
- ((struct bfd_link_hash_table *) ret);
-}
-
static unsigned long
elf_cr16_mach (flagword flags)
{
/* 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)
bfd_vma value = symval;
unsigned short is_add_mov = 0;
bfd_vma value1 = 0;
-
+
/* Get the existing value from the mcode */
value1 = ((bfd_get_32 (abfd, contents + irel->r_offset + 2) >> 16)
|(((bfd_get_32 (abfd, contents + irel->r_offset + 2) & 0xffff) << 16)));
/* Verify it's a 'arithmetic ADDD or MOVD instruction'.
For ADDD and MOVD only, convert to IMM32 -> IMM20. */
-
+
if (((code & 0xfff0) == 0x0070) || ((code & 0xfff0) == 0x0020))
is_add_mov = 1;
bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
- /* If existing value is nagavive adjust approriately
+ /* If existing value is nagavive adjust approriately
place the 16-20bits (ie 4 bit) in new opcode,
as the 0xffffxxxx, the higher 2 byte values removed. */
if (value1 & 0x80000000)
}
/* See if the value will fit in 16 bits. */
- if ((!is_add_mov)
+ if ((!is_add_mov)
&& ((long)(value + value1) < 0x7fff && (long)(value + value1) > 0))
{
unsigned short code;
bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
- /* If existing value is nagavive adjust approriately
+ /* If existing value is nagavive adjust approriately
place the 12-16bits (ie 4 bit) in new opcode,
as the 0xfffffxxx, the higher 2 byte values removed. */
if (value1 & 0x80000000)
#if 0
/* Try to turn a 16bit immediate address into a 4bit
immediate address. */
- if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
+ if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
|| (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
{
bfd_vma value = symval;
else
/* Cache the section contents for elf_link_input_bfd. */
elf_section_data (sec)->this_hdr.contents = contents;
-
+
}
if (internal_relocs != NULL
be needed, we can discard it later. We will never need this
section when generating a shared object, since they do not use
copy relocs. */
- if (! info->executable)
+ if (! bfd_link_executable (info))
{
s = bfd_make_section_anyway_with_flags (abfd,
(bed->default_use_rela_p
if (h->type == STT_FUNC
|| h->needs_plt)
{
- if (! info->executable
+ if (! bfd_link_executable (info)
&& !h->def_dynamic
&& !h->ref_dynamic)
{
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->executable)
+ if (bfd_link_executable (info))
return TRUE;
/* If there are no references to this symbol that do not use the
h->needs_copy = 1;
}
- return _bfd_elf_adjust_dynamic_copy (h, s);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Set the sizes of the dynamic sections. */
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
+ if (bfd_link_executable (info) && !info->nointerp)
{
#if 0
s = bfd_get_linker_section (dynobj, ".interp");
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. */
- if (! info->executable)
+ if (! bfd_link_executable (info))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0))
return FALSE;
the symbol was forced to be local because of a version file.
The entry in the global offset table will already have been
initialized in the relocate_section function. */
- if (info->executable
+ if (bfd_link_executable (info)
&& (info->symbolic || h->dynindx == -1)
&& h->def_regular)
{
break;
case DT_PLTGOT:
- name = ".got";
+ name = ".got.plt";
goto get_vma;
case DT_JMPREL:
name = ".rela.plt";
get_vma:
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
+ s = bfd_get_linker_section (dynobj, name);
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_PLTRELSZ:
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
- BFD_ASSERT (s != NULL);
+ s = bfd_get_linker_section (dynobj, ".rela.plt");
dyn.d_un.d_val = s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
the linker script arranges for .rela.plt to follow all
other relocation sections, we don't have to worry
about changing the DT_RELA entry. */
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+ s = bfd_get_linker_section (dynobj, ".rela.plt");
if (s != NULL)
dyn.d_un.d_val -= s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
bfd_byte *p;
bfd_size_type amt;
- BFD_ASSERT (! info->relocatable);
+ BFD_ASSERT (! bfd_link_relocatable (info));
*errmsg = NULL;
properly. */
static enum elf_reloc_type_class
-_bfd_cr16_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+_bfd_cr16_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela)
{
switch ((int) ELF32_R_TYPE (rela->r_info))
{
}
/* Definitions for setting CR16 target vector. */
-#define TARGET_LITTLE_SYM bfd_elf32_cr16_vec
+#define TARGET_LITTLE_SYM cr16_elf32_vec
#define TARGET_LITTLE_NAME "elf32-cr16"
#define ELF_ARCH bfd_arch_cr16
#define ELF_MACHINE_CODE EM_CR16
#define bfd_elf32_bfd_link_hash_table_create \
elf32_cr16_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free \
- elf32_cr16_link_hash_table_free
#define elf_backend_create_dynamic_sections \
_bfd_cr16_elf_create_dynamic_sections