* incremental-dump.cc (dump_incremental_inputs): Print COMDAT groups.

* incremental.cc (Incremental_inputs::report_input_section): Fix
	comment, indentation.
	(Incremental_inputs::report_comdat_group): New function.
	(Output_section_incremental_inputs::set_final_data_size): Adjust size
	of data for incremental input file entry.
	(Output_section_incremental_inputs::write_info_blocks): Write COMDAT
	group count, COMDAT group signatures.
	(Sized_incr_relobj::do_layout): Record kept COMDAT group info from
	an unchanged input file.
	* incremental.h (Incremental_object_entry::Incremental_object_entry):
	Initialize new data member.
	(Incremental_object_entry::add_comdat_group): New function.
	(Incremental_object_entry::get_comdat_group_count): New function.
	(Incremental_object_entry::get_comdat_signature_key): New function.
	(Incremental_object_entry::groups_): New data member.
	(Incremental_inputs::report_comdat_group): New function.
	(Incremental_input_entry_reader::get_symbol_offset): Adjust size of
	data for incremental input file entry.
	(Incremental_input_entry_reader::get_comdat_group_count): New function.
	(Incremental_input_entry_reader::get_input_section): Adjust size of
	data for incremental input file entry.
	(Incremental_input_entry_reader::get_global_symbol_reader): Likewise.
	(Incremental_input_entry_reader::get_comdat_group_signature): New
	function.
	* object.cc (Sized_relobj::include_section_group): Report kept
	COMDAT groups for incremental links.
This commit is contained in:
Cary Coutant 2011-05-26 18:44:27 +00:00
parent d8b344530c
commit 89d8a36b24
5 changed files with 144 additions and 11 deletions

View File

@ -1,3 +1,33 @@
2011-05-26 Cary Coutant <ccoutant@google.com>
* incremental-dump.cc (dump_incremental_inputs): Print COMDAT groups.
* incremental.cc (Incremental_inputs::report_input_section): Fix
comment, indentation.
(Incremental_inputs::report_comdat_group): New function.
(Output_section_incremental_inputs::set_final_data_size): Adjust size
of data for incremental input file entry.
(Output_section_incremental_inputs::write_info_blocks): Write COMDAT
group count, COMDAT group signatures.
(Sized_incr_relobj::do_layout): Record kept COMDAT group info from
an unchanged input file.
* incremental.h (Incremental_object_entry::Incremental_object_entry):
Initialize new data member.
(Incremental_object_entry::add_comdat_group): New function.
(Incremental_object_entry::get_comdat_group_count): New function.
(Incremental_object_entry::get_comdat_signature_key): New function.
(Incremental_object_entry::groups_): New data member.
(Incremental_inputs::report_comdat_group): New function.
(Incremental_input_entry_reader::get_symbol_offset): Adjust size of
data for incremental input file entry.
(Incremental_input_entry_reader::get_comdat_group_count): New function.
(Incremental_input_entry_reader::get_input_section): Adjust size of
data for incremental input file entry.
(Incremental_input_entry_reader::get_global_symbol_reader): Likewise.
(Incremental_input_entry_reader::get_comdat_group_signature): New
function.
* object.cc (Sized_relobj::include_section_group): Report kept
COMDAT groups for incremental links.
2011-05-24 David Meyer <pdox@google.com> 2011-05-24 David Meyer <pdox@google.com>
* dirsearch.cc (Dirsearch::find): Replace n1 and n2 parameters * dirsearch.cc (Dirsearch::find): Replace n1 and n2 parameters

View File

