diff options
author | Ian Lance Taylor <iant@google.com> | 2008-02-07 07:33:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2008-02-07 07:33:46 +0000 |
commit | 516cb3d01efb6f72ffa445ada40003e4e9e8e23a (patch) | |
tree | 7d422728cec6c2217ab76106f6c01479e2f2db4a /gold/layout.cc | |
parent | 1ef1f3d387940683bcba12c0bee8c5adfdef4bc7 (diff) | |
download | binutils-gdb-516cb3d01efb6f72ffa445ada40003e4e9e8e23a.tar.gz |
Support --oformat binary.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/gold/layout.cc b/gold/layout.cc index 98617f97fed..cea25b0193e 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -57,6 +57,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task) // Now we know the final size of the output file and we know where // each piece of information goes. Output_file* of = new Output_file(parameters->output_file_name()); + if (this->options_.output_format() != General_options::OUTPUT_FORMAT_ELF) + of->set_is_temporary(); of->open(file_size); // Queue up the final set of tasks. @@ -949,6 +951,9 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, else load_seg = this->find_first_load_seg(); + if (this->options_.output_format() != General_options::OUTPUT_FORMAT_ELF) + load_seg = NULL; + gold_assert(phdr_seg == NULL || load_seg != NULL); // Lay out the segment headers. @@ -2486,6 +2491,55 @@ Layout::write_sections_after_input_sections(Output_file* of) this->section_headers_->write(of); } +// Write out a binary file. This is called after the link is +// complete. IN is the temporary output file we used to generate the +// ELF code. We simply walk through the segments, read them from +// their file offset in IN, and write them to their load address in +// the output file. FIXME: with a bit more work, we could support +// S-records and/or Intel hex format here. + +void +Layout::write_binary(Output_file* in) const +{ + gold_assert(this->options_.output_format() + == General_options::OUTPUT_FORMAT_BINARY); + + // Get the size of the binary file. + uint64_t max_load_address = 0; + for (Segment_list::const_iterator p = this->segment_list_.begin(); + p != this->segment_list_.end(); + ++p) + { + if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0) + { + uint64_t max_paddr = (*p)->paddr() + (*p)->filesz(); + if (max_paddr > max_load_address) + max_load_address = max_paddr; + } + } + + Output_file out(parameters->output_file_name()); + out.open(max_load_address); + + for (Segment_list::const_iterator p = this->segment_list_.begin(); + p != this->segment_list_.end(); + ++p) + { + if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0) + { + const unsigned char* vin = in->get_input_view((*p)->offset(), + (*p)->filesz()); + unsigned char* vout = out.get_output_view((*p)->paddr(), + (*p)->filesz()); + memcpy(vout, vin, (*p)->filesz()); + out.write_output_view((*p)->paddr(), (*p)->filesz(), vout); + in->free_input_view((*p)->offset(), (*p)->filesz(), vin); + } + } + + out.close(); +} + // Print statistical information to stderr. This is used for --stats. void @@ -2617,6 +2671,10 @@ Write_after_input_sections_task::run(Workqueue*) void Close_task_runner::run(Workqueue*, const Task*) { + // If we've been asked to create a binary file, we do so here. + if (this->options_->output_format() != General_options::OUTPUT_FORMAT_ELF) + this->layout_->write_binary(this->of_); + this->of_->close(); } |