* elf64-alpha.c (ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED): Defined.
(elf64_alpha_relocate_section): Translate local_got_entries for STT_SECTION symbol to SHF_MERGE section the first time we see it. * elfxx-ia64.c (struct elfNN_ia64_local_hash_entry): Add sec_merge_done. (get_local_sym_hash): New, extracted from get_dyn_sym_info. (get_dyn_sym_info): Use it. (elfNN_ia64_relocate_section): Translate local dyn entries for STT_SECTION symbol to SHF_MERGE section the first time we see it. * write.c (adjust_reloc_syms): Mark SEC_MERGE symbols as used in reloc if it has non-zero addend. * config/tc-alpha.c (tc_gen_reloc): Reinstall SEC_MERGE check. * config/tc-sparc.c (md_apply_fix3): Likewise.
This commit is contained in:
parent
607334a109
commit
f7460f5f76
7 changed files with 129 additions and 22 deletions
|
@ -1,3 +1,17 @@
|
|||
2001-11-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* elf64-alpha.c (ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED): Defined.
|
||||
(elf64_alpha_relocate_section): Translate local_got_entries
|
||||
for STT_SECTION symbol to SHF_MERGE section the first time
|
||||
we see it.
|
||||
* elfxx-ia64.c (struct elfNN_ia64_local_hash_entry): Add
|
||||
sec_merge_done.
|
||||
(get_local_sym_hash): New, extracted from get_dyn_sym_info.
|
||||
(get_dyn_sym_info): Use it.
|
||||
(elfNN_ia64_relocate_section): Translate local dyn entries
|
||||
for STT_SECTION symbol to SHF_MERGE section the first time
|
||||
we see it.
|
||||
|
||||
2001-11-27 H.J. Lu <hjl@gnu.org>
|
||||
|
||||
* elflink.h (elf_bfd_discard_info): Skip if the input bfd isn't
|
||||
|
|
|
@ -170,8 +170,9 @@ struct alpha_elf_link_hash_entry
|
|||
|
||||
int flags;
|
||||
|
||||
/* An additional flag. */
|
||||
/* Additional flags. */
|
||||
#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10
|
||||
#define ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED 0x20
|
||||
|
||||
int use_count;
|
||||
} *got_entries;
|
||||
|
@ -3400,6 +3401,37 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
gotent = (alpha_elf_tdata(input_bfd)->
|
||||
local_got_entries[r_symndx]);
|
||||
dynamic_symbol = false;
|
||||
|
||||
/* Need to adjust local GOT entries' addends for SEC_MERGE
|
||||
unless it has been done already. */
|
||||
if ((sec->flags & SEC_MERGE)
|
||||
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
|
||||
&& elf_section_data (sec)->merge_info
|
||||
&& (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
|
||||
{
|
||||
struct alpha_elf_got_entry *ent;
|
||||
asection *msec;
|
||||
|
||||
for (ent = gotent; ent; ent = ent->next)
|
||||
{
|
||||
ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED;
|
||||
if (ent->use_count == 0)
|
||||
continue;
|
||||
msec = sec;
|
||||
ent->addend =
|
||||
_bfd_merged_section_offset (output_bfd, &msec,
|
||||
elf_section_data (sec)->
|
||||
merge_info,
|
||||
sym->st_value
|
||||
+ ent->addend,
|
||||
(bfd_vma) 0);
|
||||
ent->addend -= sym->st_value;
|
||||
ent->addend += msec->output_section->vma
|
||||
+ msec->output_offset
|
||||
- sec->output_section->vma
|
||||
- sec->output_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BFD_ASSERT(gotent != NULL);
|
||||
|
|
|
@ -111,6 +111,10 @@ struct elfNN_ia64_local_hash_entry
|
|||
{
|
||||
struct bfd_hash_entry root;
|
||||
struct elfNN_ia64_dyn_sym_info *info;
|
||||
|
||||
/* True if this hash entry's addends was translated for
|
||||
SHF_MERGE optimization. */
|
||||
unsigned sec_merge_done : 1;
|
||||
};
|
||||
|
||||
struct elfNN_ia64_local_hash_table
|
||||
|
@ -216,6 +220,9 @@ static void elfNN_ia64_dyn_sym_traverse
|
|||
PTR info));
|
||||
static boolean elfNN_ia64_create_dynamic_sections
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *info));
|
||||
static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
|
||||
PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
|
||||
bfd *abfd, const Elf_Internal_Rela *rel, boolean create));
|
||||
static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
|
||||
PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
|
||||
struct elf_link_hash_entry *h,
|
||||
|
@ -1719,6 +1726,32 @@ elfNN_ia64_create_dynamic_sections (abfd, info)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Find and/or create a hash entry for local symbol. */
|
||||
static struct elfNN_ia64_local_hash_entry *
|
||||
get_local_sym_hash (ia64_info, abfd, rel, create)
|
||||
struct elfNN_ia64_link_hash_table *ia64_info;
|
||||
bfd *abfd;
|
||||
const Elf_Internal_Rela *rel;
|
||||
boolean create;
|
||||
{
|
||||
char *addr_name;
|
||||
size_t len;
|
||||
|
||||
/* Construct a string for use in the elfNN_ia64_local_hash_table.
|
||||
name describes what was once anonymous memory. */
|
||||
|
||||
len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1;
|
||||
len += 10; /* %p slop */
|
||||
|
||||
addr_name = alloca (len);
|
||||
sprintf (addr_name, "%p:%lx",
|
||||
(void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info));
|
||||
|
||||
/* Collect the canonical entry data for this address. */
|
||||
return elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
|
||||
addr_name, create, create);
|
||||
}
|
||||
|
||||
/* Find and/or create a descriptor for dynamic symbol info. This will
|
||||
vary based on global or local symbol, and the addend to the reloc. */
|
||||
|
||||
|
@ -1739,22 +1772,8 @@ get_dyn_sym_info (ia64_info, h, abfd, rel, create)
|
|||
else
|
||||
{
|
||||
struct elfNN_ia64_local_hash_entry *loc_h;
|
||||
char *addr_name;
|
||||
size_t len;
|
||||
|
||||
/* Construct a string for use in the elfNN_ia64_local_hash_table.
|
||||
The name describes what was once anonymous memory. */
|
||||
|
||||
len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1;
|
||||
len += 10; /* %p slop */
|
||||
|
||||
addr_name = alloca (len);
|
||||
sprintf (addr_name, "%p:%lx",
|
||||
(void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info));
|
||||
|
||||
/* Collect the canonical entry data for this address. */
|
||||
loc_h = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
|
||||
addr_name, create, create);
|
||||
loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
|
||||
BFD_ASSERT (loc_h);
|
||||
|
||||
pp = &loc_h->info;
|
||||
|
@ -3482,6 +3501,37 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
sym = local_syms + r_symndx;
|
||||
sym_sec = local_sections[r_symndx];
|
||||
value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
|
||||
if ((sym_sec->flags & SEC_MERGE)
|
||||
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
|
||||
&& elf_section_data (sym_sec)->merge_info)
|
||||
{
|
||||
struct elfNN_ia64_local_hash_entry *loc_h;
|
||||
|
||||
loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, false);
|
||||
if (loc_h && ! loc_h->sec_merge_done)
|
||||
{
|
||||
struct elfNN_ia64_dyn_sym_info *dynent;
|
||||
asection *msec;
|
||||
|
||||
for (dynent = loc_h->info; dynent; dynent = dynent->next)
|
||||
{
|
||||
msec = sym_sec;
|
||||
dynent->addend =
|
||||
_bfd_merged_section_offset (output_bfd, &msec,
|
||||
elf_section_data (msec)->
|
||||
merge_info,
|
||||
sym->st_value
|
||||
+ dynent->addend,
|
||||
(bfd_vma) 0);
|
||||
dynent->addend -= sym->st_value;
|
||||
dynent->addend += msec->output_section->vma
|
||||
+ msec->output_offset
|
||||
- sym_sec->output_section->vma
|
||||
- sym_sec->output_offset;
|
||||
}
|
||||
loc_h->sec_merge_done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2001-11-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* write.c (adjust_reloc_syms): Mark SEC_MERGE symbols as used
|
||||
in reloc if it has non-zero addend.
|
||||
* config/tc-alpha.c (tc_gen_reloc): Reinstall SEC_MERGE check.
|
||||
* config/tc-sparc.c (md_apply_fix3): Likewise.
|
||||
|
||||
2001-11-28 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* as.c (parse_args): Call md_after_parse_args if defined.
|
||||
|
|
|
@ -1507,7 +1507,8 @@ tc_gen_reloc (sec, fixp)
|
|||
* at assembly time. bfd_perform_reloc doesn't know about this sort
|
||||
* of thing, and as a result we need to fake it out here.
|
||||
*/
|
||||
if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
|
||||
if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
|
||||
|| (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
|
||||
&& !S_IS_COMMON (fixp->fx_addsy))
|
||||
reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
|
||||
#endif
|
||||
|
|
|
@ -2909,12 +2909,7 @@ md_apply_fix3 (fixP, valP, segment)
|
|||
if (symbol_used_in_reloc_p (sym)
|
||||
&& (S_IS_EXTERNAL (sym)
|
||||
|| S_IS_WEAK (sym)
|
||||
#if 0 /* Although fixups against local symbols in SEC_MERGE sections
|
||||
should be treated as if they were against external symbols
|
||||
write.c:fixup_segment() will not have included the value of
|
||||
the symbol under these particular cicumstances. */
|
||||
|| (seg->flags & SEC_MERGE)
|
||||
#endif
|
||||
|| (sparc_pic_code && ! fixP->fx_pcrel)
|
||||
|| (seg != segment
|
||||
&& (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0)
|
||||
|
|
|
@ -873,6 +873,14 @@ adjust_reloc_syms (abfd, sec, xxx)
|
|||
symbol_mark_used_in_reloc (fixp->fx_addsy);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Never adjust a reloc against local symbol in a merge section
|
||||
with non-zero addend. */
|
||||
if ((symsec->flags & SEC_MERGE) && fixp->fx_offset)
|
||||
{
|
||||
symbol_mark_used_in_reloc (fixp->fx_addsy);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Is there some other reason we can't adjust this one? (E.g.,
|
||||
|
|
Loading…
Reference in a new issue