// inremental.cc -- incremental linking support for gold
-// Copyright 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Mikolaj Zalewski <mikolajz@google.com>.
// This file is part of gold.
va_end(args);
}
+// Return TRUE if a section of type SH_TYPE can be updated in place
+// during an incremental update. We can update sections of type PROGBITS,
+// NOBITS, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, and NOTE. All others
+// will be regenerated.
+
+bool
+can_incremental_update(unsigned int sh_type)
+{
+ return (sh_type == elfcpp::SHT_PROGBITS
+ || sh_type == elfcpp::SHT_NOBITS
+ || sh_type == elfcpp::SHT_INIT_ARRAY
+ || sh_type == elfcpp::SHT_FINI_ARRAY
+ || sh_type == elfcpp::SHT_PREINIT_ARRAY
+ || sh_type == elfcpp::SHT_NOTE);
+}
+
// Find the .gnu_incremental_inputs section and related sections.
template<int size, bool big_endian>
// Tell the target how big the GOT and PLT sections are.
unsigned int got_count = got_plt_reader.get_got_entry_count();
unsigned int plt_count = got_plt_reader.get_plt_entry_count();
- Output_data_got<size, big_endian>* got =
+ Output_data_got_base* got =
target->init_got_plt_for_update(symtab, layout, got_count, plt_count);
// Read the GOT entries from the base file and build the outgoing GOT.
gold_assert(plt_desc >= first_global && plt_desc < symtab_count);
Symbol* sym = this->global_symbol(plt_desc - first_global);
// Add the PLT entry only if the symbol is still referenced.
- if (sym->in_reg())
+ if (sym != NULL && sym->in_reg())
{
gold_debug(DEBUG_INCREMENTAL,
"PLT entry %d: %s",
i, sym->name());
- target->register_global_plt_entry(i, sym);
+ target->register_global_plt_entry(symtab, layout, i, sym);
}
}
}
Swap32::writeval(pov + 4, shndx);
Swap32::writeval(pov + 8, chain);
Swap32::writeval(pov + 12, nrelocs);
- Swap32::writeval(pov + 16, first_reloc * 3 * sizeof_addr);
+ Swap32::writeval(pov + 16,
+ first_reloc * (8 + 2 * sizeof_addr));
pov += 20;
}
if (sym->symtab_index() == -1U)
continue;
unsigned int flags = 0;
- if (sym->source() == Symbol::FROM_OBJECT
- && sym->object() == obj
- && sym->is_defined())
+ // If the symbol has hidden or internal visibility, we
+ // mark it as defined in the shared object so we don't
+ // try to resolve it during an incremental update.
+ if (sym->visibility() == elfcpp::STV_HIDDEN
+ || sym->visibility() == elfcpp::STV_INTERNAL)
+ flags = INCREMENTAL_SHLIB_SYM_DEF;
+ else if (sym->source() == Symbol::FROM_OBJECT
+ && sym->object() == obj
+ && sym->is_defined())
flags = INCREMENTAL_SHLIB_SYM_DEF;
else if (sym->is_copied_from_dynobj()
&& this->symtab_->get_copy_source(sym) == dynobj)
input_reader_(ibase->inputs_reader().input_file(input_file_index)),
local_symbol_count_(0), output_local_dynsym_count_(0),
local_symbol_index_(0), local_symbol_offset_(0), local_dynsym_offset_(0),
- symbols_(), incr_reloc_offset_(-1U), incr_reloc_count_(0),
- incr_reloc_output_index_(0), incr_relocs_(NULL), local_symbols_()
+ symbols_(), defined_count_(0), incr_reloc_offset_(-1U),
+ incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL),
+ local_symbols_()
{
if (this->input_reader_.is_in_system_directory())
this->set_is_in_system_directory();
this->error(_("COMDAT group has no signature"));
bool keep = layout->find_or_add_kept_section(signature, this, i, true,
true, NULL);
- if (!keep)
+ if (keep)
+ incremental_inputs->report_comdat_group(this, signature);
+ else
this->error(_("COMDAT group %s included twice in incremental link"),
signature);
}
Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym);
+ if (shndx != elfcpp::SHN_UNDEF)
+ ++this->defined_count_;
+
// If this is a linker-defined symbol that hasn't yet been defined,
// define it now.
if (input_shndx == -1U && !res->is_defined())
template<int size, bool big_endian>
void
Sized_relobj_incr<size, big_endian>::do_get_global_symbol_counts(
- const Symbol_table*, size_t*, size_t*) const
-{
- gold_unreachable();
+ const Symbol_table*,
+ size_t* defined,
+ size_t* used) const
+{
+ *defined = this->defined_count_;
+ size_t count = 0;
+ for (typename Symbols::const_iterator p = this->symbols_.begin();
+ p != this->symbols_.end();
+ ++p)
+ if (*p != NULL
+ && (*p)->source() == Symbol::FROM_OBJECT
+ && (*p)->object() == this
+ && (*p)->is_defined())
+ ++count;
+ *used = count;
}
// Read the relocs.
: Dynobj(name, NULL), ibase_(ibase),
input_file_index_(input_file_index),
input_reader_(ibase->inputs_reader().input_file(input_file_index)),
- symbols_()
+ symbols_(), defined_count_(0)
{
if (this->input_reader_.is_in_system_directory())
this->set_is_in_system_directory();
// is meaningless, as long as it's not SHN_UNDEF.
shndx = 1;
v = gsym.get_st_value();
+ ++this->defined_count_;
}
osym.put_st_name(0);
template<int size, bool big_endian>
void
Sized_incr_dynobj<size, big_endian>::do_get_global_symbol_counts(
- const Symbol_table*, size_t*, size_t*) const
-{
- gold_unreachable();
+ const Symbol_table*,
+ size_t* defined,
+ size_t* used) const
+{
+ *defined = this->defined_count_;
+ size_t count = 0;
+ for (typename Symbols::const_iterator p = this->symbols_.begin();
+ p != this->symbols_.end();
+ ++p)
+ if (*p != NULL
+ && (*p)->source() == Symbol::FROM_OBJECT
+ && (*p)->object() == this
+ && (*p)->is_defined()
+ && (*p)->dynsym_index() != -1U)
+ ++count;
+ *used = count;
}
// Allocate an incremental object of the appropriate size and endianness.