/* V850-specific support for 32-bit ELF
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
static void remember_hi16s_reloc
PARAMS ((bfd *, bfd_vma, bfd_byte *));
static bfd_byte * find_remembered_hi16s_reloc
- PARAMS ((bfd_vma addend));
+ PARAMS ((bfd_vma, boolean *));
static bfd_reloc_status_type v850_elf_final_link_relocate
PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma,
bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int));
complain_overflow_dont, /* complain_on_overflow */
v850_elf_reloc, /* special_function */
"R_V850_HI16_S", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
complain_overflow_dont, /* complain_on_overflow */
v850_elf_reloc, /* special_function */
"R_V850_HI16", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
complain_overflow_dont, /* complain_on_overflow */
v850_elf_reloc, /* special_function */
"R_V850_LO16", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
complain_overflow_dont, /* complain_on_overflow */
v850_elf_reloc, /* special_function */
"R_V850_32", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_16", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_8", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0xff, /* src_mask */
0xff, /* dst_mask */
false), /* pcrel_offset */
0xfff, /* dst_mask */
false), /* pcrel_offset */
-/* start-sanitize-v850e */
-
/* 5 bit offset from the tiny data area pointer. */
HOWTO (R_V850_TDA_4_5_OFFSET, /* type */
1, /* rightshift */
0xffff, /* dst_mask */
false), /* pcrel_offset */
-/* end-sanitize-v850e */
/* GNU extension to record C++ vtable hierarchy */
HOWTO (R_V850_GNU_VTINHERIT, /* type */
0, /* rightshift */
struct v850_elf_reloc_map
{
- unsigned char bfd_reloc_val;
+ /* BFD_RELOC_V850_CALLT_16_16_OFFSET is 258, which will not fix in an
+ unsigned char. */
+ bfd_reloc_code_real_type bfd_reloc_val;
unsigned char elf_reloc_val;
};
{ BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET },
{ BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET },
{ BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
-/* start-sanitize-v850e */
{ BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
{ BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
{ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
{ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
{ BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET },
{ BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET },
-/* end-sanitize-v850e */
{ BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY },
/* Map a bfd relocation into the appropriate howto structure */
static reloc_howto_type *
v850_elf_reloc_type_lookup (abfd, code)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
unsigned int i;
/* Set the howto pointer for an V850 ELF reloc. */
static void
v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
arelent * cache_ptr;
Elf32_Internal_Rel * dst;
{
/* Set the howto pointer for a V850 ELF reloc (type RELA). */
static void
v850_elf_info_to_howto_rela (abfd, cache_ptr, dst)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
arelent * cache_ptr;
Elf32_Internal_Rela *dst;
{
case R_V850_32:
case R_V850_16:
case R_V850_8:
-/* start-sanitize-v850e */
case R_V850_CALLT_6_7_OFFSET:
case R_V850_CALLT_16_16_OFFSET:
-/* end-sanitize-v850e */
break;
/* This relocation describes the C++ object vtable hierarchy.
return false;
break;
-/* start-sanitize-v850e */
case R_V850_SDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
case R_V850_SDA_16_16_OFFSET:
case R_V850_SDA_15_16_OFFSET:
other = V850_OTHER_SDA;
common = ".scommon";
goto small_data_common;
-/* start-sanitize-v850e */
case R_V850_ZDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
case R_V850_ZDA_16_16_OFFSET:
case R_V850_ZDA_15_16_OFFSET:
other = V850_OTHER_ZDA;
common = ".zcommon";
goto small_data_common;
-/* start-sanitize-v850e */
case R_V850_TDA_4_5_OFFSET:
case R_V850_TDA_4_4_OFFSET:
-/* end-sanitize-v850e */
case R_V850_TDA_6_8_OFFSET:
case R_V850_TDA_7_8_OFFSET:
case R_V850_TDA_7_7_OFFSET:
return ret;
}
+/*
+ * In the old version, when an entry was checked out from the table,
+ * it was deleted. This produced an error if the entry was needed
+ * more than once, as the second attempted retry failed.
+ *
+ * In the current version, the entry is not deleted, instead we set
+ * the field 'found' to true. If a second lookup matches the same
+ * entry, then we know that the hi16s reloc has already been updated
+ * and does not need to be updated a second time.
+ *
+ * TODO - TOFIX: If it is possible that we need to restore 2 different
+ * addresses from the same table entry, where the first generates an
+ * overflow, whilst the second do not, then this code will fail.
+ */
+
typedef struct hi16s_location
{
bfd_vma addend;
bfd_byte * address;
unsigned long counter;
+ boolean found;
struct hi16s_location * next;
}
hi16s_location;
if (free_hi16s == NULL)
free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s));
- entry = free_hi16s;
+ entry = free_hi16s;
free_hi16s = free_hi16s->next;
entry->addend = addend;
entry->address = address;
entry->counter = hi16s_counter ++;
+ entry->found = false;
entry->next = previous_hi16s;
previous_hi16s = entry;
}
static bfd_byte *
-find_remembered_hi16s_reloc (addend)
- bfd_vma addend;
+find_remembered_hi16s_reloc (addend, already_found)
+ bfd_vma addend;
+ boolean * already_found;
{
hi16s_location * match = NULL;
hi16s_location * entry;
hi16s_location * previous = NULL;
hi16s_location * prev;
- int i;
bfd_byte * addr;
/* Search the table. Record the most recent entry that matches. */
for (entry = previous_hi16s; entry; entry = entry->next)
{
- if (entry->addend == addend)
+ if (entry->addend == addend
+ && (match == NULL || match->counter < entry->counter))
{
- if (match == NULL || match->counter < entry->counter)
- {
- previous = prev;
- match = entry;
- }
+ previous = prev;
+ match = entry;
}
-
+
prev = entry;
}
/* Extract the address. */
addr = match->address;
-
- /* Attach the entry to the free list. */
- if (previous)
- previous->next = match->next;
- else
- previous_hi16s = match->next;
-
- match->next = free_hi16s->next;
- free_hi16s = match;
-
- match->addend = 0;
- match->address = NULL;
+
+ /* Remeber if this entry has already been used before. */
+ if (already_found)
+ * already_found = match->found;
+
+ /* Note that this entry has now been used. */
+ match->found = true;
return addr;
}
|| (OVERFLOWS (addend, insn)
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
{
- bfd_byte * hi16s_address = find_remembered_hi16s_reloc (addend);
+ boolean already_updated;
+ bfd_byte * hi16s_address = find_remembered_hi16s_reloc
+ (addend, & already_updated);
/* Amend the matching HI16_S relocation. */
if (hi16s_address != NULL)
{
- insn = bfd_get_16 (abfd, hi16s_address);
- insn += 1;
- bfd_put_16 (abfd, insn, hi16s_address);
+ if (! already_updated)
+ {
+ insn = bfd_get_16 (abfd, hi16s_address);
+ insn += 1;
+ bfd_put_16 (abfd, insn, hi16s_address);
+ }
}
else
{
bfd_put_8 (abfd, addend, address);
return bfd_reloc_ok;
-/* start-sanitize-v850e */
case R_V850_CALLT_16_16_OFFSET:
addend += bfd_get_16 (abfd, address);
insn = addend;
break;
-/* end-sanitize-v850e */
case R_V850_16:
insn |= addend;
break;
-/* start-sanitize-v850e */
case R_V850_TDA_4_5_OFFSET:
insn = bfd_get_16 (abfd, address);
addend += ((insn & 0xf) << 1);
insn &= 0xff80;
insn |= (addend >> 1);
break;
-/* end-sanitize-v850e */
case R_V850_GNU_VTINHERIT:
case R_V850_GNU_VTENTRY:
/* Insert the addend into the instruction. */
static bfd_reloc_status_type
v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
arelent * reloc;
asymbol * symbol;
- PTR data;
+ PTR data ATTRIBUTE_UNUSED;
asection * isection;
bfd * obfd;
- char ** err;
+ char ** err ATTRIBUTE_UNUSED;
{
long relocation;
/*ARGSUSED*/
static boolean
v850_elf_is_local_label_name (abfd, name)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
const char * name;
{
return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
addend, info, sym_sec, is_local)
reloc_howto_type * howto;
bfd * input_bfd;
- bfd * output_bfd;
+ bfd * output_bfd ATTRIBUTE_UNUSED;
asection * input_section;
bfd_byte * contents;
bfd_vma offset;
bfd_vma addend;
struct bfd_link_info * info;
asection * sym_sec;
- int is_local;
+ int is_local ATTRIBUTE_UNUSED;
{
unsigned long r_type = howto->type;
bfd_byte * hit_data = contents + offset;
+ input_section->output_offset
+ offset);
+ /* If the sign extension will corrupt the value then we have overflowed. */
+ if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000))
+ return bfd_reloc_overflow;
+
value = SEXT24 (value); /* Only the bottom 24 bits of the PC are valid */
break;
case R_V850_ZDA_15_16_OFFSET:
case R_V850_ZDA_16_16_OFFSET:
-/* start-sanitize-v850e */
case R_V850_ZDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
if (sym_sec == NULL)
return bfd_reloc_undefined;
case R_V850_SDA_15_16_OFFSET:
case R_V850_SDA_16_16_OFFSET:
-/* start-sanitize-v850e */
case R_V850_SDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
{
unsigned long gp;
struct bfd_link_hash_entry * h;
}
break;
-/* start-sanitize-v850e */
case R_V850_TDA_4_4_OFFSET:
case R_V850_TDA_4_5_OFFSET:
-/* end-sanitize-v850e */
case R_V850_TDA_16_16_OFFSET:
case R_V850_TDA_7_7_OFFSET:
case R_V850_TDA_7_8_OFFSET:
}
break;
-/* start-sanitize-v850e */
case R_V850_CALLT_6_7_OFFSET:
{
unsigned long ctbp;
value -= (ctbp - sym_sec->output_section->vma);
}
break;
-/* end-sanitize-v850e */
case R_V850_NONE:
case R_V850_GNU_VTINHERIT:
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
+ if (sym_hashes == NULL)
+ {
+ info->callbacks->warning
+ (info, "no hash table available", NULL, input_bfd, input_section, 0);
+
+ return false;
+ }
+
+ /* Reset the list of remembered HI16S relocs to empty. */
+ free_hi16s = previous_hi16s;
+ previous_hi16s = NULL;
+ hi16s_counter = 0;
+
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
|| r_type == R_V850_GNU_VTINHERIT)
continue;
- howto = v850_elf_howto_table + r_type;
+ howto = v850_elf_howto_table + r_type;
if (info->relocateable)
{
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
- input_section, rel->r_offset)))
+ input_section, rel->r_offset, true)))
return false;
#if 0
fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
case bfd_reloc_undefined:
if (! ((*info->callbacks->undefined_symbol)
(info, name, input_bfd, input_section,
- rel->r_offset)))
+ rel->r_offset, true)))
return false;
break;
static boolean
v850_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ asection *sec ATTRIBUTE_UNUSED;
+ const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
{
/* No got and plt entries for v850-elf */
return true;
static asection *
v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
case bfd_link_hash_common:
return h->root.u.c.p->section;
+
+ default:
+ break;
}
}
}
{
default:
case E_V850_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
-/* start-sanitize-v850e */
case E_V850E_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
case E_V850EA_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850ea); break;
-/* end-sanitize-v850e */
}
return true;
}
static void
v850_elf_final_write_processing (abfd, linker)
bfd * abfd;
- boolean linker;
+ boolean linker ATTRIBUTE_UNUSED;
{
unsigned long val;
{
default:
case 0: val = E_V850_ARCH; break;
-/* start-sanitize-v850e */
case bfd_mach_v850e: val = E_V850E_ARCH; break;
case bfd_mach_v850ea: val = E_V850EA_ARCH; break;
-/* end-sanitize-v850e */
}
elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
{
default:
case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
-/* start-sanitize-v850e */
case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break;
case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break;
-/* end-sanitize-v850e */
}
fputc ('\n', file);
static boolean
v850_elf_section_from_bfd_section (abfd, hdr, sec, retval)
- bfd * abfd;
- Elf32_Internal_Shdr * hdr;
+ bfd * abfd ATTRIBUTE_UNUSED;
+ Elf32_Internal_Shdr * hdr ATTRIBUTE_UNUSED;
asection * sec;
int * retval;
{
static boolean
v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
bfd * abfd;
- struct bfd_link_info * info;
+ struct bfd_link_info * info ATTRIBUTE_UNUSED;
const Elf_Internal_Sym * sym;
- const char ** namep;
- flagword * flagsp;
+ const char ** namep ATTRIBUTE_UNUSED;
+ flagword * flagsp ATTRIBUTE_UNUSED;
asection ** secp;
bfd_vma * valp;
{
/*ARGSIGNORED*/
static boolean
v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
- bfd * abfd;
- struct bfd_link_info * info;
- const char * name;
+ bfd * abfd ATTRIBUTE_UNUSED;
+ struct bfd_link_info * info ATTRIBUTE_UNUSED;
+ const char * name ATTRIBUTE_UNUSED;
Elf_Internal_Sym * sym;
asection * input_sec;
{
section name, which is a hack, but ought to work. */
static boolean
v850_elf_fake_sections (abfd, hdr, sec)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
Elf32_Internal_Shdr * hdr;
asection * sec;
{