bfd/ 2003-06-13 H.J. Lu * section.c (struct sec): Put back kept_section. (STD_SECTION): Put back kept_section initialisation. * bfd-in2.h: Regenerate. * elflink.h (elf_link_input_bfd): Also check discarded linkonce sections for relocateable output. Use kept_section to preserve debug information discarded by linkonce. ld/ 2003-06-13 H.J. Lu * ldlang.c (section_already_linked): Put back assignment of kept_section. --- binutils/bfd/elflink.h.linkonce 2003-06-13 08:34:09.000000000 -0700 +++ binutils/bfd/elflink.h 2003-06-14 21:39:43.000000000 -0700 @@ -5046,9 +5046,9 @@ elf_link_input_bfd (finfo, input_bfd) from discarded sections and section symbols from removed link-once sections. Complain about relocs against discarded sections. Zero relocs against removed - link-once sections. */ - if (!finfo->info->relocateable - && !elf_section_ignore_discarded_relocs (o)) + link-once sections. Preserve debug information as much + as we can. */ + if (!elf_section_ignore_discarded_relocs (o)) { Elf_Internal_Rela *rel, *relend; @@ -5057,6 +5057,7 @@ elf_link_input_bfd (finfo, input_bfd) for ( ; rel < relend; rel++) { unsigned long r_symndx = ELF_R_SYM (rel->r_info); + asection *sec; if (r_symndx >= locsymcount || (elf_bad_symtab (input_bfd) @@ -5071,14 +5072,22 @@ elf_link_input_bfd (finfo, input_bfd) /* 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 (h->root.u.def.section)) + && elf_discarded_section (sec)) { if ((o->flags & SEC_DEBUGGING) != 0) { BFD_ASSERT (r_symndx != 0); - memset (rel, 0, sizeof (*rel)); + /* Try to preserve debug information. */ + if ((o->flags & SEC_DEBUGGING) != 0 + && sec->kept_section != NULL + && sec->_cooked_size == sec->kept_section->_cooked_size) + h->root.u.def.section + = sec->kept_section; + else + memset (rel, 0, sizeof (*rel)); } else finfo->info->callbacks->error_handler @@ -5092,7 +5101,7 @@ elf_link_input_bfd (finfo, input_bfd) } else { - asection *sec = finfo->sections[r_symndx]; + sec = finfo->sections[r_symndx]; if (sec != NULL && elf_discarded_section (sec)) { @@ -5100,9 +5109,18 @@ elf_link_input_bfd (finfo, input_bfd) || (sec->flags & SEC_LINK_ONCE) != 0) { BFD_ASSERT (r_symndx != 0); - rel->r_info - = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info)); - rel->r_addend = 0; + /* Try to preserve debug information. */ + if ((o->flags & SEC_DEBUGGING) != 0 + && sec->kept_section != NULL + && sec->_cooked_size == sec->kept_section->_cooked_size) + finfo->sections[r_symndx] + = sec->kept_section; + else + { + rel->r_info + = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info)); + rel->r_addend = 0; + } } else { --- binutils/bfd/section.c.linkonce 2003-06-08 17:41:36.000000000 -0700 +++ binutils/bfd/section.c 2003-06-13 09:41:32.000000000 -0700 @@ -493,6 +493,10 @@ CODE_FRAGMENT . {* Optional information about a COMDAT entry; NULL if not COMDAT. *} . struct bfd_comdat_info *comdat; . +. {* Points to the kept section if this section is a link-once section, +. and is discarded. *} +. struct sec *kept_section; +. . {* When a section is being output, this value changes as more . linenumbers are written out. *} . file_ptr moving_line_filepos; @@ -640,8 +644,8 @@ static const asymbol global_syms[] = /* line_filepos, userdata, contents, lineno, lineno_count, */ \ 0, NULL, NULL, NULL, 0, \ \ - /* entsize, comdat, moving_line_filepos, */ \ - 0, NULL, 0, \ + /* entsize, comdat, kept_section, moving_line_filepos, */ \ + 0, NULL, NULL, 0, \ \ /* target_index, used_by_bfd, constructor_chain, owner, */ \ 0, NULL, NULL, NULL, \ --- binutils/ld/ldlang.c.linkonce 2003-05-13 08:45:34.000000000 -0700 +++ binutils/ld/ldlang.c 2003-06-13 08:52:42.000000000 -0700 @@ -1089,8 +1089,11 @@ section_already_linked (abfd, sec, data) /* Set the output_section field so that lang_add_section does not create a lang_input_section structure for this - section. */ + section. Since there might be a symbol in the section + being discarded, we must retain a pointer to the section + which we are really going to use. */ sec->output_section = bfd_abs_section_ptr; + sec->kept_section = l->sec; if (flags & SEC_GROUP) bfd_discard_group (abfd, sec);