This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: bfd/elf-m10300.c: odd code
On May 27, 2004, Alexandre Oliva <aoliva@redhat.com> wrote:
> Err... I thought this patch had gone in a while ago, but it doesn't
> look like it. I'm going ahead and checking this in. Tested on
> i686-pc-linux-gnu.
Here's another fix for mn10300 relaxation problems. We did function
relaxation using custom calling conventions (i.e., merging movm into
the caller) even for dynamic symbols. Also, C++ thunk code calls a
local alias to a global function, so we relaxed the thunk without
realizing we were actually relaxing the global function. Can't do
that. I'm not entirely sure this patch will cover correctly all cases
(e.g., can we ever decide to use custom calling conventions for a
global symbol?), but this significantly improves C++ test results with
-mrelax, so I'm going ahead and checking it in.
Index: bfd/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* elf-m10300.c (elf32_mn10300_finish_hash_table_entry): Avoid
custom calling conventions for dynamic symbols.
(mn10300_elf_relax_section): Avoid relaxing a function as a local
symbol if it's an alias to a global one.
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.50
diff -u -p -r1.50 elf-m10300.c
--- bfd/elf-m10300.c 27 May 2004 04:07:41 -0000 1.50
+++ bfd/elf-m10300.c 27 May 2004 06:13:06 -0000
@@ -1705,9 +1705,10 @@ mn10300_elf_relocate_section (output_bfd
static bfd_boolean
elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
struct bfd_hash_entry *gen_entry;
- PTR in_args ATTRIBUTE_UNUSED;
+ PTR in_args;
{
struct elf32_mn10300_link_hash_entry *entry;
+ struct bfd_link_info *link_info = (struct bfd_link_info *)in_args;
unsigned int byte_count = 0;
entry = (struct elf32_mn10300_link_hash_entry *) gen_entry;
@@ -1721,11 +1722,16 @@ elf32_mn10300_finish_hash_table_entry (g
return TRUE;
/* If there are no named calls to this symbol, or there's nothing we
- can move from the function itself into the "call" instruction, then
- note that all "call" instructions should be converted into "calls"
- instructions and return. */
+ can move from the function itself into the "call" instruction,
+ then note that all "call" instructions should be converted into
+ "calls" instructions and return. If a symbol is available for
+ dynamic symbol resolution (overridable or overriding), avoid
+ custom calling conventions. */
if (entry->direct_calls == 0
- || (entry->stack_size == 0 && entry->movm_args == 0))
+ || (entry->stack_size == 0 && entry->movm_args == 0)
+ || (elf_hash_table (link_info)->dynamic_sections_created
+ && ELF_ST_VISIBILITY (entry->root.other) != STV_INTERNAL
+ && ELF_ST_VISIBILITY (entry->root.other) != STV_HIDDEN))
{
/* Make a note that we should convert "call" instructions to "calls"
instructions for calls to this symbol. */
@@ -2000,6 +2006,11 @@ mn10300_elf_relax_section (abfd, sec, li
sec_shndx = _bfd_elf_section_from_bfd_section (input_bfd,
section);
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+ - symtab_hdr->sh_info);
+ hashes = elf_sym_hashes (input_bfd);
+ end_hashes = hashes + symcount;
+
/* Look at each function defined in this section and
update info for that function. */
isymend = isymbuf + symtab_hdr->sh_info;
@@ -2010,6 +2021,22 @@ mn10300_elf_relax_section (abfd, sec, li
{
struct elf_link_hash_table *elftab;
bfd_size_type amt;
+ struct elf_link_hash_entry **lhashes = hashes;
+
+ /* Skip a local symbol if it aliases a
+ global one. */
+ for (; lhashes < end_hashes; lhashes++)
+ {
+ hash = (struct elf32_mn10300_link_hash_entry *) *lhashes;
+ if ((hash->root.root.type == bfd_link_hash_defined
+ || hash->root.root.type == bfd_link_hash_defweak)
+ && hash->root.root.u.def.section == section
+ && hash->root.type == STT_FUNC
+ && hash->root.root.u.def.value == isym->st_value)
+ break;
+ }
+ if (lhashes != end_hashes)
+ continue;
if (isym->st_shndx == SHN_UNDEF)
sym_sec = bfd_und_section_ptr;
@@ -2047,10 +2074,6 @@ mn10300_elf_relax_section (abfd, sec, li
}
}
- symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
- - symtab_hdr->sh_info);
- hashes = elf_sym_hashes (input_bfd);
- end_hashes = hashes + symcount;
for (; hashes < end_hashes; hashes++)
{
hash = (struct elf32_mn10300_link_hash_entry *) *hashes;
@@ -2104,10 +2127,10 @@ mn10300_elf_relax_section (abfd, sec, li
the final initialization steps on each. */
elf32_mn10300_link_hash_traverse (hash_table,
elf32_mn10300_finish_hash_table_entry,
- NULL);
+ link_info);
elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
elf32_mn10300_finish_hash_table_entry,
- NULL);
+ link_info);
/* All entries in the hash table are fully initialized. */
hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED;
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}