This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Refactor Output_data_reloc_base::do_write for MIPS-specific relocs.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c32482d65c43f40572a0722b48c20b3f571666a3

commit c32482d65c43f40572a0722b48c20b3f571666a3
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Tue Mar 8 12:24:39 2016 -0800

    Refactor Output_data_reloc_base::do_write for MIPS-specific relocs.
    
    This patch is a simple refactoring that will allow the MIPS backend to
    replace the Output_data_reloc_base::do_write() method without copying
    its entire implementation. I've moved the implementation of do_write()
    into a function template, which can be instantiated with a custom
    class to write the MIPS-specific relocation format. The custom class
    for MIPS needs access to the symbol index and address from
    Output_reloc, so I've included the part of Vlad's MIPS-64 patch that
    makes those accessor methods public.
    
    2016-03-08  Cary Coutant  <ccoutant@gmail.com>
                Vladimir Radosavljevic  <vladimir.radosavljevic@imgtec.com>
    
    gold/
    	* output.cc (Output_reloc_writer): New type.
    	(Output_data_reloc_base::do_write): Move implementation to template
    	in output.h and replace with invocation of template.
    	* output.h (Output_file): Move to top of file.
    	(Output_reloc::get_symbol_index): Move to public interface.
    	(Output_reloc::get_address): Likewise.
    	(Output_data_reloc_base::do_write_generic): New function template.

Diff:
---
 gold/ChangeLog |  11 +++
 gold/output.cc |  41 +++-----
 gold/output.h  | 296 ++++++++++++++++++++++++++++++++-------------------------
 3 files changed, 191 insertions(+), 157 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 3419290..d3ec5de 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,14 @@
+2016-03-08  Cary Coutant  <ccoutant@gmail.com>
+            Vladimir Radosavljevic  <vladimir.radosavljevic@imgtec.com>
+
+	* output.cc (Output_reloc_writer): New type.
+	(Output_data_reloc_base::do_write): Move implementation to template
+	in output.h and replace with invocation of template.
+	* output.h (Output_file): Move to top of file.
+	(Output_reloc::get_symbol_index): Move to public interface.
+	(Output_reloc::get_address): Likewise.
+	(Output_data_reloc_base::do_write_generic): New function template.
+
 2016-03-04  Cary Coutant  <ccoutant@gmail.com>
 
 	PR gold/19019
diff --git a/gold/output.cc b/gold/output.cc
index f9d4f23..077e2c4 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1252,6 +1252,19 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>
     os->set_should_link_to_dynsym();
 }
 
+// Standard relocation writer, which just calls Output_reloc::write().
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+struct Output_reloc_writer
+{
+  typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
+  typedef std::vector<Output_reloc_type> Relocs;
+
+  static void
+  write(typename Relocs::const_iterator p, unsigned char* pov)
+  { p->write(pov); }
+};
+
 // Write out relocation data.
 
 template<int sh_type, bool dynamic, int size, bool big_endian>
@@ -1259,32 +1272,8 @@ void
 Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
     Output_file* of)
 {
-  const off_t off = this->offset();
-  const off_t oview_size = this->data_size();
-  unsigned char* const oview = of->get_output_view(off, oview_size);
-
-  if (this->sort_relocs())
-    {
-      gold_assert(dynamic);
-      std::sort(this->relocs_.begin(), this->relocs_.end(),
-		Sort_relocs_comparison());
-    }
-
-  unsigned char* pov = oview;
-  for (typename Relocs::const_iterator p = this->relocs_.begin();
-       p != this->relocs_.end();
-       ++p)
-    {
-      p->write(pov);
-      pov += reloc_size;
-    }
-
-  gold_assert(pov - oview == oview_size);
-
-  of->write_output_view(off, oview_size, oview);
-
-  // We no longer need the relocation entries.
-  this->relocs_.clear();
+  typedef Output_reloc_writer<sh_type, dynamic, size, big_endian> Writer;
+  this->do_write_generic<Writer>(of);
 }
 
 // Class Output_relocatable_relocs.
diff --git a/gold/output.h b/gold/output.h
index 9d05b67..0b96a03 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -23,6 +23,7 @@
 #ifndef GOLD_OUTPUT_H
 #define GOLD_OUTPUT_H
 
+#include <algorithm>
 #include <list>
 #include <vector>
 
@@ -37,7 +38,6 @@ namespace gold
 class General_options;
 class Object;
 class Symbol;
-class Output_file;
 class Output_merge_base;
 class Output_section;
 class Relocatable_relocs;
@@ -49,6 +49,131 @@ class Sized_relobj;
 template<int size, bool big_endian>
 class Sized_relobj_file;
 
