Find the first .init and .fini sections correctly.

Clobber millicode syms via a hash traversal here.  elf_adjust_dynamic_symbol
really ought to let us look at all dynamic symbols, but it doesn't.
This commit is contained in:
Alan Modra 2000-09-15 10:24:50 +00:00
parent ad525611ab
commit d5c73c2f38
2 changed files with 90 additions and 57 deletions

View File

@ -1,3 +1,15 @@
2000-09-15 Alan Modra <alan@linuxcare.com.au>
* elf32-hppa.c (hppa_add_stub): Dont set first_init_sec and
first_fini_sec here.
(elf32_hppa_size_stubs): Instead correctly find the first .init
and .fini section here.
2000-09-15 David Huggins-Daines <dhd@linuxcare.com>
* elf32-hppa.c (clobber_millicode_symbols): New function.
(elf32_hppa_size_dynamic_sections): Call it.
2000-09-14 Alan Modra <alan@linuxcare.com.au>
* elf32-hppa.c (elf32_hppa_link_hash_entry): Make pic_call

View File

@ -345,6 +345,9 @@ static boolean hppa_discard_copies
PARAMS ((struct elf_link_hash_entry *, PTR));
#endif
static boolean clobber_millicode_symbols
PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
static boolean elf32_hppa_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
@ -621,27 +624,11 @@ hppa_add_stub (stub_name, section, sec_count, info)
stub_sec = hplink->stub_section_created[sec_count];
if (stub_sec == NULL)
{
int special_sec = 0;
/* We only want one stub for .init and .fini because glibc
splits the _init and _fini functions into two parts. We
don't want to put a stub in the middle of a function.
It would be better to merge all the stub sections for an
output section if the output section + stubs is small enough.
This would fix the .init and .fini case and also allow stubs
to be merged. It's more linker work though. */
if (strncmp (section->name, ".init", 5) == 0)
{
if (hplink->first_init_sec != 0)
stub_sec = hplink->stub_section_created[hplink->first_init_sec-1];
special_sec = 1;
}
stub_sec = hplink->stub_section_created[hplink->first_init_sec - 1];
else if (strncmp (section->name, ".fini", 5) == 0)
{
if (hplink->first_fini_sec != 0)
stub_sec = hplink->stub_section_created[hplink->first_fini_sec-1];
special_sec = 2;
}
stub_sec = hplink->stub_section_created[hplink->first_fini_sec - 1];
if (stub_sec == NULL)
{
size_t len;
@ -657,14 +644,6 @@ hppa_add_stub (stub_name, section, sec_count, info)
stub_sec = (*hplink->add_stub_section) (s_name, section);
if (stub_sec == NULL)
return NULL;
if (special_sec != 0)
{
if (special_sec == 1)
hplink->first_init_sec = sec_count + 1;
else
hplink->first_fini_sec = sec_count + 1;
}
}
hplink->stub_section_created[sec_count] = stub_sec;
}
@ -2127,6 +2106,27 @@ hppa_discard_copies (h, inf)
#endif
/* This function is called via elf_link_hash_traverse to force
millicode symbols local so they do not end up as globals in the
dynamic symbol table. We ought to be able to do this in
adjust_dynamic_symbol, but our adjust_dynamic_symbol is not called
for all dynamic symbols. Arguably, this is a bug in
elf_adjust_dynamic_symbol. */
static boolean
clobber_millicode_symbols (h, info)
struct elf_link_hash_entry *h;
struct bfd_link_info *info;
{
if (h->type == STT_PARISC_MILLI)
{
h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
elf32_hppa_hide_symbol(info, h);
}
return true;
}
/* Set the sizes of the dynamic sections. */
static boolean
@ -2158,6 +2158,11 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
/* Force millicode symbols local. */
elf_link_hash_traverse (&hplink->root,
clobber_millicode_symbols,
info);
/* DT_INIT and DT_FINI need a .plt entry. Make sure they have
one. */
funcname = info->init_function;
@ -2511,6 +2516,50 @@ elf32_hppa_size_stubs (stub_bfd, multi_subspace, info,
/* Now we can free the external symbols. */
free (ext_syms);
/* Go looking for .init and .fini sections. We only want one
stub section for each of .init* and .fini* because glibc
splits the _init and _fini functions into multiple parts, and
putting a stub in the middle of a function is not a good idea.
It would be better to merge all the stub sections for an
output section if the output section + stubs is small enough.
This would fix the .init and .fini case and also allow stubs
to be merged. It's more linker work though. */
for (section = input_bfd->sections;
section != NULL;
section = section->next, sec_count++)
{
if (hplink->first_init_sec == 0)
{
if (strncmp (section->name, ".init", 5) == 0)
hplink->first_init_sec = sec_count + 1;
}
if (hplink->first_fini_sec == 0)
{
if (strncmp (section->name, ".fini", 5) == 0)
hplink->first_fini_sec = sec_count + 1;
}
#if ! LONG_BRANCH_PIC_IN_SHLIB
/* If this is a shared link, find all the stub reloc
sections. */
if (info->shared)
{
char *name;
asection *reloc_sec;
name = bfd_malloc (strlen (section->name)
+ sizeof STUB_SUFFIX
+ 5);
if (name == NULL)
return false;
sprintf (name, ".rela%s%s", section->name, STUB_SUFFIX);
reloc_sec = bfd_get_section_by_name (hplink->root.dynobj, name);
hplink->reloc_section_created[sec_count] = reloc_sec;
free (name);
}
#endif
}
if (info->shared && hplink->multi_subspace)
{
unsigned int symndx;
@ -2558,7 +2607,8 @@ elf32_hppa_size_stubs (stub_bfd, multi_subspace, info,
{
stub_entry = hppa_add_stub (stub_name,
sec,
sec_count + sec->index,
(sec_count + sec->index
- input_bfd->section_count),
info);
if (!stub_entry)
goto error_ret_free_local;
@ -2578,30 +2628,6 @@ elf32_hppa_size_stubs (stub_bfd, multi_subspace, info,
}
}
}
#if LONG_BRANCH_PIC_IN_SHLIB
sec_count += input_bfd->section_count;
#else
if (! info->shared)
sec_count += input_bfd->section_count;
else
for (section = input_bfd->sections;
section != NULL;
section = section->next, sec_count++)
{
char *name;
asection *reloc_sec;
name = bfd_malloc (strlen (section->name)
+ sizeof STUB_SUFFIX
+ 5);
if (name == NULL)
return false;
sprintf (name, ".rela%s%s", section->name, STUB_SUFFIX);
reloc_sec = bfd_get_section_by_name (hplink->root.dynobj, name);
hplink->reloc_section_created[sec_count] = reloc_sec;
free (name);
}
#endif
}
while (1)
@ -3735,11 +3761,6 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
hplink = hppa_link_hash_table (info);
dynobj = hplink->root.dynobj;
/* Millicode symbols should not be put in the dynamic
symbol table under any circumstances. */
if (ELF_ST_TYPE (sym->st_info) == STT_PARISC_MILLI)
h->dynindx = -1;
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma value;