mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-01-31 14:04:12 +00:00
* gold.h (Incremental_argument_list): Remove (invalid) forward
declaration. * incremental.cc (Incremental_inputs::report_achive): New method. (Incremental_inputs::report_object): New method. (Incremental_inputs::report_script): New method. (Incremental_inputs::finalize_inputs): New method. (Incremental_inputs::finalize): Call finalize_inputs(). (Incremental_inputs::sized_create_incremental_inputs_section_data): Create inputs entries. * incremental.h (Incremental_input_type): New enum. (Incremental_inputs::Incremental_input): Initialize new fields. (Incremental_inputs::report_inputs): New method. (Incremental_inputs::report_achive): New method. (Incremental_inputs::report_object): New method. (Incremental_inputs::report_script): New method. (Incremental_inputs::finalize_inputs): New method. (Incremental_inputs::Input_info): New struct. (Incremental_inputs::Input_info_map): New typedef. (Incremental_inputs::lock_): New field. (Incremental_inputs::Inputs_): New field. (Incremental_inputs::Inputs_map): New field. * main.cc (main): Call Incremental_input::report_inputs. * options.h (Input_argument_list): Typedef moved from Input_arguments. (Input_file_group::Files): Remove, use ::Input_argument_list. (Input_file_group::Input_argument_list): Remove, use ::Input_argument_list. * plugin.cc (Plugin_manager::add_input_file): Add error in incremental build. * read_syms.cc (do_read_syms): Call Incremental_input::report_* functions. * script.cc (read_input_script): Call Incremental_input::report_script. * script.h (Script_info): New class.
This commit is contained in:
parent
17a37d488c
commit
072fe7ce7a
@ -1,3 +1,40 @@
|
||||
2009-05-15 Mikolaj Zalewski <mikolajz@google.com>
|
||||
|
||||
* gold.h (Incremental_argument_list): Remove (invalid) forward
|
||||
declaration.
|
||||
* incremental.cc (Incremental_inputs::report_achive): New method.
|
||||
(Incremental_inputs::report_object): New method.
|
||||
(Incremental_inputs::report_script): New method.
|
||||
(Incremental_inputs::finalize_inputs): New method.
|
||||
(Incremental_inputs::finalize): Call finalize_inputs().
|
||||
(Incremental_inputs::sized_create_incremental_inputs_section_data):
|
||||
Create inputs entries.
|
||||
* incremental.h (Incremental_input_type): New enum.
|
||||
(Incremental_inputs::Incremental_input): Initialize new fields.
|
||||
(Incremental_inputs::report_inputs): New method.
|
||||
(Incremental_inputs::report_achive): New method.
|
||||
(Incremental_inputs::report_object): New method.
|
||||
(Incremental_inputs::report_script): New method.
|
||||
(Incremental_inputs::finalize_inputs): New method.
|
||||
(Incremental_inputs::Input_info): New struct.
|
||||
(Incremental_inputs::Input_info_map): New typedef.
|
||||
(Incremental_inputs::lock_): New field.
|
||||
(Incremental_inputs::Inputs_): New field.
|
||||
(Incremental_inputs::Inputs_map): New field.
|
||||
* main.cc (main): Call Incremental_input::report_inputs.
|
||||
* options.h (Input_argument_list): Typedef moved from
|
||||
Input_arguments.
|
||||
(Input_file_group::Files): Remove, use ::Input_argument_list.
|
||||
(Input_file_group::Input_argument_list): Remove, use
|
||||
::Input_argument_list.
|
||||
* plugin.cc (Plugin_manager::add_input_file): Add error in
|
||||
incremental build.
|
||||
* read_syms.cc (do_read_syms): Call Incremental_input::report_*
|
||||
functions.
|
||||
* script.cc (read_input_script): Call
|
||||
Incremental_input::report_script.
|
||||
* script.h (Script_info): New class.
|
||||
|
||||
2009-04-27 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* x86_64.cc (do_adjust_output_section): Set entsize to
|
||||
|
@ -148,7 +148,6 @@ namespace gold
|
||||
|
||||
class General_options;
|
||||
class Command_line;
|
||||
class Input_argument_list;
|
||||
class Dirsearch;
|
||||
class Input_objects;
|
||||
class Mapfile;
|
||||
@ -293,7 +292,7 @@ queue_initial_tasks(const General_options&,
|
||||
|
||||
// Queue up the set of tasks to be done before
|
||||
// the middle set of tasks. Only used when garbage
|
||||
// collection is to be done.
|
||||
// collection is to be done.
|
||||
extern void
|
||||
queue_middle_gc_tasks(const General_options&,
|
||||
const Task*,
|
||||
|
@ -86,7 +86,7 @@ class Incremental_inputs_header_write
|
||||
Incremental_inputs_header_write(unsigned char *p)
|
||||
: p_(reinterpret_cast<internal::Incremental_inputs_header_data*>(p))
|
||||
{ }
|
||||
|
||||
|
||||
static const int data_size = sizeof(internal::Incremental_inputs_header_data);
|
||||
|
||||
void
|
||||
@ -179,12 +179,114 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
|
||||
this->strtab_->add(args.c_str(), true, &this->command_line_key_);
|
||||
}
|
||||
|
||||
// Record that the input argument INPUT is an achive ARCHIVE. This is
|
||||
// called by Read_symbols after finding out the type of the file.
|
||||
|
||||
void
|
||||
Incremental_inputs::report_archive(const Input_argument* input,
|
||||
Archive* archive)
|
||||
{
|
||||
Hold_lock hl(*this->lock_);
|
||||
|
||||
Input_info info;
|
||||
info.type = INCREMENTAL_INPUT_ARCHIVE;
|
||||
info.archive = archive;
|
||||
inputs_map_.insert(std::make_pair(input, info));
|
||||
}
|
||||
|
||||
// Record that the input argument INPUT is an object OBJ. This is
|
||||
// called by Read_symbols after finding out the type of the file.
|
||||
|
||||
void
|
||||
Incremental_inputs::report_object(const Input_argument* input,
|
||||
Object* obj)
|
||||
{
|
||||
Hold_lock hl(*this->lock_);
|
||||
|
||||
Input_info info;
|
||||
info.type = (obj->is_dynamic()
|
||||
? INCREMENTAL_INPUT_SHARED_LIBRARY
|
||||
: INCREMENTAL_INPUT_OBJECT);
|
||||
info.object = obj;
|
||||
inputs_map_.insert(std::make_pair(input, info));
|
||||
}
|
||||
|
||||
// Record that the input argument INPUT is an script SCRIPT. This is
|
||||
// called by read_script after parsing the script and reading the list
|
||||
// of inputs added by this script.
|
||||
|
||||
void
|
||||
Incremental_inputs::report_script(const Input_argument* input,
|
||||
Script_info* script)
|
||||
{
|
||||
Hold_lock hl(*this->lock_);
|
||||
|
||||
Input_info info;
|
||||
info.type = INCREMENTAL_INPUT_SCRIPT;
|
||||
info.script = script;
|
||||
inputs_map_.insert(std::make_pair(input, info));
|
||||
}
|
||||
|
||||
// Compute indexes in the order in which the inputs should appear in
|
||||
// .gnu_incremental_inputs. This needs to be done after all the
|
||||
// scripts are parsed. The function is first called for the command
|
||||
// line inputs arguments and may call itself recursively for e.g. a
|
||||
// list of elements of a group or a list of inputs added by a script.
|
||||
// The [BEGIN; END) interval to analyze and *INDEX is the current
|
||||
// value of the index (that will be updated).
|
||||
|
||||
void
|
||||
Incremental_inputs::finalize_inputs(
|
||||
Input_argument_list::const_iterator begin,
|
||||
Input_argument_list::const_iterator end,
|
||||
unsigned int* index)
|
||||
{
|
||||
for (Input_argument_list::const_iterator p = begin; p != end; ++p)
|
||||
{
|
||||
if (p->is_group())
|
||||
{
|
||||
finalize_inputs(p->group()->begin(), p->group()->end(), index);
|
||||
continue;
|
||||
}
|
||||
|
||||
Inputs_info_map::iterator it = inputs_map_.find(&(*p));
|
||||
// TODO: turn it into an assert when the code will be more stable.
|
||||
if (it == inputs_map_.end())
|
||||
{
|
||||
gold_error("internal error: %s: incremental build info not provided",
|
||||
(p->is_file() ? p->file().name() : "[group]"));
|
||||
continue;
|
||||
}
|
||||
Input_info* info = &it->second;
|
||||
info->index = *index;
|
||||
(*index)++;
|
||||
this->strtab_->add(p->file().name(), false, &info->filename_key);
|
||||
if (info->type == INCREMENTAL_INPUT_SCRIPT)
|
||||
{
|
||||
finalize_inputs(info->script->inputs()->begin(),
|
||||
info->script->inputs()->end(),
|
||||
index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the incremental link information. Called from
|
||||
// Layout::finalize.
|
||||
|
||||
void
|
||||
Incremental_inputs::finalize()
|
||||
{
|
||||
unsigned int index = 0;
|
||||
finalize_inputs(this->inputs_->begin(), this->inputs_->end(), &index);
|
||||
|
||||
// Sanity check.
|
||||
for (Inputs_info_map::const_iterator p = inputs_map_.begin();
|
||||
p != inputs_map_.end();
|
||||
++p)
|
||||
{
|
||||
gold_assert(p->second.filename_key != 0);
|
||||
}
|
||||
|
||||
this->strtab_->set_string_offsets();
|
||||
}
|
||||
|
||||
@ -213,7 +315,7 @@ Incremental_inputs::create_incremental_inputs_section_data()
|
||||
#endif
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sized creation of .gnu_incremental_inputs section.
|
||||
@ -221,22 +323,49 @@ Incremental_inputs::create_incremental_inputs_section_data()
|
||||
template<int size, bool big_endian>
|
||||
Output_section_data*
|
||||
Incremental_inputs::sized_create_inputs_section_data()
|
||||
{
|
||||
unsigned int sz =
|
||||
{
|
||||
const int entry_size =
|
||||
Incremental_inputs_entry_write<size, big_endian>::data_size;
|
||||
const int header_size =
|
||||
Incremental_inputs_header_write<size, big_endian>::data_size;
|
||||
|
||||
unsigned int sz = header_size + entry_size * this->inputs_map_.size();
|
||||
unsigned char* buffer = new unsigned char[sz];
|
||||
unsigned char* inputs_base = buffer + header_size;
|
||||
|
||||
Incremental_inputs_header_write<size, big_endian> header_writer(buffer);
|
||||
|
||||
gold_assert(this->command_line_key_ > 0);
|
||||
int cmd_offset = this->strtab_->get_offset_from_key(this->command_line_key_);
|
||||
|
||||
|
||||
header_writer.put_version(INCREMENTAL_LINK_VERSION);
|
||||
header_writer.put_input_file_count(0); // TODO: store input files data.
|
||||
header_writer.put_input_file_count(this->inputs_map_.size());
|
||||
header_writer.put_command_line_offset(cmd_offset);
|
||||
header_writer.put_reserved(0);
|
||||
|
||||
|
||||
for (Inputs_info_map::const_iterator it = this->inputs_map_.begin();
|
||||
it != this->inputs_map_.end();
|
||||
++it)
|
||||
{
|
||||
gold_assert(it->second.index < this->inputs_map_.size());
|
||||
|
||||
unsigned char* entry_buffer =
|
||||
inputs_base + it->second.index * entry_size;
|
||||
Incremental_inputs_entry_write<size, big_endian> entry(entry_buffer);
|
||||
int filename_offset =
|
||||
this->strtab_->get_offset_from_key(it->second.filename_key);
|
||||
entry.put_filename_offset(filename_offset);
|
||||
// TODO: add per input data and timestamp. Currently we store
|
||||
// an out-of-bounds offset for future version of gold to reject
|
||||
// such an incremental_inputs section.
|
||||
entry.put_data_offset(0xffffffff);
|
||||
entry.put_timestamp_sec(0);
|
||||
entry.put_timestamp_usec(0);
|
||||
entry.put_input_type(it->second.type);
|
||||
entry.put_reserved(0);
|
||||
}
|
||||
|
||||
return new Output_data_const_buffer(buffer, sz, 8,
|
||||
"** incremental link inputs list");
|
||||
"** incremental link inputs list");
|
||||
}
|
||||
|
||||
} // End namespace gold.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#ifndef GOLD_INCREMENTAL_H
|
||||
#define GOLD_INCREMENTAL_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "stringpool.h"
|
||||
@ -37,20 +38,49 @@ class Incremental_inputs_checker;
|
||||
class Object;
|
||||
class Output_section_data;
|
||||
|
||||
// Incremental input type as stored in .gnu_incremental_inputs.
|
||||
|
||||
enum Incremental_input_type
|
||||
{
|
||||
INCREMENTAL_INPUT_INVALID = 0,
|
||||
INCREMENTAL_INPUT_OBJECT = 1,
|
||||
INCREMENTAL_INPUT_ARCHIVE = 2,
|
||||
INCREMENTAL_INPUT_SHARED_LIBRARY = 3,
|
||||
INCREMENTAL_INPUT_SCRIPT = 4
|
||||
};
|
||||
|
||||
// This class contains the information needed during an incremental
|
||||
// build about the inputs necessary to build the .gnu_incremental_inputs.
|
||||
class Incremental_inputs
|
||||
{
|
||||
public:
|
||||
Incremental_inputs()
|
||||
: command_line_key_(0), strtab_(new Stringpool())
|
||||
: lock_(new Lock()), inputs_(NULL), command_line_key_(0),
|
||||
strtab_(new Stringpool())
|
||||
{ }
|
||||
~Incremental_inputs() { delete this->strtab_; }
|
||||
|
||||
// Record the command line.
|
||||
void
|
||||
report_command_line(int argc, const char* const* argv);
|
||||
|
||||
|
||||
// Record the input arguments obtained from parsing the command line.
|
||||
void
|
||||
report_inputs(const Input_arguments& inputs)
|
||||
{ this->inputs_ = &inputs; }
|
||||
|
||||
// Record that the input argument INPUT is an archive ARCHIVE.
|
||||
void
|
||||
report_archive(const Input_argument* input, Archive* archive);
|
||||
|
||||
// Record that the input argument INPUT is to an object OBJ.
|
||||
void
|
||||
report_object(const Input_argument* input, Object* obj);
|
||||
|
||||
// Record that the input argument INPUT is to an script SCRIPT.
|
||||
void
|
||||
report_script(const Input_argument* input, Script_info* script);
|
||||
|
||||
// Prepare for layout. Called from Layout::finalize.
|
||||
void
|
||||
finalize();
|
||||
@ -58,8 +88,8 @@ class Incremental_inputs
|
||||
// Create the content of the .gnu_incremental_inputs section.
|
||||
Output_section_data*
|
||||
create_incremental_inputs_section_data();
|
||||
|
||||
// Return the .gnu_incremental_strtab stringpool.
|
||||
|
||||
// Return the .gnu_incremental_strtab stringpool.
|
||||
Stringpool*
|
||||
get_stringpool()
|
||||
{ return this->strtab_; }
|
||||
@ -68,7 +98,57 @@ class Incremental_inputs
|
||||
// Code for each of the four possible variants of create_inputs_section_data.
|
||||
template<int size, bool big_endian>
|
||||
Output_section_data*
|
||||
sized_create_inputs_section_data();
|
||||
sized_create_inputs_section_data();
|
||||
|
||||
// Compute indexes in the order in which the inputs should appear in
|
||||
// .gnu_incremental_inputs and put file names to the stringtable.
|
||||
// This needs to be done after all the scripts are parsed.
|
||||
|
||||
void
|
||||
finalize_inputs(Input_argument_list::const_iterator begin,
|
||||
Input_argument_list::const_iterator end,
|
||||
unsigned int* index);
|
||||
|
||||
// Additional data about an input needed for an incremental link.
|
||||
// None of these pointers is owned by the structure.
|
||||
struct Input_info
|
||||
{
|
||||
Input_info()
|
||||
: type(INCREMENTAL_INPUT_INVALID), archive(NULL), object(NULL),
|
||||
script(NULL), filename_key(0), index(0)
|
||||
{ }
|
||||
|
||||
// Type of the file pointed by this argument.
|
||||
Incremental_input_type type;
|
||||
|
||||
// Present if type == INCREMENTAL_INPUT_ARCHIVE.
|
||||
Archive* archive;
|
||||
|
||||
// Present if type == INCREMENTAL_INPUT_OBJECT or
|
||||
// INCREMENTAL_INPUT_SHARED_LIBRARY.
|
||||
Object* object;
|
||||
|
||||
// Present if type == INCREMENTAL_INPUT_SCRIPT.
|
||||
Script_info* script;
|
||||
|
||||
// Key of the filename string in the section stringtable.
|
||||
Stringpool::Key filename_key;
|
||||
|
||||
// Position of the entry information in the output section.
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
typedef std::map<const Input_argument*, Input_info> Inputs_info_map;
|
||||
|
||||
// A lock guarding access to inputs_ during the first phase of linking, when
|
||||
// report_ function may be called from multiple threads.
|
||||
Lock* lock_;
|
||||
|
||||
// The list of input arguments obtained from parsing the command line.
|
||||
const Input_arguments* inputs_;
|
||||
|
||||
// A map containing additional information about the input elements.
|
||||
Inputs_info_map inputs_map_;
|
||||
|
||||
// The key of the command line string in the string pool.
|
||||
Stringpool::Key command_line_key_;
|
||||
|
@ -221,7 +221,10 @@ main(int argc, char** argv)
|
||||
&command_line.script_options());
|
||||
|
||||
if (layout.incremental_inputs() != NULL)
|
||||
layout.incremental_inputs()->report_command_line(argc, argv);
|
||||
{
|
||||
layout.incremental_inputs()->report_command_line(argc, argv);
|
||||
layout.incremental_inputs()->report_inputs(command_line.inputs());
|
||||
}
|
||||
|
||||
// Get the search path from the -L options.
|
||||
Dirsearch search_path;
|
||||
|
@ -1275,14 +1275,15 @@ class Input_argument
|
||||
Input_file_group* group_;
|
||||
};
|
||||
|
||||
typedef std::vector<Input_argument> Input_argument_list;
|
||||
|
||||
// A group from the command line. This is a set of arguments within
|
||||
// --start-group ... --end-group.
|
||||
|
||||
class Input_file_group
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Input_argument> Files;
|
||||
typedef Files::const_iterator const_iterator;
|
||||
typedef Input_argument_list::const_iterator const_iterator;
|
||||
|
||||
Input_file_group()
|
||||
: files_()
|
||||
@ -1304,7 +1305,7 @@ class Input_file_group
|
||||
{ return this->files_.end(); }
|
||||
|
||||
private:
|
||||
Files files_;
|
||||
Input_argument_list files_;
|
||||
};
|
||||
|
||||
// A list of files from the command line or a script.
|
||||
@ -1312,7 +1313,6 @@ class Input_file_group
|
||||
class Input_arguments
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Input_argument> Input_argument_list;
|
||||
typedef Input_argument_list::const_iterator const_iterator;
|
||||
|
||||
Input_arguments()
|
||||
|
@ -407,6 +407,9 @@ Plugin_manager::add_input_file(char *pathname)
|
||||
Input_argument* input_argument = new Input_argument(file);
|
||||
Task_token* next_blocker = new Task_token(true);
|
||||
next_blocker->add_blocker();
|
||||
if (this->layout_->incremental_inputs())
|
||||
gold_error(_("Input files added by plug-ins in --incremental mode not "
|
||||
"supported yet.\n"));
|
||||
this->workqueue_->queue_soon(new Read_symbols(this->input_objects_,
|
||||
this->symtab_,
|
||||
this->layout_,
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "script.h"
|
||||
#include "readsyms.h"
|
||||
#include "plugin.h"
|
||||
#include "layout.h"
|
||||
#include "incremental.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
@ -199,7 +201,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
|
||||
{
|
||||
bool is_thin_archive
|
||||
= memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0;
|
||||
if (is_thin_archive
|
||||
if (is_thin_archive
|
||||
|| memcmp(ehdr, Archive::armag, Archive::sarmag) == 0)
|
||||
{
|
||||
// This is an archive.
|
||||
@ -207,7 +209,13 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
|
||||
input_file, is_thin_archive,
|
||||
this->dirpath_, this);
|
||||
arch->setup();
|
||||
|
||||
|
||||
if (this->layout_->incremental_inputs())
|
||||
{
|
||||
const Input_argument* ia = this->input_argument_;
|
||||
this->layout_->incremental_inputs()->report_archive(ia, arch);
|
||||
}
|
||||
|
||||
// Unlock the archive so it can be used in the next task.
|
||||
arch->unlock(this);
|
||||
|
||||
@ -280,6 +288,12 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
|
||||
Read_symbols_data* sd = new Read_symbols_data;
|
||||
obj->read_symbols(sd);
|
||||
|
||||
if (this->layout_->incremental_inputs())
|
||||
{
|
||||
const Input_argument* ia = this->input_argument_;
|
||||
this->layout_->incremental_inputs()->report_object(ia, obj);
|
||||
}
|
||||
|
||||
// Opening the file locked it, so now we need to unlock it. We
|
||||
// need to unlock it before queuing the Add_symbols task,
|
||||
// because the workqueue doesn't know about our lock on the
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "target-select.h"
|
||||
#include "script.h"
|
||||
#include "script-c.h"
|
||||
#include "incremental.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
@ -1414,6 +1415,13 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
|
||||
this_blocker = nb;
|
||||
}
|
||||
|
||||
if (layout->incremental_inputs())
|
||||
{
|
||||
// Like new Read_symbols(...) above, we rely on close.inputs()
|
||||
// getting leaked by closure.
|
||||
Script_info* info = new Script_info(closure.inputs());
|
||||
layout->incremental_inputs()->report_script(input_argument, info);
|
||||
}
|
||||
*used_next_blocker = true;
|
||||
|
||||
return true;
|
||||
|
@ -45,6 +45,7 @@ class Symbol_table;
|
||||
class Layout;
|
||||
class Mapfile;
|
||||
class Input_argument;
|
||||
class Input_arguments;
|
||||
class Input_objects;
|
||||
class Input_group;
|
||||
class Input_file;
|
||||
@ -382,6 +383,26 @@ class Script_options
|
||||
Script_sections script_sections_;
|
||||
};
|
||||
|
||||
// Information about a script input that will persist during the whole linker
|
||||
// run. Needed only during an incremental build to retrieve the input files
|
||||
// added by this script.
|
||||
|
||||
class Script_info
|
||||
{
|
||||
public:
|
||||
Script_info(Input_arguments* inputs)
|
||||
: inputs_(inputs)
|
||||
{ }
|
||||
|
||||
// Returns the input files included because of this script.
|
||||
Input_arguments*
|
||||
inputs()
|
||||
{ return inputs_; }
|
||||
|
||||
private:
|
||||
Input_arguments* inputs_;
|
||||
};
|
||||
|
||||
// FILE was found as an argument on the command line, but was not
|
||||
// recognized as an ELF file. Try to read it as a script. Return
|
||||
// true if the file was handled. This has to handle /usr/lib/libc.so
|
||||
|
Loading…
x
Reference in New Issue
Block a user