/* V850-specific support for 32-bit ELF
- Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/v850.h"
+#include "libiberty.h"
-/* sign-extend a 24-bit number */
-#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
+/* Sign-extend a 24-bit number. */
+#define SEXT24(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000)
static reloc_howto_type *v850_elf_reloc_type_lookup
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static bfd_reloc_status_type v850_elf_perform_relocation
- PARAMS ((bfd *, int, bfd_vma, bfd_byte *));
+ PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *));
static boolean v850_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
static void remember_hi16s_reloc
Elf_Internal_Sym *, asection *));
static boolean v850_elf_section_from_shdr
PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
-
-/* Note: It is REQUIRED that the 'type' value of each entry in this array
- match the index of the entry in the array. */
+static boolean v850_elf_gc_sweep_hook
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static asection * v850_elf_gc_mark_hook
+ PARAMS ((bfd *, struct bfd_link_info *,
+ Elf_Internal_Rela *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+
+/* Note: It is REQUIRED that the 'type' value of each entry
+ in this array match the index of the entry in the array. */
static reloc_howto_type v850_elf_howto_table[] =
{
/* This reloc does nothing. */
/* 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;
+ unsigned int elf_reloc_val;
};
static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
};
\f
-/* Map a bfd relocation into the appropriate howto structure */
+/* Map a bfd relocation into the appropriate howto structure. */
+
static reloc_howto_type *
v850_elf_reloc_type_lookup (abfd, code)
bfd * abfd ATTRIBUTE_UNUSED;
{
unsigned int i;
- for (i = 0;
- i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
- i++)
- {
- if (v850_elf_reloc_map[i].bfd_reloc_val == code)
- {
- BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val);
+ for (i = ARRAY_SIZE (v850_elf_reloc_map); i --;)
+ if (v850_elf_reloc_map[i].bfd_reloc_val == code)
+ {
+ unsigned int elf_reloc_val = v850_elf_reloc_map[i].elf_reloc_val;
- return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
- }
- }
+ BFD_ASSERT (v850_elf_howto_table[elf_reloc_val].type == elf_reloc_val);
+
+ return v850_elf_howto_table + elf_reloc_val;
+ }
return NULL;
}
\f
/* Set the howto pointer for an V850 ELF reloc. */
+
static void
v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
bfd * abfd ATTRIBUTE_UNUSED;
#ifdef DEBUG
fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
bfd_get_section_name (abfd, sec),
- bfd_get_filename (abfd));
+ bfd_archive_filename (abfd));
#endif
dynobj = elf_hash_table (info)->dynobj;
return false;
break;
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
+ /* This relocation describes which C++ vtable entries
+ are actually used. Record for later use during GC. */
case R_V850_GNU_VTENTRY:
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return false;
small_data_common:
if (h)
{
- h->other |= other; /* flag which type of relocation was used */
+ /* Flag which type of relocation was used. */
+ h->other |= other;
if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
&& (h->other & V850_OTHER_ERROR) == 0)
{
sprintf (buff, msg, h->root.root.string);
info->callbacks->warning (info, buff, h->root.root.string,
- abfd, h->root.u.def.section, 0);
+ abfd, h->root.u.def.section,
+ (bfd_vma) 0);
bfd_set_error (bfd_error_bad_value);
h->other |= V850_OTHER_ERROR;
&& h->root.u.c.p
&& !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
{
- asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
+ asection * section;
+
+ section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
section->flags |= SEC_IS_COMMON;
}
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.
- */
+/* 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_byte * address;
{
hi16s_location * entry = NULL;
+ bfd_size_type amt = sizeof (* free_hi16s);
/* Find a free structure. */
if (free_hi16s == NULL)
- free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s));
+ free_hi16s = (hi16s_location *) bfd_zalloc (abfd, amt);
entry = free_hi16s;
free_hi16s = free_hi16s->next;
/* FIXME: The code here probably ought to be removed and the code in reloc.c
allowed to do its stuff instead. At least for most of the relocs, anwyay. */
+
static bfd_reloc_status_type
v850_elf_perform_relocation (abfd, r_type, addend, address)
- bfd * abfd;
- int r_type;
- bfd_vma addend;
- bfd_byte * address;
+ bfd *abfd;
+ unsigned int r_type;
+ bfd_vma addend;
+ bfd_byte *address;
{
unsigned long insn;
bfd_signed_vma saddend = (bfd_signed_vma) addend;
insn = bfd_get_32 (abfd, address);
insn &= ~0xfffe003f;
insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
- bfd_put_32 (abfd, insn, address);
+ bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
case R_V850_9_PCREL:
0x00000000
+ 0x00006fff (bit 15 not set, so the top half is zero)
------------
- 0x00006fff which is wrong (assuming that fred is at 0xffff)
- */
-
+ 0x00006fff which is wrong (assuming that fred is at 0xffff). */
{
long result;
{
insn = bfd_get_16 (abfd, hi16s_address);
insn += 1;
- bfd_put_16 (abfd, insn, hi16s_address);
+ bfd_put_16 (abfd, (bfd_vma) insn, hi16s_address);
}
}
else
if (addend & 1)
return bfd_reloc_dangerous;
- insn = (addend & ~1) | (insn & 1);
+ insn = (addend &~ (bfd_vma) 1) | (insn & 1);
break;
case R_V850_TDA_6_8_OFFSET:
insn &= 0x0001ffdf;
insn |= (addend & 1) << 5;
- insn |= (addend & ~1) << 16;
+ insn |= (addend &~ (bfd_vma) 1) << 16;
- bfd_put_32 (abfd, insn, address);
+ bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
case R_V850_CALLT_6_7_OFFSET:
}
- bfd_put_16 (abfd, insn, address);
+ bfd_put_16 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
}
\f
/* Insert the addend into the instruction. */
+
static bfd_reloc_status_type
v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
bfd * abfd ATTRIBUTE_UNUSED;
/* If there is an output BFD,
and the symbol is not a section name (which is only defined at final link time),
and either we are not putting the addend into the instruction
- or the addend is zero, so there is nothing to add into the instruction
+ or the addend is zero, so there is nothing to add into the instruction
then just fixup the address and return. */
if (obfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
}
#if 0
else if (obfd != NULL)
- {
- return bfd_reloc_continue;
- }
+ return bfd_reloc_continue;
#endif
/* Catch relocs involving undefined symbols. */
relocation += symbol->section->output_offset;
relocation += reloc->addend;
+#if 0 /* Since this reloc is going to be processed later on, we should
+ not make it pc-relative here. To test this, try assembling and
+ linking this program:
+
+ .text
+ .globl _start
+ nop
+ _start:
+ jr foo
+
+ .section ".foo","ax"
+ nop
+ foo:
+ nop */
if (reloc->howto->pc_relative == true)
{
/* Here the variable relocation holds the final address of the
symbol we are relocating against, plus any addend. */
relocation -= isection->output_section->vma + isection->output_offset;
- /* Deal with pcrel_offset */
+ /* Deal with pcrel_offset. */
relocation -= reloc->address;
}
-
+#endif
reloc->addend = relocation;
return bfd_reloc_ok;
}
}
\f
/* Perform a relocation as part of a final link. */
+
static bfd_reloc_status_type
v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
input_section, contents, offset, value,
asection * sym_sec;
int is_local ATTRIBUTE_UNUSED;
{
- unsigned long r_type = howto->type;
+ unsigned int r_type = howto->type;
bfd_byte * hit_data = contents + offset;
/* Adjust the value according to the relocation. */
if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000))
return bfd_reloc_overflow;
- value = SEXT24 (value); /* Only the bottom 24 bits of the PC are valid */
+ /* Only the bottom 24 bits of the PC are valid */
+ value = SEXT24 (value);
break;
case R_V850_HI16_S:
h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
if (h == (struct bfd_link_hash_entry *) NULL
|| h->type != bfd_link_hash_defined)
- return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
+ /* Actually this indicates that __ep could not be found. */
+ return bfd_reloc_continue;
ep = (h->u.def.value
+ h->u.def.section->output_section->vma
h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
if (h == (struct bfd_link_hash_entry *) NULL
|| h->type != bfd_link_hash_defined)
- return (bfd_reloc_dangerous + 1); /* Actually this indicates that __ctbp could not be found. */
+ /* Actually this indicates that __ctbp could not be found. */
+ return bfd_reloc_dangerous + 1;
ctbp = (h->u.def.value
+ h->u.def.section->output_section->vma
}
\f
/* Relocate an V850 ELF section. */
+
static boolean
v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
contents, relocs, local_syms, local_sections)
if (sym_hashes == NULL)
{
info->callbacks->warning
- (info, "no hash table available", NULL, input_bfd, input_section, 0);
+ (info, "no hash table available",
+ NULL, input_bfd, input_section, (bfd_vma) 0);
return false;
}
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
#if 0
{
char * name;
+
name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
name = (name == NULL) ? "<none>" : name;
-fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
- sec->name, name, sym->st_name,
- sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend);
+ fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
+ sec->name, name, sym->st_name,
+ sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend);
}
#endif
}
+ sec->output_section->vma
+ sec->output_offset);
#if 0
-fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
- sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation);
+ fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
+ sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation);
#endif
}
else if (h->root.type == bfd_link_hash_undefweak)
{
#if 0
-fprintf (stderr, "undefined: sec: %s, name: %s\n",
- sec->name, h->root.root.string);
+ fprintf (stderr, "undefined: sec: %s, name: %s\n",
+ sec->name, h->root.root.string);
#endif
relocation = 0;
}
input_section, rel->r_offset, true)))
return false;
#if 0
-fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
+ fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
#endif
relocation = 0;
}
}
- /* FIXME: We should use the addend, but the COFF relocations
- don't. */
+ /* FIXME: We should use the addend, but the COFF relocations don't. */
r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
input_section,
contents, rel->r_offset,
asection *sec ATTRIBUTE_UNUSED;
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
{
- /* No got and plt entries for v850-elf */
+ /* No got and plt entries for v850-elf. */
return true;
}
}
return NULL;
}
+
/* Set the right machine number. */
+
static boolean
v850_elf_object_p (abfd)
bfd *abfd;
}
/* Store the machine number in the flags field. */
+
static void
v850_elf_final_write_processing (abfd, linker)
bfd * abfd;
}
/* Function to keep V850 specific file flags. */
+
static boolean
v850_elf_set_private_flags (abfd, flags)
bfd * abfd;
return true;
}
-/* Copy backend specific data from one object module to another */
+/* Copy backend specific data from one object module to another. */
+
static boolean
v850_elf_copy_private_bfd_data (ibfd, obfd)
bfd * ibfd;
elf_gp (obfd) = elf_gp (ibfd);
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
elf_flags_init (obfd) = true;
+
return true;
}
-/* Merge backend specific data from an object file to the output
- object file when linking. */
+/* Merge backend specific data from an object file
+ to the output object file when linking. */
static boolean
v850_elf_merge_private_bfd_data (ibfd, obfd)
bfd * ibfd;
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 bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
return true;
}
if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH)
&& (in_flags & EF_V850_ARCH) != E_V850_ARCH)
_bfd_error_handler (_("%s: Architecture mismatch with previous modules"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
return true;
}
-/* Display the flags field */
+
+/* Display the flags field. */
static boolean
v850_elf_print_private_bfd_data (abfd, ptr)
static asymbol v850_elf_zcom_symbol;
static asymbol * v850_elf_zcom_symbol_ptr;
-/* Given a BFD section, try to locate the corresponding ELF section
- index. */
+/* Given a BFD section, try to locate the
+ corresponding ELF section index. */
static boolean
v850_elf_section_from_bfd_section (abfd, hdr, sec, retval)
return true;
}
-/*ARGSIGNORED*/
static boolean
v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
bfd * abfd ATTRIBUTE_UNUSED;
return true;
}
-/* Set the correct type for a V850 ELF section. We do this by the
- section name, which is a hack, but ought to work. */
+/* Set the correct type for a V850 ELF section. We do this
+ by the section name, which is a hack, but ought to work. */
+
static boolean
v850_elf_fake_sections (abfd, hdr, sec)
bfd * abfd ATTRIBUTE_UNUSED;
#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
#define TARGET_LITTLE_NAME "elf32-v850"
#define ELF_ARCH bfd_arch_v850
-#define ELF_MACHINE_CODE EM_CYGNUS_V850
+#define ELF_MACHINE_CODE EM_V850
+#define ELF_MACHINE_ALT1 EM_CYGNUS_V850
#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto v850_elf_info_to_howto_rela