aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc159
1 files changed, 159 insertions, 0 deletions
diff --git a/gold/output.cc b/gold/output.cc
new file mode 100644
index 0000000..fcba113
--- /dev/null
+++ b/gold/output.cc
@@ -0,0 +1,159 @@
+// output.cc -- manage the output file for gold
+
+#include "gold.h"
+
+#include <cstdlib>
+
+#include "object.h"
+#include "output.h"
+
+namespace gold
+{
+
+// Output_data methods.
+
+Output_data::~Output_data()
+{
+}
+
+// Output_data_const methods.
+
+void
+Output_data_const::write(Output_file* output, off_t off)
+{
+ output->write(off, data_.data(), data_.size());
+}
+
+// Output_section methods.
+
+// Construct an Output_section. NAME will point into a Stringpool.
+
+Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
+ elfcpp::Elf_Xword flags)
+ : name_(name),
+ addr_(0),
+ addralign_(0),
+ entsize_(0),
+ offset_(0),
+ size_(0),
+ link_(0),
+ info_(0),
+ type_(type),
+ flags_(flags)
+{
+}
+
+// Add an input section to an Output_section. We don't keep track of
+// input sections for an Output_section. Instead, each Object keeps
+// track of the Output_section for each of its input sections.
+
+template<int size, bool big_endian>
+off_t
+Output_section::add_input_section(Object* object, const char* secname,
+ const elfcpp::Shdr<size, big_endian>& shdr)
+{
+ elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
+ if ((addralign & (addralign - 1)) != 0)
+ {
+ fprintf(stderr, _("%s: %s: invalid alignment %lu for section \"%s\"\n"),
+ program_name, object->name().c_str(),
+ static_cast<unsigned long>(addralign), secname);
+ gold_exit(false);
+ }
+ this->size_ = (this->size_ + addralign - 1) &~ (addralign - 1);
+
+ if (addralign > this->addralign_)
+ this->addralign_ = addralign;
+
+ off_t ret = this->size_;
+ this->size_ += shdr.get_sh_size();
+
+ return ret;
+}
+
+// Output segment methods.
+
+Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
+ : output_sections_(),
+ vaddr_(0),
+ paddr_(0),
+ memsz_(0),
+ align_(0),
+ offset_(0),
+ filesz_(0),
+ type_(type),
+ flags_(flags)
+{
+}
+
+// Add an Output_section to an Output_segment.
+
+void
+Output_segment::add_output_section(Output_section* os)
+{
+ // So that PT_NOTE segments will work correctly, we need to ensure
+ // that all SHT_NOTE sections are adjacent. This will normally
+ // happen automatically, because all the SHT_NOTE input sections
+ // will wind up in the same output section. However, it is possible
+ // for multiple SHT_NOTE input sections to have different section
+ // flags, and thus be in different output sections, but for the
+ // different section flags to map into the same segment flags and
+ // thus the same output segment.
+ if (os->type() == elfcpp::SHT_NOTE)
+ {
+ for (Section_list::iterator p = this->output_sections_.begin();
+ p != this->output_sections_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::SHT_NOTE)
+ {
+ ++p;
+ this->output_sections_.insert(p, os);
+ return;
+ }
+ }
+ }
+
+ this->output_sections_.push_back(os);
+}
+
+// Output_file methods.
+
+void
+Output_file::write(off_t, const void*, off_t)
+{
+ abort();
+}
+
+// Instantiate the templates we need. We could use the configure
+// script to restrict this to only the ones for implemented targets.
+
+template
+off_t
+Output_section::add_input_section<32, false>(
+ Object* object,
+ const char* secname,
+ const elfcpp::Shdr<32, false>& shdr);
+
+template
+off_t
+Output_section::add_input_section<32, true>(
+ Object* object,
+ const char* secname,
+ const elfcpp::Shdr<32, true>& shdr);
+
+template
+off_t
+Output_section::add_input_section<64, false>(
+ Object* object,
+ const char* secname,
+ const elfcpp::Shdr<64, false>& shdr);
+
+template
+off_t
+Output_section::add_input_section<64, true>(
+ Object* object,
+ const char* secname,
+ const elfcpp::Shdr<64, true>& shdr);
+
+} // End namespace gold.