[RFC] PR ld/13621
Mark Wielaard
mjw@redhat.com
Mon Jan 30 08:23:00 GMT 2012
On Mon, Jan 30, 2012 at 11:56:49AM +1100, Richard Henderson wrote:
> At first I attempted to SEC_KEEP any section with global symbols. But
> this ran into all sorts of testsuite failures re .got. In those cases
> the _GLOBAL_OFFSET_TABLE_ symbol still exists, which causes .got to
> be kept instead of removed as unused later in the link.
My attempt was using a separate flag to indicate global symbols
were present for the an input section. This works for the example
given in the bug report, but doesn't for the actual gc 4.7 case.
I assume because multiple input files define the same symbol, some
as undefined, and the output section gets associated with the "wrong"
input section. Maybe a solution could be to do te registration in
_bfd_elf_merge_symbol?
Cheers,
Mark
-------------- next part --------------
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 1523660..fae3bfd 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1392,6 +1392,9 @@ typedef struct bfd_section
/* Nonzero if this section uses RELA relocations, rather than REL. */
unsigned int use_rela_p:1;
+ /* Nonzero if there are global symbols associated with this section. */
+ unsigned int global_syms_p:1;
+
/* Bits used by various backends. The generic code doesn't touch
these fields. */
@@ -1674,8 +1677,8 @@ extern asection bfd_ind_section;
/* linker_mark, linker_has_input, gc_mark, decompress_status, */ \
0, 0, 1, 0, \
\
- /* segment_mark, sec_info_type, use_rela_p, */ \
- 0, 0, 0, \
+ /* segment_mark, sec_info_type, use_rela_p, global_syms_p, */ \
+ 0, 0, 0, 0, \
\
/* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */ \
0, 0, 0, 0, 0, 0, \
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index b76266d..50c7890 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -57,8 +57,8 @@ static asection bfd_debug_section =
"*DEBUG*", 0, 0, NULL, NULL, 0, 0,
/* linker_mark, linker_has_input, gc_mark, compress_status, */
0, 0, 1, 0,
- /* segment_mark, sec_info_type, use_rela_p, */
- 0, 0, 0,
+ /* segment_mark, sec_info_type, use_rela_p, global_syms_p, */
+ 0, 0, 0, 0,
/* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */
0, 0, 0, 0, 0, 0,
/* vma, lma, size, rawsize, compressed_size, relax, relax_count, */
diff --git a/bfd/elf.c b/bfd/elf.c
index 9c9ba75..8f4e595 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6320,6 +6320,7 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
}
osec->use_rela_p = isec->use_rela_p;
+ osec->global_syms_p = isec->global_syms_p;
return TRUE;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1d1ca0b..47191cf 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3903,8 +3903,20 @@ error_free_dyn:
sec = bfd_und_section_ptr;
isym->st_shndx = SHN_UNDEF;
}
- else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
- value -= sec->vma;
+ else
+ {
+ /* If we have a global symbol for a section, then we need
+ to keep it around, even if the section ends up empty.
+ Except for .gnu.warning sections which are "special"
+ (see above). */
+ if (flags == BSF_GLOBAL
+ && ! CONST_STRNEQ (bfd_get_section_name (abfd, sec),
+ ".gnu.warning"))
+ sec->global_syms_p = 1;
+
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+ value -= sec->vma;
+ }
}
name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
diff --git a/bfd/section.c b/bfd/section.c
index 7c1f750..803de74 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -391,6 +391,9 @@ CODE_FRAGMENT
. {* Nonzero if this section uses RELA relocations, rather than REL. *}
. unsigned int use_rela_p:1;
.
+. {* Nonzero if there are global symbols associated with this section. *}
+. unsigned int global_syms_p:1;
+.
. {* Bits used by various backends. The generic code doesn't touch
. these fields. *}
.
@@ -673,8 +676,8 @@ CODE_FRAGMENT
. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \
. 0, 0, 1, 0, \
. \
-. {* segment_mark, sec_info_type, use_rela_p, *} \
-. 0, 0, 0, \
+. {* segment_mark, sec_info_type, use_rela_p, global_syms_p, *} \
+. 0, 0, 0, 0, \
. \
. {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \
. 0, 0, 0, 0, 0, 0, \
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5e01fc0..c7b24a2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3903,6 +3903,7 @@ strip_excluded_output_sections (void)
continue;
exclude = (output_section->rawsize == 0
+ && output_section->global_syms_p == 0
&& (output_section->flags & SEC_KEEP) == 0
&& !bfd_section_removed_from_list (link_info.output_bfd,
output_section));
More information about the Binutils
mailing list