aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2011-04-05 20:16:17 +0000
committerCary Coutant <ccoutant@google.com>2011-04-05 20:16:17 +0000
commitb961d0d7b65a2bdfd465f774db948c199fddaa06 (patch)
treefac883ba6bfa4b2a6bb87a79326f3b5747590140 /gold
parenta869183fab276723f2f7eb55af604e106007285f (diff)
downloadgdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.zip
gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.tar.gz
gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.tar.bz2
* 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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog40
-rw-r--r--gold/incremental-dump.cc74
-rw-r--r--gold/incremental.cc96
-rw-r--r--gold/incremental.h429
4 files changed, 417 insertions, 222 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index ec59508..98c7a6f 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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
diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc
index e59b1c5..6f79f4d 100644
--- a/gold/incremental-dump.cc
+++ b/gold/incremental-dump.cc
@@ -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:
diff --git a/gold/incremental.cc b/gold/incremental.cc
index e5f71f5..a38b12b 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -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,60 +206,108 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
return true;
}
-// Determine whether an incremental link based on the existing output file
-// can be done.
+// Set up the readers into the incremental info sections.
template<int size, bool big_endian>
-bool
-Sized_incremental_binary<size, big_endian>::do_check_inputs(
- Incremental_inputs* incremental_inputs)
+void
+Sized_incremental_binary<size, big_endian>::setup_readers()
{
unsigned int inputs_shndx;
unsigned int symtab_shndx;
unsigned int relocs_shndx;
- unsigned int plt_got_shndx;
+ unsigned int got_plt_shndx;
unsigned int strtab_shndx;
- if (!do_find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
- &relocs_shndx, &plt_got_shndx,
- &strtab_shndx))
- {
- explain_no_incremental(_("no incremental data from previous build"));
- return false;
- }
+ 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(view(inputs_location));
- View symtab_view(view(symtab_location));
- View relocs_view(view(relocs_location));
- View strtab_view(view(strtab_location));
+ 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);
- Incremental_inputs_reader<size, big_endian>
- incoming_inputs(inputs_view.data(), strtab);
+ 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.
+
+template<int size, bool big_endian>
+bool
+Sized_incremental_binary<size, big_endian>::do_check_inputs(
+ Incremental_inputs* incremental_inputs)
+{
+ if (!this->has_incremental_info_)
+ {
+ explain_no_incremental(_("no incremental data from previous build"));
+ return false;
+ }
- 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
{
diff --git a/gold/incremental.h b/gold/incremental.h
index b799f7b..815f761 100644
--- a/gold/incremental.h
+++ b/gold/incremental.h
@@ -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)