On Sat, Mar 02, 2013 at 10:36:50AM -0500, Brian Callahan wrote:
> Hi tech --
>
> While doing some ports testing with clang, I came across the
> binutils bug mentioned here:
> http://lists.gnu.org/archive/html/bug-binutils/2004-07/msg00000.html
>
> Below is a backport of the commit mentioned later in the thread. It
> fixes the issue.
> I was able to rebuild working kernels and do a full 'make build' on
> amd64, loongson, and macppc with this patch. But since it affects
> all archs, testing on the archs I don't have access to will be
> needed.
>
> OK?
This patch does not apply, it seems your mail client is wrapping lines.
>
> ~Brian
>
> Index: elf-bfd.h
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils/bfd/elf-bfd.h,v
> retrieving revision 1.8
> diff -u -p -r1.8 elf-bfd.h
> --- elf-bfd.h 2 Nov 2004 20:45:06 -0000 1.8
> +++ elf-bfd.h 16 Feb 2013 22:43:53 -0000
> @@ -1055,8 +1055,8 @@ struct bfd_elf_section_data
> #define elf_discarded_section(sec) \
> (!bfd_is_abs_section (sec) \
> && bfd_is_abs_section ((sec)->output_section) \
> - && sec->sec_info_type != ELF_INFO_TYPE_MERGE \
> - && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
> + && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \
> + && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
>
> #define get_elf_backend_data(abfd) \
> ((const struct elf_backend_data *) (abfd)->xvec->backend_data)
> Index: elflink.c
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils/bfd/elflink.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 elflink.c
> --- elflink.c 24 Nov 2004 16:55:31 -0000 1.9
> +++ elflink.c 16 Feb 2013 22:43:56 -0000
> @@ -6239,6 +6239,9 @@ elf_link_output_extsym (struct elf_link_
> return TRUE;
> }
>
> +/* Return TRUE if special handling is done for relocs in SEC against
> + symbols defined in discarded sections. */
> +
> static bfd_boolean
> elf_section_ignore_discarded_relocs (asection *sec)
> {
> @@ -6261,6 +6264,26 @@ elf_section_ignore_discarded_relocs (ase
> return FALSE;
> }
>
> +/* Return TRUE if we should complain about a reloc in SEC against a
> + symbol defined in a discarded section. */
> +
> +static bfd_boolean
> +elf_section_complain_discarded (asection *sec)
> +{
> + if (strncmp (".stab", sec->name, 5) == 0
> + && (!sec->name[5] ||
> + (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
> + return FALSE;
> +
> + if (strcmp (".eh_frame", sec->name) == 0)
> + return FALSE;
> +
> + if (strcmp (".gcc_except_table", sec->name) == 0)
> + return FALSE;
> +
> + return TRUE;
> +}
> +
> /* Link an input file into the linker output file. This function
> handles all the sections and relocations of the input file at once.
> This is so that we only have to read the local symbols once, and
> @@ -6532,13 +6555,16 @@ elf_link_input_bfd (struct elf_final_lin
> if (!elf_section_ignore_discarded_relocs (o))
> {
> Elf_Internal_Rela *rel, *relend;
> + bfd_boolean complain = elf_section_complain_discarded (o);
>
> rel = internal_relocs;
> relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
> for ( ; rel < relend; rel++)
> {
> unsigned long r_symndx = rel->r_info >> r_sym_shift;
> - asection *sec;
> + asection **ps, *sec;
> + struct elf_link_hash_entry *h = NULL;
> + const char *sym_name;
>
> if (r_symndx >= locsymcount
> || (elf_bad_symtab (input_bfd)
> @@ -6551,79 +6577,70 @@ elf_link_input_bfd (struct elf_final_lin
> || h->root.type == bfd_link_hash_warning)
> h = (struct elf_link_hash_entry *) h->root.u.i.link;
>
> - /* Complain if the definition comes from a
> - discarded section. */
> - sec = h->root.u.def.section;
> - if ((h->root.type == bfd_link_hash_defined
> - || h->root.type == bfd_link_hash_defweak)
> - && elf_discarded_section (sec))
> - {
> - if ((o->flags & SEC_DEBUGGING) != 0)
> - {
> - BFD_ASSERT (r_symndx != 0);
> - /* Try to preserve debug information. */
> - if ((o->flags & SEC_DEBUGGING) != 0
> - && sec->kept_section != NULL
> - && sec->_raw_size == sec->kept_section->_raw_size)
> - h->root.u.def.section
> - = sec->kept_section;
> - else
> - memset (rel, 0, sizeof (*rel));
> - }
> - else
> - finfo->info->callbacks->error_handler
> - (LD_DEFINITION_IN_DISCARDED_SECTION,
> - _("%T: discarded in section `%s' from %s\n"),
> - h->root.root.string,
> - h->root.root.string,
> - h->root.u.def.section->name,
> - bfd_archive_filename (h->root.u.def.section->owner));
> - }
> - }
> - else
> - {
> - sec = finfo->sections[r_symndx];
> -
> - if (sec != NULL && elf_discarded_section (sec))
> - {
> - if ((o->flags & SEC_DEBUGGING) != 0
> - || (sec->flags & SEC_LINK_ONCE) != 0)
> - {
> - BFD_ASSERT (r_symndx != 0);
> - /* Try to preserve debug information. */
> - if ((o->flags & SEC_DEBUGGING) != 0
> - && sec->kept_section != NULL
> - && sec->_raw_size == sec->kept_section->_raw_size)
> - finfo->sections[r_symndx]
> - = sec->kept_section;
> - else
> - {
> - rel->r_info &= r_type_mask;
> - rel->r_addend = 0;
> - }
> - }
> - else
> - {
> - static int count;
> - int ok;
> - char *buf;
> -
> - ok = asprintf (&buf, "local symbol %d",
> - count++);
> - if (ok <= 0)
> - buf = (char *) "local symbol";
> - finfo->info->callbacks->error_handler
> - (LD_DEFINITION_IN_DISCARDED_SECTION,
> - _("%T: discarded in section `%s' from %s\n"),
> - buf, buf, sec->name,
> - bfd_archive_filename (input_bfd));
> - if (ok != -1)
> - free (buf);
> - }
> - }
> - }
> - }
> - }
> + if (h->root.type != bfd_link_hash_defined
> + && h->root.type != bfd_link_hash_defweak)
> + continue;
> +
> + ps = &h->root.u.def.section;
> + sym_name = h->root.root.string;
> + }
> + else
> + {
> + Elf_Internal_Sym *sym = isymbuf + r_symndx;
> + ps = &finfo->sections[r_symndx];
> + sym_name = bfd_elf_local_sym_name (input_bfd, sym);
> + }
> +
> + /* Complain if the definition comes from a
> + discarded section. */
> + if ((sec = *ps) != NULL && elf_discarded_section (sec))
> + {
> + if ((o->flags & SEC_DEBUGGING) != 0)
> + {
> + BFD_ASSERT (r_symndx != 0);
> +
> + /* Try to preserve debug information.
> + FIXME: This is quite broken. Modifying
> + the symbol here means we will be changing
> + all uses of the symbol, not just those in
> + debug sections. The only thing that makes
> + this half reasonable is that debug sections
> + tend to come after other sections. Of
> + course, that doesn't help with globals.
> + ??? All link-once sections of the same name
> + ought to define the same set of symbols, so
> + it would seem that globals ought to always
> + be defined in the kept section. */
> + if (sec->kept_section != NULL
> + && sec->_cooked_size ==
> sec->kept_section->_cooked_size)
> + {
> + *ps = sec->kept_section;
> + continue;
> + }
> + }
> + else if (complain)
> + {
> + finfo->info->callbacks->error_handler
> + (LD_DEFINITION_IN_DISCARDED_SECTION,
> + _("`%T' referenced in section `%s' of %B: "
> + "defined in discarded section `%s'
> of %B\n"),
> + sym_name,
> + sym_name, o->name, input_bfd,
> + sec->name, sec->owner);
> + }
> +
> + /* Remove the symbol reference from the reloc, but
> + don't kill the reloc completely. This is so that
> + a zero value will be written into the section,
> + which may have non-zero contents put there by the
> + assembler. Zero in things like an eh_frame fde
> + pc_begin allows stack unwinders to recognize the
> + fde as bogus. */
> + rel->r_info &= r_type_mask;
> + rel->r_addend = 0;
> + }
> + }
> + }
>
> /* Relocate the section by invoking a back end routine.
>