* 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:
parent
a869183fab
commit
b961d0d7b6
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
{
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user