aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2016-03-08 12:24:39 -0800
committerCary Coutant <ccoutant@gmail.com>2016-03-08 15:06:59 -0800
commitc32482d65c43f40572a0722b48c20b3f571666a3 (patch)
treec496e6566aaf984af0f0150c9a3325d1032712cc /gold
parentd1ed1c7d69e6656de213b12594e702afec31a66d (diff)
downloadgdb-c32482d65c43f40572a0722b48c20b3f571666a3.zip
gdb-c32482d65c43f40572a0722b48c20b3f571666a3.tar.gz
gdb-c32482d65c43f40572a0722b48c20b3f571666a3.tar.bz2
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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog11
-rw-r--r--gold/output.cc41
-rw-r--r--gold/output.h296
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)