* incremental-dump.cc (dump_incremental_inputs): Change signature

to take a Sized_incremental_binary; change caller.  Use readers
	in Sized_incremental_binary.
	* incremental.cc
	(Sized_incremental_binary::find_incremental_inputs_sections):
	Rename do_find_incremental_inputs_sections to this.
	(Sized_incremental_binary::setup_readers): New function.
	(Sized_incremental_binary::do_check_inputs): Check
	has_incremental_info_ flag; move setup code to setup_readers;
	use input readers.
	(Sized_incremental_binary::do_file_is_unchanged): New function.
	(Sized_incremental_binary::do_get_input_reader): New function.
	* incremental.h (class Incremental_binary): Move to end of file.
	(Incremental_binary::file_is_unchanged): New function.
	(Incremental_binary::do_file_is_unchanged): New function.
	(Incremental_binary::Input_reader): New class.
	(Incremental_binary::get_input_reader): New function.
	(class Sized_incremental_binary): Move to end of file.
	(Sized_incremental_binary::Sized_incremental_binary): Setup the
	input section reader classes.
	(Sized_incremental_binary::has_incremental_info): New function.
	(Sized_incremental_binary::inputs_reader): New function.
	(Sized_incremental_binary::symtab_reader): New function.
	(Sized_incremental_binary::relocs_reader): New function.
	(Sized_incremental_binary::got_plt_reader): New function.
	(Sized_incremental_binary::do_file_is_unchanged): New function.
	(Sized_incremental_binary::Sized_input_reader): New class.
	(Sized_incremental_binary::get_input_reader): New function.
	(Sized_incremental_binary::find_incremental_inputs_sections):
	Rename do_find_incremental_inputs_sections to this.
	(Sized_incremental_binary::setup_readers): New function.
	(Sized_incremental_binary::has_incremental_info_): New data member.
	(Sized_incremental_binary::inputs_reader_): New data member.
	(Sized_incremental_binary::symtab_reader_): New data member.
	(Sized_incremental_binary::relocs_reader_): New data member.
	(Sized_incremental_binary::got_plt_reader_): New data member.
	(Sized_incremental_binary::current_input_file_): New data member.
This commit is contained in:
Cary Coutant 2011-04-05 20:16:17 +00:00
parent a869183fab
commit b961d0d7b6
4 changed files with 422 additions and 227 deletions

View File

@ -1,3 +1,43 @@
2011-04-05 Cary Coutant <ccoutant@google.com>
* incremental-dump.cc (dump_incremental_inputs): Change signature
to take a Sized_incremental_binary; change caller. Use readers
in Sized_incremental_binary.
* incremental.cc
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::do_check_inputs): Check
has_incremental_info_ flag; move setup code to setup_readers;
use input readers.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::do_get_input_reader): New function.
* incremental.h (class Incremental_binary): Move to end of file.
(Incremental_binary::file_is_unchanged): New function.
(Incremental_binary::do_file_is_unchanged): New function.
(Incremental_binary::Input_reader): New class.
(Incremental_binary::get_input_reader): New function.
(class Sized_incremental_binary): Move to end of file.
(Sized_incremental_binary::Sized_incremental_binary): Setup the
input section reader classes.
(Sized_incremental_binary::has_incremental_info): New function.
(Sized_incremental_binary::inputs_reader): New function.
(Sized_incremental_binary::symtab_reader): New function.
(Sized_incremental_binary::relocs_reader): New function.
(Sized_incremental_binary::got_plt_reader): New function.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::Sized_input_reader): New class.
(Sized_incremental_binary::get_input_reader): New function.
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::has_incremental_info_): New data member.
(Sized_incremental_binary::inputs_reader_): New data member.
(Sized_incremental_binary::symtab_reader_): New data member.
(Sized_incremental_binary::relocs_reader_): New data member.
(Sized_incremental_binary::got_plt_reader_): New data member.
(Sized_incremental_binary::current_input_file_): New data member.
2011-04-05 Paul Pluzhnikov <ppluzhnikov@google.com>
PR gold/12640

View File

