diff options
author | Ian Lance Taylor <ian@airs.com> | 2010-08-03 15:05:05 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2010-08-03 15:05:05 +0000 |
commit | 1e3811b0c6bb6bcc0cd5e006375f4afccc6a0640 (patch) | |
tree | 617ac4122ab4a3bbd8c146b4c0b499a74efb1117 /gold/layout.cc | |
parent | 7af0c62018c46f61c3653a2662faace8598da2ea (diff) | |
download | gdb-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.cc | 32 |
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) |