summaryrefslogtreecommitdiff
path: root/gold/incremental.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2011-06-08 04:05:24 +0000
committerCary Coutant <ccoutant@google.com>2011-06-08 04:05:24 +0000
commit73e402772fa5f72f67e57d115db1932b2efe6c83 (patch)
tree28ab3c7f25067b1dfa3f1f4ed489d6440dfe4f11 /gold/incremental.cc
parentdb5331f21a670cba8c7d51532168deefee333d41 (diff)
downloadbinutils-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.cc80
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);
}
}