X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Ficf.cc;h=a60db7abc8d2fc7b7ebde167dcb90dd76d4459d7;hb=aa1f7fb133a5a4f95af8286f58b689d6ae131488;hp=09dcba60f46aa2387cb86790b46e1a17878b4b53;hpb=4e271fffeca9db3e0eea8d57b98aa7130f941225;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/icf.cc b/gold/icf.cc index 09dcba60f4..a60db7abc8 100644 --- a/gold/icf.cc +++ b/gold/icf.cc @@ -1,6 +1,6 @@ // icf.cc -- Identical Code Folding. // -// Copyright 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2009-2020 Free Software Foundation, Inc. // Written by Sriraman Tallam . // This file is part of gold. @@ -130,6 +130,26 @@ // folded causing unpredictable run-time behaviour if the pointers were used // in comparisons. // +// Notes regarding C++ exception handling : +// -------------------------------------- +// +// It is possible for two sections to have identical text, identical +// relocations, but different exception handling metadata (unwind +// information in the .eh_frame section, and/or handler information in +// a .gcc_except_table section). Thus, if a foldable section is +// referenced from a .eh_frame FDE, we must include in its checksum +// the contents of that FDE as well as of the CIE that the FDE refers +// to. The CIE and FDE in turn probably contain relocations to the +// personality routine and LSDA, which are handled like any other +// relocation for ICF purposes. This logic is helped by the fact that +// gcc with -ffunction-sections puts each function's LSDA in its own +// .gcc_except_table. section. Given sections for two +// functions with nontrivial exception handling logic, we will +// determine on the first iteration that their .gcc_except_table +// sections are identical and can be folded, and on the second +// iteration that their .text and .eh_frame contents (including the +// now-merged .gcc_except_table relocations for the LSDA) are +// identical and can be folded. // // // How to run : --icf=[safe|all|none] @@ -148,6 +168,8 @@ #include "elfcpp.h" #include "int_encoding.h" +#include + namespace gold { @@ -213,6 +235,45 @@ preprocess_for_unique_sections(const std::vector& id_section, } } +// For SHF_MERGE sections that use REL relocations, the addend is stored in +// the text section at the relocation offset. Read the addend value given +// the pointer to the addend in the text section and the addend size. +// Update the addend value if a valid addend is found. +// Parameters: +// RELOC_ADDEND_PTR : Pointer to the addend in the text section. +// ADDEND_SIZE : The size of the addend. +// RELOC_ADDEND_VALUE : Pointer to the addend that is updated. + +inline void +get_rel_addend(const unsigned char* reloc_addend_ptr, + const unsigned int addend_size, + uint64_t* reloc_addend_value) +{ + switch (addend_size) + { + case 0: + break; + case 1: + *reloc_addend_value = + read_from_pointer<8>(reloc_addend_ptr); + break; + case 2: + *reloc_addend_value = + read_from_pointer<16>(reloc_addend_ptr); + break; + case 4: + *reloc_addend_value = + read_from_pointer<32>(reloc_addend_ptr); + break; + case 8: + *reloc_addend_value = + read_from_pointer<64>(reloc_addend_ptr); + break; + default: + gold_unreachable(); + } +} + // This returns the buffer containing the section's contents, both // text and relocs. Relocs are differentiated as those pointing to // sections that could be folded and those that cannot. Only relocs @@ -220,29 +281,35 @@ preprocess_for_unique_sections(const std::vector& id_section, // subsequent invocations of this function. // Parameters : // FIRST_ITERATION : true if it is the first invocation. +// FIXED_CACHE : String that stores the portion of the result that +// does not change from iteration to iteration; +// written if first_iteration is true, read if it's false. // SECN : Section for which contents are desired. -// SECTION_NUM : Unique section number of this section. +// SELF_SECN : Relocations that target this section will be +// considered "relocations to self" so that recursive +// functions can be folded. Should normally be the +// same as `secn` except when processing extra identity +// regions. // NUM_TRACKED_RELOCS : Vector reference to store the number of relocs // to ICF sections. // KEPT_SECTION_ID : Vector which maps folded sections to kept sections. -// SECTION_CONTENTS : Store the section's text and relocs to non-ICF -// sections. +// START_OFFSET : Only consider the part of the section at and after +// this offset. +// END_OFFSET : Only consider the part of the section before this +// offset. static std::string get_section_contents(bool first_iteration, + std::string* fixed_cache, const Section_id& secn, - unsigned int section_num, + const Section_id& self_secn, unsigned int* num_tracked_relocs, Symbol_table* symtab, const std::vector& kept_section_id, - std::vector* section_contents) + section_offset_type start_offset = 0, + section_offset_type end_offset = + std::numeric_limits::max()) { - // Lock the object so we can read from it. This is only called - // single-threaded from queue_middle_tasks, so it is OK to lock. - // Unfortunately we have no way to pass in a Task token. - const Task* dummy_task = reinterpret_cast(-1); - Task_lock_obj tl(dummy_task, secn.first); - section_size_type plen; const unsigned char* contents = NULL; if (first_iteration) @@ -253,9 +320,6 @@ get_section_contents(bool first_iteration, std::string buffer; std::string icf_reloc_buffer; - if (num_tracked_relocs) - *num_tracked_relocs = 0; - Icf::Reloc_info_list& reloc_info_list = symtab->icf()->reloc_info_list(); @@ -269,25 +333,59 @@ get_section_contents(bool first_iteration, if (it_reloc_info_list != reloc_info_list.end()) { - Icf::Sections_reachable_info v = + Icf::Sections_reachable_info &v = (it_reloc_info_list->second).section_info; // Stores the information of the symbol pointed to by the reloc. - Icf::Symbol_info s = (it_reloc_info_list->second).symbol_info; + const Icf::Symbol_info &s = (it_reloc_info_list->second).symbol_info; // Stores the addend and the symbol value. - Icf::Addend_info a = (it_reloc_info_list->second).addend_info; + Icf::Addend_info &a = (it_reloc_info_list->second).addend_info; // Stores the offset of the reloc. - Icf::Offset_info o = (it_reloc_info_list->second).offset_info; - Icf::Reloc_addend_size_info reloc_addend_size_info = + const Icf::Offset_info &o = (it_reloc_info_list->second).offset_info; + const Icf::Reloc_addend_size_info &reloc_addend_size_info = (it_reloc_info_list->second).reloc_addend_size_info; Icf::Sections_reachable_info::iterator it_v = v.begin(); - Icf::Symbol_info::iterator it_s = s.begin(); + Icf::Symbol_info::const_iterator it_s = s.begin(); Icf::Addend_info::iterator it_a = a.begin(); - Icf::Offset_info::iterator it_o = o.begin(); - Icf::Reloc_addend_size_info::iterator it_addend_size = + Icf::Offset_info::const_iterator it_o = o.begin(); + Icf::Reloc_addend_size_info::const_iterator it_addend_size = reloc_addend_size_info.begin(); for (; it_v != v.end(); ++it_v, ++it_s, ++it_a, ++it_o, ++it_addend_size) { + Symbol* gsym = *it_s; + bool is_section_symbol = false; + + // Ignore relocations outside the region we were told to look at + if (static_cast(*it_o) < start_offset + || static_cast(*it_o) >= end_offset) + continue; + + // A -1 value in the symbol vector indicates a local section symbol. + if (gsym == reinterpret_cast(-1)) + { + is_section_symbol = true; + gsym = NULL; + } + + if (first_iteration + && it_v->first != NULL) + { + Symbol_location loc; + loc.object = it_v->first; + loc.shndx = it_v->second; + loc.offset = convert_types(it_a->first + + it_a->second); + // Look through function descriptors + parameters->target().function_location(&loc); + if (loc.shndx != it_v->second) + { + it_v->second = loc.shndx; + // Modify symvalue/addend to the code entry. + it_a->first = loc.offset; + it_a->second = 0; + } + } + // ADDEND_STR stores the symbol value and addend and offset, // each at most 16 hex digits long. it_a points to a pair // where first is the symbol value and second is the @@ -296,10 +394,10 @@ get_section_contents(bool first_iteration, // It would be nice if we could use format macros in inttypes.h // here but there are not in ISO/IEC C++ 1998. - snprintf(addend_str, sizeof(addend_str), "%llx %llx %llux", + snprintf(addend_str, sizeof(addend_str), "%llx %llx %llx", static_cast((*it_a).first), static_cast((*it_a).second), - static_cast(*it_o)); + static_cast(*it_o - start_offset)); // If the symbol pointed to by the reloc is not in an ordinary // section or if the symbol type is not FROM_OBJECT, then the @@ -309,8 +407,8 @@ get_section_contents(bool first_iteration, if (first_iteration) { // If the symbol name is available, use it. - if ((*it_s) != NULL) - buffer.append((*it_s)->name()); + if (gsym != NULL) + buffer.append(gsym->name()); // Append the addend. buffer.append(addend_str); buffer.append("@"); @@ -322,8 +420,8 @@ get_section_contents(bool first_iteration, // If this reloc turns back and points to the same section, // like a recursive call, use a special symbol to mark this. - if (reloc_secn.first == secn.first - && reloc_secn.second == secn.second) + if (reloc_secn.first == self_secn.first + && reloc_secn.second == self_secn.second) { if (first_iteration) { @@ -337,10 +435,10 @@ get_section_contents(bool first_iteration, symtab->icf()->section_to_int_map(); Icf::Uniq_secn_id_map::iterator section_id_map_it = section_id_map.find(reloc_secn); - bool is_sym_preemptible = (*it_s != NULL - && !(*it_s)->is_from_dynobj() - && !(*it_s)->is_undefined() - && (*it_s)->is_preemptible()); + bool is_sym_preemptible = (gsym != NULL + && !gsym->is_from_dynobj() + && !gsym->is_undefined() + && gsym->is_preemptible()); if (!is_sym_preemptible && section_id_map_it != section_id_map.end()) { @@ -373,63 +471,55 @@ get_section_contents(bool first_iteration, // This reloc points to a merge section. Hash the // contents of this section. if ((secn_flags & elfcpp::SHF_MERGE) != 0 - && parameters->target().can_icf_inline_merge_sections ()) + && parameters->target().can_icf_inline_merge_sections()) { uint64_t entsize = (it_v->first)->section_entsize(it_v->second); long long offset = it_a->first; - unsigned long long addend = it_a->second; - // Ignoring the addend when it is a negative value. See the - // comments in Merged_symbol_value::Value in object.h. - if (addend < 0xffffff00) - offset = offset + addend; - - // For SHT_REL relocation sections, the addend is stored in the - // text section at the relocation offset. + // Handle SHT_RELA and SHT_REL addends. Only one of these + // addends exists. When pointing to a merge section, the + // addend only matters if it's relative to a section + // symbol. In order to unambiguously identify the target + // of the relocation, the compiler (and assembler) must use + // a local non-section symbol unless Symbol+Addend does in + // fact point directly to the target. (In other words, + // a bias for a pc-relative reference or a non-zero based + // access forces the use of a local symbol, and the addend + // is used only to provide that bias.) uint64_t reloc_addend_value = 0; - const unsigned char* reloc_addend_ptr = - contents + static_cast(*it_o); - switch(*it_addend_size) + if (is_section_symbol) { - case 0: - { - break; - } - case 1: - { - reloc_addend_value = - read_from_pointer<8>(reloc_addend_ptr); - break; - } - case 2: - { - reloc_addend_value = - read_from_pointer<16>(reloc_addend_ptr); - break; - } - case 4: - { - reloc_addend_value = - read_from_pointer<32>(reloc_addend_ptr); - break; - } - case 8: - { - reloc_addend_value = - read_from_pointer<64>(reloc_addend_ptr); - break; - } - default: - gold_unreachable(); + // Get the SHT_RELA addend. For RELA relocations, + // we have the addend from the relocation. + reloc_addend_value = it_a->second; + + // Handle SHT_REL addends. + // For REL relocations, we need to fetch the addend + // from the section contents. + const unsigned char* reloc_addend_ptr = + contents + static_cast(*it_o); + + // Update the addend value with the SHT_REL addend if + // available. + get_rel_addend(reloc_addend_ptr, *it_addend_size, + &reloc_addend_value); + + // Ignore the addend when it is a negative value. + // See the comments in Merged_symbol_value::value + // in object.h. + if (reloc_addend_value < 0xffffff00) + offset = offset + reloc_addend_value; } - offset = offset + reloc_addend_value; section_size_type secn_len; + const unsigned char* str_contents = (it_v->first)->section_contents(it_v->second, &secn_len, false) + offset; + gold_assert (offset < (long long) secn_len); + if ((secn_flags & elfcpp::SHF_STRINGS) != 0) { // String merge section. @@ -470,17 +560,21 @@ get_section_contents(bool first_iteration, } else { - // Use the entsize to determine the length. - buffer.append(reinterpret_cast secn_len) + bufsize = secn_len - offset; + buffer.append(reinterpret_cast(str_contents), - entsize); + bufsize); } buffer.append("@"); } - else if ((*it_s) != NULL) + else if (gsym != NULL) { // If symbol name is available use that. - buffer.append((*it_s)->name()); + buffer.append(gsym->name()); // Append the addend. buffer.append(addend_str); buffer.append("@"); @@ -504,16 +598,48 @@ get_section_contents(bool first_iteration, if (first_iteration) { buffer.append("Contents = "); - buffer.append(reinterpret_cast(contents), plen); - // Store the section contents that dont change to avoid recomputing + + const unsigned char* slice_end = + contents + std::min(plen, end_offset); + + if (contents + start_offset < slice_end) + { + buffer.append(reinterpret_cast(contents + start_offset), + slice_end - (contents + start_offset)); + } + } + + // Add any extra identity regions. + std::pair + extra_range = symtab->icf()->extra_identity_list().equal_range(secn); + for (Icf::Extra_identity_list::const_iterator it_ext = extra_range.first; + it_ext != extra_range.second; ++it_ext) + { + std::string external_fixed; + std::string external_all = + get_section_contents(first_iteration, &external_fixed, + it_ext->second.section, self_secn, + num_tracked_relocs, symtab, + kept_section_id, it_ext->second.offset, + it_ext->second.offset + it_ext->second.length); + buffer.append(external_fixed); + icf_reloc_buffer.append(external_all, external_fixed.length(), + std::string::npos); + } + + if (first_iteration) + { + // Store the section contents that don't change to avoid recomputing // during the next call to this function. - (*section_contents)[section_num] = buffer; + *fixed_cache = buffer; } else { gold_assert(buffer.empty()); + // Reuse the contents computed in the previous iteration. - buffer.append((*section_contents)[section_num]); + buffer.append(*fixed_cache); } buffer.append(icf_reloc_buffer); @@ -550,6 +676,7 @@ match_sections(unsigned int iteration_num, std::vector* num_tracked_relocs, std::vector* kept_section_id, const std::vector& id_section, + const std::vector& section_addraligns, std::vector* is_secn_or_group_unique, std::vector* section_contents) { @@ -576,32 +703,34 @@ match_sections(unsigned int iteration_num, continue; Section_id secn = id_section[i]; + + // Lock the object so we can read from it. This is only called + // single-threaded from queue_middle_tasks, so it is OK to lock. + // Unfortunately we have no way to pass in a Task token. + const Task* dummy_task = reinterpret_cast(-1); + Task_lock_obj tl(dummy_task, secn.first); + std::string this_secn_contents; uint32_t cksum; + std::string* this_secn_cache = &((*section_contents)[i]); if (iteration_num == 1) { unsigned int num_relocs = 0; - this_secn_contents = get_section_contents(true, secn, i, &num_relocs, - symtab, (*kept_section_id), - section_contents); + this_secn_contents = get_section_contents(true, this_secn_cache, + secn, secn, &num_relocs, + symtab, (*kept_section_id)); (*num_tracked_relocs)[i] = num_relocs; } else { if ((*kept_section_id)[i] != i) { - // This section is already folded into something. See - // if it should point to a different kept section. - unsigned int kept_section = (*kept_section_id)[i]; - if (kept_section != (*kept_section_id)[kept_section]) - { - (*kept_section_id)[i] = (*kept_section_id)[kept_section]; - } + // This section is already folded into something. continue; } - this_secn_contents = get_section_contents(false, secn, i, NULL, - symtab, (*kept_section_id), - section_contents); + this_secn_contents = get_section_contents(false, this_secn_cache, + secn, secn, NULL, + symtab, (*kept_section_id)); } const unsigned char* this_secn_contents_array = @@ -631,7 +760,25 @@ match_sections(unsigned int iteration_num, this_secn_contents.c_str(), this_secn_contents.length()) != 0) continue; - (*kept_section_id)[i] = kept_section; + + // Check section alignment here. + // The section with the larger alignment requirement + // should be kept. We assume alignment can only be + // zero or positive integral powers of two. + uint64_t align_i = section_addraligns[i]; + uint64_t align_kept = section_addraligns[kept_section]; + if (align_i <= align_kept) + { + (*kept_section_id)[i] = kept_section; + } + else + { + (*kept_section_id)[kept_section] = i; + it->second = i; + full_section_contents[kept_section].swap( + full_section_contents[i]); + } + converged = false; break; } @@ -648,6 +795,26 @@ match_sections(unsigned int iteration_num, (*is_secn_or_group_unique)[i] = true; } + // If a section was folded into another section that was later folded + // again then the former has to be updated. + for (unsigned int i = 0; i < id_section.size(); i++) + { + // Find the end of the folding chain + unsigned int kept = i; + while ((*kept_section_id)[kept] != kept) + { + kept = (*kept_section_id)[kept]; + } + // Update every element of the chain + unsigned int current = i; + while ((*kept_section_id)[current] != kept) + { + unsigned int next = (*kept_section_id)[current]; + (*kept_section_id)[current] = kept; + current = next; + } + } + return converged; } @@ -669,8 +836,115 @@ is_function_ctor_or_dtor(const std::string& section_name) return false; } +// Iterate through the .eh_frame section that has index +// `ehframe_shndx` in `object`, adding entries to extra_identity_list_ +// that will cause the contents of each FDE and its CIE to be included +// in the logical ICF identity of the function that the FDE refers to. + +bool +Icf::add_ehframe_links(Relobj* object, unsigned int ehframe_shndx, + Reloc_info& relocs) +{ + section_size_type contents_len; + const unsigned char* pcontents = object->section_contents(ehframe_shndx, + &contents_len, + false); + const unsigned char* p = pcontents; + const unsigned char* pend = pcontents + contents_len; + + Sections_reachable_info::iterator it_target = relocs.section_info.begin(); + Sections_reachable_info::iterator it_target_end = relocs.section_info.end(); + Offset_info::iterator it_offset = relocs.offset_info.begin(); + Offset_info::iterator it_offset_end = relocs.offset_info.end(); + + // Maps section offset to the length of the CIE defined at that offset. + typedef Unordered_map Cie_map; + Cie_map cies; + + uint32_t (*read_swap_32)(const unsigned char*); + if (object->is_big_endian()) + read_swap_32 = &elfcpp::Swap<32, true>::readval; + else + read_swap_32 = &elfcpp::Swap<32, false>::readval; + + // TODO: The logic for parsing the CIE/FDE framing is copied from + // Eh_frame::do_add_ehframe_input_section() and might want to be + // factored into a shared helper function. + while (p < pend) + { + if (pend - p < 4) + return false; + + unsigned int len = read_swap_32(p); + p += 4; + if (len == 0) + { + // We should only find a zero-length entry at the end of the + // section. + if (p < pend) + return false; + break; + } + // We don't support a 64-bit .eh_frame. + if (len == 0xffffffff) + return false; + if (static_cast(pend - p) < len) + return false; + + const unsigned char* const pentend = p + len; + + if (pend - p < 4) + return false; + + unsigned int id = read_swap_32(p); + p += 4; + + if (id == 0) + { + // CIE. + cies.insert(std::make_pair(p - pcontents, len - 4)); + } + else + { + // FDE. + Cie_map::const_iterator it; + it = cies.find((p - pcontents) - (id - 4)); + if (it == cies.end()) + return false; + + // Figure out which section this FDE refers into. The word at `p` + // is an address, and we expect to see a relocation there. If not, + // this FDE isn't ICF-relevant. + while (it_offset != it_offset_end + && it_target != it_target_end + && static_cast(*it_offset) < (p - pcontents)) + { + ++it_offset; + ++it_target; + } + if (it_offset != it_offset_end + && it_target != it_target_end + && static_cast(*it_offset) == (p - pcontents)) + { + // Found a reloc. Add this FDE and its CIE as extra identity + // info for the section it refers to. + Extra_identity_info rec_fde = {Section_id(object, ehframe_shndx), + p - pcontents, len - 4}; + Extra_identity_info rec_cie = {Section_id(object, ehframe_shndx), + it->first, it->second}; + extra_identity_list_.insert(std::make_pair(*it_target, rec_fde)); + extra_identity_list_.insert(std::make_pair(*it_target, rec_cie)); + } + } + + p = pentend; + } + + return true; +} + // This is the main ICF function called in gold.cc. This does the -// initialization and calls match_sections repeatedly (twice by default) +// initialization and calls match_sections repeatedly (thrice by default) // which computes the crc checksums and detects identical functions. void @@ -679,6 +953,7 @@ Icf::find_identical_sections(const Input_objects* input_objects, { unsigned int section_num = 0; std::vector num_tracked_relocs; + std::vector section_addraligns; std::vector is_secn_or_group_unique; std::vector section_contents; const Target& target = parameters->target(); @@ -694,12 +969,18 @@ Icf::find_identical_sections(const Input_objects* input_objects, // Unfortunately we have no way to pass in a Task token. const Task* dummy_task = reinterpret_cast(-1); Task_lock_obj tl(dummy_task, *p); + std::vector eh_frame_ind; - for (unsigned int i = 0;i < (*p)->shnum(); ++i) + for (unsigned int i = 0; i < (*p)->shnum(); ++i) { const std::string section_name = (*p)->section_name(i); if (!is_section_foldable_candidate(section_name)) - continue; + { + if (is_prefix_of(".eh_frame", section_name.c_str())) + eh_frame_ind.push_back(i); + continue; + } + if (!(*p)->is_section_included(i)) continue; if (parameters->options().gc_sections() @@ -719,18 +1000,44 @@ Icf::find_identical_sections(const Input_objects* input_objects, this->section_id_[Section_id(*p, i)] = section_num; this->kept_section_id_.push_back(section_num); num_tracked_relocs.push_back(0); + section_addraligns.push_back((*p)->section_addralign(i)); is_secn_or_group_unique.push_back(false); section_contents.push_back(""); section_num++; } + + for (std::vector::iterator it_eh_ind = eh_frame_ind.begin(); + it_eh_ind != eh_frame_ind.end(); ++it_eh_ind) + { + // gc_process_relocs() recorded relocations for this + // section even though we can't fold it. We need to + // use those relocations to associate other foldable + // sections with the FDEs and CIEs that are relevant + // to them, so we can avoid merging sections that + // don't have identical exception-handling behavior. + + Section_id sect(*p, *it_eh_ind); + Reloc_info_list::iterator it_rel = this->reloc_info_list().find(sect); + if (it_rel != this->reloc_info_list().end()) + { + if (!add_ehframe_links(*p, *it_eh_ind, it_rel->second)) + { + gold_warning(_("could not parse eh_frame section %s(%s); ICF " + "might not preserve exception handling " + "behavior"), + (*p)->name().c_str(), + (*p)->section_name(*it_eh_ind).c_str()); + } + } + } } unsigned int num_iterations = 0; - // Default number of iterations to run ICF is 2. + // Default number of iterations to run ICF is 3. unsigned int max_iterations = (parameters->options().icf_iterations() > 0) ? parameters->options().icf_iterations() - : 2; + : 3; bool converged = false; @@ -739,8 +1046,8 @@ Icf::find_identical_sections(const Input_objects* input_objects, num_iterations++; converged = match_sections(num_iterations, symtab, &num_tracked_relocs, &this->kept_section_id_, - this->id_section_, &is_secn_or_group_unique, - §ion_contents); + this->id_section_, section_addraligns, + &is_secn_or_group_unique, §ion_contents); } if (parameters->options().print_icf_sections()) @@ -768,7 +1075,7 @@ Icf::find_identical_sections(const Input_objects* input_objects, else if (sym->source() == Symbol::FROM_OBJECT && !sym->object()->is_dynamic()) { - Object* obj = sym->object(); + Relobj* obj = static_cast(sym->object()); bool is_ordinary; unsigned int shndx = sym->shndx(&is_ordinary); if (is_ordinary) @@ -785,7 +1092,7 @@ Icf::find_identical_sections(const Input_objects* input_objects, // Unfolds the section denoted by OBJ and SHNDX if folded. void -Icf::unfold_section(Object* obj, unsigned int shndx) +Icf::unfold_section(Relobj* obj, unsigned int shndx) { Section_id secn(obj, shndx); Uniq_secn_id_map::iterator it = this->section_id_.find(secn); @@ -802,7 +1109,7 @@ Icf::unfold_section(Object* obj, unsigned int shndx) // is different from this section. bool -Icf::is_section_folded(Object* obj, unsigned int shndx) +Icf::is_section_folded(Relobj* obj, unsigned int shndx) { Section_id secn(obj, shndx); Uniq_secn_id_map::iterator it = this->section_id_.find(secn); @@ -816,7 +1123,7 @@ Icf::is_section_folded(Object* obj, unsigned int shndx) // This function returns the folded section for the given section. Section_id -Icf::get_folded_section(Object* dup_obj, unsigned int dup_shndx) +Icf::get_folded_section(Relobj* dup_obj, unsigned int dup_shndx) { Section_id dup_secn(dup_obj, dup_shndx); Uniq_secn_id_map::iterator it = this->section_id_.find(dup_secn);