+// This class represents the output file.
+
+class Output_file
+{
+ public:
+  Output_file(const char* name);
+
+  // Indicate that this is a temporary file which should not be
+  // output.
+  void
+  set_is_temporary()
+  { this->is_temporary_ = true; }
+
+  // Try to open an existing file. Returns false if the file doesn't
+  // exist, has a size of 0 or can't be mmaped.  This method is
+  // thread-unsafe.  If BASE_NAME is not NULL, use the contents of
+  // that file as the base for incremental linking.
+  bool
+  open_base_file(const char* base_name, bool writable);
+
+  // Open the output file.  FILE_SIZE is the final size of the file.
+  // If the file already exists, it is deleted/truncated.  This method
+  // is thread-unsafe.
+  void
+  open(off_t file_size);
+
+  // Resize the output file.  This method is thread-unsafe.
+  void
+  resize(off_t file_size);
+
+  // Close the output file (flushing all buffered data) and make sure
+  // there are no errors.  This method is thread-unsafe.
+  void
+  close();
+
+  // Return the size of this file.
+  off_t
+  filesize()
+  { return this->file_size_; }
+
+  // Return the name of this file.
+  const char*
+  filename()
+  { return this->name_; }
+
+  // We currently always use mmap which makes the view handling quite
+  // simple.  In the future we may support other approaches.
+
+  // Write data to the output file.
+  void
+  write(off_t offset, const void* data, size_t len)
+  { memcpy(this->base_ + offset, data, len); }
+
+  // Get a buffer to use to write to the file, given the offset into
+  // the file and the size.
+  unsigned char*
+  get_output_view(off_t start, size_t size)
+  {
+    gold_assert(start >= 0
+		&& start + static_cast<off_t>(size) <= this->file_size_);
+    return this->base_ + start;
+  }
+
+  // VIEW must have been returned by get_output_view.  Write the
+  // buffer to the file, passing in the offset and the size.
+  void
+  write_output_view(off_t, size_t, unsigned char*)
+  { }
+
+  // Get a read/write buffer.  This is used when we want to write part
+  // of the file, read it in, and write it again.
+  unsigned char*
+  get_input_output_view(off_t start, size_t size)
+  { return this->get_output_view(start, size); }
+
+  // Write a read/write buffer back to the file.
+  void
+  write_input_output_view(off_t, size_t, unsigned char*)
+  { }
+
+  // Get a read buffer.  This is used when we just want to read part
+  // of the file back it in.
+  const unsigned char*
+  get_input_view(off_t start, size_t size)
+  { return this->get_output_view(start, size); }
+
+  // Release a read bfufer.
+  void
+  free_input_view(off_t, size_t, const unsigned char*)
+  { }
+
+ private:
+  // Map the file into memory or, if that fails, allocate anonymous
+  // memory.
+  void
+  map();
+
+  // Allocate anonymous memory for the file.
+  bool
+  map_anonymous();
+
+  // Map the file into memory.
+  bool
+  map_no_anonymous(bool);
+
+  // Unmap the file from memory (and flush to disk buffers).
+  void
+  unmap();
+
+  // File name.
+  const char* name_;
+  // File descriptor.
+  int o_;
+  // File size.
+  off_t file_size_;
+  // Base of file mapped into memory.
+  unsigned char* base_;
+  // True iff base_ points to a memory buffer rather than an output file.
+  bool map_is_anonymous_;
+  // True if base_ was allocated using new rather than mmap.
+  bool map_is_allocated_;
+  // True if this is a temporary file which should not be output.
+  bool is_temporary_;
+};
+
 // An abtract class for data which has to go into the output file.
 
 class Output_data
@@ -1150,11 +1275,6 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 	      r2) const
   { return this->compare(r2) < 0; }
 
- private:
-  // Record that we need a dynamic symbol index.
-  void
-  set_needs_dynsym_index();
-
   // Return the symbol index.
   unsigned int
   get_symbol_index() const;
@@ -1163,6 +1283,11 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Address
   get_address() const;
 
