aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog40
-rw-r--r--gold/incremental-dump.cc15
-rw-r--r--gold/incremental.cc147
-rw-r--r--gold/incremental.h81
-rw-r--r--gold/object.h28
5 files changed, 288 insertions, 23 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index d9da5f8..94c19bc 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,43 @@
+2011-04-25 Cary Coutant <ccoutant@google.com>
+
+ * incremental-dump.cc (dump_incremental_inputs): Print local
+ symbol info for each input file.
+ * incremental.cc
+ (Output_section_incremental_inputs::set_final_data_size): Add local
+ symbol info to input file entries in incremental info.
+ (Output_section_incremental_inputs::write_info_blocks): Likewise.
+ (Sized_incr_relobj::Sized_incr_relobj): Initialize new data members.
+ (Sized_incr_relobj::do_add_symbols): Cosmetic change.
+ (Sized_incr_relobj::do_count_local_symbols): Replace stub with
+ implementation.
+ (Sized_incr_relobj::do_finalize_local_symbols): Likewise.
+ (Sized_incr_relobj::do_relocate): Write the local symbols.
+ (Sized_incr_dynobj::do_add_symbols): Cosmetic change.
+ * incremental.h (Incremental_inputs_reader::get_symbol_offset):
+ Adjust size of input file header.
+ (Incremental_inputs_reader::get_local_symbol_offset): New function.
+ (Incremental_inputs_reader::get_local_symbol_count): New function.
+ (Incremental_inputs_reader::get_input_section): Adjust size of input
+ file header.
+ (Incremental_inputs_reader::get_global_symbol_reader): Likewise.
+ (Sized_incr_relobj::This): New typedef.
+ (Sized_incr_relobj::sym_size): New const data member.
+ (Sized_incr_relobj::Local_symbol): New struct.
+ (Sized_incr_relobj::do_output_local_symbol_count): New function.
+ (Sized_incr_relobj::do_local_symbol_offset): New function.
+ (Sized_incr_relobj::local_symbol_count_): New data member.
+ (Sized_incr_relobj::output_local_dynsym_count_): New data member.
+ (Sized_incr_relobj::local_symbol_index_): New data member.
+ (Sized_incr_relobj::local_symbol_offset_): New data member.
+ (Sized_incr_relobj::local_dynsym_offset_): New data member.
+ (Sized_incr_relobj::local_symbols_): New data member.
+ * object.h (Relobj::output_local_symbol_count): New function.
+ (Relobj::local_symbol_offset): New function.
+ (Relobj::do_output_local_symbol_count): New function.
+ (Relobj::do_local_symbol_offset): New function.
+ (Sized_relobj::do_output_local_symbol_count): New function.
+ (Sized_relobj::do_local_symbol_offset): New function.
+
2011-04-22 Vladimir Simonov <sv@sw.ru>
* descriptors.cc (set_close_on_exec): New function.
diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc
index 3a77ee8..5ac6e6c 100644
--- a/gold/incremental-dump.cc
+++ b/gold/incremental-dump.cc
@@ -138,18 +138,17 @@ dump_incremental_inputs(const char* argv0, const char* filename,
switch (input_type)
{
case INCREMENTAL_INPUT_OBJECT:
- printf("Object\n");
- printf(" Input section count: %d\n",
- input_file.get_input_section_count());
- printf(" Symbol count: %d\n",
- input_file.get_global_symbol_count());
- break;
case INCREMENTAL_INPUT_ARCHIVE_MEMBER:
- printf("Archive member\n");
+ printf("%s\n", (input_type == INCREMENTAL_INPUT_OBJECT
+ ? "Object" : "Archive member"));
printf(" Input section count: %d\n",
input_file.get_input_section_count());
- printf(" Symbol count: %d\n",
+ printf(" Global symbol count: %d\n",
input_file.get_global_symbol_count());
+ printf(" Local symbol offset: %d\n",
+ input_file.get_local_symbol_offset());
+ printf(" Local symbol count: %d\n",
+ input_file.get_local_symbol_count());
break;
case INCREMENTAL_INPUT_ARCHIVE:
printf("Archive\n");
diff --git a/gold/incremental.cc b/gold/incremental.cc
index 3de22f1..1250d70 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -1055,8 +1055,9 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
Incremental_object_entry* entry = (*p)->object_entry();
gold_assert(entry != NULL);
(*p)->set_info_offset(info_offset);
- // Input section count + global symbol count.
- info_offset += 8;
+ // Input section count, global symbol count, local symbol offset,
+ // local symbol count.
+ info_offset += 16;
// Each input section.
info_offset += (entry->get_input_section_count()
* (8 + 2 * sizeof_addr));
@@ -1295,13 +1296,18 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
Incremental_object_entry* entry = (*p)->object_entry();
gold_assert(entry != NULL);
const Object* obj = entry->object();
+ const Relobj* relobj = static_cast<const Relobj*>(obj);
const Object::Symbols* syms = obj->get_global_symbols();
// Write the input section count and global symbol count.
unsigned int nsections = entry->get_input_section_count();
unsigned int nsyms = syms->size();
+ off_t locals_offset = relobj->local_symbol_offset();
+ unsigned int nlocals = relobj->output_local_symbol_count();
Swap32::writeval(pov, nsections);
Swap32::writeval(pov + 4, nsyms);
- pov += 8;
+ Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
+ Swap32::writeval(pov + 12, nlocals);
+ pov += 16;
// Build a temporary array to map input section indexes
// from the original object file index to the index in the
@@ -1671,8 +1677,11 @@ Sized_incr_relobj<size, big_endian>::Sized_incr_relobj(
: Sized_relobj_base<size, big_endian>(name, NULL), ibase_(ibase),
input_file_index_(input_file_index),
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_(), section_offsets_(), incr_reloc_offset_(-1U),
- incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL)
+ 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();
@@ -1756,7 +1765,7 @@ Sized_incr_relobj<size, big_endian>::do_add_symbols(
unsigned int isym_count = isymtab.symbol_count();
unsigned int first_global = symtab_count - isym_count;
- unsigned const char* sym_p;
+ const unsigned char* sym_p;
for (unsigned int i = 0; i < nsyms; ++i)
{
Incremental_global_symbol_reader<big_endian> info =
@@ -2027,10 +2036,40 @@ Sized_incr_relobj<size, big_endian>::do_scan_relocs(Symbol_table*,
template<int size, bool big_endian>
void
Sized_incr_relobj<size, big_endian>::do_count_local_symbols(
- Stringpool_template<char>*,
+ Stringpool_template<char>* pool,
Stringpool_template<char>*)
{
- // FIXME: Count local symbols.
+ const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+
+ // Set the count of local symbols based on the incremental info.
+ unsigned int nlocals = this->input_reader_.get_local_symbol_count();
+ this->local_symbol_count_ = nlocals;
+ this->local_symbols_.reserve(nlocals);
+
+ // Get views of the base file's symbol table and string table.
+ Incremental_binary::View symtab_view(NULL);
+ unsigned int symtab_count;
+ elfcpp::Elf_strtab strtab(NULL, 0);
+ this->ibase_->get_symtab_view(&symtab_view, &symtab_count, &strtab);
+
+ // Read the local symbols from the base file's symbol table.
+ off_t off = this->input_reader_.get_local_symbol_offset();
+ const unsigned char* symp = symtab_view.data() + off;
+ for (unsigned int i = 0; i < nlocals; ++i, symp += sym_size)
+ {
+ elfcpp::Sym<size, big_endian> sym(symp);
+ const char* name;
+ if (!strtab.get_c_string(sym.get_st_name(), &name))
+ name = "";
+ gold_debug(DEBUG_INCREMENTAL, "Local symbol %d: %s", i, name);
+ name = pool->add(name, true, NULL);
+ this->local_symbols_.push_back(Local_symbol(name,
+ sym.get_st_value(),
+ sym.get_st_size(),
+ sym.get_st_shndx(),
+ sym.get_st_type(),
+ false));
+ }
}
// Finalize the local symbols.
@@ -2039,11 +2078,12 @@ template<int size, bool big_endian>
unsigned int
Sized_incr_relobj<size, big_endian>::do_finalize_local_symbols(
unsigned int index,
- off_t,
+ off_t off,
Symbol_table*)
{
- // FIXME: Finalize local symbols.
- return index;
+ this->local_symbol_index_ = index;
+ this->local_symbol_offset_ = off;
+ return index + this->local_symbol_count_;
}
// Set the offset where local dynamic symbol information will be stored.
@@ -2109,6 +2149,91 @@ Sized_incr_relobj<size, big_endian>::do_relocate(const Symbol_table*,
}
of->write_output_view(off, len, view);
+
+ // Get views into the output file for the portions of the symbol table
+ // and the dynamic symbol table that we will be writing.
+ off_t symtab_off = layout->symtab_section()->offset();
+ off_t output_size = this->local_symbol_count_ * This::sym_size;
+ unsigned char* oview = NULL;
+ if (output_size > 0)
+ oview = of->get_output_view(symtab_off + this->local_symbol_offset_,
+ output_size);
+
+ off_t dyn_output_size = this->output_local_dynsym_count_ * sym_size;
+ unsigned char* dyn_oview = NULL;
+ if (dyn_output_size > 0)
+ dyn_oview = of->get_output_view(this->local_dynsym_offset_,
+ dyn_output_size);
+
+ // Write the local symbols.
+ unsigned char* ov = oview;
+ unsigned char* dyn_ov = dyn_oview;
+ const Stringpool* sympool = layout->sympool();
+ const Stringpool* dynpool = layout->dynpool();
+ Output_symtab_xindex* symtab_xindex = layout->symtab_xindex();
+ Output_symtab_xindex* dynsym_xindex = layout->dynsym_xindex();
+ for (unsigned int i = 0; i < this->local_symbol_count_; ++i)
+ {
+ Local_symbol& lsym(this->local_symbols_[i]);
+
+ bool is_ordinary;
+ unsigned int st_shndx = this->adjust_sym_shndx(i, lsym.st_shndx,
+ &is_ordinary);
+ if (is_ordinary)
+ {
+ Output_section* os = this->ibase_->output_section(st_shndx);
+ st_shndx = os->out_shndx();
+ if (st_shndx >= elfcpp::SHN_LORESERVE)
+ {
+ symtab_xindex->add(this->local_symbol_index_ + i, st_shndx);
+ if (lsym.needs_dynsym_entry)
+ dynsym_xindex->add(lsym.output_dynsym_index, st_shndx);
+ st_shndx = elfcpp::SHN_XINDEX;
+ }
+ }
+
+ // Write the symbol to the output symbol table.
+ {
+ elfcpp::Sym_write<size, big_endian> osym(ov);
+ osym.put_st_name(sympool->get_offset(lsym.name));
+ osym.put_st_value(lsym.st_value);
+ osym.put_st_size(lsym.st_size);
+ osym.put_st_info(elfcpp::STB_LOCAL,
+ static_cast<elfcpp::STT>(lsym.st_type));
+ osym.put_st_other(0);
+ osym.put_st_shndx(st_shndx);
+ ov += sym_size;
+ }
+
+ // Write the symbol to the output dynamic symbol table.
+ if (lsym.needs_dynsym_entry)
+ {
+ gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+ elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+ osym.put_st_name(dynpool->get_offset(lsym.name));
+ osym.put_st_value(lsym.st_value);
+ osym.put_st_size(lsym.st_size);
+ osym.put_st_info(elfcpp::STB_LOCAL,
+ static_cast<elfcpp::STT>(lsym.st_type));
+ osym.put_st_other(0);
+ osym.put_st_shndx(st_shndx);
+ dyn_ov += sym_size;
+ }
+ }
+
+ if (output_size > 0)
+ {
+ gold_assert(ov - oview == output_size);
+ of->write_output_view(symtab_off + this->local_symbol_offset_,
+ output_size, oview);
+ }
+
+ if (dyn_output_size > 0)
+ {
+ gold_assert(dyn_ov - dyn_oview == dyn_output_size);
+ of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
+ dyn_oview);
+ }
}
// Set the offset of a section.
@@ -2187,7 +2312,7 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
unsigned int isym_count = isymtab.symbol_count();
unsigned int first_global = symtab_count - isym_count;
- unsigned const char* sym_p;
+ const unsigned char* sym_p;
for (unsigned int i = 0; i < nsyms; ++i)
{
bool is_def;
diff --git a/gold/incremental.h b/gold/incremental.h
index dad5d66..41ae188 100644
--- a/gold/incremental.h
+++ b/gold/incremental.h
@@ -725,7 +725,7 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count();
- return (this->info_offset_ + 8
+ return (this->info_offset_ + 16
+ section_count * input_section_entry_size
+ symndx * 20);
}
@@ -746,6 +746,26 @@ class Incremental_inputs_reader
}
}
+ // Return the offset of the first local symbol -- for objects only.
+ unsigned int
+ get_local_symbol_offset() const
+ {
+ gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+ || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+ return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 8);
+ }
+
+ // Return the local symbol count -- for objects only.
+ unsigned int
+ get_local_symbol_count() const
+ {
+ gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+ || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+ return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 12);
+ }
+
// Return the object count -- for scripts only.
unsigned int
get_object_count() const
@@ -816,7 +836,7 @@ class Incremental_inputs_reader
{
Input_section_info info;
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 8
+ + this->info_offset_ + 16
+ n * input_section_entry_size);
unsigned int name_offset = Swap32::readval(p);
info.name = this->inputs_->get_string(name_offset);
@@ -834,7 +854,7 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count();
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 8
+ + this->info_offset_ + 16
+ section_count * input_section_entry_size
+ n * 20);
return Incremental_global_symbol_reader<big_endian>(p);
@@ -1522,12 +1542,42 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
}
private:
+ // For convenience.
+ typedef Sized_incr_relobj<size, big_endian> This;
+ static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+
typedef typename Sized_relobj_base<size, big_endian>::Output_sections
Output_sections;
typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
typedef typename Inputs_reader::Incremental_input_entry_reader
Input_entry_reader;
+ // A local symbol.
+ struct Local_symbol
+ {
+ Local_symbol(const char* name_, Address value_, unsigned int size_,
+ unsigned int shndx_, unsigned int type_,
+ bool needs_dynsym_entry_)
+ : st_value(value_), name(name_), st_size(size_), st_shndx(shndx_),
+ st_type(type_), output_dynsym_index(0),
+ needs_dynsym_entry(needs_dynsym_entry_)
+ { }
+ // The symbol value.
+ Address st_value;
+ // The symbol name. This points to the stringpool entry.
+ const char* name;
+ // The symbol size.
+ unsigned int st_size;
+ // The output section index.
+ unsigned int st_shndx : 28;
+ // The symbol type.
+ unsigned int st_type : 4;
+ // The index of the symbol in the output dynamic symbol table.
+ unsigned int output_dynsym_index : 31;
+ // TRUE if the symbol needs to appear in the dynamic symbol table.
+ unsigned int needs_dynsym_entry : 1;
+ };
+
// Return TRUE if this is an incremental (unchanged) input file.
bool
do_is_incremental() const
@@ -1625,7 +1675,17 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const
- { return 0; }
+ { return this->local_symbol_count_; }
+
+ // Return the number of local symbols in the output symbol table.
+ unsigned int
+ do_output_local_symbol_count() const
+ { return this->local_symbol_count_; }
+
+ // Return the file offset for local symbols in the output symbol table.
+ off_t
+ do_local_symbol_offset() const
+ { return this->local_symbol_offset_; }
// Read the relocs.
void
@@ -1671,6 +1731,17 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
unsigned int input_file_index_;
// The reader for the input file.
Input_entry_reader input_reader_;
+ // The number of local symbols.
+ unsigned int local_symbol_count_;
+ // The number of local symbols which go into the output file's dynamic
+ // symbol table.
+ unsigned int output_local_dynsym_count_;
+ // This starting symbol index in the output symbol table.
+ unsigned int local_symbol_index_;
+ // The file offset for local symbols in the output symbol table.
+ unsigned int local_symbol_offset_;
+ // The file offset for local symbols in the output symbol table.
+ unsigned int local_dynsym_offset_;
// The entries in the symbol table for the external symbols.
Symbols symbols_;
// For each input section, the offset of the input section in its
@@ -1686,6 +1757,8 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
unsigned int incr_reloc_output_index_;
// A copy of the incremental relocations from this object.
unsigned char* incr_relocs_;
+ // The local symbols.
+ std::vector<Local_symbol> local_symbols_;
};
// An incremental Dynobj. This class represents a shared object that has
diff --git a/gold/object.h b/gold/object.h
index c814e76..dc56136 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -987,6 +987,16 @@ class Relobj : public Object
local_symbol_count() const
{ return this->do_local_symbol_count(); }
+ // The number of local symbols in the output symbol table.
+ virtual unsigned int
+ output_local_symbol_count() const
+ { return this->do_output_local_symbol_count(); }
+
+ // The file offset for local symbols in the output symbol table.
+ virtual off_t
+ local_symbol_offset() const
+ { return this->do_local_symbol_offset(); }
+
// Initial local symbol processing: count the number of local symbols
// in the output symbol table and dynamic symbol table; add local symbol
// names to *POOL and *DYNPOOL.
@@ -1115,6 +1125,14 @@ class Relobj : public Object
virtual unsigned int
do_local_symbol_count() const = 0;
+ // Return the number of output local symbols--implemented by child class.
+ virtual unsigned int
+ do_output_local_symbol_count() const = 0;
+
+ // Return the file offset for local symbols--implemented by child class.
+ virtual off_t
+ do_local_symbol_offset() const = 0;
+
// Count local symbols--implemented by child class.
virtual void
do_count_local_symbols(Stringpool_template<char>*,
@@ -1911,6 +1929,16 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
do_local_symbol_count() const
{ return this->local_symbol_count_; }
+ // Return the number of local symbols in the output symbol table.
+ unsigned int
+ do_output_local_symbol_count() const
+ { return this->output_local_symbol_count_; }
+
+ // Return the number of local symbols in the output symbol table.
+ off_t
+ do_local_symbol_offset() const
+ { return this->local_symbol_offset_; }
+
// Lay out the input sections.
void
do_layout(Symbol_table*, Layout*, Read_symbols_data*);