* 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.
This commit is contained in:
Cary Coutant 2011-07-06 21:19:32 +00:00
parent 438640d112
commit 9fbd3822ad
12 changed files with 175 additions and 42 deletions

View file

@ -1,3 +1,37 @@
2011-07-06 Cary Coutant <ccoutant@google.com>
* 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.
2011-07-05 Doug Kwan <dougkwan@google.com>
PR gold/12771

View file

@ -925,9 +925,11 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
|| strcmp(argv[i], "--incremental-unchanged") == 0
|| strcmp(argv[i], "--incremental-unknown") == 0
|| is_prefix_of("--incremental-base=", argv[i])
|| is_prefix_of("--incremental-patch=", argv[i])
|| is_prefix_of("--debug=", argv[i]))
continue;
if (strcmp(argv[i], "--incremental-base") == 0
|| strcmp(argv[i], "--incremental-patch") == 0
|| strcmp(argv[i], "--debug") == 0)
{
// When these options are used without the '=', skip the

View file

@ -168,6 +168,11 @@ Free_list::allocate(off_t len, uint64_t align, off_t minoff)
off_t start = p->start_ > minoff ? p->start_ : minoff;
start = align_address(start, align);
off_t end = start + len;
if (end > p->end_ && p->end_ == this->length_ && this->extend_)
{
this->length_ = end;
p->end_ = end;
}
if (end <= p->end_)
{
if (p->start_ + 3 >= start && p->end_ <= end + 3)
@ -186,6 +191,12 @@ Free_list::allocate(off_t len, uint64_t align, off_t minoff)
return start;
}
}
if (this->extend_)
{
off_t start = align_address(this->length_, align);
this->length_ = start + len;
return start;
}
return -1;
}
@ -1413,6 +1424,21 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
&& strcmp(name + strlen(name) - 3, "str") == 0)
this->have_stabstr_section_ = true;
// During a full incremental link, we add patch space to most
// PROGBITS and NOBITS sections. Flag those that may be
// arbitrarily padded.
if ((type == elfcpp::SHT_PROGBITS || type == elfcpp::SHT_NOBITS)
&& order != ORDER_INTERP
&& order != ORDER_INIT
&& order != ORDER_PLT
&& order != ORDER_FINI
&& order != ORDER_RELRO_LAST
&& order != ORDER_NON_RELRO_FIRST
&& strcmp(name, ".ctors") != 0
&& strcmp(name, ".dtors") != 0
&& strcmp(name, ".jcr") != 0)
os->set_is_patch_space_allowed();
// If we have already attached the sections to segments, then we
// need to attach this one now. This happens for sections created
// directly by the linker.

View file

@ -234,6 +234,17 @@ parse_double(const char* option_name, const char* arg, double* retval)
option_name, arg);
}
void
parse_percent(const char* option_name, const char* arg, double* retval)
{
char* endptr;
*retval = strtod(arg, &endptr) / 100.0;
if (*endptr != '\0')
gold_fatal(_("%s: invalid option value "
"(expected a floating point number): %s"),
option_name, arg);
}
void
parse_string(const char* option_name, const char* arg, const char** retval)
{

View file

@ -97,6 +97,9 @@ parse_uint64(const char* option_name, const char* arg, uint64_t* retval);
extern void
parse_double(const char* option_name, const char* arg, double* retval);
extern void
parse_percent(const char* option_name, const char* arg, double* retval);
extern void
parse_string(const char* option_name, const char* arg, const char** retval);
@ -372,6 +375,12 @@ struct Struct_special : public Struct_var
#default_value__, helpstring__, helparg__, false, \
double, double, options::parse_double)
#define DEFINE_percent(varname__, dashes__, shortname__, default_value__, \
helpstring__, helparg__) \
DEFINE_var(varname__, dashes__, shortname__, default_value__ / 100.0, \
#default_value__, helpstring__, helparg__, false, \
double, double, options::parse_percent)
#define DEFINE_string(varname__, dashes__, shortname__, default_value__, \
helpstring__, helparg__) \
DEFINE_var(varname__, dashes__, shortname__, default_value__, \
@ -813,6 +822,10 @@ class General_options
DEFINE_special(incremental_unknown, options::TWO_DASHES, '\0',
N_("Use timestamps to check files (default)"), NULL);
DEFINE_percent(incremental_patch, options::TWO_DASHES, '\0', 10,
N_("Amount of extra space to allocate for patches"),
N_("PERCENT"));
DEFINE_string(init, options::ONE_DASH, '\0', "_init",
N_("Call SYMBOL at load-time"), N_("SYMBOL"));

View file

@ -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();
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;
}
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)
// 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)"));
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 or SHT_NOBITS
// 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)