+ private:
+  // Record that we need a dynamic symbol index.
+  void
+  set_needs_dynsym_index();
+
   // Codes for local_sym_index_.
   enum
   {
@@ -1487,6 +1612,40 @@ class Output_data_reloc_base : public Output_data_reloc_generic
   void
   do_write(Output_file*);
 
+  // Generic implementation of do_write, allowing a customized
+  // class for writing the output relocation (e.g., for MIPS-64).
+  template<class Output_reloc_writer>
+  void
+  do_write_generic(Output_file* of)
+  {
+    const off_t off = this->offset();
+    const off_t oview_size = this->data_size();
+    unsigned char* const oview = of->get_output_view(off, oview_size);
+
+    if (this->sort_relocs())
+      {
+	gold_assert(dynamic);
+	std::sort(this->relocs_.begin(), this->relocs_.end(),
+		  Sort_relocs_comparison());
+      }
+
+    unsigned char* pov = oview;
+    for (typename Relocs::const_iterator p = this->relocs_.begin();
+	 p != this->relocs_.end();
+	 ++p)
+      {
+	Output_reloc_writer::write(p, pov);
+	pov += reloc_size;
+      }
+
+    gold_assert(pov - oview == oview_size);
+
+    of->write_output_view(off, oview_size, oview);
+
+    // We no longer need the relocation entries.
+    this->relocs_.clear();
+  }
+
   // Set the entry size and the link.
   void
   do_adjust_output_section(Output_section* os);
@@ -4756,131 +4915,6 @@ class Output_segment
   bool is_unique_segment_ : 1;
 };
 
-// This class represents the output file.
-
-class Output_file
-{
- public:
-  Output_file(const char* name);
-
-  // Indicate that this is a temporary file which should not be
-  // output.
-  void
-  set_is_temporary()
-  { this->is_temporary_ = true; }
-
-  // Try to open an existing file. Returns false if the file doesn't
-  // exist, has a size of 0 or can't be mmaped.  This method is
-  // thread-unsafe.  If BASE_NAME is not NULL, use the contents of
-  // that file as the base for incremental linking.
-  bool
-  open_base_file(const char* base_name, bool writable);
-
-  // Open the output file.  FILE_SIZE is the final size of the file.
-  // If the file already exists, it is deleted/truncated.  This method
-  // is thread-unsafe.
-  void
-  open(off_t file_size);
-
-  // Resize the output file.  This method is thread-unsafe.
-  void
-  resize(off_t file_size);
-
-  // Close the output file (flushing all buffered data) and make sure
-  // there are no errors.  This method is thread-unsafe.
-  void
-  close();
-
-  // Return the size of this file.
-  off_t
-  filesize()
-  { return this->file_size_; }
-
-  // Return the name of this file.
-  const char*
-  filename()
-  { return this->name_; }
-
-  // We currently always use mmap which makes the view handling quite
-  // simple.  In the future we may support other approaches.
-
-  // Write data to the output file.
-  void
-  write(off_t offset, const void* data, size_t len)
-  { memcpy(this->base_ + offset, data, len); }
-
-  // Get a buffer to use to write to the file, given the offset into
-  // the file and the size.
-  unsigned char*
-  get_output_view(off_t start, size_t size)
-  {
-    gold_assert(start >= 0
-		&& start + static_cast<off_t>(size) <= this->file_size_);
-    return this->base_ + start;
-  }
-
-  // VIEW must have been returned by get_output_view.  Write the
-  // buffer to the file, passing in the offset and the size.
-  void
-  write_output_view(off_t, size_t, unsigned char*)
-  { }
-
-  // Get a read/write buffer.  This is used when we want to write part
-  // of the file, read it in, and write it again.
-  unsigned char*
-  get_input_output_view(off_t start, size_t size)
-  { return this->get_output_view(start, size); }
-
-  // Write a read/write buffer back to the file.
-  void
-  write_input_output_view(off_t, size_t, unsigned char*)
-  { }
-
-  // Get a read buffer.  This is used when we just want to read part
-  // of the file back it in.
-  const unsigned char*
-  get_input_view(off_t start, size_t size)
-  { return this->get_output_view(start, size); }
-
-  // Release a read bfufer.
-  void
-  free_input_view(off_t, size_t, const unsigned char*)
-  { }
-
- private:
-  // Map the file into memory or, if that fails, allocate anonymous
-  // memory.
-  void
-  map();
-
-  // Allocate anonymous memory for the file.
-  bool
-  map_anonymous();
-
-  // Map the file into memory.
-  bool
-  map_no_anonymous(bool);
-
-  // Unmap the file from memory (and flush to disk buffers).
-  void
-  unmap();
-
-  // File name.
-  const char* name_;
-  // File descriptor.
-  int o_;
-  // File size.
-  off_t file_size_;
-  // Base of file mapped into memory.
-  unsigned char* base_;
-  // True iff base_ points to a memory buffer rather than an output file.
-  bool map_is_anonymous_;
-  // True if base_ was allocated using new rather than mmap.
-  bool map_is_allocated_;
-  // True if this is a temporary file which should not be output.
-  bool is_temporary_;
-};
-
 } // End namespace gold.
 
 #endif // !defined(GOLD_OUTPUT_H)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]