From 5146f4485680b0029143c2e17bf5393dd4b89792 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Wed, 8 Jun 2011 04:05:25 +0000 Subject: * 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. --- gold/incremental.cc | 80 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 16 deletions(-) (limited to 'gold/incremental.cc') diff --git a/gold/incremental.cc b/gold/incremental.cc index 98f09d0..c92bb07 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -630,10 +630,14 @@ Sized_incremental_binary::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::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::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::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::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); } } -- cgit v1.1