+2011-03-30 Cary Coutant <ccoutant@google.com>
+
+ * archive.cc (Archive::include_member): Adjust call to report_object.
+ (Add_archive_symbols::run): Add script_info to call to
+ report_archive_begin.
+ (Lib_group::include_member): Adjust call to report_object.
+ (Add_lib_group_symbols::run): Adjust call to report_object.
+ * incremental-dump.cc (dump_incremental_inputs): Remove unnecessary
+ blocks. Add object count for script input files.
+ * incremental.cc (Incremental_inputs::report_archive_begin): Add
+ script_info parameter; change all callers.
+ (Incremental_inputs::report_object): Add script_info parameter;
+ change all callers.
+ (Incremental_inputs::report_script): Store backpointer to
+ incremental info entry.
+ (Output_section_incremental_inputs::set_final_data_size): Record
+ additional information for scripts.
+ (Output_section_incremental_inputs::write_info_blocks): Likewise.
+ * incremental.h (Incremental_script_entry::add_object): New function.
+ (Incremental_script_entry::get_object_count): New function.
+ (Incremental_script_entry::get_object): New function.
+ (Incremental_script_entry::objects_): New data member; adjust
+ constructor.
+ (Incremental_inputs::report_archive_begin): Add script_info parameter.
+ (Incremental_inputs::report_object): Add script_info parameter.
+ (Incremental_inputs_reader::get_object_count): New function.
+ (Incremental_inputs_reader::get_object_offset): New function.
+ * options.cc (Input_arguments::add_file): Return reference to
+ new input argument.
+ * options.h (Input_argument::set_script_info): New function.
+ (Input_argument::script_info): New function.
+ (Input_argument::script_info_): New data member; adjust all
+ constructors.
+ (Input_file_group::add_file): Return reference to new input argument.
+ (Input_file_lib::add_file): Likewise.
+ (Input_arguments::add_file): Likewise.
+ * readsyms.cc (Add_symbols::run): Adjust call to report_object.
+ * script.cc (Parser_closure::Parser_closure): Add script_info
+ parameter; adjust all callers.
+ (Parser_closure::script_info): New function.
+ (Parser_closure::script_info_): New data member.
+ (read_input_script): Report scripts earlier to incremental info.
+ (script_add_file): Set script_info in Input_argument.
+ (script_add_library): Likewise.
+ * script.h (Script_options::Script_info): Rewrite class.
+
2011-03-29 Cary Coutant <ccoutant@google.com>
* archive.cc (Library_base::should_include_member): Move
{
{
if (layout->incremental_inputs() != NULL)
- layout->incremental_inputs()->report_object(obj, this);
+ layout->incremental_inputs()->report_object(obj, this, NULL);
Read_symbols_data sd;
obj->read_symbols(&sd);
obj->layout(symtab, layout, &sd);
// For an incremental link, begin recording layout information.
Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
if (incremental_inputs != NULL)
- incremental_inputs->report_archive_begin(this->archive_);
+ incremental_inputs->report_archive_begin(this->archive_,
+ this->input_argument_->script_info());
bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
this->input_objects_,
if (input_objects->add_object(obj))
{
if (layout->incremental_inputs() != NULL)
- layout->incremental_inputs()->report_object(obj, this);
+ layout->incremental_inputs()->report_object(obj, this, NULL);
obj->layout(symtab, layout, sd);
obj->add_symbols(symtab, sd, layout);
}
// For an incremental link, begin recording layout information.
Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
if (incremental_inputs != NULL)
- incremental_inputs->report_archive_begin(this->lib_);
+ incremental_inputs->report_archive_begin(this->lib_, NULL);
this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
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());
- }
+ 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(" Input section count: %d\n",
- input_file.get_input_section_count());
- printf(" Symbol count: %d\n",
- input_file.get_global_symbol_count());
- }
+ printf("Archive member\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:
- {
- printf("Archive\n");
- printf(" Member count: %d\n", input_file.get_member_count());
- printf(" Unused symbol count: %d\n",
- input_file.get_unused_symbol_count());
- }
+ printf("Archive\n");
+ printf(" Member count: %d\n", input_file.get_member_count());
+ printf(" Unused symbol count: %d\n",
+ input_file.get_unused_symbol_count());
break;
case INCREMENTAL_INPUT_SHARED_LIBRARY:
- {
- printf("Shared library\n");
- printf(" Symbol count: %d\n",
- input_file.get_global_symbol_count());
- }
+ printf("Shared library\n");
+ printf(" Symbol count: %d\n",
+ input_file.get_global_symbol_count());
break;
case INCREMENTAL_INPUT_SCRIPT:
printf("Linker script\n");
+ printf(" Object count: %d\n", input_file.get_object_count());
break;
default:
fprintf(stderr, "%s: invalid file type for object %u: %d\n",
// input objects until report_archive_end is called.
void
-Incremental_inputs::report_archive_begin(Library_base* arch)
+Incremental_inputs::report_archive_begin(Library_base* arch,
+ Script_info* script_info)
{
Stringpool::Key filename_key;
Timespec mtime = arch->get_mtime();
new Incremental_archive_entry(filename_key, mtime);
arch->set_incremental_info(entry);
this->inputs_.push_back(entry);
+
+ if (script_info != NULL)
+ {
+ Incremental_script_entry* script_entry = script_info->incremental_info();
+ gold_assert(script_entry != NULL);
+ script_entry->add_object(entry);
+ }
}
// Visitor class for processing the unused global symbols in a library.
// Add_symbols task after finding out the type of the file.
void
-Incremental_inputs::report_object(Object* obj, Library_base* arch)
+Incremental_inputs::report_object(Object* obj, Library_base* arch,
+ Script_info* script_info)
{
Stringpool::Key filename_key;
Timespec mtime = obj->input_file()->file().get_mtime();
arch_entry->add_object(obj_entry);
}
+ if (script_info != NULL)
+ {
+ Incremental_script_entry* script_entry = script_info->incremental_info();
+ gold_assert(script_entry != NULL);
+ script_entry->add_object(obj_entry);
+ }
+
this->current_object_ = obj;
this->current_object_entry_ = obj_entry;
}
Incremental_script_entry* entry =
new Incremental_script_entry(filename_key, script, mtime);
this->inputs_.push_back(entry);
+ script->set_incremental_info(entry);
}
// Finalize the incremental link information. Called from
switch ((*p)->type())
{
case INCREMENTAL_INPUT_SCRIPT:
- // No supplemental info for a script.
- (*p)->set_info_offset(0);
+ {
+ Incremental_script_entry *entry = (*p)->script_entry();
+ gold_assert(entry != NULL);
+ (*p)->set_info_offset(info_offset);
+ // Object count.
+ info_offset += 4;
+ // Each member.
+ info_offset += (entry->get_object_count() * 4);
+ }
break;
case INCREMENTAL_INPUT_OBJECT:
case INCREMENTAL_INPUT_ARCHIVE_MEMBER:
switch ((*p)->type())
{
case INCREMENTAL_INPUT_SCRIPT:
- // No supplemental info for a script.
+ {
+ gold_assert(static_cast<unsigned int>(pov - oview)
+ == (*p)->get_info_offset());
+ Incremental_script_entry* entry = (*p)->script_entry();
+ gold_assert(entry != NULL);
+
+ // Write the object count.
+ unsigned int nobjects = entry->get_object_count();
+ Swap32::writeval(pov, nobjects);
+ pov += 4;
+
+ // For each object, write the offset to its input file entry.
+ for (unsigned int i = 0; i < nobjects; ++i)
+ {
+ Incremental_input_entry* obj = entry->get_object(i);
+ Swap32::writeval(pov, obj->get_offset());
+ pov += 4;
+ }
+ }
break;
case INCREMENTAL_INPUT_OBJECT:
public:
Incremental_script_entry(Stringpool::Key filename_key, Script_info* script,
Timespec mtime)
- : Incremental_input_entry(filename_key, mtime), script_(script)
+ : Incremental_input_entry(filename_key, mtime), script_(script), objects_()
{ }
+ // Add a member object to the archive.
+ void
+ add_object(Incremental_input_entry* obj_entry)
+ {
+ this->objects_.push_back(obj_entry);
+ }
+
+ // Return the number of objects included by this script.
+ unsigned int
+ get_object_count()
+ { return this->objects_.size(); }
+
+ // Return the Nth object.
+ Incremental_input_entry*
+ get_object(unsigned int n)
+ {
+ gold_assert(n < this->objects_.size());
+ return this->objects_[n];
+ }
+
protected:
virtual Incremental_input_type
do_type() const
private:
// Information about the script file.
Script_info* script_;
+ // Objects that have been included by this script.
+ std::vector<Incremental_input_entry*> objects_;
};
// Class for recording input object files.
// Record the initial info for archive file ARCHIVE.
void
- report_archive_begin(Library_base* arch);
+ report_archive_begin(Library_base* arch, Script_info* script_info);
// Record the final info for archive file ARCHIVE.
void
// Record the info for object file OBJ. If ARCH is not NULL,
// attach the object file to the archive.
void
- report_object(Object* obj, Library_base* arch);
+ report_object(Object* obj, Library_base* arch, Script_info* script_info);
// Record an input section belonging to object file OBJ.
void
}
}
+ // Return the object count -- for scripts only.
+ unsigned int
+ get_object_count() const
+ {
+ gold_assert(this->type_ == INCREMENTAL_INPUT_SCRIPT);
+ return Swap32::readval(this->inputs_->p_ + this->info_offset_);
+ }
+
+ // Return the input file offset for object N -- for scripts only.
+ unsigned int
+ get_object_offset(unsigned int n) const
+ {
+ gold_assert(this->type_ == INCREMENTAL_INPUT_SCRIPT);
+ return Swap32::readval(this->inputs_->p_ + this->info_offset_
+ + 4 + n * 4);
+ }
+
// Return the member count -- for archives only.
unsigned int
get_member_count() const
// Add a file to the list.
-void
+Input_argument&
Input_arguments::add_file(const Input_file_argument& file)
{
if (this->in_group_)
{
gold_assert(!this->input_argument_list_.empty());
gold_assert(this->input_argument_list_.back().is_group());
- this->input_argument_list_.back().group()->add_file(file);
+ return this->input_argument_list_.back().group()->add_file(file);
}
- else if (this->in_lib_)
+ if (this->in_lib_)
{
gold_assert(!this->input_argument_list_.empty());
gold_assert(this->input_argument_list_.back().is_lib());
- this->input_argument_list_.back().lib()->add_file(file);
+ return this->input_argument_list_.back().lib()->add_file(file);
}
- else
- this->input_argument_list_.push_back(Input_argument(file));
+ this->input_argument_list_.push_back(Input_argument(file));
+ return this->input_argument_list_.back();
}
// Start a group.
public:
// Create a file or library argument.
explicit Input_argument(Input_file_argument file)
- : is_file_(true), file_(file), group_(NULL), lib_(NULL)
+ : is_file_(true), file_(file), group_(NULL), lib_(NULL), script_info_(NULL)
{ }
// Create a group argument.
explicit Input_argument(Input_file_group* group)
- : is_file_(false), group_(group), lib_(NULL)
+ : is_file_(false), group_(group), lib_(NULL), script_info_(NULL)
{ }
// Create a lib argument.
explicit Input_argument(Input_file_lib* lib)
- : is_file_(false), group_(NULL), lib_(lib)
+ : is_file_(false), group_(NULL), lib_(lib), script_info_(NULL)
{ }
// Return whether this is a file.
return this->lib_;
}
+ // If a script generated this argument, store a pointer to the script info.
+ // Currently used only for recording incremental link information.
+ void
+ set_script_info(Script_info* info)
+ { this->script_info_ = info; }
+
+ Script_info*
+ script_info() const
+ { return this->script_info_; }
+
private:
bool is_file_;
Input_file_argument file_;
Input_file_group* group_;
Input_file_lib* lib_;
+ Script_info* script_info_;
};
typedef std::vector<Input_argument> Input_argument_list;
{ }
// Add a file to the end of the group.
- void
+ Input_argument&
add_file(const Input_file_argument& arg)
- { this->files_.push_back(Input_argument(arg)); }
+ {
+ this->files_.push_back(Input_argument(arg));
+ return this->files_.back();
+ }
// Iterators to iterate over the group contents.
{ }
// Add a file to the end of the lib.
- void
+ Input_argument&
add_file(const Input_file_argument& arg)
- { this->files_.push_back(Input_argument(arg)); }
+ {
+ this->files_.push_back(Input_argument(arg));
+ return this->files_.back();
+ }
const Position_dependent_options&
options() const
{ }
// Add a file.
- void
+ Input_argument&
add_file(const Input_file_argument& arg);
// Start a group (the --start-group option).
Incremental_inputs* incremental_inputs =
this->layout_->incremental_inputs();
if (incremental_inputs != NULL)
- incremental_inputs->report_object(this->object_, NULL);
+ incremental_inputs->report_object(this->object_, NULL,
+ this->input_argument_->script_info());
this->object_->layout(this->symtab_, this->layout_, this->sd_);
this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
delete this->sd_;
Command_line* command_line,
Script_options* script_options,
Lex* lex,
- bool skip_on_incompatible_target)
+ bool skip_on_incompatible_target,
+ Script_info* script_info)
: filename_(filename), posdep_options_(posdep_options),
parsing_defsym_(parsing_defsym), in_group_(in_group),
is_in_sysroot_(is_in_sysroot),
found_incompatible_target_(false),
command_line_(command_line), script_options_(script_options),
version_script_info_(script_options->version_script_info()),
- lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
+ lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL),
+ script_info_(script_info)
{
// We start out processing C symbols in the default lex mode.
this->language_stack_.push_back(Version_script_info::LANGUAGE_C);
this->language_stack_.pop_back();
}
+ // Return a pointer to the incremental info.
+ Script_info*
+ script_info()
+ { return this->script_info_; }
+
private:
// The name of the file we are reading.
const char* filename_;
std::vector<Version_script_info::Language> language_stack_;
// New input files found to add to the link.
Input_arguments* inputs_;
+ // Pointer to incremental linking info.
+ Script_info* script_info_;
};
// FILE was found as an argument on the command line. Try to read it
Lex lex(input_string.c_str(), input_string.length(), PARSING_LINKER_SCRIPT);
+ Script_info* script_info = NULL;
+ if (layout->incremental_inputs() != NULL)
+ {
+ const std::string& filename = input_file->filename();
+ Timespec mtime = input_file->file().get_mtime();
+ script_info = new Script_info();
+ layout->incremental_inputs()->report_script(filename, script_info, mtime);
+ }
+
Parser_closure closure(input_file->filename().c_str(),
input_argument->file().options(),
false,
NULL,
layout->script_options(),
&lex,
- input_file->will_search_for());
+ input_file->will_search_for(),
+ script_info);
bool old_saw_sections_clause =
layout->script_options()->saw_sections_clause();
this_blocker = nb;
}
- if (layout->incremental_inputs() != NULL)
- {
- // Like new Read_symbols(...) above, we rely on closure.inputs()
- // getting leaked by closure.
- const std::string& filename = input_file->filename();
- Script_info* info = new Script_info(closure.inputs());
- Timespec mtime = input_file->file().get_mtime();
- layout->incremental_inputs()->report_script(filename, info, mtime);
- }
-
*used_next_blocker = true;
return true;
cmdline,
script_options,
&lex,
- false);
+ false,
+ NULL);
if (yyparse(&closure) != 0)
{
input_file.file().unlock(task);
Position_dependent_options posdep_options;
Parser_closure closure("command line", posdep_options, true,
- false, false, NULL, this, &lex, false);
+ false, false, NULL, this, &lex, false, NULL);
if (yyparse(&closure) != 0)
return false;
Input_file_argument::INPUT_FILE_TYPE_FILE,
extra_search_path, false,
closure->position_dependent_options());
- closure->inputs()->add_file(file);
+ Input_argument& arg = closure->inputs()->add_file(file);
+ arg.set_script_info(closure->script_info());
}
// Called by the bison parser to add a library to the link.
Input_file_argument::INPUT_FILE_TYPE_LIBRARY,
"", false,
closure->position_dependent_options());
- closure->inputs()->add_file(file);
+ Input_argument& arg = closure->inputs()->add_file(file);
+ arg.set_script_info(closure->script_info());
}
// Called by the bison parser to start a group. If we are already in
struct Version_tree;
struct Version_expression;
class Lazy_demangler;
+class Incremental_script_entry;
// This class represents an expression in a linker script.
class Script_info
{
public:
- Script_info(Input_arguments* inputs)
- : inputs_(inputs)
+ Script_info()
+ : incremental_script_entry_(NULL)
{ }
- // Returns the input files included because of this script.
- Input_arguments*
- inputs()
- { return this->inputs_; }
+ // Store a pointer to the incremental information for this script.
+ void
+ set_incremental_info(Incremental_script_entry* entry)
+ { this->incremental_script_entry_ = entry; }
+
+ // Return the pointer to the incremental information for this script.
+ Incremental_script_entry*
+ incremental_info() const
+ { return this->incremental_script_entry_; }
private:
- Input_arguments* inputs_;
+ Incremental_script_entry* incremental_script_entry_;
};
// FILE was found as an argument on the command line, but was not