diff options
author | Cary Coutant <ccoutant@google.com> | 2011-06-08 04:05:24 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2011-06-08 04:05:24 +0000 |
commit | 73e402772fa5f72f67e57d115db1932b2efe6c83 (patch) | |
tree | 28ab3c7f25067b1dfa3f1f4ed489d6440dfe4f11 /gold/incremental.cc | |
parent | db5331f21a670cba8c7d51532168deefee333d41 (diff) | |
download | binutils-redhat-73e402772fa5f72f67e57d115db1932b2efe6c83.tar.gz |
* common.cc (Symbol_table::do_allocate_commons_list): For incremental
update, allocate common from bss section's free list.
* incremental-dump.cc (dump_incremental_inputs): Print flag for
linker-defined symbols.
* incremental.cc (Sized_incremental_binary::do_process_got_plt):
Skip GOT and PLT entries that are no longer referenced.
(Output_section_incremental_inputs::write_info_blocks): Mark
linker-defined symbols.
(Sized_incr_relobj::do_add_symbols): Process linker-defined symbols.
* output.cc (Output_section::allocate): New function.
* output.h (Output_section::allocate): New function.
* resolve.cc (Symbol_table::report_resolve_problem): Add case for
linker-defined symbols.
(Symbol::override_base_with_special): Copy is_predefined_ flag.
* symtab.cc (Symbol::init_fields): Initialize is_predefined_ flag.
(Symbol::init_base_output_data): Likewise.
(Symbol::init_base_output_segment): Likewise.
(Symbol::init_base_constant): Likewise.
(Sized_symbol::init_output_data): Likewise.
(Sized_symbol::init_output_segment): Likewise.
(Sized_symbol::init_constant): Likewise.
(Symbol_table::do_define_in_output_data): Likewise.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_as_constant): Likewise.
* symtab.h (Symbol::is_predefined): New function.
(Symbol::init_base_output_data): Add is_predefined parameter.
(Symbol::init_base_output_segment): Likewise.
(Symbol::init_base_constant): Likewise.
(Symbol::is_predefined_): New data member.
(Sized_symbol::init_output_data): Add is_predefined parameter.
(Sized_symbol::init_output_segment): Likewise.
(Sized_symbol::init_constant): Likewise.
(enum Symbol_table::Defined): Add INCREMENTAL_BASE.
Diffstat (limited to 'gold/incremental.cc')
-rw-r--r-- | gold/incremental.cc | 80 |
1 files changed, 64 insertions, 16 deletions
diff --git a/gold/incremental.cc b/gold/incremental.cc index 98f09d0737..c92bb07aa5 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -630,10 +630,14 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt( // FIXME: This should really be a fatal error (corrupt input). gold_assert(symndx >= first_global && symndx < symtab_count); Symbol* sym = this->global_symbol(symndx - first_global); - gold_debug(DEBUG_INCREMENTAL, - "GOT entry %d, type %02x: %s", - i, got_type, sym->name()); - target->reserve_global_got_entry(i, sym, got_type); + // Add the GOT entry only if the symbol is still referenced. + if (sym != NULL && sym->in_reg()) + { + gold_debug(DEBUG_INCREMENTAL, + "GOT entry %d, type %02x: %s", + i, got_type, sym->name()); + target->reserve_global_got_entry(i, sym, got_type); + } } } @@ -644,10 +648,14 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt( // FIXME: This should really be a fatal error (corrupt input). gold_assert(plt_desc >= first_global && plt_desc < symtab_count); Symbol* sym = this->global_symbol(plt_desc - first_global); - gold_debug(DEBUG_INCREMENTAL, - "PLT entry %d: %s", - i, sym->name()); - target->register_global_plt_entry(i, sym); + // Add the PLT entry only if the symbol is still referenced. + if (sym->in_reg()) + { + gold_debug(DEBUG_INCREMENTAL, + "PLT entry %d: %s", + i, sym->name()); + target->register_global_plt_entry(i, sym); + } } } @@ -1548,14 +1556,24 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks( if (sym->is_forwarder()) sym = this->symtab_->resolve_forwards(sym); unsigned int shndx = 0; - if (sym->source() == Symbol::FROM_OBJECT - && sym->object() == obj - && sym->is_defined()) + if (sym->source() != Symbol::FROM_OBJECT) + { + // The symbol was defined by the linker (e.g., common). + // We mark these symbols with a special SHNDX of -1, + // but exclude linker-predefined symbols and symbols + // copied from shared objects. + if (!sym->is_predefined() + && !sym->is_copied_from_dynobj()) + shndx = -1U; + } + else if (sym->object() == obj && sym->is_defined()) { bool is_ordinary; unsigned int orig_shndx = sym->shndx(&is_ordinary); if (is_ordinary) shndx = index_map[orig_shndx]; + else + shndx = 1; } unsigned int symtab_index = sym->symtab_index(); unsigned int chain = 0; @@ -2026,7 +2044,7 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols( st_bind = elfcpp::STB_GLOBAL; unsigned int input_shndx = info.shndx(); - if (input_shndx == 0) + if (input_shndx == 0 || input_shndx == -1U) { shndx = elfcpp::SHN_UNDEF; v = 0; @@ -2053,10 +2071,40 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols( osym.put_st_other(gsym.get_st_other()); osym.put_st_shndx(shndx); - this->symbols_[i] = - symtab->add_from_incrobj(this, name, NULL, &sym); - this->ibase_->add_global_symbol(output_symndx - first_global, - this->symbols_[i]); + Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym); + + // If this is a linker-defined symbol that hasn't yet been defined, + // define it now. + if (input_shndx == -1U && !res->is_defined()) + { + shndx = gsym.get_st_shndx(); + v = gsym.get_st_value(); + Elf_size_type symsize = gsym.get_st_size(); + if (shndx == elfcpp::SHN_ABS) + { + symtab->define_as_constant(name, NULL, + Symbol_table::INCREMENTAL_BASE, + v, symsize, st_type, st_bind, + gsym.get_st_visibility(), 0, + false, false); + } + else + { + Output_section* os = this->ibase_->output_section(shndx); + gold_assert(os != NULL && os->has_fixed_layout()); + v -= os->address(); + if (symsize > 0) + os->reserve(v, symsize); + symtab->define_in_output_data(name, NULL, + Symbol_table::INCREMENTAL_BASE, + os, v, symsize, st_type, st_bind, + gsym.get_st_visibility(), 0, + false, false); + } + } + + this->symbols_[i] = res; + this->ibase_->add_global_symbol(output_symndx - first_global, res); } } |