1 // inremental.h -- incremental linking support for gold -*- C++ -*-
3 // Copyright 2009 Free Software Foundation, Inc.
4 // Written by Mikolaj Zalewski <mikolajz@google.com>.
6 // This file is part of gold.
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
23 #ifndef GOLD_INCREMENTAL_H
24 #define GOLD_INCREMENTAL_H
29 #include "elfcpp_file.h"
30 #include "stringpool.h"
31 #include "workqueue.h"
40 class Incremental_inputs_checker
;
42 class Output_section_data
;
44 // Incremental input type as stored in .gnu_incremental_inputs.
46 enum Incremental_input_type
48 INCREMENTAL_INPUT_INVALID
= 0,
49 INCREMENTAL_INPUT_OBJECT
= 1,
50 INCREMENTAL_INPUT_ARCHIVE
= 2,
51 INCREMENTAL_INPUT_SHARED_LIBRARY
= 3,
52 INCREMENTAL_INPUT_SCRIPT
= 4
55 // Header of the .gnu_incremental_input section.
56 struct Incremental_inputs_header_data
58 // Incremental linker version.
59 elfcpp::Elf_Word version
;
61 // Numer of input files in the link.
62 elfcpp::Elf_Word input_file_count
;
64 // Offset of command line options in .gnu_incremental_strtab.
65 elfcpp::Elf_Word command_line_offset
;
68 elfcpp::Elf_Word reserved
;
71 // Reader class for .gnu_incremental_inputs header. See
72 // Incremental_inputs_header_data for fields descriptions.
74 template<int size
, bool big_endian
>
75 class Incremental_inputs_header
78 typedef Incremental_inputs_header_data Data_type
;
79 typedef elfcpp::Convert
<32, big_endian
> Convert32
;
82 Incremental_inputs_header(const unsigned char *p
)
83 : p_(reinterpret_cast<const Data_type
*>(p
))
86 static const int data_size
= sizeof(Data_type
);
90 { return Convert32::convert_host(this->p_
->version
); }
93 get_input_file_count() const
94 { return Convert32::convert_host(this->p_
->input_file_count
); }
97 get_command_line_offset() const
98 { return Convert32::convert_host(this->p_
->command_line_offset
); }
102 { return Convert32::convert_host(this->p_
->reserved
); }
108 // Writer class for .gnu_incremental_inputs header. See
109 // Incremental_inputs_header_data for fields descriptions.
111 template<int size
, bool big_endian
>
112 class Incremental_inputs_header_write
115 typedef Incremental_inputs_header_data Data_type
;
116 typedef elfcpp::Convert
<32, big_endian
> Convert32
;
119 Incremental_inputs_header_write(unsigned char *p
)
120 : p_(reinterpret_cast<Data_type
*>(p
))
123 static const int data_size
= sizeof(Data_type
);
126 put_version(elfcpp::Elf_Word v
)
127 { this->p_
->version
= Convert32::convert_host(v
); }
130 put_input_file_count(elfcpp::Elf_Word v
)
131 { this->p_
->input_file_count
= Convert32::convert_host(v
); }
134 put_command_line_offset(elfcpp::Elf_Word v
)
135 { this->p_
->command_line_offset
= Convert32::convert_host(v
); }
138 put_reserved(elfcpp::Elf_Word v
)
139 { this->p_
->reserved
= Convert32::convert_host(v
); }
145 // Data stored in .gnu_incremental_input after the header for each of the
146 // Incremental_input_header_data::input_file_count input entries.
147 struct Incremental_inputs_entry_data
149 // Offset of file name in .gnu_incremental_strtab section.
150 elfcpp::Elf_Word filename_offset
;
152 // Offset of data in .gnu_incremental_input.
153 elfcpp::Elf_Word data_offset
;
155 // Timestamp (in seconds).
156 elfcpp::Elf_Xword timestamp_sec
;
158 // Nano-second part of timestamp (if supported).
159 elfcpp::Elf_Word timestamp_nsec
;
161 // Type of the input entry.
162 elfcpp::Elf_Half input_type
;
165 elfcpp::Elf_Half reserved
;
168 // Reader class for an .gnu_incremental_inputs entry. See
169 // Incremental_inputs_entry_data for fields descriptions.
170 template<int size
, bool big_endian
>
171 class Incremental_inputs_entry
174 typedef Incremental_inputs_entry_data Data_type
;
175 typedef elfcpp::Convert
<32, big_endian
> Convert32
;
176 typedef elfcpp::Convert
<64, big_endian
> Convert64
;
179 Incremental_inputs_entry(const unsigned char *p
)
180 : p_(reinterpret_cast<const Data_type
*>(p
))
183 static const int data_size
= sizeof(Data_type
);
186 get_filename_offset()
187 { return Convert32::convert_host(this->p_
->filename_offset
); }
191 { return Convert32::convert_host(this->p_
->data_offset
); }
195 { return Convert64::convert_host(this->p_
->timestamp_sec
); }
199 { return Convert32::convert_host(this->p_
->timestamp_nsec
); }
203 { return Convert32::convert_host(this->p_
->input_type
); }
207 { return Convert32::convert_host(this->p_
->reserved
); }
213 // Writer class for an .gnu_incremental_inputs entry. See
214 // Incremental_inputs_entry_data for fields descriptions.
215 template<int size
, bool big_endian
>
216 class Incremental_inputs_entry_write
219 typedef Incremental_inputs_entry_data Data_type
;
220 typedef elfcpp::Convert
<32, big_endian
> Convert32
;
221 typedef elfcpp::Convert
<64, big_endian
> Convert64
;
224 Incremental_inputs_entry_write(unsigned char *p
)
225 : p_(reinterpret_cast<Data_type
*>(p
))
228 static const int data_size
= sizeof(Data_type
);
231 put_filename_offset(elfcpp::Elf_Word v
)
232 { this->p_
->filename_offset
= Convert32::convert_host(v
); }
235 put_data_offset(elfcpp::Elf_Word v
)
236 { this->p_
->data_offset
= Convert32::convert_host(v
); }
239 put_timestamp_sec(elfcpp::Elf_Xword v
)
240 { this->p_
->timestamp_sec
= Convert64::convert_host(v
); }
243 put_timestamp_nsec(elfcpp::Elf_Word v
)
244 { this->p_
->timestamp_nsec
= Convert32::convert_host(v
); }
247 put_input_type(elfcpp::Elf_Word v
)
248 { this->p_
->input_type
= Convert32::convert_host(v
); }
251 put_reserved(elfcpp::Elf_Word v
)
252 { this->p_
->reserved
= Convert32::convert_host(v
); }
258 // An object representing the ELF file we edit during an incremental build.
259 // Similar to Object or Dynobj, but operates on Output_file and contains
260 // method specific to file edition (TBD). This is the abstract parent class
261 // implemented in Sized_incremental_binary<size, big_endian> for a specific
262 // endianness and size.
264 class Incremental_binary
267 Incremental_binary(Output_file
* output
, Target
* target
)
268 : output_(output
), target_(target
)
272 ~Incremental_binary()
275 // Functions and types for the elfcpp::Elf_file interface. This
276 // permit us to use Incremental_binary as the File template parameter for
279 // The View class is returned by view. It must support a single
280 // method, data(). This is trivial, because Output_file::get_output_view
281 // does what we need.
285 View(const unsigned char* p
)
294 const unsigned char* p_
;
299 view(off_t file_offset
, section_size_type data_size
)
300 { return View(this->output_
->get_input_view(file_offset
, data_size
)); }
302 // A location in the file.
308 Location(off_t fo
, section_size_type ds
)
309 : file_offset(fo
), data_size(ds
)
313 : file_offset(0), data_size(0)
317 // Get a View given a Location.
318 View
view(Location loc
)
319 { return View(this->view(loc
.file_offset
, loc
.data_size
)); }
323 error(const char* format
, ...) const ATTRIBUTE_PRINTF_2
;
325 // Find the .gnu_incremental_inputs section. It selects the first section
326 // of type SHT_GNU_INCREMENTAL_INPUTS. Returns false if such a section
329 find_incremental_inputs_section(Location
* location
,
330 unsigned int* strtab_shndx
)
331 { return do_find_incremental_inputs_section(location
, strtab_shndx
); }
333 // Check the .gnu_incremental_inputs section to see whether an incremental
334 // build is possible.
335 // TODO: on success, should report what files needs to be rebuilt.
336 // INCREMENTAL_INPUTS is used to read the canonical form of the command line
337 // and read the input arguments. TODO: for items that don't need to be
338 // rebuilt, we should also copy the incremental input information.
340 check_inputs(Incremental_inputs
* incremental_inputs
)
341 { return do_check_inputs(incremental_inputs
); }
344 // Find incremental inputs section.
346 do_find_incremental_inputs_section(Location
* location
,
347 unsigned int* strtab_shndx
) = 0;
349 // Check the .gnu_incremental_inputs section to see whether an incremental
350 // build is possible.
352 do_check_inputs(Incremental_inputs
* incremental_inputs
) = 0;
355 // Edited output file object.
356 Output_file
* output_
;
357 // Target of the output file.
361 template<int size
, bool big_endian
>
362 class Sized_incremental_binary
: public Incremental_binary
365 Sized_incremental_binary(Output_file
* output
,
366 const elfcpp::Ehdr
<size
, big_endian
>& ehdr
,
368 : Incremental_binary(output
, target
), elf_file_(this, ehdr
)
373 do_find_incremental_inputs_section(Location
* location
,
374 unsigned int* strtab_shndx
);
377 do_check_inputs(Incremental_inputs
* incremental_inputs
);
380 // Output as an ELF file.
381 elfcpp::Elf_file
<size
, big_endian
, Incremental_binary
> elf_file_
;
384 // Create an Incremental_binary object for FILE. Returns NULL is this is not
385 // possible, e.g. FILE is not an ELF file or has an unsupported target.
387 open_incremental_binary(Output_file
* file
);
389 // Code invoked early during an incremental link that checks what files need
391 class Incremental_checker
394 // Check if the file named OUTPUT_NAME can be linked incrementally.
395 // INCREMENTAL_INPUTS must have the canonical form of the command line
396 // and input arguments filled - at this point of linking other fields are
397 // probably not filled yet. TODO: for inputs that don't need to be
398 // rebuilt, this function should fill the incremental input information.
399 Incremental_checker(const char* output_name
,
400 Incremental_inputs
* incremental_inputs
)
401 : output_name_(output_name
), incremental_inputs_(incremental_inputs
)
404 // Analyzes the output file to check if incremental linking is possible and
405 // what files needs to be relinked.
407 can_incrementally_link_output_file();
410 // Name of the output file to analyze.
411 const char* output_name_
;
413 // The Incremental_inputs object. At this stage of link, only the command
414 // line and inputs are filled.
415 Incremental_inputs
* incremental_inputs_
;
418 // This class contains the information needed during an incremental
419 // build about the inputs necessary to build the .gnu_incremental_inputs.
420 class Incremental_inputs
424 : lock_(new Lock()), inputs_(NULL
), command_line_key_(0),
425 strtab_(new Stringpool())
427 ~Incremental_inputs() { delete this->strtab_
; }
429 // Record the command line.
431 report_command_line(int argc
, const char* const* argv
);
433 // Record the input arguments obtained from parsing the command line.
435 report_inputs(const Input_arguments
& inputs
)
436 { this->inputs_
= &inputs
; }
438 // Record that the input argument INPUT is an archive ARCHIVE.
440 report_archive(const Input_argument
* input
, Archive
* archive
);
442 // Record that the input argument INPUT is to an object OBJ.
444 report_object(const Input_argument
* input
, Object
* obj
);
446 // Record that the input argument INPUT is to an script SCRIPT.
448 report_script(const Input_argument
* input
, Timespec mtime
,
449 Script_info
* script
);
451 // Prepare for layout. Called from Layout::finalize.
455 // Create the content of the .gnu_incremental_inputs section.
457 create_incremental_inputs_section_data();
459 // Return the .gnu_incremental_strtab stringpool.
462 { return this->strtab_
; }
464 // Return the canonical form of the command line, as will be stored in
465 // .gnu_incremental_strtab.
468 { return this->command_line_
; }
470 // Return the input files found in the command line.
471 const Input_arguments
*
473 { return this->inputs_
; }
476 // Code for each of the four possible variants of create_inputs_section_data.
477 template<int size
, bool big_endian
>
479 sized_create_inputs_section_data();
481 // Compute indexes in the order in which the inputs should appear in
482 // .gnu_incremental_inputs and put file names to the stringtable.
483 // This needs to be done after all the scripts are parsed.
486 finalize_inputs(Input_argument_list::const_iterator begin
,
487 Input_argument_list::const_iterator end
,
488 unsigned int* index
);
490 // Additional data about an input needed for an incremental link.
491 // None of these pointers is owned by the structure.
495 : type(INCREMENTAL_INPUT_INVALID
), archive(NULL
), filename_key(0),
499 // Type of the file pointed by this argument.
500 Incremental_input_type type
;
504 // Present if type == INCREMENTAL_INPUT_ARCHIVE.
507 // Present if type == INCREMENTAL_INPUT_OBJECT or
508 // INCREMENTAL_INPUT_SHARED_LIBRARY.
511 // Present if type == INCREMENTAL_INPUT_SCRIPT.
515 // Key of the filename string in the section stringtable.
516 Stringpool::Key filename_key
;
518 // Position of the entry information in the output section.
521 // Last modification time of the file.
525 typedef std::map
<const Input_argument
*, Input_info
> Inputs_info_map
;
527 // A lock guarding access to inputs_ during the first phase of linking, when
528 // report_ function may be called from multiple threads.
531 // The list of input arguments obtained from parsing the command line.
532 const Input_arguments
* inputs_
;
534 // A map containing additional information about the input elements.
535 Inputs_info_map inputs_map_
;
537 // Canonical form of the command line, as will be stored in
538 // .gnu_incremental_strtab.
539 std::string command_line_
;
541 // The key of the command line string in the string pool.
542 Stringpool::Key command_line_key_
;
544 // The .gnu_incremental_strtab string pool associated with the
545 // .gnu_incremental_inputs.
549 } // End namespace gold.
551 #endif // !defined(GOLD_INCREMENTAL_H)