@ -73,48 +73,24 @@ find_input_containing_global(
template<int size, bool big_endian>
static void
dump_incremental_inputs(const char* argv0, const char* filename,
Incremental_binary* inc)
Sized_incremental_binary<size, big_endian>* inc)
{
bool t;
unsigned int inputs_shndx;
unsigned int isymtab_shndx;
unsigned int irelocs_shndx;
unsigned int igot_plt_shndx;
unsigned int istrtab_shndx;
typedef Incremental_binary::Location Location;
typedef Incremental_binary::View View;
typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
typedef typename Inputs_reader::Incremental_input_entry_reader Entry_reader;
// Find the .gnu_incremental_inputs, _symtab, _relocs, and _strtab sections.
t = inc->find_incremental_inputs_sections(&inputs_shndx, &isymtab_shndx,
&irelocs_shndx, &igot_plt_shndx,
&istrtab_shndx);
if (!t)
if (!inc->has_incremental_info())
{
fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv0,
filename);
exit(1);
}
elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc);
// Get a view of the .gnu_incremental_inputs section.
Location inputs_location(elf_file.section_contents(inputs_shndx));
View inputs_view(inc->view(inputs_location));
// Get the .gnu_incremental_strtab section as a string table.
Location istrtab_location(elf_file.section_contents(istrtab_shndx));
View istrtab_view(inc->view(istrtab_location));
elfcpp::Elf_strtab istrtab(istrtab_view.data(), istrtab_location.data_size);
// Create a reader object for the .gnu_incremental_inputs section.
Incremental_inputs_reader<size, big_endian>
incremental_inputs(inputs_view.data(), istrtab);
incremental_inputs(inc->inputs_reader());
if (incremental_inputs.version() != 1)
{
@ -265,6 +241,8 @@ dump_incremental_inputs(const char* argv0, const char* filename,
// Get a view of the .symtab section.
elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc);
unsigned int symtab_shndx = elf_file.find_section_by_type(elfcpp::SHT_SYMTAB);
if (symtab_shndx == elfcpp::SHN_UNDEF) // Not found.
{
@ -288,16 +266,6 @@ dump_incremental_inputs(const char* argv0, const char* filename,
View strtab_view(inc->view(strtab_location));
elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
// Get a view of the .gnu_incremental_symtab section.
Location isymtab_location(elf_file.section_contents(isymtab_shndx));
View isymtab_view(inc->view(isymtab_location));
// Get a view of the .gnu_incremental_relocs section.
Location irelocs_location(elf_file.section_contents(irelocs_shndx));
View irelocs_view(inc->view(irelocs_location));
// The .gnu_incremental_symtab section contains entries that parallel
// the global symbols of the main symbol table. The sh_info field
// of the main symbol table's section header tells us how many global
@ -306,15 +274,13 @@ dump_incremental_inputs(const char* argv0, const char* filename,
// use the size of the .gnu_incremental_symtab section to deduce
// the number of global symbols + forced-local symbols there are
// in the symbol table.
Incremental_symtab_reader<big_endian> isymtab(inc->symtab_reader());
Incremental_relocs_reader<size, big_endian> irelocs(inc->relocs_reader());
unsigned int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned int nsyms = symtab_location.data_size / sym_size;
unsigned int nglobals = isymtab_location.data_size / 4;
unsigned int nglobals = isymtab.symbol_count();
unsigned int first_global = nsyms - nglobals;
unsigned const char* sym_p = symtab_view.data() + first_global * sym_size;
unsigned const char* isym_p = isymtab_view.data();
Incremental_symtab_reader<big_endian> isymtab(isymtab_view.data());
Incremental_relocs_reader<size, big_endian> irelocs(irelocs_view.data());
printf("\nGlobal symbol table:\n");
for (unsigned int i = 0; i < nglobals; i++)
@ -356,15 +322,9 @@ dump_incremental_inputs(const char* argv0, const char* filename,
offset = sym_info.next_offset;
}
sym_p += sym_size;
isym_p += 4;
}
// Get a view of the .gnu_incremental_got_plt section.
Location igot_plt_location(elf_file.section_contents(igot_plt_shndx));
View igot_plt_view(inc->view(igot_plt_location));
Incremental_got_plt_reader<big_endian> igot_plt(igot_plt_view.data());
Incremental_got_plt_reader<big_endian> igot_plt(inc->got_plt_reader());
unsigned int ngot = igot_plt.get_got_entry_count();
unsigned int nplt = igot_plt.get_plt_entry_count();
@ -464,22 +424,30 @@ main(int argc, char** argv)
{
#ifdef HAVE_TARGET_32_LITTLE
case Parameters::TARGET_32_LITTLE:
dump_incremental_inputs<32, false>(argv[0], filename, inc);
dump_incremental_inputs<32, false>(
argv[0], filename,
static_cast<Sized_incremental_binary<32, false>*>(inc));
break;
#endif
#ifdef HAVE_TARGET_32_BIG
case Parameters::TARGET_32_BIG:
dump_incremental_inputs<32, true>(argv[0], filename, inc);
dump_incremental_inputs<32, true>(
argv[0], filename,
static_cast<Sized_incremental_binary<32, true>*>(inc));
break;
#endif
#ifdef HAVE_TARGET_64_LITTLE
case Parameters::TARGET_64_LITTLE:
dump_incremental_inputs<64, false>(argv[0], filename, inc);
dump_incremental_inputs<64, false>(
argv[0], filename,
static_cast<Sized_incremental_binary<64, false>*>(inc));
break;
#endif
#ifdef HAVE_TARGET_64_BIG
case Parameters::TARGET_64_BIG:
dump_incremental_inputs<64, true>(argv[0], filename, inc);
dump_incremental_inputs<64, true>(
argv[0], filename,
static_cast<Sized_incremental_binary<64, true>*>(inc));
break;
#endif
default:

View File

@ -154,7 +154,7 @@ Incremental_binary::error(const char* format, ...) const
template<int size, bool big_endian>
bool
Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
Sized_incremental_binary<size, big_endian>::find_incremental_inputs_sections(
unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
unsigned int* p_relocs_shndx,
@ -206,6 +206,50 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
return true;
}
// Set up the readers into the incremental info sections.
template<int size, bool big_endian>
void
Sized_incremental_binary<size, big_endian>::setup_readers()
{
unsigned int inputs_shndx;
unsigned int symtab_shndx;
unsigned int relocs_shndx;
unsigned int got_plt_shndx;
unsigned int strtab_shndx;
if (!this->find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
&relocs_shndx, &got_plt_shndx,
&strtab_shndx))
return;
Location inputs_location(this->elf_file_.section_contents(inputs_shndx));
Location symtab_location(this->elf_file_.section_contents(symtab_shndx));
Location relocs_location(this->elf_file_.section_contents(relocs_shndx));
Location got_plt_location(this->elf_file_.section_contents(got_plt_shndx));
Location strtab_location(this->elf_file_.section_contents(strtab_shndx));
View inputs_view = this->view(inputs_location);
View symtab_view = this->view(symtab_location);
View relocs_view = this->view(relocs_location);
View got_plt_view = this->view(got_plt_location);
View strtab_view = this->view(strtab_location);
elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
this->inputs_reader_ =
Incremental_inputs_reader<size, big_endian>(inputs_view.data(), strtab);
this->symtab_reader_ =
Incremental_symtab_reader<big_endian>(symtab_view.data(),
symtab_location.data_size);
this->relocs_reader_ =
Incremental_relocs_reader<size, big_endian>(relocs_view.data(),
relocs_location.data_size);
this->got_plt_reader_ =
Incremental_got_plt_reader<big_endian>(got_plt_view.data());
this->has_incremental_info_ = true;
}
// Determine whether an incremental link based on the existing output file
// can be done.
@ -214,52 +258,56 @@ bool
Sized_incremental_binary<size, big_endian>::do_check_inputs(
Incremental_inputs* incremental_inputs)
{
unsigned int inputs_shndx;
unsigned int symtab_shndx;
unsigned int relocs_shndx;
unsigned int plt_got_shndx;
unsigned int strtab_shndx;
if (!do_find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
&relocs_shndx, &plt_got_shndx,
&strtab_shndx))
if (!this->has_incremental_info_)
{
explain_no_incremental(_("no incremental data from previous build"));
return false;
}
Location inputs_location(this->elf_file_.section_contents(inputs_shndx));
Location symtab_location(this->elf_file_.section_contents(symtab_shndx));
Location relocs_location(this->elf_file_.section_contents(relocs_shndx));
Location strtab_location(this->elf_file_.section_contents(strtab_shndx));
View inputs_view(view(inputs_location));
View symtab_view(view(symtab_location));
View relocs_view(view(relocs_location));
View strtab_view(view(strtab_location));
elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
Incremental_inputs_reader<size, big_endian>
incoming_inputs(inputs_view.data(), strtab);
if (incoming_inputs.version() != INCREMENTAL_LINK_VERSION)
if (this->inputs_reader_.version() != INCREMENTAL_LINK_VERSION)
{
explain_no_incremental(_("different version of incremental build data"));
return false;
}
if (incremental_inputs->command_line() != incoming_inputs.command_line())
if (incremental_inputs->command_line() != this->inputs_reader_.command_line())
{
explain_no_incremental(_("command line changed"));
return false;
}
// TODO: compare incremental_inputs->inputs() with entries in data_view.
return true;
}
// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
// with respect to the base file.
template<int size, bool big_endian>
bool
Sized_incremental_binary<size, big_endian>::do_file_is_unchanged(
const Input_argument* input_argument) const
{
Incremental_disposition disp =
input_argument->file().options().incremental_disposition();
if (disp != INCREMENTAL_CHECK)
return disp == INCREMENTAL_UNCHANGED;
// FIXME: Handle INCREMENTAL_CHECK.
return false;
}
template<int size, bool big_endian>
Incremental_binary::Input_reader*
Sized_incremental_binary<size, big_endian>::do_get_input_reader(
const char*)
{
unsigned int file_index = this->current_input_file_++;
gold_assert(file_index < this->inputs_reader_.input_file_count());
return new Sized_input_reader(this->inputs_reader_.input_file(file_index));
}
namespace
{

View File

@ -42,6 +42,7 @@ class Incremental_script_entry;
class Incremental_object_entry;
class Incremental_archive_entry;
class Incremental_inputs;
class Incremental_binary;
class Object;
// Incremental input type as stored in .gnu_incremental_inputs.
@ -55,147 +56,6 @@ enum Incremental_input_type
INCREMENTAL_INPUT_SCRIPT = 5
};
// An object representing the ELF file we edit during an incremental build.
// Similar to Object or Dynobj, but operates on Output_file and contains
// method specific to file edition (TBD). This is the abstract parent class
// implemented in Sized_incremental_binary<size, big_endian> for a specific
// endianness and size.
class Incremental_binary
{
public:
Incremental_binary(Output_file* output, Target* target)
: output_(output), target_(target)
{ }
virtual
~Incremental_binary()
{ }
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Incremental_binary as the File template parameter for
// elfcpp::Elf_file.
// The View class is returned by view. It must support a single
// method, data(). This is trivial, because Output_file::get_output_view
// does what we need.
class View
{
public:
View(const unsigned char* p)
: p_(p)
{ }
const unsigned char*
data() const
{ return this->p_; }
private:
const unsigned char* p_;
};
// Return a View.
View
view(off_t file_offset, section_size_type data_size)
{ return View(this->output_->get_input_view(file_offset, data_size)); }
// A location in the file.
struct Location
{
off_t file_offset;
off_t data_size;
Location(off_t fo, section_size_type ds)
: file_offset(fo), data_size(ds)
{ }
Location()
: file_offset(0), data_size(0)
{ }
};
// Get a View given a Location.
View
view(Location loc)
{ return View(this->view(loc.file_offset, loc.data_size)); }
// Report an error.
void
error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
// Find the .gnu_incremental_inputs and related sections. It selects the
// first section of type SHT_GNU_INCREMENTAL_INPUTS,
// SHT_GNU_INCREMENTAL_SYMTAB, and SHT_GNU_INCREMENTAL_RELOCS.
// Returns false if the sections are not found.
bool
find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
unsigned int* p_relocs_shndx,
unsigned int* p_got_plt_shndx,
unsigned int* p_strtab_shndx)
{
return do_find_incremental_inputs_sections(p_inputs_shndx, p_symtab_shndx,
p_relocs_shndx, p_got_plt_shndx,
p_strtab_shndx);
}
// Check the .gnu_incremental_inputs section to see whether an incremental
// build is possible.
// TODO: on success, should report what files needs to be rebuilt.
// INCREMENTAL_INPUTS is used to read the canonical form of the command line
// and read the input arguments. TODO: for items that don't need to be
// rebuilt, we should also copy the incremental input information.
virtual bool
check_inputs(Incremental_inputs* incremental_inputs)
{ return do_check_inputs(incremental_inputs); }
protected:
// Find incremental inputs section.
virtual bool
do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
unsigned int* p_relocs_shndx,
unsigned int* p_got_plt_shndx,
unsigned int* p_strtab_shndx) = 0;
// Check the .gnu_incremental_inputs section to see whether an incremental
// build is possible.
virtual bool
do_check_inputs(Incremental_inputs* incremental_inputs) = 0;
private:
// Edited output file object.
Output_file* output_;
// Target of the output file.
Target* target_;
};
template<int size, bool big_endian>
class Sized_incremental_binary : public Incremental_binary
{
public:
Sized_incremental_binary(Output_file* output,
const elfcpp::Ehdr<size, big_endian>& ehdr,
Target* target)
: Incremental_binary(output, target), elf_file_(this, ehdr)
{ }
protected:
virtual bool
do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
unsigned int* p_relocs_shndx,
unsigned int* p_got_plt_shndx,
unsigned int* p_strtab_shndx);
virtual bool
do_check_inputs(Incremental_inputs* incremental_inputs);
private:
// Output as an ELF file.
elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
};
// Create an Incremental_binary object for FILE. Returns NULL is this is not
// possible, e.g. FILE is not an ELF file or has an unsupported target.
@ -689,7 +549,12 @@ class Incremental_inputs_reader
typedef elfcpp::Swap<64, big_endian> Swap64;
public:
Incremental_inputs_reader(const unsigned char* p, elfcpp::Elf_strtab& strtab)
Incremental_inputs_reader()
: p_(NULL), strtab_(NULL, 0), input_file_count_(0)
{ }
Incremental_inputs_reader(const unsigned char* p,
const elfcpp::Elf_strtab& strtab)
: p_(p), strtab_(strtab)
{ this->input_file_count_ = Swap32::readval(this->p_ + 4); }
@ -939,16 +804,29 @@ template<bool big_endian>
class Incremental_symtab_reader
{
public:
Incremental_symtab_reader(const unsigned char* p) : p_(p)
Incremental_symtab_reader()
: p_(NULL), len_(0)
{ }
Incremental_symtab_reader(const unsigned char* p, off_t len)
: p_(p), len_(len)
{ }
// Return the count of symbols in this section.
unsigned int
symbol_count() const
{ return static_cast<unsigned int>(this->len_ / 4); }
// Return the list head for symbol table entry N.
unsigned int get_list_head(unsigned int n) const
unsigned int
get_list_head(unsigned int n) const
{ return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4 * n); }
private:
// Base address of the .gnu_incremental_relocs section.
const unsigned char* p_;
// Size of the section.
off_t len_;
};
// Reader class for the .gnu_incremental_relocs section.
@ -967,9 +845,19 @@ class Incremental_relocs_reader
// Size of each entry.
static const unsigned int reloc_size = 8 + 2 * field_size;
Incremental_relocs_reader(const unsigned char* p) : p_(p)
Incremental_relocs_reader()
: p_(NULL), len_(0)
{ }
Incremental_relocs_reader(const unsigned char* p, off_t len)
: p_(p), len_(len)
{ }
// Return the count of relocations in this section.
unsigned int
reloc_count() const
{ return static_cast<unsigned int>(this->len_ / reloc_size); }
// Return the relocation type for relocation entry at offset OFF.
unsigned int
get_r_type(unsigned int off) const
@ -1002,6 +890,8 @@ class Incremental_relocs_reader
private:
// Base address of the .gnu_incremental_relocs section.
const unsigned char* p_;
// Size of the section.
off_t len_;
};
// Reader class for the .gnu_incremental_got_plt section.
@ -1010,6 +900,10 @@ template<bool big_endian>
class Incremental_got_plt_reader
{
public:
Incremental_got_plt_reader()
: p_(NULL), got_count_(0), got_desc_p_(NULL), plt_desc_p_(NULL)
{ }
Incremental_got_plt_reader(const unsigned char* p) : p_(p)
{
this->got_count_ = elfcpp::Swap<32, big_endian>::readval(p);
@ -1063,6 +957,251 @@ class Incremental_got_plt_reader
const unsigned char* plt_desc_p_;
};
// An object representing the ELF file we edit during an incremental build.
// Similar to Object or Dynobj, but operates on Output_file and contains
// methods to support incremental updating. This is the abstract parent class
// implemented in Sized_incremental_binary<size, big_endian> for a specific
// endianness and size.
class Incremental_binary
{
public:
Incremental_binary(Output_file* output, Target* target)
: output_(output), target_(target)
{ }
virtual
~Incremental_binary()
{ }
// Check the .gnu_incremental_inputs section to see whether an incremental
// build is possible.
bool
check_inputs(Incremental_inputs* incremental_inputs)
{ return this->do_check_inputs(incremental_inputs); }
// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
// with respect to the base file.
bool
file_is_unchanged(const Input_argument* input_argument) const
{ return this->do_file_is_unchanged(input_argument); }
// Report an error.
void
error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
// Wrapper class for a sized Incremental_input_entry_reader.
class Input_reader
{
public:
Input_reader()
{ }
virtual
~Input_reader()
{ }
const char*
filename() const
{ return this->do_filename(); }
Timespec
get_mtime() const
{ return this->do_get_mtime(); }
Incremental_input_type
type() const
{ return this->do_type(); }
protected:
virtual const char*
do_filename() const = 0;
virtual Timespec
do_get_mtime() const = 0;
virtual Incremental_input_type
do_type() const = 0;
};
Input_reader*
get_input_reader(const char* filename)
{ return this->do_get_input_reader(filename); }
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Incremental_binary as the File template parameter for
// elfcpp::Elf_file.
// The View class is returned by view. It must support a single
// method, data(). This is trivial, because Output_file::get_output_view
// does what we need.
class View
{
public:
View(const unsigned char* p)
: p_(p)
{ }
const unsigned char*
data() const
{ return this->p_; }
private:
const unsigned char* p_;
};
// Return a View.
View
view(off_t file_offset, section_size_type data_size)
{ return View(this->output_->get_input_view(file_offset, data_size)); }
// A location in the file.
struct Location
{
off_t file_offset;
off_t data_size;
Location(off_t fo, section_size_type ds)
: file_offset(fo), data_size(ds)
{ }
Location()
: file_offset(0), data_size(0)
{ }
};
// Get a View given a Location.
View
view(Location loc)
{ return View(this->view(loc.file_offset, loc.data_size)); }
protected:
// Check the .gnu_incremental_inputs section to see whether an incremental
// build is possible.
virtual bool
do_check_inputs(Incremental_inputs* incremental_inputs) = 0;
// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
// with respect to the base file.
virtual bool
do_file_is_unchanged(const Input_argument* input_argument) const = 0;
virtual Input_reader*
do_get_input_reader(const char* filename) = 0;
private:
// Edited output file object.
Output_file* output_;
// Target of the output file.
Target* target_;
};
template<int size, bool big_endian>
class Sized_incremental_binary : public Incremental_binary
{
public:
Sized_incremental_binary(Output_file* output,
const elfcpp::Ehdr<size, big_endian>& ehdr,
Target* target)
: Incremental_binary(output, target), elf_file_(this, ehdr),
has_incremental_info_(false), inputs_reader_(), symtab_reader_(),
relocs_reader_(), got_plt_reader_(), current_input_file_(0)
{ this->setup_readers(); }
// Returns TRUE if the file contains incremental info.
bool
has_incremental_info() const
{ return this->has_incremental_info_; }
// Readers for the incremental info sections.
Incremental_inputs_reader<size, big_endian>
inputs_reader() const
{ return this->inputs_reader_; }
Incremental_symtab_reader<big_endian>
symtab_reader() const
{ return this->symtab_reader_; }
Incremental_relocs_reader<size, big_endian>
relocs_reader() const
{ return this->relocs_reader_; }
Incremental_got_plt_reader<big_endian>
got_plt_reader() const
{ return this->got_plt_reader_; }
protected:
virtual bool
do_check_inputs(Incremental_inputs* incremental_inputs);
// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
// with respect to the base file.
virtual bool
do_file_is_unchanged(const Input_argument* input_argument) const;
// Wrapper class for a sized Incremental_input_entry_reader.
class Sized_input_reader : public Input_reader
{
public:
typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
typedef typename Inputs_reader::Incremental_input_entry_reader
Input_entry_reader;
Sized_input_reader(Input_entry_reader r)
: Input_reader(), reader_(r)
{ }
virtual
~Sized_input_reader()
{ }
private:
const char*
do_filename() const
{ return this->reader_.filename(); }
Timespec
do_get_mtime() const
{ return this->reader_.get_mtime(); }
Incremental_input_type
do_type() const
{ return this->reader_.type(); }
Input_entry_reader reader_;
};
virtual Input_reader*
do_get_input_reader(const char* filename);
private:
bool
find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
unsigned int* p_symtab_shndx,
unsigned int* p_relocs_shndx,
unsigned int* p_got_plt_shndx,
unsigned int* p_strtab_shndx);
void
setup_readers();
// Output as an ELF file.
elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
// Readers for the incremental info sections.
bool has_incremental_info_;
Incremental_inputs_reader<size, big_endian> inputs_reader_;
Incremental_symtab_reader<big_endian> symtab_reader_;
Incremental_relocs_reader<size, big_endian> relocs_reader_;
Incremental_got_plt_reader<big_endian> got_plt_reader_;
// Index of the current input file entry.
int current_input_file_;
};
} // End namespace gold.
#endif // !defined(GOLD_INCREMENTAL_H)