@ -153,6 +153,8 @@ dump_incremental_inputs(const char* argv0, const char* filename,
input_file.get_first_dyn_reloc()); input_file.get_first_dyn_reloc());
printf(" Dynamic reloc count: %d\n", printf(" Dynamic reloc count: %d\n",
input_file.get_dyn_reloc_count()); input_file.get_dyn_reloc_count());
printf(" COMDAT group count: %d\n",
input_file.get_comdat_group_count());
break; break;
case INCREMENTAL_INPUT_ARCHIVE: case INCREMENTAL_INPUT_ARCHIVE:
printf("Archive\n"); printf("Archive\n");
@ -212,6 +214,11 @@ dump_incremental_inputs(const char* argv0, const char* filename,
static_cast<long long>(info.sh_size), static_cast<long long>(info.sh_size),
info.name); info.name);
} }
unsigned int ncomdat = input_file.get_comdat_group_count();
for (unsigned int i = 0; i < ncomdat; ++i)
printf(" Comdat group: %s\n",
input_file.get_comdat_group_signature(i));
} }
// Get a view of the .symtab section. // Get a view of the .symtab section.

View File

@ -1028,9 +1028,7 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial,
} }
} }
// Record the input object file OBJ. If ARCH is not NULL, attach // Record an input section SHNDX from object file OBJ.
// the object file to the archive. This is called by the
// Add_symbols task after finding out the type of the file.
void void
Incremental_inputs::report_input_section(Object* obj, unsigned int shndx, Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
@ -1039,13 +1037,27 @@ Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
Stringpool::Key key = 0; Stringpool::Key key = 0;
if (name != NULL) if (name != NULL)
this->strtab_->add(name, true, &key); this->strtab_->add(name, true, &key);
gold_assert(obj == this->current_object_); gold_assert(obj == this->current_object_);
gold_assert(this->current_object_entry_ != NULL); gold_assert(this->current_object_entry_ != NULL);
this->current_object_entry_->add_input_section(shndx, key, sh_size); this->current_object_entry_->add_input_section(shndx, key, sh_size);
} }
// Record a kept COMDAT group belonging to object file OBJ.
void
Incremental_inputs::report_comdat_group(Object* obj, const char* name)
{
Stringpool::Key key = 0;
if (name != NULL)
this->strtab_->add(name, true, &key);
gold_assert(obj == this->current_object_);
gold_assert(this->current_object_entry_ != NULL);
this->current_object_entry_->add_comdat_group(key);
}
// Record that the input argument INPUT is a script SCRIPT. This is // Record that the input argument INPUT is a script SCRIPT. This is
// called by read_script after parsing the script and reading the list // called by read_script after parsing the script and reading the list
// of inputs added by this script. // of inputs added by this script.
@ -1173,14 +1185,17 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
gold_assert(entry != NULL); gold_assert(entry != NULL);
(*p)->set_info_offset(info_offset); (*p)->set_info_offset(info_offset);
// Input section count, global symbol count, local symbol offset, // Input section count, global symbol count, local symbol offset,
// local symbol count, first dynamic reloc, dynamic reloc count. // local symbol count, first dynamic reloc, dynamic reloc count,
info_offset += 24; // comdat group count.
info_offset += 28;
// Each input section. // Each input section.
info_offset += (entry->get_input_section_count() info_offset += (entry->get_input_section_count()
* (8 + 2 * sizeof_addr)); * (8 + 2 * sizeof_addr));
// Each global symbol. // Each global symbol.
const Object::Symbols* syms = entry->object()->get_global_symbols(); const Object::Symbols* syms = entry->object()->get_global_symbols();
info_offset += syms->size() * 20; info_offset += syms->size() * 20;
// Each comdat group.
info_offset += entry->get_comdat_group_count() * 4;
} }
break; break;
case INCREMENTAL_INPUT_SHARED_LIBRARY: case INCREMENTAL_INPUT_SHARED_LIBRARY:
@ -1424,13 +1439,15 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
unsigned int nlocals = relobj->output_local_symbol_count(); unsigned int nlocals = relobj->output_local_symbol_count();
unsigned int first_dynrel = relobj->first_dyn_reloc(); unsigned int first_dynrel = relobj->first_dyn_reloc();
unsigned int ndynrel = relobj->dyn_reloc_count(); unsigned int ndynrel = relobj->dyn_reloc_count();
unsigned int ncomdat = entry->get_comdat_group_count();
Swap32::writeval(pov, nsections); Swap32::writeval(pov, nsections);
Swap32::writeval(pov + 4, nsyms); Swap32::writeval(pov + 4, nsyms);
Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset)); Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
Swap32::writeval(pov + 12, nlocals); Swap32::writeval(pov + 12, nlocals);
Swap32::writeval(pov + 16, first_dynrel); Swap32::writeval(pov + 16, first_dynrel);
Swap32::writeval(pov + 20, ndynrel); Swap32::writeval(pov + 20, ndynrel);
pov += 24; Swap32::writeval(pov + 24, ncomdat);
pov += 28;
// Build a temporary array to map input section indexes // Build a temporary array to map input section indexes
// from the original object file index to the index in the // from the original object file index to the index in the
@ -1507,6 +1524,17 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
pov += 20; pov += 20;
} }
// For each kept COMDAT group, write the group signature.
for (unsigned int i = 0; i < ncomdat; i++)
{
Stringpool::Key key = entry->get_comdat_signature_key(i);
off_t name_offset = 0;
if (key != 0)
name_offset = strtab->get_offset_from_key(key);
Swap32::writeval(pov, name_offset);
pov += 4;
}
delete[] index_map; delete[] index_map;
} }
break; break;
@ -1862,6 +1890,20 @@ Sized_relobj_incr<size, big_endian>::do_layout(
out_sections[i] = os; out_sections[i] = os;
this->section_offsets()[i] = static_cast<Address>(sect.sh_offset); this->section_offsets()[i] = static_cast<Address>(sect.sh_offset);
} }
// Process the COMDAT groups.
unsigned int ncomdat = this->input_reader_.get_comdat_group_count();
for (unsigned int i = 0; i < ncomdat; i++)
{
const char* signature = this->input_reader_.get_comdat_group_signature(i);
if (signature == NULL || signature[0] == '\0')
this->error(_("COMDAT group has no signature"));
bool keep = layout->find_or_add_kept_section(signature, this, i, true,
true, NULL);
if (!keep)
this->error(_("COMDAT group %s included twice in incremental link"),
signature);
}
} }
// Layout sections whose layout was deferred while waiting for // Layout sections whose layout was deferred while waiting for

