diff options
Diffstat (limited to 'gold/gc.h')
-rw-r--r-- | gold/gc.h | 66 |
1 files changed, 46 insertions, 20 deletions
@@ -235,30 +235,45 @@ gc_process_relocs( Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc); Object* dst_obj; unsigned int dst_indx; - typename elfcpp::Elf_types<size>::Elf_Addr dst_off; + typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; + Address dst_off; if (r_sym < local_count) { gold_assert(plocal_syms != NULL); typename elfcpp::Sym<size, big_endian> lsym(plocal_syms + r_sym * sym_size); - unsigned int shndx = lsym.get_st_shndx(); + dst_indx = lsym.get_st_shndx(); bool is_ordinary; - shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary); dst_obj = src_obj; - dst_indx = shndx; - dst_off = lsym.get_st_value(); + dst_off = lsym.get_st_value() + addend; if (is_icf_tracked) { + Address symvalue = dst_off - addend; if (is_ordinary) - (*secvec).push_back(Section_id(dst_obj, dst_indx)); + { + Symbol_location loc; + loc.object = dst_obj; + loc.shndx = dst_indx; + loc.offset = convert_types<off_t, Address>(dst_off); + // Look through function descriptors. + parameters->target().function_location(&loc); + if (loc.shndx != dst_indx) + { + // Modify symvalue/addend to the code entry. + symvalue = loc.offset; + addend = 0; + } + (*secvec).push_back(Section_id(loc.object, loc.shndx)); + } else (*secvec).push_back(Section_id(NULL, 0)); (*symvec).push_back(NULL); - long long symvalue = static_cast<long long>(lsym.get_st_value()); - (*addendvec).push_back(std::make_pair(symvalue, - static_cast<long long>(addend))); + (*addendvec).push_back(std::make_pair( + static_cast<long long>(symvalue), + static_cast<long long>(addend))); uint64_t reloc_offset = convert_to_section_size_type(reloc.get_r_offset()); (*offsetvec).push_back(reloc_offset); @@ -279,7 +294,7 @@ gc_process_relocs( symtab->icf()->set_section_has_function_pointers( src_obj, lsym.get_st_shndx()); - if (!is_ordinary || shndx == src_indx) + if (!is_ordinary || dst_indx == src_indx) continue; } else @@ -291,14 +306,14 @@ gc_process_relocs( dst_obj = NULL; dst_indx = 0; - dst_off = 0; bool is_ordinary = false; if (gsym->source() == Symbol::FROM_OBJECT) { dst_obj = gsym->object(); dst_indx = gsym->shndx(&is_ordinary); - dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value(); } + dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value(); + dst_off += addend; // When doing safe folding, check to see if this relocation is that // of a function pointer being taken. @@ -326,17 +341,29 @@ gc_process_relocs( } if (is_icf_tracked) { + Address symvalue = dst_off - addend; if (is_ordinary && gsym->source() == Symbol::FROM_OBJECT) - (*secvec).push_back(Section_id(dst_obj, dst_indx)); + { + Symbol_location loc; + loc.object = dst_obj; + loc.shndx = dst_indx; + loc.offset = convert_types<off_t, Address>(dst_off); + // Look through function descriptors. + parameters->target().function_location(&loc); + if (loc.shndx != dst_indx) + { + // Modify symvalue/addend to the code entry. + symvalue = loc.offset; + addend = 0; + } + (*secvec).push_back(Section_id(loc.object, loc.shndx)); + } else (*secvec).push_back(Section_id(NULL, 0)); (*symvec).push_back(gsym); - Sized_symbol<size>* sized_gsym = - static_cast<Sized_symbol<size>* >(gsym); - long long symvalue = - static_cast<long long>(sized_gsym->value()); - (*addendvec).push_back(std::make_pair(symvalue, - static_cast<long long>(addend))); + (*addendvec).push_back(std::make_pair( + static_cast<long long>(symvalue), + static_cast<long long>(addend))); uint64_t reloc_offset = convert_to_section_size_type(reloc.get_r_offset()); (*offsetvec).push_back(reloc_offset); @@ -353,7 +380,6 @@ gc_process_relocs( if (parameters->options().gc_sections()) { symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx); - dst_off += addend; parameters->sized_target<size, big_endian>() ->gc_add_reference(symtab, src_obj, src_indx, dst_obj, dst_indx, dst_off); |