[gold patch] Incremental 8/18: Initial support for incremental update

Cary Coutant ccoutant@google.com
Mon Apr 11 23:09:00 GMT 2011


>> +      if (options.has_plugins())
>> +     gold_error(_("incremental linking is incompatible with --plugin"));
>
> Will this be possible at some future date?

It could be, but I haven't thought through all the implications. With
plugins, it's hard to guarantee that all the restrictions we impose
are met. What should we do with an IR file marked
--incremental-unchanged? The LTO plugin would probably still prefer to
claim it, and would have to if it's a pure IR file. The use cases for
LTO and for incremental linking seem opposed to each other -- LTO
wants to see and recompile as much as possible, while incremental
linking wants to see minimal changes.

>> +      // Incremental update link.  Process the list of input files
>> +      // stored in the base file, and queue a task for each file:
>> +      // a Read_symbols task for a changed file, and an Add_symbols task
>> +      // for an unchanged file.  We need to mark all the space used by
>> +      // unchanged files before we can start any tasks running.
>> +      std::list<Task*> tasks;
>
> Add tasks.reserve(input_file_count);

OK.

>> +// Process an incremental input file: if it is unchanged from the previous
>> +// link, return a task to add its symbols from the base file's incremental
>> +// info; if it has changed, return a normal Read_symbols task.  We create a
>> +// task for every input file, if only to report the file for rebuilding the
>> +// incremental info.
>> +
>> +Task*
>> +process_incremental_input(Incremental_binary* ibase,
>> +                       unsigned int input_file_index,
>> +                       Input_objects* input_objects,
>> +                       Symbol_table* symtab,
>> +                       Layout* layout,
>> +                       Dirsearch* search_path,
>> +                       Mapfile* mapfile,
>> +                       Task_token* this_blocker,
>> +                       Task_token* next_blocker)
>> +{
>
> This function should be static.

OK.

>> +  gold_debug(DEBUG_INCREMENTAL,   "Incremental object: %s, type %d",
>> +          input_reader->filename(), input_type);
>
> s/   / /

OK.

>> +  if (input_type == INCREMENTAL_INPUT_ARCHIVE)
>> +    {
>> +      Incremental_library* lib = ibase->get_library(input_file_index);
>> +      gold_assert(lib != NULL);
>> +      if (lib->filename() == "<group>"
>> +       || !ibase->file_has_changed(input_file_index))
>
> Hmmm.  For extreme cleanliness, suppose we change "<group>" to "/group/"
> or some other name containing a '/', so that we know for sure that there
> is no input file with that name.

Good idea. I was bothered by that myself, and intended to come back to
this with a cleaner solution. I'll use "/group/" for now.

>> @@ -396,7 +586,8 @@ queue_middle_tasks(const General_options& options,
>>    // generate an empty file.  Existing builds depend on being able to
>>    // pass an empty archive to the linker and get an empty object file
>>    // out.  In order to do this we need to use a default target.
>> -  if (input_objects->number_of_input_objects() == 0)
>> +  if (input_objects->number_of_input_objects() == 0
>> +      && layout->incremental_base() == NULL)
>>      parameters_force_valid_target();
>
> Why this change?

If there are no changed files at all, we want to base the target on
the base file rather than the arbitrary target that
parameters_force_valid_target() would choose.

Hmmm, if there are no changed files, we have no work to do, and we
should have just exited the link by this point. I'll take a closer
look at this.

>> +// Allocate an incremental object of the appropriate size and endianness.
>> +Object*
>> +make_sized_incremental_object(
>> +    Incremental_binary* base,
>> +    unsigned int input_file_index,
>> +    Incremental_input_type input_type,
>> +    const Incremental_binary::Input_reader* input_reader);
>
> Add "extern".

OK.

>> @@ -869,7 +1086,9 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
>>        this->eh_frame_section_ = os;
>>        this->eh_frame_data_ = new Eh_frame();
>>
>> -      if (parameters->options().eh_frame_hdr())
>> +      // For incremental linking, we do not optimize .eh_frame sections
>> +      // or create a .eh_frame_hdr section.
>> +      if (parameters->options().eh_frame_hdr() && !parameters->incremental())
>>       {
>>         Output_section* hdr_os =
>>           this->choose_output_section(NULL, ".eh_frame_hdr",
>> @@ -901,14 +1120,15 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
>>
>>    gold_assert(this->eh_frame_section_ == os);
>>
>> -  if (this->eh_frame_data_->add_ehframe_input_section(object,
>> -                                                   symbols,
>> -                                                   symbols_size,
>> -                                                   symbol_names,
>> -                                                   symbol_names_size,
>> -                                                   shndx,
>> -                                                   reloc_shndx,
>> -                                                   reloc_type))
>> +  if (!parameters->incremental()
>> +      && this->eh_frame_data_->add_ehframe_input_section(object,
>> +                                                      symbols,
>> +                                                      symbols_size,
>> +                                                      symbol_names,
>> +                                                      symbol_names_size,
>> +                                                      shndx,
>> +                                                      reloc_shndx,
>> +                                                      reloc_type))
>>      {
>>        os->update_flags_for_input_section(shdr.get_sh_flags());
>>
>
> Where do these things happen when doing an incremental link?

I haven't yet implemented the .eh_frame_hdr section for incremental
linking -- my plan is to rebuild it from scratch rather than try to
update it in place, but that means it'll need to rescan all the
.eh_frame sections from the unchanged files as well as changed files.

> This is OK with those changes.

Thanks. I'll post an updated patch when I resolve the
parameters_force_valid_target() issue. Or, if it's OK with you, I can
commit this patch with the changes you've noted and follow up later
with another patch to improve the no-changed-files case.

-cary



More information about the Binutils mailing list