X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Ftarget-reloc.h;h=e1c3cc37b69892120bc26935a820919dadc9d922;hb=e94cf1277329c4eaba3b398b446e693550463c77;hp=09f5076d8572d1d8156f77ba0cfac9bc1e3f3bce;hpb=8851eccaec28f25f56fab5ba5d8ae44f71729975;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 09f5076d85..e1c3cc37b6 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -1,6 +1,6 @@ // target-reloc.h -- target specific relocation support -*- C++ -*- -// Copyright 2006, 2007 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -78,10 +78,12 @@ scan_relocs( gold_assert(plocal_syms != NULL); typename elfcpp::Sym lsym(plocal_syms + r_sym * sym_size); - const unsigned int shndx = lsym.get_st_shndx(); - if (shndx < elfcpp::SHN_LORESERVE + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(lsym.get_st_shndx())) + && !object->is_section_included(shndx)) { // RELOC is a relocation against a local symbol in a // section we are discarding. We can ignore this @@ -117,6 +119,31 @@ scan_relocs( } } +// Behavior for relocations to discarded comdat sections. + +enum Comdat_behavior +{ + CB_UNDETERMINED, // Not yet determined -- need to look at section name. + CB_PRETEND, // Attempt to map to the corresponding kept section. + CB_IGNORE, // Ignore the relocation. + CB_WARNING // Print a warning. +}; + +// Decide what the linker should do for relocations that refer to discarded +// comdat sections. This decision is based on the name of the section being +// relocated. + +inline Comdat_behavior +get_comdat_behavior(const char* name) +{ + if (Layout::is_debug_info_section(name)) + return CB_PRETEND; + if (strcmp(name, ".eh_frame") == 0 + || strcmp(name, ".gcc_except_table") == 0) + return CB_IGNORE; + return CB_WARNING; +} + // This function implements the generic part of relocation processing. // The template parameter Relocate must be a class type which provides // a single function, relocate(), which implements the machine @@ -157,6 +184,8 @@ relocate_section( Sized_relobj* object = relinfo->object; unsigned int local_count = object->local_symbol_count(); + Comdat_behavior comdat_behavior = CB_UNDETERMINED; + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) { Reltype reloc(prelocs); @@ -185,6 +214,44 @@ relocate_section( { sym = NULL; psymval = object->local_symbol(r_sym); + + // If the local symbol belongs to a section we are discarding, + // and that section is a debug section, try to find the + // corresponding kept section and map this symbol to its + // counterpart in the kept section. + bool is_ordinary; + unsigned int shndx = psymval->input_shndx(&is_ordinary); + if (is_ordinary + && shndx != elfcpp::SHN_UNDEF + && !object->is_section_included(shndx)) + { + if (comdat_behavior == CB_UNDETERMINED) + { + const char* name = + object->section_name(relinfo->data_shndx).c_str(); + comdat_behavior = get_comdat_behavior(name); + } + if (comdat_behavior == CB_PRETEND) + { + bool found; + typename elfcpp::Elf_types::Elf_Addr value = + object->map_to_kept_section(shndx, &found); + if (found) + symval.set_output_value(value + psymval->input_value()); + else + symval.set_output_value(0); + } + else + { + if (comdat_behavior == CB_WARNING) + gold_warning_at_location(relinfo, i, offset, + _("Relocation refers to discarded " + "comdat section")); + symval.set_output_value(0); + } + symval.set_no_output_symtab_entry(); + psymval = &symval; + } } else { @@ -217,7 +284,8 @@ relocate_section( if (sym != NULL && sym->is_undefined() && sym->binding() != elfcpp::STB_WEAK - && !parameters->options().shared()) + && (!parameters->options().shared() // -shared + || parameters->options().defs())) // -z defs gold_undefined_symbol(sym, relinfo, i, offset); if (sym != NULL && sym->has_warning()) @@ -332,10 +400,12 @@ scan_relocatable_relocs( gold_assert(plocal_syms != NULL); typename elfcpp::Sym lsym(plocal_syms + r_sym * sym_size); - const unsigned int shndx = lsym.get_st_shndx(); - if (shndx < elfcpp::SHN_LORESERVE + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(lsym.get_st_shndx())) + && !object->is_section_included(shndx)) { // RELOC is a relocation against a local symbol // defined in a section we are discarding. Discard @@ -375,7 +445,7 @@ relocate_for_relocatable( off_t offset_in_output_section, const Relocatable_relocs* rr, unsigned char* view, - typename elfcpp::Elf_types::Elf_Addr, + typename elfcpp::Elf_types::Elf_Addr view_address, section_size_type, unsigned char* reloc_view, section_size_type reloc_view_size) @@ -427,7 +497,10 @@ relocate_for_relocatable( // the output section corresponding to input section // in which this symbol is defined. gold_assert(r_sym < local_count); - unsigned int shndx = object->local_symbol_input_shndx(r_sym); + bool is_ordinary; + unsigned int shndx = + object->local_symbol_input_shndx(r_sym, &is_ordinary); + gold_assert(is_ordinary); section_offset_type dummy; Output_section* os = object->output_section(shndx, &dummy); gold_assert(os != NULL); @@ -466,6 +539,12 @@ relocate_for_relocatable( gold_assert(new_offset != -1); } + // In an object file, r_offset is an offset within the section. + // In an executable or dynamic object, generated by + // --emit-relocs, r_offset is an absolute address. + if (!parameters->options().relocatable()) + new_offset += view_address; + reloc_write.put_r_offset(new_offset); reloc_write.put_r_info(elfcpp::elf_r_info(new_symndx, r_type));