View file

@ -3427,6 +3427,12 @@ class Output_section : public Output_data
has_fixed_layout() const
{ return this->has_fixed_layout_; }
// Set flag to allow patch space for this section. Used for full
// incremental links.
void
set_is_patch_space_allowed()
{ this->is_patch_space_allowed_ = true; }
// Reserve space within the fixed layout for the section. Used for
// incremental update links.
void
@ -3890,6 +3896,8 @@ class Output_section : public Output_data
bool always_keeps_input_sections_ : 1;
// Whether this section has a fixed layout, for incremental update links.
bool has_fixed_layout_ : 1;
// True if we can add patch space to this section.
bool is_patch_space_allowed_ : 1;
// For SHT_TLS sections, the offset of this section relative to the base
// of the TLS segment.
uint64_t tls_offset_;
@ -3900,6 +3908,8 @@ class Output_section : public Output_data
// List of available regions within the section, for incremental
// update links.
Free_list free_list_;
// Amount added as patch space for incremental linking.
off_t patch_space_;
};
// An output segment. PT_LOAD segments are built from collections of

View file

@ -248,6 +248,14 @@ Parameters::incremental() const
return this->incremental_mode_ != General_options::INCREMENTAL_OFF;
}
// Return true if we are doing a full incremental link.
bool
Parameters::incremental_full() const
{
return this->incremental_mode_ == General_options::INCREMENTAL_FULL;
}
// Return true if we are doing an incremental update.
bool

View file

@ -159,6 +159,10 @@ class Parameters
bool
incremental() const;
// Return true if we are doing a full incremental link.
bool
incremental_full() const;
// Return true if we are doing an incremental update.
bool
incremental_update() const;

View file

@ -1903,7 +1903,7 @@ MOSTLYCLEANFILES += two_file_test_tmp_2.o
incremental_test_2: two_file_test_1_v1.o two_file_test_1.o two_file_test_1b.o \
two_file_test_2.o two_file_test_main.o gcctestdir/ld
cp -f two_file_test_1_v1.o two_file_test_tmp_2.o
$(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
$(CXXLINK) -Wl,--incremental-full,--incremental-patch=100 -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
@sleep 1
cp -f two_file_test_1.o two_file_test_tmp_2.o
$(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o

View file

@ -4783,7 +4783,7 @@ uninstall-am:
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test_2: two_file_test_1_v1.o two_file_test_1.o two_file_test_1b.o \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.o two_file_test_main.o gcctestdir/ld
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f two_file_test_1_v1.o two_file_test_tmp_2.o
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-full,--incremental-patch=100 -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ @sleep 1
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ cp -f two_file_test_1.o two_file_test_tmp_2.o
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o

View file

@ -62,7 +62,7 @@
bool
t1()
{
return t1_2() == 0;
return t1_2() == 0; // Intentionally wrong.
}
// 2 Code in file 1 refers to global data in file 2.
@ -70,7 +70,7 @@ t1()
bool
t2()
{
return v2 == 0;
return v2 == 0; // Intentionally wrong.
}
// 3 Code in file 1 referes to common symbol in file 2.
@ -78,7 +78,7 @@ t2()
bool
t3()
{
return v3 == 0;
return v3 == 0; // Intentionally wrong.
}
// 4 Code in file 1 refers to offset within global data in file 2.
@ -231,13 +231,6 @@ t17()
bool
t18()
{
char c = 'a';
for (int i = 0; i < T17_COUNT; ++i)
{
const char* s = f18(i);
if (s[0] != c || s[1] != '\0')
return false;
++c;
}
// Stubbed out; full implementation in two_file_test_1.cc.
return true;
}