/* Matsushita 10300 specific support for 32-bit ELF
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "elf-bfd.h"
#include "elf/mn10300.h"
+static bfd_reloc_status_type mn10300_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));
+static boolean mn10300_elf_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean mn10300_elf_relax_section
+ PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
+static bfd_byte * mn10300_elf_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, asymbol **));
+static unsigned long elf_mn10300_mach PARAMS ((flagword));
+
+void _bfd_mn10300_elf_final_write_processing PARAMS ((bfd *, boolean));
+boolean _bfd_mn10300_elf_object_p PARAMS ((bfd *));
+boolean _bfd_mn10300_elf_merge_private_bfd_data PARAMS ((bfd *,bfd *));
+
struct elf32_mn10300_link_hash_entry {
/* The basic elf link hash table entry. */
struct elf_link_hash_entry root;
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
+ while (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
h = (struct elf32_mn10300_link_hash_entry *) h->root.root.u.i.link;
if (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
else
{
+ bfd_size_type amt = symtab_hdr->sh_size;
/* Go get them off disk. */
- extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
if (extsyms == NULL)
goto error_return;
free_extsyms = extsyms;
if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd)
- != symtab_hdr->sh_size))
+ || bfd_bread (extsyms, amt, input_bfd) != amt)
goto error_return;
}
{
/* A local symbol. */
Elf_Internal_Sym isym;
+ struct elf_link_hash_table *elftab;
+ bfd_size_type amt;
bfd_elf32_swap_symbol_in (input_bfd,
extsyms + r_index, &isym);
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = bfd_malloc (strlen (sym_name) + 10);
+ amt = strlen (sym_name) + 10;
+ new_name = bfd_malloc (amt);
if (new_name == 0)
goto error_return;
sym_name, (int) sym_sec);
sym_name = new_name;
- hash = (struct elf32_mn10300_link_hash_entry *)
- elf_link_hash_lookup (&hash_table->static_hash_table->root,
- sym_name, true,
- true, false);
+ elftab = &hash_table->static_hash_table->root;
+ hash = ((struct elf32_mn10300_link_hash_entry *)
+ elf_link_hash_lookup (elftab, sym_name,
+ true, true, false));
free (new_name);
}
else
if (isym.st_shndx == shndx
&& ELF_ST_TYPE (isym.st_info) == STT_FUNC)
{
+ struct elf_link_hash_table *elftab;
+ bfd_size_type amt;
+
if (isym.st_shndx == SHN_UNDEF)
sym_sec = bfd_und_section_ptr;
else if (isym.st_shndx > 0
else if (isym.st_shndx == SHN_COMMON)
sym_sec = bfd_com_section_ptr;
- sym_name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- isym.st_name);
+ sym_name = (bfd_elf_string_from_elf_section
+ (input_bfd, symtab_hdr->sh_link,
+ isym.st_name));
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = bfd_malloc (strlen (sym_name) + 10);
+ amt = strlen (sym_name) + 10;
+ new_name = bfd_malloc (amt);
if (new_name == 0)
goto error_return;
sym_name, (int) sym_sec);
sym_name = new_name;
- hash = (struct elf32_mn10300_link_hash_entry *)
- elf_link_hash_lookup (&hash_table->static_hash_table->root,
- sym_name, true,
- true, false);
+ elftab = &hash_table->static_hash_table->root;
+ hash = ((struct elf32_mn10300_link_hash_entry *)
+ elf_link_hash_lookup (elftab, sym_name,
+ true, true, false));
free (new_name);
compute_function_info (input_bfd, hash,
isym.st_value, contents);
extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
else
{
+ bfd_size_type amt = symtab_hdr->sh_size;
/* Go get them off disk. */
- extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
if (extsyms == NULL)
goto error_return;
free_extsyms = extsyms;
if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd)
- != symtab_hdr->sh_size))
+ || bfd_bread (extsyms, amt, input_bfd) != amt)
goto error_return;
}
asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
+ struct elf_link_hash_table *elftab;
+ bfd_size_type amt;
bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = bfd_malloc (strlen (sym_name) + 10);
+ amt = strlen (sym_name) + 10;
+ new_name = bfd_malloc (amt);
if (new_name == 0)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec);
sym_name = new_name;
- sym_hash = (struct elf32_mn10300_link_hash_entry *)
- elf_link_hash_lookup (&hash_table->static_hash_table->root,
- sym_name, false,
- false, false);
+ elftab = &hash_table->static_hash_table->root;
+ sym_hash = ((struct elf32_mn10300_link_hash_entry *)
+ elf_link_hash_lookup (elftab, sym_name,
+ false, false, false));
free (new_name);
if (sym_hash == NULL)
extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
else
{
+ bfd_size_type amt = symtab_hdr->sh_size;
/* Go get them off disk. */
- extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
if (extsyms == NULL)
goto error_return;
free_extsyms = extsyms;
if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
- != symtab_hdr->sh_size))
+ || bfd_bread (extsyms, amt, abfd) != amt)
goto error_return;
}
}
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = bfd_malloc (strlen (sym_name) + 10);
+ new_name = bfd_malloc ((bfd_size_type) strlen (sym_name) + 10);
if (new_name == 0)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec);
case 0x91:
case 0x92:
case 0x93:
+ /* sp-based offsets are zero-extended. */
+ if (code >= 0x90 && code <= 0x93
+ && (long)value < 0)
+ continue;
+
/* Note that we've changed the relocation contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
free_relocs = NULL;
&& (value & 0x8000))
continue;
+ /* mov imm16, an zero-extends the immediate. */
+ if (code == 0xdc
+ && (long)value < 0)
+ continue;
+
/* Note that we've changed the relocation contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
free_relocs = NULL;
break;
/* mov (abs32),an -> mov (abs16),an
- mov (d32,sp),an -> mov (d32,sp),an
- mov (d32,sp),dn -> mov (d32,sp),dn
- movbu (d32,sp),dn -> movbu (d32,sp),dn
- movhu (d32,sp),dn -> movhu (d32,sp),dn
+ mov (d32,sp),an -> mov (d16,sp),an
+ mov (d32,sp),dn -> mov (d16,sp),dn
+ movbu (d32,sp),dn -> movbu (d16,sp),dn
+ movhu (d32,sp),dn -> movhu (d16,sp),dn
add imm32,dn -> add imm16,dn
cmp imm32,dn -> cmp imm16,dn
add imm32,an -> add imm16,an
cmp imm32,an -> cmp imm16,an
- and imm32,dn -> and imm32,dn
- or imm32,dn -> or imm32,dn
- xor imm32,dn -> xor imm32,dn
- btst imm32,dn -> btst imm32,dn */
+ and imm32,dn -> and imm16,dn
+ or imm32,dn -> or imm16,dn
+ xor imm32,dn -> xor imm16,dn
+ btst imm32,dn -> btst imm16,dn */
case 0xa0:
case 0xb0:
case 0xe1:
case 0xe2:
case 0xe3:
+ /* cmp imm16, an zero-extends the immediate. */
+ if (code == 0xdc
+ && (long)value < 0)
+ continue;
+
+ /* So do sp-based offsets. */
+ if (code >= 0xb0 && code <= 0xb3
+ && (long)value < 0)
+ continue;
+
/* Note that we've changed the relocation contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
free_relocs = NULL;
irelend = irel + sec->reloc_count;
/* Actually delete the bytes. */
- memmove (contents + addr, contents + addr + count, toaddr - addr - count);
+ memmove (contents + addr, contents + addr + count,
+ (size_t) (toaddr - addr - count));
sec->_cooked_size -= count;
/* Adjust all the relocs. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
memcpy (data, elf_section_data (input_section)->this_hdr.contents,
- input_section->_raw_size);
+ (size_t) input_section->_raw_size);
if ((input_section->flags & SEC_RELOC) != 0
&& input_section->reloc_count > 0)
Elf_Internal_Sym *isymp;
asection **secpp;
Elf32_External_Sym *esym, *esymend;
+ bfd_size_type size;
if (symtab_hdr->contents != NULL)
external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
else
{
- external_syms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_info
- * sizeof (Elf32_External_Sym)));
- if (external_syms == NULL && symtab_hdr->sh_info > 0)
+ size = symtab_hdr->sh_info;
+ size *= sizeof (Elf32_External_Sym);
+ external_syms = (Elf32_External_Sym *) bfd_malloc (size);
+ if (external_syms == NULL && size != 0)
goto error_return;
if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (external_syms, sizeof (Elf32_External_Sym),
- symtab_hdr->sh_info, input_bfd)
- != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym))))
+ || bfd_bread (external_syms, size, input_bfd) != size)
goto error_return;
}
if (internal_relocs == NULL)
goto error_return;
- internal_syms = ((Elf_Internal_Sym *)
- bfd_malloc (symtab_hdr->sh_info
- * sizeof (Elf_Internal_Sym)));
- if (internal_syms == NULL && symtab_hdr->sh_info > 0)
+ size = symtab_hdr->sh_info;
+ size *= sizeof (Elf_Internal_Sym);
+ internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
+ if (internal_syms == NULL && size != 0)
goto error_return;
- sections = (asection **) bfd_malloc (symtab_hdr->sh_info
- * sizeof (asection *));
- if (sections == NULL && symtab_hdr->sh_info > 0)
+ size = symtab_hdr->sh_info;
+ size *= sizeof (asection *);
+ sections = (asection **) bfd_malloc (size);
+ if (sections == NULL && size != 0)
goto error_return;
isymp = internal_syms;
bfd *abfd;
{
struct elf32_mn10300_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct elf32_mn10300_link_hash_table);
- ret = ((struct elf32_mn10300_link_hash_table *)
- bfd_alloc (abfd, sizeof (struct elf32_mn10300_link_hash_table)));
+ ret = (struct elf32_mn10300_link_hash_table *) bfd_alloc (abfd, amt);
if (ret == (struct elf32_mn10300_link_hash_table *) NULL)
return NULL;
}
ret->flags = 0;
+ amt = sizeof (struct elf_link_hash_table);
ret->static_hash_table
- = ((struct elf32_mn10300_link_hash_table *)
- bfd_alloc (abfd, sizeof (struct elf_link_hash_table)));
+ = (struct elf32_mn10300_link_hash_table *) bfd_alloc (abfd, amt);
if (ret->static_hash_table == NULL)
{
bfd_release (abfd, ret);
return &ret->root.root;
}
-static int
+static unsigned long
elf_mn10300_mach (flags)
flagword flags;
{
#define TARGET_LITTLE_SYM bfd_elf32_mn10300_vec
#define TARGET_LITTLE_NAME "elf32-mn10300"
#define ELF_ARCH bfd_arch_mn10300
-#define ELF_MACHINE_CODE EM_CYGNUS_MN10300
+#define ELF_MACHINE_CODE EM_MN10300
+#define ELF_MACHINE_ALT1 EM_CYGNUS_MN10300
#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto mn10300_info_to_howto