aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-14 02:34:22 +0000
committerIan Lance Taylor <iant@google.com>2008-02-14 02:34:22 +0000
commitfd247bfe68f03688b12c8583933f5471f1ed0a86 (patch)
tree7847ca84e6de4934f78ae5cad55a14513d657daa /gold
parent718e06bc33d8d01e10d192aeba2d10da773e3954 (diff)
downloadbinutils-fd247bfe68f03688b12c8583933f5471f1ed0a86.zip
binutils-fd247bfe68f03688b12c8583933f5471f1ed0a86.tar.gz
binutils-fd247bfe68f03688b12c8583933f5471f1ed0a86.tar.bz2
Set load address for orphan sections.
Diffstat (limited to 'gold')
-rw-r--r--gold/script-sections.cc42
1 files changed, 33 insertions, 9 deletions
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index db0c53b..68cba6b 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -80,7 +80,7 @@ class Sections_element
// Set section addresses. This includes applying assignments if the
// the expression is an absolute value.
virtual void
- set_section_addresses(Symbol_table*, Layout*, uint64_t*)
+ set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*)
{ }
// Check a constraint (ONLY_IF_RO, etc.) on an output section. If
@@ -139,7 +139,7 @@ class Sections_element_assignment : public Sections_element
// absolute symbols when setting dot.
void
set_section_addresses(Symbol_table* symtab, Layout* layout,
- uint64_t* dot_value)
+ uint64_t* dot_value, uint64_t*)
{
this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
}
@@ -182,11 +182,12 @@ class Sections_element_dot_assignment : public Sections_element
// Update the dot symbol while setting section addresses.
void
set_section_addresses(Symbol_table* symtab, Layout* layout,
- uint64_t* dot_value)
+ uint64_t* dot_value, uint64_t* load_address)
{
Output_section* dummy;
*dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value,
NULL, &dummy);
+ *load_address = *dot_value;
}
// Print for debugging.
@@ -1215,7 +1216,7 @@ class Output_section_definition : public Sections_element
// Set the section address.
void
set_section_addresses(Symbol_table* symtab, Layout* layout,
- uint64_t* dot_value);
+ uint64_t* dot_value, uint64_t* load_address);
// Check a constraint (ONLY_IF_RO, etc.) on an output section. If
// this section is constrained, and the input sections do not match,
@@ -1560,7 +1561,8 @@ Output_section_definition::place_orphan_here(const Output_section *os,
void
Output_section_definition::set_section_addresses(Symbol_table* symtab,
Layout* layout,
- uint64_t* dot_value)
+ uint64_t* dot_value,
+ uint64_t* load_address)
{
uint64_t address;
if (this->address_ == NULL)
@@ -1594,6 +1596,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
address = align_address(address, align);
+ uint64_t start_address = address;
+
*dot_value = address;
// The address of non-SHF_ALLOC sections is forced to zero,
@@ -1663,6 +1667,12 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
&input_sections);
gold_assert(input_sections.empty());
+
+ if (this->load_address_ == NULL || this->output_section_ == NULL)
+ *load_address = *dot_value;
+ else
+ *load_address = (this->output_section_->load_address()
+ + (*dot_value - start_address));
}
// Check a constraint (ONLY_IF_RO, etc.) on an output section. If
@@ -1845,7 +1855,7 @@ class Orphan_output_section : public Sections_element
// Set section addresses.
void
- set_section_addresses(Symbol_table*, Layout*, uint64_t*);
+ set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*);
// Get the list of segments to use for an allocated section when
// using a PHDRS clause. If this is an allocated section, return
@@ -1884,15 +1894,23 @@ Orphan_output_section::place_orphan_here(const Output_section* os,
void
Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
- uint64_t* dot_value)
+ uint64_t* dot_value,
+ uint64_t* load_address)
{
typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list;
+ bool have_load_address = *load_address != *dot_value;
+
uint64_t address = *dot_value;
address = align_address(address, this->os_->addralign());
if ((this->os_->flags() & elfcpp::SHF_ALLOC) != 0)
- this->os_->set_address(address);
+ {
+ this->os_->set_address(address);
+ if (have_load_address)
+ this->os_->set_load_address(align_address(*load_address,
+ this->os_->addralign()));
+ }
Input_section_list input_sections;
address += this->os_->get_input_sections(address, "", &input_sections);
@@ -1919,6 +1937,11 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
address += size;
}
+ if (!have_load_address)
+ *load_address = address;
+ else
+ *load_address += address - *dot_value;
+
*dot_value = address;
}
@@ -2327,10 +2350,11 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout)
// For a relocatable link, we implicitly set dot to zero.
uint64_t dot_value = 0;
+ uint64_t load_address = 0;
for (Sections_elements::iterator p = this->sections_elements_->begin();
p != this->sections_elements_->end();
++p)
- (*p)->set_section_addresses(symtab, layout, &dot_value);
+ (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address);
if (this->phdrs_elements_ != NULL)
{