summaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2011-07-06 21:19:32 +0000
committerCary Coutant <ccoutant@google.com>2011-07-06 21:19:32 +0000
commit9fbd3822ad34dced1ec88410f3f1b447d30e6435 (patch)
tree095ca61510e2bbeca8a22eb82909691b0d945da1 /gold/output.cc
parent438640d1120a37fb0309164e84c82e01fe98c5a9 (diff)
* incremental.cc (Incremental_inputs::report_command_line): Ignore
--incremental-patch option. * layout.cc (Free_list::allocate): Extend allocation beyond original end if enabled. (Layout::make_output_section): Mark sections that should get patch space. * options.cc (parse_percent): New function. * options.h (parse_percent): New function. (DEFINE_percent): New macro. (General_options): Add --incremental-patch option. * output.cc (Output_section::Output_section): Initialize new data members. (Output_section::add_input_section): Print section name when out of patch space. (Output_section::add_output_section_data): Likewise. (Output_section::set_final_data_size): Add patch space when doing --incremental-full. (Output_section::do_reset_address_and_file_offset): Remove patch space. (Output_segment::set_section_list_addresses): Print debug output only if --incremental-update. * output.h (Output_section::set_is_patch_space_allowed): New function. (Output_section::is_patch_space_allowed_): New data member. (Output_section::patch_space_): New data member. * parameters.cc (Parameters::incremental_full): New function. * parameters.h (Parameters::incremental_full): New function * testsuite/Makefile.am (incremental_test_2): Add test for --incremental-patch option. * testsuite/Makefile.in: Regenerate. * testsuite/two_file_test_1_v1.cc (t1, t2, t3): Add comments. (t18): Remove function body.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc92
1 files changed, 62 insertions, 30 deletions
diff --git a/gold/output.cc b/gold/output.cc
index 8a781c5e87..b9cfafd9cd 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -2153,10 +2153,12 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
is_noload_(false),
always_keeps_input_sections_(false),
has_fixed_layout_(false),
+ is_patch_space_allowed_(false),
tls_offset_(0),
checkpoint_(NULL),
lookup_maps_(new Output_section_lookup_maps),
- free_list_()
+ free_list_(),
+ patch_space_(0)
{
// An unallocated section has no address. Forcing this means that
// we don't need special treatment for symbols defined in debug
@@ -2271,7 +2273,9 @@ Output_section::add_input_section(Layout* layout,
offset_in_section = this->free_list_.allocate(input_section_size,
addralign, 0);
if (offset_in_section == -1)
- gold_fallback(_("out of patch space; relink with --incremental-full"));
+ gold_fallback(_("out of patch space in section %s; "
+ "relink with --incremental-full"),
+ this->name());
aligned_offset_in_section = offset_in_section;
}
else
@@ -2375,8 +2379,9 @@ Output_section::add_output_section_data(Output_section_data* posd)
offset_in_section = this->free_list_.allocate(posd->data_size(),
posd->addralign(), 0);
if (offset_in_section == -1)
- gold_fallback(_("out of patch space; "
- "relink with --incremental-full"));
+ gold_fallback(_("out of patch space in section %s; "
+ "relink with --incremental-full"),
+ this->name());
// Finalize the address and offset now.
uint64_t addr = this->address();
off_t offset = this->offset();
@@ -2946,30 +2951,48 @@ Output_section::update_data_size()
void
Output_section::set_final_data_size()
{
+ off_t data_size;
+
if (this->input_sections_.empty())
+ data_size = this->current_data_size_for_child();
+ else
{
- this->set_data_size(this->current_data_size_for_child());
- return;
- }
+ if (this->must_sort_attached_input_sections()
+ || this->input_section_order_specified())
+ this->sort_attached_input_sections();
- if (this->must_sort_attached_input_sections()
- || this->input_section_order_specified())
- this->sort_attached_input_sections();
+ uint64_t address = this->address();
+ off_t startoff = this->offset();
+ off_t off = startoff + this->first_input_offset_;
+ for (Input_section_list::iterator p = this->input_sections_.begin();
+ p != this->input_sections_.end();
+ ++p)
+ {
+ off = align_address(off, p->addralign());
+ p->set_address_and_file_offset(address + (off - startoff), off,
+ startoff);
+ off += p->data_size();
+ }
+ data_size = off - startoff;
+ }
- uint64_t address = this->address();
- off_t startoff = this->offset();
- off_t off = startoff + this->first_input_offset_;
- for (Input_section_list::iterator p = this->input_sections_.begin();
- p != this->input_sections_.end();
- ++p)
+ // For full incremental links, we want to allocate some patch space
+ // in most sections for subsequent incremental updates.
+ if (this->is_patch_space_allowed_ && parameters->incremental_full())
{
- off = align_address(off, p->addralign());
- p->set_address_and_file_offset(address + (off - startoff), off,
- startoff);
- off += p->data_size();
+ double pct = parameters->options().incremental_patch();
+ off_t extra = static_cast<off_t>(data_size * pct);
+ off_t new_size = align_address(data_size + extra, this->addralign());
+ this->patch_space_ = new_size - data_size;
+ gold_debug(DEBUG_INCREMENTAL,
+ "set_final_data_size: %08lx + %08lx: section %s",
+ static_cast<long>(data_size),
+ static_cast<long>(this->patch_space_),
+ this->name());
+ data_size = new_size;
}
- this->set_data_size(off - startoff);
+ this->set_data_size(data_size);
}
// Reset the address and file offset.
@@ -2988,8 +3011,16 @@ Output_section::do_reset_address_and_file_offset()
p != this->input_sections_.end();
++p)
p->reset_address_and_file_offset();
+
+ // Remove any patch space that was added in set_final_data_size.
+ if (this->patch_space_ > 0)
+ {
+ this->set_current_data_size_for_child(this->current_data_size_for_child()
+ - this->patch_space_);
+ this->patch_space_ = 0;
+ }
}
-
+
// Return true if address and file offset have the values after reset.
bool
@@ -4265,14 +4296,15 @@ Output_segment::set_section_list_addresses(Layout* layout, bool reset,
(*p)->finalize_data_size();
}
- gold_debug(DEBUG_INCREMENTAL,
- "set_section_list_addresses: %08lx %08lx %s",
- static_cast<long>(off),
- static_cast<long>((*p)->data_size()),
- ((*p)->output_section() != NULL
- ? (*p)->output_section()->name() : "(special)"));
-
- // We want to ignore the size of a SHF_TLS or SHT_NOBITS
+ if (parameters->incremental_update())
+ gold_debug(DEBUG_INCREMENTAL,
+ "set_section_list_addresses: %08lx %08lx %s",
+ static_cast<long>(off),
+ static_cast<long>((*p)->data_size()),
+ ((*p)->output_section() != NULL
+ ? (*p)->output_section()->name() : "(special)"));
+
+ // We want to ignore the size of a SHF_TLS SHT_NOBITS
// section. Such a section does not affect the size of a
// PT_LOAD segment.
if (!(*p)->is_section_flag_set(elfcpp::SHF_TLS)