aboutsummaryrefslogtreecommitdiff
path: root/gold/incremental.h
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/incremental.h
parenta869183fab276723f2f7eb55af604e106007285f (diff)
downloadfsf-binutils-gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.zip
fsf-binutils-gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.tar.gz
fsf-binutils-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/incremental.h')
-rw-r--r--gold/incremental.h429
1 files changed, 284 insertions, 145 deletions
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)