* elf-m10300.c (elf32_mn10300_link_hash_entry): Add value.

(elf32_mn10300_count_hash_table_entries): New.
(elf32_mn10300_list_hash_table_entries): New.
(sort_by_value): New.
(mn10300_elf_relax_section): Don't skip data sections; restrict
code-specific tests to code-specific areas so that potential
indirect calls can be detected.  Check for multiple local symbols
at the same address and merge their flags.
(elf32_mn10300_link_hash_newfunc): Initialize value.
This commit is contained in:
DJ Delorie 2006-08-14 20:05:00 +00:00
parent b59eed7911
commit eb13e63f94
2 changed files with 107 additions and 12 deletions

View File

@ -1,3 +1,15 @@
2006-08-14 DJ Delorie <dj@redhat.com>
* elf-m10300.c (elf32_mn10300_link_hash_entry): Add value.
(elf32_mn10300_count_hash_table_entries): New.
(elf32_mn10300_list_hash_table_entries): New.
(sort_by_value): New.
(mn10300_elf_relax_section): Don't skip data sections; restrict
code-specific tests to code-specific areas so that potential
indirect calls can be detected. Check for multiple local symbols
at the same address and merge their flags.
(elf32_mn10300_link_hash_newfunc): Initialize value.
2006-08-14 Thiemo Seufer <ths@mips.com>
* elfxx-mips.c (_bfd_mips_elf_symbol_processing,

View File

@ -85,6 +85,9 @@ struct elf32_mn10300_link_hash_entry {
prologue deleted. */
#define MN10300_DELETED_PROLOGUE_BYTES 0x2
unsigned char flags;
/* Calculated value. */
bfd_vma value;
};
/* We derive a hash table from the main elf linker hash table so
@ -1602,6 +1605,42 @@ elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
return TRUE;
}
/* Used to count hash table entries. */
static bfd_boolean
elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
PTR in_args)
{
int *count = (int *)in_args;
(*count) ++;
return TRUE;
}
/* Used to enumerate hash table entries into a linear array. */
static bfd_boolean
elf32_mn10300_list_hash_table_entries (struct bfd_hash_entry *gen_entry,
PTR in_args)
{
struct bfd_hash_entry ***ptr = (struct bfd_hash_entry ***) in_args;
**ptr = gen_entry;
(*ptr) ++;
return TRUE;
}
/* Used to sort the array created by the above. */
static int
sort_by_value (const void *va, const void *vb)
{
struct elf32_mn10300_link_hash_entry *a
= *(struct elf32_mn10300_link_hash_entry **)va;
struct elf32_mn10300_link_hash_entry *b
= *(struct elf32_mn10300_link_hash_entry **)vb;
return a->value - b->value;
}
/* This function handles relaxing for the mn10300.
There are quite a few relaxing opportunities available on the mn10300:
@ -1697,9 +1736,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
char *new_name;
/* If there's nothing to do in this section, skip it. */
if (! (((section->flags & SEC_RELOC) != 0
&& section->reloc_count != 0)
|| (section->flags & SEC_CODE) != 0))
if (! ((section->flags & SEC_RELOC) != 0
&& section->reloc_count != 0))
continue;
if ((section->flags & SEC_ALLOC) == 0)
continue;
/* Get cached copy of section contents if it exists. */
@ -1802,13 +1842,17 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
elf_sym_hashes (input_bfd)[r_index];
}
/* If this is not a "call" instruction, then we
should convert "call" instructions to "calls"
instructions. */
code = bfd_get_8 (input_bfd,
contents + irel->r_offset - 1);
if (code != 0xdd && code != 0xcd)
hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
sym_name = hash->root.root.root.string;
if ((section->flags & SEC_CODE) != 0)
{
/* If this is not a "call" instruction, then we
should convert "call" instructions to "calls"
instructions. */
code = bfd_get_8 (input_bfd,
contents + irel->r_offset - 1);
if (code != 0xdd && code != 0xcd)
hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
}
/* If this is a jump/call, then bump the
direct_calls counter. Else force "call" to
@ -1901,6 +1945,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
free (new_name);
compute_function_info (input_bfd, hash,
isym->st_value, contents);
hash->value = isym->st_value;
}
}
@ -1962,6 +2007,44 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
elf32_mn10300_finish_hash_table_entry,
link_info);
{
/* This section of code collects all our local symbols, sorts
them by value, and looks for multiple symbols referring to
the same address. For those symbols, the flags are merged.
At this point, the only flag that can be set is
MN10300_CONVERT_CALL_TO_CALLS, so we simply OR the flags
together. */
int static_count = 0, i;
struct elf32_mn10300_link_hash_entry **entries;
struct elf32_mn10300_link_hash_entry **ptr;
elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
elf32_mn10300_count_hash_table_entries,
&static_count);
entries = (struct elf32_mn10300_link_hash_entry **)
bfd_malloc (static_count * sizeof (struct elf32_mn10300_link_hash_entry *));
ptr = entries;
elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
elf32_mn10300_list_hash_table_entries,
&ptr);
qsort (entries, static_count, sizeof(entries[0]), sort_by_value);
for (i=0; i<static_count-1; i++)
if (entries[i]->value && entries[i]->value == entries[i+1]->value)
{
int v = entries[i]->flags;
int j;
for (j=i+1; j<static_count && entries[j]->value == entries[i]->value; j++)
v |= entries[j]->flags;
for (j=i; j<static_count && entries[j]->value == entries[i]->value; j++)
entries[j]->flags = v;
i = j-1;
}
}
/* All entries in the hash table are fully initialized. */
hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED;
@ -2795,8 +2878,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
into a 16bit immediate, displacement or absolute address. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_32
|| ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOT32
|| ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTOFF32
|| ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTPC32)
|| ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTOFF32)
{
bfd_vma value = symval;
@ -3677,6 +3759,7 @@ elf32_mn10300_link_hash_newfunc (entry, table, string)
ret->movm_args = 0;
ret->movm_stack_size = 0;
ret->flags = 0;
ret->value = 0;
}
return (struct bfd_hash_entry *) ret;