From 43193fe9fc39138c912095ba6f21c4302abafe5e Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Fri, 6 Apr 2018 16:06:16 -0700 Subject: Further improve warnings for relocations referring to discarded sections. Relocations referring to discarded sections are now treated as errors instead of warnings. Also with this patch, we will now print the section group signature and the object file with the prevailing definition of that group along with the name of the symbol that the relocation is referring to. This additional information should be much more useful to anyone trying to track down the source of such errors. To do so, we now map each discarded section to the Kept_section info in the Layout class, and defer the logic that maps a discarded section to its counterpart in the kept group. This gives us the information we need to identify the signature symbol given the discarded section, and the name of the object file that provided the prevailing (i.e., first) definition of that group. gold/ * object.cc (Sized_relobj_file::include_section_group): Store reference to Kept_section info for discarded comdat sections regardless of size. Move size checking to map_to_kept_section. (Sized_relobj_file::include_linkonce_section): Likewise. (Sized_relobj_file::map_to_kept_section): Add section name parameter. Insert size checking logic from above functions. (Sized_relobj_file::find_kept_section_object): New method. (Sized_relobj_file::get_symbol_name): New method. * object.h (Sized_relobj_file::map_to_kept_section): Add section_name parameter. Adjust all callers. (Sized_relobj_file::find_kept_section_object): New method. (Sized_relobj_file::get_symbol_name): New method. (Sized_relobj_file::Kept_comdat_section): Replace object and shndx fields with sh_size, kept_section, symndx, and is_comdat fields. (Sized_relobj_file::set_kept_comdat_section): Replace kept_object and kept_shndx parameters with is_comdat, symndx, sh_size, and kept_section. (Sized_relobj_file::get_kept_comdat_section): Likewise. * target-reloc.h (enum Comdat_behavior): Change CB_WARNING to CB_ERROR. Adjust all references. (issue_undefined_symbol_error): New function template. (relocate_section): Pass section name to map_to_kept_section. Move discarded section code to new function above. * aarch64.cc (Target_aarch64::scan_reloc_section_for_stubs): Move declaration for gsym out one level. Call issue_discarded_error. * arm.cc (Target_arm::scan_reloc_section_for_stubs): Likewise. * powerpc.cc (Relocate_comdat_behavior): Change CB_WARNING to CB_ERROR. --- gold/object.cc | 179 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 60 deletions(-) (limited to 'gold/object.cc') diff --git a/gold/object.cc b/gold/object.cc index 0dbb0cb..2b58f04 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1112,42 +1112,17 @@ Sized_relobj_file::include_section_group( { (*omit)[shndx] = true; - if (is_comdat) - { - Relobj* kept_object = kept_section->object(); - if (kept_section->is_comdat()) - { - // Find the corresponding kept section, and store - // that info in the discarded section table. - unsigned int kept_shndx; - uint64_t kept_size; - if (kept_section->find_comdat_section(mname, &kept_shndx, - &kept_size)) - { - // We don't keep a mapping for this section if - // it has a different size. The mapping is only - // used for relocation processing, and we don't - // want to treat the sections as similar if the - // sizes are different. Checking the section - // size is the approach used by the GNU linker. - if (kept_size == member_shdr.get_sh_size()) - this->set_kept_comdat_section(shndx, kept_object, - kept_shndx); - } - } - else - { - // The existing section is a linkonce section. Add - // a mapping if there is exactly one section in the - // group (which is true when COUNT == 2) and if it - // is the same size. - if (count == 2 - && (kept_section->linkonce_size() - == member_shdr.get_sh_size())) - this->set_kept_comdat_section(shndx, kept_object, - kept_section->shndx()); - } - } + // Store a mapping from this section to the Kept_section + // information for the group. This mapping is used for + // relocation processing and diagnostics. + // If the kept section is a linkonce section, we don't + // bother with it unless the comdat group contains just + // a single section, making it easy to match up. + if (is_comdat + && (kept_section->is_comdat() || count == 2)) + this->set_kept_comdat_section(shndx, true, symndx, + member_shdr.get_sh_size(), + kept_section); } } @@ -1212,10 +1187,8 @@ Sized_relobj_file::include_linkonce_section( // that the kept section is another linkonce section. If it is // the same size, record it as the section which corresponds to // this one. - if (kept2->object() != NULL - && !kept2->is_comdat() - && kept2->linkonce_size() == sh_size) - this->set_kept_comdat_section(index, kept2->object(), kept2->shndx()); + if (kept2->object() != NULL && !kept2->is_comdat()) + this->set_kept_comdat_section(index, false, 0, sh_size, kept2); } else if (!include1) { @@ -1226,13 +1199,8 @@ Sized_relobj_file::include_linkonce_section( // this linkonce section. We'll handle the simple case where // the group has only one member section. Otherwise, it's not // worth the effort. - unsigned int kept_shndx; - uint64_t kept_size; - if (kept1->object() != NULL - && kept1->is_comdat() - && kept1->find_single_comdat_section(&kept_shndx, &kept_size) - && kept_size == sh_size) - this->set_kept_comdat_section(index, kept1->object(), kept_shndx); + if (kept1->object() != NULL && kept1->is_comdat()) + this->set_kept_comdat_section(index, false, 0, sh_size, kept1); } else { @@ -2844,26 +2812,117 @@ template typename Sized_relobj_file::Address Sized_relobj_file::map_to_kept_section( unsigned int shndx, - bool* found) const + std::string& section_name, + bool* pfound) const { - Relobj* kept_object; - unsigned int kept_shndx; - if (this->get_kept_comdat_section(shndx, &kept_object, &kept_shndx)) - { - Sized_relobj_file* kept_relobj = - static_cast*>(kept_object); - Output_section* os = kept_relobj->output_section(kept_shndx); - Address offset = kept_relobj->get_output_section_offset(kept_shndx); - if (os != NULL && offset != invalid_address) + Kept_section* kept_section; + bool is_comdat; + uint64_t sh_size; + unsigned int symndx; + bool found = false; + + if (this->get_kept_comdat_section(shndx, &is_comdat, &symndx, &sh_size, + &kept_section)) + { + Relobj* kept_object = kept_section->object(); + unsigned int kept_shndx = 0; + if (!kept_section->is_comdat()) + { + // The kept section is a linkonce section. + if (sh_size == kept_section->linkonce_size()) + found = true; + } + else { - *found = true; - return os->address() + offset; + if (is_comdat) + { + // Find the corresponding kept section. + // Since we're using this mapping for relocation processing, + // we don't want to match sections unless they have the same + // size. + uint64_t kept_size; + if (kept_section->find_comdat_section(section_name, &kept_shndx, + &kept_size)) + { + if (sh_size == kept_size) + found = true; + } + } + else + { + uint64_t kept_size; + if (kept_section->find_single_comdat_section(&kept_shndx, + &kept_size) + && sh_size == kept_size) + found = true; + } + } + + if (found) + { + Sized_relobj_file* kept_relobj = + static_cast*>(kept_object); + Output_section* os = kept_relobj->output_section(kept_shndx); + Address offset = kept_relobj->get_output_section_offset(kept_shndx); + if (os != NULL && offset != invalid_address) + { + *pfound = true; + return os->address() + offset; + } } } - *found = false; + *pfound = false; return 0; } +// Look for a kept section corresponding to the given discarded section, +// and return its object file. + +template +Relobj* +Sized_relobj_file::find_kept_section_object( + unsigned int shndx, unsigned int *symndx_p) const +{ + Kept_section* kept_section; + bool is_comdat; + uint64_t sh_size; + if (this->get_kept_comdat_section(shndx, &is_comdat, symndx_p, &sh_size, + &kept_section)) + return kept_section->object(); + return NULL; +} + +// Return the name of symbol SYMNDX. + +template +const char* +Sized_relobj_file::get_symbol_name(unsigned int symndx) +{ + if (this->symtab_shndx_ == 0) + return NULL; + + section_size_type symbols_size; + const unsigned char* symbols = this->section_contents(this->symtab_shndx_, + &symbols_size, + false); + + unsigned int symbol_names_shndx = + this->adjust_shndx(this->section_link(this->symtab_shndx_)); + section_size_type names_size; + const unsigned char* symbol_names_u = + this->section_contents(symbol_names_shndx, &names_size, false); + const char* symbol_names = reinterpret_cast(symbol_names_u); + + const unsigned char* p = symbols + symndx * This::sym_size; + + if (p >= symbols + symbols_size) + return NULL; + + elfcpp::Sym sym(p); + + return symbol_names + sym.get_st_name(); +} + // Get symbol counts. template -- cgit v1.1