/* Matsushita 10300 specific support for 32-bit ELF
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
does absolutely nothing. */
#define USE_RELA
-
static reloc_howto_type elf_mn10300_howto_table[] =
{
/* Dummy relocation. Does nothing. */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
+
+ /* Standard 24 bit reloc. */
+ HOWTO (R_MN10300_24,
+ 0,
+ 2,
+ 24,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ bfd_elf_generic_reloc,
+ "R_MN10300_24",
+ false,
+ 0xffffff,
+ 0xffffff,
+ false),
+
};
struct mn10300_reloc_map
{
- unsigned char bfd_reloc_val;
+ bfd_reloc_code_real_type bfd_reloc_val;
unsigned char elf_reloc_val;
};
{ BFD_RELOC_32_PCREL, R_MN10300_PCREL32, },
{ BFD_RELOC_16_PCREL, R_MN10300_PCREL16, },
{ BFD_RELOC_8_PCREL, R_MN10300_PCREL8, },
+ { BFD_RELOC_24, R_MN10300_24, },
{ BFD_RELOC_VTABLE_INHERIT, R_MN10300_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_MN10300_GNU_VTENTRY },
};
static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
unsigned int i;
static void
mn10300_info_to_howto (abfd, cache_ptr, dst)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
arelent *cache_ptr;
Elf32_Internal_Rela *dst;
{
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
if (!elf_bad_symtab (abfd))
sym_hashes_end -= symtab_hdr->sh_info;
static asection *
mn10300_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;
}
}
}
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 value;
bfd_vma addend;
- struct bfd_link_info *info;
- asection *sym_sec;
- int is_local;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ asection *sym_sec ATTRIBUTE_UNUSED;
+ int is_local ATTRIBUTE_UNUSED;
{
unsigned long r_type = howto->type;
bfd_byte *hit_data = contents + offset;
bfd_put_32 (input_bfd, value, hit_data);
return bfd_reloc_ok;
+ case R_MN10300_24:
+ value += addend;
+
+ if ((long)value > 0x7fffff || (long)value < -0x800000)
+ return bfd_reloc_overflow;
+
+ bfd_put_8 (input_bfd, value & 0xff, hit_data);
+ bfd_put_8 (input_bfd, (value >> 8) & 0xff, hit_data + 1);
+ bfd_put_8 (input_bfd, (value >> 16) & 0xff, hit_data + 2);
+ return bfd_reloc_ok;
+
case R_MN10300_16:
value += addend;
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.root.string, input_bfd,
- input_section, rel->r_offset)))
+ input_section, rel->r_offset, true)))
return false;
relocation = 0;
}
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
elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
struct bfd_hash_entry *gen_entry;
- PTR in_args;
+ PTR in_args ATTRIBUTE_UNUSED;
{
struct elf32_mn10300_link_hash_entry *entry;
unsigned int byte_count = 0;
This is only done if the resulting code is no larger
than the original code.
-
* jmp:32 -> jmp:16 2 bytes
* jmp:16 -> bra:8 1 byte
{
struct elf32_mn10300_link_hash_entry *hash;
Elf_Internal_Sym *sym;
- asection *sym_sec;
+ asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
- Elf_Internal_Shdr *hdr;
/* Get cached copy of section contents if it exists. */
if (elf_section_data (section)->this_hdr.contents != NULL)
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = alloca (strlen (sym_name) + 10);
+ new_name = bfd_malloc (strlen (sym_name) + 10);
+ if (new_name == 0)
+ goto error_return;
+
sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
sym_name = new_name;
elf_link_hash_lookup (&hash_table->static_hash_table->root,
sym_name, true,
true, false);
+ free (new_name);
}
else
{
shndx = _bfd_elf_section_from_bfd_section (input_bfd,
section);
-
/* Look at each function defined in this section and
update info for that function. */
esym = extsyms;
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = alloca (strlen (sym_name) + 10);
+ new_name = bfd_malloc (strlen (sym_name) + 10);
+ if (new_name == 0)
+ goto error_return;
+
sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
sym_name = new_name;
elf_link_hash_lookup (&hash_table->static_hash_table->root,
sym_name, true,
true, false);
+ free (new_name);
compute_function_info (input_bfd, hash,
isym.st_value, contents);
}
goto error_return;
}
-
shndx = _bfd_elf_section_from_bfd_section (input_bfd, section);
/* Now look for any function in this section which needs
{
Elf_Internal_Sym isym;
struct elf32_mn10300_link_hash_entry *sym_hash;
- asection *sym_sec;
+ asection *sym_sec = NULL;
const char *sym_name;
- Elf_Internal_Shdr *hdr;
char *new_name;
bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
sym_sec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
sym_sec = bfd_com_section_ptr;
+ else
+ abort ();
sym_name = bfd_elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = alloca (strlen (sym_name) + 10);
+ new_name = bfd_malloc (strlen (sym_name) + 10);
+ if (new_name == 0)
+ goto error_return;
sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
sym_name = new_name;
sym_name, false,
false, false);
+ free (new_name);
if (sym_hash == NULL)
continue;
}
}
-
/* (Re)initialize for the basic instruction shortening/relaxing pass. */
contents = NULL;
extsyms = NULL;
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
Elf_Internal_Sym isym;
- asection *sym_sec;
- Elf_Internal_Shdr *hdr;
+ asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
sym_sec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
sym_sec = bfd_com_section_ptr;
+ else
+ abort ();
symval = (isym.st_value
+ sym_sec->output_section->vma
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
- new_name = alloca (strlen (sym_name) + 10);
+ new_name = bfd_malloc (strlen (sym_name) + 10);
+ if (new_name == 0)
+ goto error_return;
sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
sym_name = new_name;
h = (struct elf32_mn10300_link_hash_entry *)
elf_link_hash_lookup (&hash_table->static_hash_table->root,
sym_name, false, false, false);
+ free (new_name);
}
else
{
bra lab2
lab1: lab1:
-
This happens when the bCC can't reach lab2 at assembly time,
but due to other relaxations it can reach at link time. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_PCREL8)
*again = true;
}
+ /* Try to turn a 24 immediate, displacement or absolute address
+ into a 8 immediate, displacement or absolute address. */
+ if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_24)
+ {
+ bfd_vma value = symval;
+ value += irel->r_addend;
+
+ /* See if the value will fit in 8 bits. */
+ if ((long)value < 0x7f && (long)value > -0x80)
+ {
+ unsigned char code;
+
+ /* AM33 insns which have 24 operands are 6 bytes long and
+ will have 0xfd as the first byte. */
+
+ /* Get the first opcode. */
+ code = bfd_get_8 (abfd, contents + irel->r_offset - 3);
+
+ if (code == 0xfd)
+ {
+ /* Get the second opcode. */
+ code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
+
+ /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit
+ equivalent instructions exists. */
+ if (code != 0x6b && code != 0x7b
+ && code != 0x8b && code != 0x9b
+ && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08
+ || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b
+ || (code & 0x0f) == 0x0e))
+ {
+ /* Not safe if the high bit is on as relaxing may
+ move the value out of high mem and thus not fit
+ in a signed 8bit value. This is currently over
+ conservative. */
+ if ((value & 0x80) == 0)
+ {
+ /* Note that we've changed the relocation contents,
+ etc. */
+ elf_section_data (sec)->relocs = internal_relocs;
+ free_relocs = NULL;
+
+ elf_section_data (sec)->this_hdr.contents = contents;
+ free_contents = NULL;
+
+ symtab_hdr->contents = (bfd_byte *) extsyms;
+ free_extsyms = NULL;
+
+ /* Fix the opcode. */
+ bfd_put_8 (abfd, 0xfb, contents + irel->r_offset - 3);
+ bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
+
+ /* Fix the relocation's type. */
+ irel->r_info
+ = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MN10300_8);
+
+ /* Delete two bytes of data. */
+ if (!mn10300_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 1, 2))
+ goto error_return;
+
+ /* That will change things, so, we should relax
+ again. Note that this is not required, and it
+ may be slow. */
+ *again = true;
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
/* Try to turn a 32bit immediate, displacement or absolute address
into a 16bit immediate, displacement or absolute address. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_32)
bfd_vma value = symval;
value += irel->r_addend;
+ /* See if the value will fit in 24 bits.
+ We allow any 16bit match here. We prune those we can't
+ handle below. */
+ if ((long)value < 0x7fffff && (long)value > -0x800000)
+ {
+ unsigned char code;
+
+ /* AM33 insns which have 32bit operands are 7 bytes long and
+ will have 0xfe as the first byte. */
+
+ /* Get the first opcode. */
+ code = bfd_get_8 (abfd, contents + irel->r_offset - 3);
+
+ if (code == 0xfe)
+ {
+ /* Get the second opcode. */
+ code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
+
+ /* All the am33 32 -> 24 relaxing possibilities. */
+ /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit
+ equivalent instructions exists. */
+ if (code != 0x6b && code != 0x7b
+ && code != 0x8b && code != 0x9b
+ && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08
+ || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b
+ || (code & 0x0f) == 0x0e))
+ {
+ /* Not safe if the high bit is on as relaxing may
+ move the value out of high mem and thus not fit
+ in a signed 16bit value. This is currently over
+ conservative. */
+ if ((value & 0x8000) == 0)
+ {
+ /* Note that we've changed the relocation contents,
+ etc. */
+ elf_section_data (sec)->relocs = internal_relocs;
+ free_relocs = NULL;
+
+ elf_section_data (sec)->this_hdr.contents = contents;
+ free_contents = NULL;
+
+ symtab_hdr->contents = (bfd_byte *) extsyms;
+ free_extsyms = NULL;
+
+ /* Fix the opcode. */
+ bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 3);
+ bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
+
+ /* Fix the relocation's type. */
+ irel->r_info
+ = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MN10300_24);
+
+ /* Delete one byte of data. */
+ if (!mn10300_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 3, 1))
+ goto error_return;
+
+ /* That will change things, so, we should relax
+ again. Note that this is not required, and it
+ may be slow. */
+ *again = true;
+ break;
+ }
+ }
+
+ }
+ }
+
/* See if the value will fit in 16 bits.
We allow any 16bit match here. We prune those we can't
handle below. */
if (hash->movm_args & 0x08)
hash->movm_stack_size += 8 * 4;
- /* start-sanitize-am33 */
if (bfd_get_mach (abfd) == bfd_mach_am33)
{
/* "exother" space. e0, e1, mdrq, mcrh, mcrl, mcvf */
if (hash->movm_args & 0x4)
hash->movm_stack_size += 2 * 4;
}
- /* end-sanitize-am33 */
}
/* Now look for the two stack adjustment variants. */
return true;
}
- sym_hash = (struct elf32_mn10300_link_hash_entry **)(elf_sym_hashes (abfd));
+ sym_hash = (struct elf32_mn10300_link_hash_entry **) (elf_sym_hashes (abfd));
sym_hash_end = (sym_hash
+ (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
- symtab_hdr->sh_info));
default:
return bfd_mach_mn10300;
- /* start-sanitize-am33 */
case E_MN10300_MACH_AM33:
return bfd_mach_am33;
- /* end-sanitize-am33 */
}
}
file. This gets the MN10300 architecture right based on the machine
number. */
-/*ARGSUSED*/
void
_bfd_mn10300_elf_final_write_processing (abfd, linker)
bfd *abfd;
- boolean linker;
+ boolean linker ATTRIBUTE_UNUSED;
{
unsigned long val;
- unsigned int i;
- Elf_Internal_Shdr **hdrpp;
- const char *name;
- asection *sec;
switch (bfd_get_mach (abfd))
{
val = E_MN10300_MACH_MN10300;
break;
- /* start-sanitize-am33 */
case bfd_mach_am33:
val = E_MN10300_MACH_AM33;
break;
- /* end-sanitize-am33 */
}
elf_elfheader (abfd)->e_flags &= ~ (EF_MN10300_MACH);
return true;
}
-
#define TARGET_LITTLE_SYM bfd_elf32_mn10300_vec
#define TARGET_LITTLE_NAME "elf32-mn10300"
#define ELF_ARCH bfd_arch_mn10300
#define bfd_elf32_bfd_merge_private_bfd_data \
_bfd_mn10300_elf_merge_private_bfd_data
-
#include "elf32-target.h"