aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-04 22:54:31 +0000
committerIan Lance Taylor <iant@google.com>2008-02-04 22:54:31 +0000
commit1c4f3631bde4d056e02555d72009693de26da4bf (patch)
treef2ecece1db200a3681dfd01d6f6f429fc00789a2 /gold/output.cc
parent15893b88b0e64f14a08e952a07d3e517c7926c8e (diff)
downloadfsf-binutils-gdb-1c4f3631bde4d056e02555d72009693de26da4bf.zip
fsf-binutils-gdb-1c4f3631bde4d056e02555d72009693de26da4bf.tar.gz
fsf-binutils-gdb-1c4f3631bde4d056e02555d72009693de26da4bf.tar.bz2
Implement PHDRS.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc49
1 files changed, 49 insertions, 0 deletions
diff --git a/gold/output.cc b/gold/output.cc
index 8eb79fa..f0f4de2 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -2480,6 +2480,55 @@ Output_segment::output_section_count_list(const Output_data_list* pdl) const
return count;
}
+// Return the section attached to the list segment with the lowest
+// load address. This is used when handling a PHDRS clause in a
+// linker script.
+
+Output_section*
+Output_segment::section_with_lowest_load_address() const
+{
+ Output_section* found = NULL;
+ uint64_t found_lma = 0;
+ this->lowest_load_address_in_list(&this->output_data_, &found, &found_lma);
+
+ Output_section* found_data = found;
+ this->lowest_load_address_in_list(&this->output_bss_, &found, &found_lma);
+ if (found != found_data && found_data != NULL)
+ {
+ gold_error(_("nobits section %s may not precede progbits section %s "
+ "in same segment"),
+ found->name(), found_data->name());
+ return NULL;
+ }
+
+ return found;
+}
+
+// Look through a list for a section with a lower load address.
+
+void
+Output_segment::lowest_load_address_in_list(const Output_data_list* pdl,
+ Output_section** found,
+ uint64_t* found_lma) const
+{
+ for (Output_data_list::const_iterator p = pdl->begin();
+ p != pdl->end();
+ ++p)
+ {
+ if (!(*p)->is_section())
+ continue;
+ Output_section* os = static_cast<Output_section*>(*p);
+ uint64_t lma = (os->has_load_address()
+ ? os->load_address()
+ : os->address());
+ if (*found == NULL || lma < *found_lma)
+ {
+ *found = os;
+ *found_lma = lma;
+ }
+ }
+}
+
// Write the segment data into *OPHDR.
template<int size, bool big_endian>