aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-08-03 15:05:05 +0000
committerIan Lance Taylor <ian@airs.com>2010-08-03 15:05:05 +0000
commit1e3811b0c6bb6bcc0cd5e006375f4afccc6a0640 (patch)
tree617ac4122ab4a3bbd8c146b4c0b499a74efb1117 /gold/layout.cc
parent7af0c62018c46f61c3653a2662faace8598da2ea (diff)
downloadgdb-1e3811b0c6bb6bcc0cd5e006375f4afccc6a0640.zip
gdb-1e3811b0c6bb6bcc0cd5e006375f4afccc6a0640.tar.gz
gdb-1e3811b0c6bb6bcc0cd5e006375f4afccc6a0640.tar.bz2
PR 11712
* layout.cc (relaxation_loop_body): If address of load segment is set, adjust address to include headers if possible.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc32
1 files changed, 28 insertions, 4 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 1107fa6..3a01e92 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1655,17 +1655,41 @@ Layout::relaxation_loop_body(
|| this->script_options_->saw_sections_clause());
// If the address of the load segment we found has been set by
- // --section-start rather than by a script, then we don't want to
- // use it for the file and segment headers.
+ // --section-start rather than by a script, then adjust the VMA and
+ // LMA downward if possible to include the file and section headers.
+ uint64_t header_gap = 0;
if (load_seg != NULL
&& load_seg->are_addresses_set()
- && !this->script_options_->saw_sections_clause())
- load_seg = NULL;
+ && !this->script_options_->saw_sections_clause()
+ && !parameters->options().relocatable())
+ {
+ file_header->finalize_data_size();
+ segment_headers->finalize_data_size();
+ size_t sizeof_headers = (file_header->data_size()
+ + segment_headers->data_size());
+ const uint64_t abi_pagesize = target->abi_pagesize();
+ uint64_t hdr_paddr = load_seg->paddr() - sizeof_headers;
+ hdr_paddr &= ~(abi_pagesize - 1);
+ uint64_t subtract = load_seg->paddr() - hdr_paddr;
+ if (load_seg->paddr() < subtract || load_seg->vaddr() < subtract)
+ load_seg = NULL;
+ else
+ {
+ load_seg->set_addresses(load_seg->vaddr() - subtract,
+ load_seg->paddr() - subtract);
+ header_gap = subtract - sizeof_headers;
+ }
+ }
// Lay out the segment headers.
if (!parameters->options().relocatable())
{
gold_assert(segment_headers != NULL);
+ if (header_gap != 0 && load_seg != NULL)
+ {
+ Output_data_zero_fill* z = new Output_data_zero_fill(header_gap, 1);
+ load_seg->add_initial_output_data(z);
+ }
if (load_seg != NULL)
load_seg->add_initial_output_data(segment_headers);
if (phdr_seg != NULL)