View File

@ -325,7 +325,7 @@ class Incremental_object_entry : public Incremental_input_entry
Incremental_object_entry(Stringpool::Key filename_key, Object* obj, Incremental_object_entry(Stringpool::Key filename_key, Object* obj,
unsigned int arg_serial, Timespec mtime) unsigned int arg_serial, Timespec mtime)
: Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj), : Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj),
is_member_(false), sections_() is_member_(false), sections_(), groups_()
{ this->sections_.reserve(obj->shnum()); } { this->sections_.reserve(obj->shnum()); }
// Get the object. // Get the object.
@ -368,6 +368,21 @@ class Incremental_object_entry : public Incremental_input_entry
get_input_section_size(unsigned int n) const get_input_section_size(unsigned int n) const
{ return this->sections_[n].sh_size_; } { return this->sections_[n].sh_size_; }
// Add a kept COMDAT group.
void
add_comdat_group(Stringpool::Key signature_key)
{ this->groups_.push_back(signature_key); }
// Return the number of COMDAT groups.
unsigned int
get_comdat_group_count() const
{ return this->groups_.size(); }
// Return the stringpool key for the signature of the Nth comdat group.
Stringpool::Key
get_comdat_signature_key(unsigned int n) const
{ return this->groups_[n]; }
protected: protected:
virtual Incremental_input_type virtual Incremental_input_type
do_type() const do_type() const
@ -400,6 +415,9 @@ class Incremental_object_entry : public Incremental_input_entry
off_t sh_size_; off_t sh_size_;
}; };
std::vector<Input_section> sections_; std::vector<Input_section> sections_;
// COMDAT groups.
std::vector<Stringpool::Key> groups_;
}; };
// Class for recording shared library input files. // Class for recording shared library input files.
@ -546,6 +564,10 @@ class Incremental_inputs
report_input_section(Object* obj, unsigned int shndx, const char* name, report_input_section(Object* obj, unsigned int shndx, const char* name,
off_t sh_size); off_t sh_size);
// Record a kept COMDAT group belonging to object file OBJ.
void
report_comdat_group(Object* obj, const char* name);
// Record the info for input script SCRIPT. // Record the info for input script SCRIPT.
void void
report_script(Script_info* script, unsigned int arg_serial, report_script(Script_info* script, unsigned int arg_serial,
@ -814,7 +836,7 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER); || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count(); unsigned int section_count = this->get_input_section_count();
return (this->info_offset_ + 24 return (this->info_offset_ + 28
+ section_count * input_section_entry_size + section_count * input_section_entry_size
+ symndx * 20); + symndx * 20);
} }
@ -869,6 +891,16 @@ class Incremental_inputs_reader
return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 20); return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 20);
} }
// Return the COMDAT group count -- for objects only.
unsigned int
get_comdat_group_count() const
{
gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 24);
}
// Return the object count -- for scripts only. // Return the object count -- for scripts only.
unsigned int unsigned int
get_object_count() const get_object_count() const
@ -939,7 +971,7 @@ class Incremental_inputs_reader
{ {
Input_section_info info; Input_section_info info;
const unsigned char* p = (this->inputs_->p_ const unsigned char* p = (this->inputs_->p_
+ this->info_offset_ + 24 + this->info_offset_ + 28
+ n * input_section_entry_size); + n * input_section_entry_size);
unsigned int name_offset = Swap32::readval(p); unsigned int name_offset = Swap32::readval(p);
info.name = this->inputs_->get_string(name_offset); info.name = this->inputs_->get_string(name_offset);
@ -957,12 +989,27 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER); || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count(); unsigned int section_count = this->get_input_section_count();
const unsigned char* p = (this->inputs_->p_ const unsigned char* p = (this->inputs_->p_
+ this->info_offset_ + 24 + this->info_offset_ + 28
+ section_count * input_section_entry_size + section_count * input_section_entry_size
+ n * 20); + n * 20);
return Incremental_global_symbol_reader<big_endian>(p); return Incremental_global_symbol_reader<big_endian>(p);
} }
// Return the signature of the Nth comdat group -- for objects only.
const char*
get_comdat_group_signature(unsigned int n) const
{
unsigned int section_count = this->get_input_section_count();
unsigned int symbol_count = this->get_global_symbol_count();
const unsigned char* p = (this->inputs_->p_
+ this->info_offset_ + 28
+ section_count * input_section_entry_size
+ symbol_count * 20
+ n * 4);
unsigned int name_offset = Swap32::readval(p);
return this->inputs_->get_string(name_offset);
}
// Return the output symbol index for the Nth global symbol -- for shared // Return the output symbol index for the Nth global symbol -- for shared
// libraries only. Sets *IS_DEF to TRUE if the symbol is defined in this // libraries only. Sets *IS_DEF to TRUE if the symbol is defined in this
// input file. // input file.

View File

@ -825,6 +825,13 @@ Sized_relobj_file<size, big_endian>::include_section_group(
is_comdat = true; is_comdat = true;
} }
if (is_comdat && include_group)
{
Incremental_inputs* incremental_inputs = layout->incremental_inputs();
if (incremental_inputs != NULL)
incremental_inputs->report_comdat_group(this, signature.c_str());
}
size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word); size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
std::vector<unsigned int> shndxes; std::vector<unsigned int> shndxes;