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>
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.
#ifndef GOLD_OUTPUT_H
#define GOLD_OUTPUT_H
+#include <algorithm>
#include <list>
#include <vector>
class General_options;
class Object;
class Symbol;
-class Output_file;
class Output_merge_base;
class Output_section;
class Relocatable_relocs;
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
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;
Address
get_address() const;
+ private:
+ // Record that we need a dynamic symbol index.
+ void
+ set_needs_dynsym_index();
+
// Codes for local_sym_index_.
enum
{
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);
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)