This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
ELF/m68k visibility handling in shared libraries
- From: Andreas Schwab <schwab at suse dot de>
- To: binutils at sources dot redhat dot com
- Date: Fri, 29 Nov 2002 23:24:38 +0100
- Subject: ELF/m68k visibility handling in shared libraries
The linker didn't properly resolve pc-relative relocations against symbols
that are forced to be local due to visibility changes when creating a
shared library.
Andreas.
2002-11-29 Andreas Schwab <schwab@suse.de>
* elf32-m68k.c (struct elf_m68k_link_hash_table): Add sym_sec
member.
(elf_m68k_link_hash_table_create): Initialize it.
(elf_m68k_check_relocs): Handle symbols that are forced to be
local due to visibility changes.
(elf_m68k_adjust_dynamic_symbol): Likewise.
(elf_m68k_size_dynamic_sections): Likewise.
(elf_m68k_discard_copies): Likewise.
(elf_m68k_relocate_section): Likewise.
Index: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.47
diff -u -p -a -u -p -a -r1.47 bfd/elf32-m68k.c
--- bfd/elf32-m68k.c 28 Nov 2002 11:55:40 -0000 1.47
+++ bfd/elf32-m68k.c 29 Nov 2002 22:09:51 -0000
@@ -277,6 +277,9 @@ struct elf_m68k_link_hash_entry
struct elf_m68k_link_hash_table
{
struct elf_link_hash_table root;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Declare this now that the above structures are defined. */
@@ -349,6 +352,8 @@ elf_m68k_link_hash_table_create (abfd)
return NULL;
}
+ ret->sym_sec.abfd = NULL;
+
return &ret->root.root;
}
@@ -516,7 +521,8 @@ elf_m68k_check_relocs (abfd, info, sec,
if (h->got.refcount == 0)
{
/* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
if (!bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
@@ -593,7 +599,8 @@ elf_m68k_check_relocs (abfd, info, sec,
}
/* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
if (!bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
@@ -620,6 +627,7 @@ elf_m68k_check_relocs (abfd, info, sec,
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (!info->symbolic
+ || h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
@@ -694,17 +702,33 @@ elf_m68k_check_relocs (abfd, info, sec,
only called if we are using an m68kelf linker hash table,
which means that h is really a pointer to an
elf_m68k_link_hash_entry. */
- if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8
- || ELF32_R_TYPE (rel->r_info) == R_68K_PC16
- || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)
- && info->symbolic)
+ if (ELF32_R_TYPE (rel->r_info) == R_68K_PC8
+ || ELF32_R_TYPE (rel->r_info) == R_68K_PC16
+ || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)
{
- struct elf_m68k_link_hash_entry *eh;
struct elf_m68k_pcrel_relocs_copied *p;
+ struct elf_m68k_pcrel_relocs_copied **head;
+
+ if (h != NULL)
+ {
+ struct elf_m68k_link_hash_entry *eh
+ = (struct elf_m68k_link_hash_entry *) h;
+ head = &eh->pcrel_relocs_copied;
+ }
+ else
+ {
+ asection *s;
+ s = (bfd_section_from_r_symndx
+ (abfd, &elf_m68k_hash_table (info)->sym_sec,
+ sec, r_symndx));
+ if (s == NULL)
+ return false;
- eh = (struct elf_m68k_link_hash_entry *) h;
+ head = ((struct elf_m68k_pcrel_relocs_copied **)
+ &elf_section_data (s)->local_dynrel);
+ }
- for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
+ for (p = *head; p != NULL; p = p->next)
if (p->section == sreloc)
break;
@@ -714,8 +738,8 @@ elf_m68k_check_relocs (abfd, info, sec,
bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
if (p == NULL)
return false;
- p->next = eh->pcrel_relocs_copied;
- eh->pcrel_relocs_copied = p;
+ p->next = *head;
+ *head = p;
p->section = sreloc;
p->count = 0;
}
@@ -950,7 +974,8 @@ elf_m68k_adjust_dynamic_symbol (info, h)
}
/* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
@@ -1121,14 +1146,16 @@ elf_m68k_size_dynamic_sections (output_b
s->_raw_size = 0;
}
- /* If this is a -Bsymbolic shared link, then we need to discard all PC
- relative relocs against symbols defined in a regular object. We
- allocated space for them in the check_relocs routine, but we will not
- fill them in in the relocate_section routine. */
- if (info->shared && info->symbolic)
+ /* If this is a -Bsymbolic shared link, then we need to discard all
+ PC relative relocs against symbols defined in a regular object.
+ For the normal shared case we discard the PC relative relocs
+ against symbols that have become local due to visibility changes.
+ We allocated space for them in the check_relocs routine, but we
+ will not fill them in in the relocate_section routine. */
+ if (info->shared)
elf_m68k_link_hash_traverse (elf_m68k_hash_table (info),
elf_m68k_discard_copies,
- (PTR) NULL);
+ (PTR) info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
@@ -1255,23 +1282,28 @@ elf_m68k_size_dynamic_sections (output_b
}
/* This function is called via elf_m68k_link_hash_traverse if we are
- creating a shared object with -Bsymbolic. It discards the space
- allocated to copy PC relative relocs against symbols which are defined
- in regular objects. We allocated space for them in the check_relocs
- routine, but we won't fill them in in the relocate_section routine. */
+ creating a shared object. In the -Bsymbolic case it discards the
+ space allocated to copy PC relative relocs against symbols which
+ are defined in regular objects. For the normal shared case, if
+ discards space for pc-relative relocs that have become local due to
+ symbol visibility changes. We allocated space for them in the
+ check_relocs routine, but we won't fill them in in the
+ relocate_section routine. */
static boolean
-elf_m68k_discard_copies (h, ignore)
+elf_m68k_discard_copies (h, inf)
struct elf_m68k_link_hash_entry *h;
- PTR ignore ATTRIBUTE_UNUSED;
+ PTR inf;
{
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
struct elf_m68k_pcrel_relocs_copied *s;
if (h->root.root.type == bfd_link_hash_warning)
h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link;
- /* We only discard relocs for symbols defined in a regular object. */
- if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ || (!info->symbolic
+ && (h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0))
return true;
for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
@@ -1591,7 +1623,9 @@ elf_m68k_relocate_section (output_bfd, i
case R_68K_PC8:
case R_68K_PC16:
case R_68K_PC32:
- if (h == NULL)
+ if (h == NULL
+ || (info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
break;
/* Fall through. */
case R_68K_8:
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."