+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>
* dirsearch.cc (Dirsearch::find): Replace n1 and n2 parameters
input_file.get_first_dyn_reloc());
printf(" Dynamic reloc count: %d\n",
input_file.get_dyn_reloc_count());
+ printf(" COMDAT group count: %d\n",
+ input_file.get_comdat_group_count());
break;
case INCREMENTAL_INPUT_ARCHIVE:
printf("Archive\n");
static_cast<long long>(info.sh_size),
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.
}
}
-// Record the input object file OBJ. If ARCH is not NULL, attach
-// the object file to the archive. This is called by the
-// Add_symbols task after finding out the type of the file.
+// Record an input section SHNDX from object file OBJ.
void
Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
Stringpool::Key key = 0;
if (name != NULL)
- this->strtab_->add(name, true, &key);
+ this->strtab_->add(name, true, &key);
gold_assert(obj == this->current_object_);
gold_assert(this->current_object_entry_ != NULL);
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
// called by read_script after parsing the script and reading the list
// of inputs added by this script.
gold_assert(entry != NULL);
(*p)->set_info_offset(info_offset);
// Input section count, global symbol count, local symbol offset,
- // local symbol count, first dynamic reloc, dynamic reloc count.
- info_offset += 24;
+ // local symbol count, first dynamic reloc, dynamic reloc count,
+ // comdat group count.
+ info_offset += 28;
// Each input section.
info_offset += (entry->get_input_section_count()
* (8 + 2 * sizeof_addr));
// Each global symbol.
const Object::Symbols* syms = entry->object()->get_global_symbols();
info_offset += syms->size() * 20;
+ // Each comdat group.
+ info_offset += entry->get_comdat_group_count() * 4;
}
break;
case INCREMENTAL_INPUT_SHARED_LIBRARY:
unsigned int nlocals = relobj->output_local_symbol_count();
unsigned int first_dynrel = relobj->first_dyn_reloc();
unsigned int ndynrel = relobj->dyn_reloc_count();
+ unsigned int ncomdat = entry->get_comdat_group_count();
Swap32::writeval(pov, nsections);
Swap32::writeval(pov + 4, nsyms);
Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
Swap32::writeval(pov + 12, nlocals);
Swap32::writeval(pov + 16, first_dynrel);
Swap32::writeval(pov + 20, ndynrel);
- pov += 24;
+ Swap32::writeval(pov + 24, ncomdat);
+ pov += 28;
// Build a temporary array to map input section indexes
// from the original object file index to the index in the
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;
}
break;
out_sections[i] = os;
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
Incremental_object_entry(Stringpool::Key filename_key, Object* obj,
unsigned int arg_serial, Timespec mtime)
: Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj),
- is_member_(false), sections_()
+ is_member_(false), sections_(), groups_()
{ this->sections_.reserve(obj->shnum()); }
// Get the object.
get_input_section_size(unsigned int n) const
{ 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:
virtual Incremental_input_type
do_type() const
off_t sh_size_;
};
std::vector<Input_section> sections_;
+
+ // COMDAT groups.
+ std::vector<Stringpool::Key> groups_;
};
// Class for recording shared library input files.
report_input_section(Object* obj, unsigned int shndx, const char* name,
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.
void
report_script(Script_info* script, unsigned int arg_serial,
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
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
+ symndx * 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.
unsigned int
get_object_count() const
{
Input_section_info info;
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 24
+ + this->info_offset_ + 28
+ n * input_section_entry_size);
unsigned int name_offset = Swap32::readval(p);
info.name = this->inputs_->get_string(name_offset);
|| 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_ + 24
+ + this->info_offset_ + 28
+ section_count * input_section_entry_size
+ n * 20);
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
// libraries only. Sets *IS_DEF to TRUE if the symbol is defined in this
// input file.
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);
std::vector<unsigned int> shndxes;