aboutsummaryrefslogtreecommitdiff
path: root/gold/reloc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/reloc.cc')
-rw-r--r--gold/reloc.cc46
1 files changed, 43 insertions, 3 deletions
diff --git a/gold/reloc.cc b/gold/reloc.cc
index f88151f..d361f16 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -22,6 +22,8 @@
#include "gold.h"
+#include <algorithm>
+
#include "workqueue.h"
#include "symtab.h"
#include "output.h"
@@ -159,6 +161,11 @@ Relocate_task::run(Workqueue*)
{
this->object_->relocate(this->options_, this->symtab_, this->layout_,
this->of_);
+
+ // This is normally the last thing we will do with an object, so
+ // uncache all views.
+ this->object_->clear_view_cache_marks();
+
this->object_->release();
}
@@ -376,8 +383,20 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options,
// Write out the local symbols.
this->write_local_symbols(of, layout->sympool(), layout->dynpool());
+
+ // We should no longer need the local symbol values.
+ this->clear_local_symbols();
}
+// Sort a Read_multiple vector by file offset.
+struct Read_multiple_compare
+{
+ inline bool
+ operator()(const File_read::Read_multiple_entry& rme1,
+ const File_read::Read_multiple_entry& rme2) const
+ { return rme1.file_offset < rme2.file_offset; }
+};
+
// Write section data to the output file. PSHDRS points to the
// section headers. Record the views in *PVIEWS for use when
// relocating.
@@ -386,11 +405,14 @@ template<int size, bool big_endian>
void
Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
Output_file* of,
- Views* pviews) const
+ Views* pviews)
{
unsigned int shnum = this->shnum();
const std::vector<Map_to_output>& map_sections(this->map_to_output());
+ File_read::Read_multiple rm;
+ bool is_sorted = true;
+
const unsigned char* p = pshdrs + This::shdr_size;
for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
{
@@ -468,7 +490,13 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
unsigned char* buffer = os->postprocessing_buffer();
view = buffer + view_start;
if (output_offset != -1)
- this->read(shdr.get_sh_offset(), view_size, view);
+ {
+ off_t sh_offset = shdr.get_sh_offset();
+ if (!rm.empty() && rm.back().file_offset > sh_offset)
+ is_sorted = false;
+ rm.push_back(File_read::Read_multiple_entry(sh_offset,
+ view_size, view));
+ }
}
else
{
@@ -477,7 +505,11 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
else
{
view = of->get_output_view(view_start, view_size);
- this->read(shdr.get_sh_offset(), view_size, view);
+ off_t sh_offset = shdr.get_sh_offset();
+ if (!rm.empty() && rm.back().file_offset > sh_offset)
+ is_sorted = false;
+ rm.push_back(File_read::Read_multiple_entry(sh_offset,
+ view_size, view));
}
}
@@ -490,6 +522,14 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
pvs->is_input_output_view = output_offset == -1;
pvs->is_postprocessing_view = os->requires_postprocessing();
}
+
+ // Actually read the data.
+ if (!rm.empty())
+ {
+ if (!is_sorted)
+ std::sort(rm.begin(), rm.end(), Read_multiple_compare());
+ this->read_multiple(rm);
+ }
}
// Relocate section data. VIEWS points to the section data as views