sparc .got fill failure
Richard Henderson
rth@redhat.com
Sun Mar 31 01:29:00 GMT 2002
On Sat, Mar 30, 2002 at 06:19:47PM -0800, David S. Miller wrote:
> > Sure enough, the resulting libgcc/_bb.oS, due to
> > this hidden transformation, lacks the GOT10/GOT22 relocs for
> > __bb_exit_func and thus it does not get resolved at link
> > time because the linker doesn't see it anywhere.
Actually, the GOT10/GOT22 relocs are still there, but the linker
failed to actually fill in the .got entry.
The following appears to fix the problem. I'm currently running
a combined binutils+gcc bootstrap on (32-bit) solaris, but it'd
be good if one of you could build glibc on linux, as that will
stress things a bit more...
r~
* elf32-sparc.c (WILL_CALL_FINISH_DYNAMIC_SYMBOL): New.
(elf32_sparc_relocate_section): Use it to figure out when to
initialize .got entries.
* elf64-sparc.c: Similarly.
Index: elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.36
diff -c -p -d -r1.36 elf32-sparc.c
*** elf32-sparc.c 2002/02/19 12:40:27 1.36
--- elf32-sparc.c 2002/03/31 09:23:21
*************** elf32_sparc_relax_section (abfd, section
*** 1084,1089 ****
--- 1084,1100 ----
return true;
}
+ /* This is the condition under which finish_dynamic_symbol will be called
+ from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
+ routine, we'll need to do something about initializing any .plt and .got
+ entries in relocate_section. */
+ #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* Relocate a SPARC ELF section. */
static boolean
*************** elf32_sparc_relocate_section (output_bfd
*** 1133,1141 ****
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
! bfd_vma relocation;
bfd_reloc_status_type r;
boolean is_plt = false;
r_type = ELF32_R_TYPE (rel->r_info);
--- 1144,1153 ----
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
! bfd_vma relocation, off;
bfd_reloc_status_type r;
boolean is_plt = false;
+ boolean unresolved_reloc;
r_type = ELF32_R_TYPE (rel->r_info);
*************** elf32_sparc_relocate_section (output_bfd
*** 1175,1180 ****
--- 1187,1193 ----
h = NULL;
sym = NULL;
sec = NULL;
+ unresolved_reloc = false;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
*************** elf32_sparc_relocate_section (output_bfd
*** 1187,1257 ****
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
! if (((r_type == R_SPARC_WPLT30
! || r_type == R_SPARC_PLT32)
! && h->plt.offset != (bfd_vma) -1)
! || ((r_type == R_SPARC_GOT10
! || r_type == R_SPARC_GOT13
! || r_type == R_SPARC_GOT22)
! && elf_hash_table (info)->dynamic_sections_created
! && (! info->shared
! || (! info->symbolic && h->dynindx != -1)
! || (h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_REGULAR) == 0))
! || (info->shared
! && ((! info->symbolic && h->dynindx != -1)
! || (h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_REGULAR) == 0)
! && (r_type == R_SPARC_8
! || r_type == R_SPARC_16
! || r_type == R_SPARC_32
! || r_type == R_SPARC_DISP8
! || r_type == R_SPARC_DISP16
! || r_type == R_SPARC_DISP32
! || r_type == R_SPARC_WDISP30
! || r_type == R_SPARC_WDISP22
! || r_type == R_SPARC_WDISP19
! || r_type == R_SPARC_WDISP16
! || r_type == R_SPARC_HI22
! || r_type == R_SPARC_22
! || r_type == R_SPARC_13
! || r_type == R_SPARC_LO10
! || r_type == R_SPARC_UA16
! || r_type == R_SPARC_UA32
! || ((r_type == R_SPARC_PC10
! || r_type == R_SPARC_PC22)
! && strcmp (h->root.root.string,
! "_GLOBAL_OFFSET_TABLE_") != 0))
! && ((input_section->flags & SEC_ALLOC) != 0
! /* DWARF will emit R_SPARC_32 relocations in its
! sections against symbols defined externally
! in shared libraries. We can't do anything
! with them here. */
! || ((input_section->flags & SEC_DEBUGGING) != 0
! && (h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
! {
! /* In these cases, we don't need the relocation
! value. We check specially because in some
! obscure cases sec->output_section will be NULL. */
! relocation = 0;
! }
else
relocation = (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
else if (h->root.type == bfd_link_hash_undefweak)
! relocation = 0;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! relocation = 0;
else
{
if (! ((*info->callbacks->undefined_symbol)
--- 1200,1229 ----
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ relocation = 0;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
! if (sec->output_section == NULL)
! /* Set a flag that will be cleared later if we find a
! relocation value for this symbol. output_section
! is typically NULL for symbols satisfied by a shared
! library. */
! unresolved_reloc = true;
else
relocation = (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
else if (h->root.type == bfd_link_hash_undefweak)
! ;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! ;
else
{
if (! ((*info->callbacks->undefined_symbol)
*************** elf32_sparc_relocate_section (output_bfd
*** 1260,1266 ****
(!info->shared || info->no_undefined
|| ELF_ST_VISIBILITY (h->other)))))
return false;
- relocation = 0;
}
}
--- 1232,1237 ----
*************** elf32_sparc_relocate_section (output_bfd
*** 1279,1292 ****
if (h != NULL)
{
! bfd_vma off;
off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
! if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
! && (info->symbolic || h->dynindx == -1)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a
--- 1250,1266 ----
if (h != NULL)
{
! boolean dyn;
off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
+ dyn = elf_hash_table (info)->dynamic_sections_created;
! if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared
! && (info->symbolic
! || h->dynindx == -1
! || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a
*************** elf32_sparc_relocate_section (output_bfd
*** 1310,1322 ****
h->got.offset |= 1;
}
}
!
! relocation = sgot->output_offset + off - got_base;
}
else
{
- bfd_vma off;
-
BFD_ASSERT (local_got_offsets != NULL
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
--- 1284,1294 ----
h->got.offset |= 1;
}
}
! else
! unresolved_reloc = false;
}
else
{
BFD_ASSERT (local_got_offsets != NULL
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
*************** elf32_sparc_relocate_section (output_bfd
*** 1355,1364 ****
local_got_offsets[r_symndx] |= 1;
}
-
- relocation = sgot->output_offset + off - got_base;
}
!
break;
case R_SPARC_PLT32:
--- 1327,1334 ----
local_got_offsets[r_symndx] |= 1;
}
}
! relocation = sgot->output_offset + off - got_base;
break;
case R_SPARC_PLT32:
*************** elf32_sparc_relocate_section (output_bfd
*** 1396,1401 ****
--- 1366,1372 ----
relocation = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
+ unresolved_reloc = false;
if (r_type == R_SPARC_PLT32)
{
r_type = R_SPARC_32;
*************** elf32_sparc_relocate_section (output_bfd
*** 1581,1586 ****
--- 1552,1569 ----
default:
break;
}
+
+ /* ??? Copied from elf32-i386.c, debugging section check and all. */
+ if (unresolved_reloc
+ && !(info->shared
+ && (input_section->flags & SEC_DEBUGGING) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ (*_bfd_error_handler)
+ (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ bfd_archive_filename (input_bfd),
+ bfd_get_section_name (input_bfd, input_section),
+ (long) rel->r_offset,
+ h->root.root.string);
r = bfd_reloc_continue;
if (r_type == R_SPARC_WDISP16)
Index: elf64-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sparc.c,v
retrieving revision 1.49
diff -c -p -d -r1.49 elf64-sparc.c
*** elf64-sparc.c 2002/02/19 12:40:28 1.49
--- elf64-sparc.c 2002/03/31 09:23:22
*************** sparc64_elf_relax_section (abfd, section
*** 1881,1886 ****
--- 1881,1897 ----
return true;
}
+ /* This is the condition under which finish_dynamic_symbol will be called
+ from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
+ routine, we'll need to do something about initializing any .plt and
+ .got entries in relocate_section. */
+ #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* Relocate a SPARC64 ELF section. */
static boolean
*************** sparc64_elf_relocate_section (output_bfd
*** 1928,1936 ****
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
! bfd_vma relocation;
bfd_reloc_status_type r;
boolean is_plt = false;
r_type = ELF64_R_TYPE_ID (rel->r_info);
if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
--- 1939,1948 ----
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
! bfd_vma relocation, off;
bfd_reloc_status_type r;
boolean is_plt = false;
+ boolean unresolved_reloc;
r_type = ELF64_R_TYPE_ID (rel->r_info);
if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
*************** sparc64_elf_relocate_section (output_bfd
*** 1965,1970 ****
--- 1977,1983 ----
h = NULL;
sym = NULL;
sec = NULL;
+ unresolved_reloc = false;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
*************** sparc64_elf_relocate_section (output_bfd
*** 1977,2092 ****
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
- boolean skip_it = false;
sec = h->root.u.def.section;
!
! switch (r_type)
! {
! case R_SPARC_WPLT30:
! case R_SPARC_PLT32:
! case R_SPARC_HIPLT22:
! case R_SPARC_LOPLT10:
! case R_SPARC_PCPLT32:
! case R_SPARC_PCPLT22:
! case R_SPARC_PCPLT10:
! case R_SPARC_PLT64:
! if (h->plt.offset != (bfd_vma) -1)
! skip_it = true;
! break;
!
! case R_SPARC_GOT10:
! case R_SPARC_GOT13:
! case R_SPARC_GOT22:
! if (elf_hash_table(info)->dynamic_sections_created
! && (!info->shared
! || (!info->symbolic && h->dynindx != -1)
! || !(h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_REGULAR)))
! skip_it = true;
! break;
!
! case R_SPARC_PC10:
! case R_SPARC_PC22:
! case R_SPARC_PC_HH22:
! case R_SPARC_PC_HM10:
! case R_SPARC_PC_LM22:
! if (!strcmp(h->root.root.string, "_GLOBAL_OFFSET_TABLE_"))
! break;
! /* FALLTHRU */
!
! case R_SPARC_8:
! case R_SPARC_16:
! case R_SPARC_32:
! case R_SPARC_DISP8:
! case R_SPARC_DISP16:
! case R_SPARC_DISP32:
! case R_SPARC_WDISP30:
! case R_SPARC_WDISP22:
! case R_SPARC_HI22:
! case R_SPARC_22:
! case R_SPARC_13:
! case R_SPARC_LO10:
! case R_SPARC_UA32:
! case R_SPARC_10:
! case R_SPARC_11:
! case R_SPARC_64:
! case R_SPARC_OLO10:
! case R_SPARC_HH22:
! case R_SPARC_HM10:
! case R_SPARC_LM22:
! case R_SPARC_WDISP19:
! case R_SPARC_WDISP16:
! case R_SPARC_7:
! case R_SPARC_5:
! case R_SPARC_6:
! case R_SPARC_DISP64:
! case R_SPARC_HIX22:
! case R_SPARC_LOX10:
! case R_SPARC_H44:
! case R_SPARC_M44:
! case R_SPARC_L44:
! case R_SPARC_UA64:
! case R_SPARC_UA16:
! if (info->shared
! && ((!info->symbolic && h->dynindx != -1)
! || !(h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_REGULAR))
! && ((input_section->flags & SEC_ALLOC) != 0
! /* DWARF will emit R_SPARC_{32,64} relocations in
! its sections against symbols defined externally
! in shared libraries. We can't do anything
! with them here. */
! || ((input_section->flags & SEC_DEBUGGING) != 0
! && (h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))
! skip_it = true;
! break;
! }
!
! if (skip_it)
! {
! /* In these cases, we don't need the relocation
! value. We check specially because in some
! obscure cases sec->output_section will be NULL. */
! relocation = 0;
! }
else
! {
! relocation = (h->root.u.def.value
! + sec->output_section->vma
! + sec->output_offset);
! }
}
else if (h->root.type == bfd_link_hash_undefweak)
! relocation = 0;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! relocation = 0;
else
{
if (! ((*info->callbacks->undefined_symbol)
--- 1990,2019 ----
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ relocation = 0;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
! if (sec->output_section == NULL)
! /* Set a flag that will be cleared later if we find a
! relocation value for this symbol. output_section
! is typically NULL for symbols satisfied by a shared
! library. */
! unresolved_reloc = true;
else
! relocation = (h->root.u.def.value
! + sec->output_section->vma
! + sec->output_offset);
}
else if (h->root.type == bfd_link_hash_undefweak)
! ;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! ;
else
{
if (! ((*info->callbacks->undefined_symbol)
*************** sparc64_elf_relocate_section (output_bfd
*** 2107,2113 ****
}
}
! do_dynreloc:
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
--- 2034,2040 ----
}
}
! do_dynreloc:
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
*************** do_dynreloc:
*** 2326,2339 ****
if (h != NULL)
{
! bfd_vma off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
! if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
! && (info->symbolic || h->dynindx == -1)
! && (h->elf_link_hash_flags
! & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a -Bsymbolic
link and the symbol is defined locally, or the symbol
--- 2253,2270 ----
if (h != NULL)
{
! boolean dyn;
!
! off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
+ dyn = elf_hash_table (info)->dynamic_sections_created;
! if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared
! && (info->symbolic
! || h->dynindx == -1
! || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
! && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a -Bsymbolic
link and the symbol is defined locally, or the symbol
*************** do_dynreloc:
*** 2356,2367 ****
h->got.offset |= 1;
}
}
! relocation = sgot->output_offset + off - got_base;
}
else
{
- bfd_vma off;
-
BFD_ASSERT (local_got_offsets != NULL);
off = local_got_offsets[r_symndx];
BFD_ASSERT (off != (bfd_vma) -1);
--- 2287,2297 ----
h->got.offset |= 1;
}
}
! else
! unresolved_reloc = false;
}
else
{
BFD_ASSERT (local_got_offsets != NULL);
off = local_got_offsets[r_symndx];
BFD_ASSERT (off != (bfd_vma) -1);
*************** do_dynreloc:
*** 2407,2414 ****
else
bfd_put_64 (output_bfd, relocation, sgot->contents + off);
}
- relocation = sgot->output_offset + off - got_base;
}
goto do_default;
case R_SPARC_WPLT30:
--- 2337,2344 ----
else
bfd_put_64 (output_bfd, relocation, sgot->contents + off);
}
}
+ relocation = sgot->output_offset + off - got_base;
goto do_default;
case R_SPARC_WPLT30:
*************** do_dynreloc:
*** 2440,2445 ****
--- 2370,2376 ----
relocation = (splt->output_section->vma
+ splt->output_offset
+ sparc64_elf_plt_entry_offset (h->plt.offset));
+ unresolved_reloc = false;
if (r_type == R_SPARC_WPLT30)
goto do_wplt30;
if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
*************** do_dynreloc:
*** 2622,2627 ****
--- 2553,2569 ----
relocation, rel->r_addend);
break;
}
+
+ if (unresolved_reloc
+ && !(info->shared
+ && (input_section->flags & SEC_DEBUGGING) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ (*_bfd_error_handler)
+ (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ bfd_archive_filename (input_bfd),
+ bfd_get_section_name (input_bfd, input_section),
+ (long) rel->r_offset,
+ h->root.root.string);
switch (r)
{
More information about the Binutils
mailing list