PR ld/11843
[binutils.git] / gold / incremental.h
bloba94f39719c961c864880aa515a2c423357eb62dd
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
26 #include <map>
27 #include <vector>
29 #include "elfcpp_file.h"
30 #include "stringpool.h"
31 #include "workqueue.h"
32 #include "fileread.h"
33 #include "output.h"
35 namespace gold
38 class Archive;
39 class Input_argument;
40 class Incremental_inputs_checker;
41 class Object;
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;
67 // Padding.
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
77 private:
78 typedef Incremental_inputs_header_data Data_type;
79 typedef elfcpp::Convert<32, big_endian> Convert32;
81 public:
82 Incremental_inputs_header(const unsigned char *p)
83 : p_(reinterpret_cast<const Data_type*>(p))
84 { }
86 static const int data_size = sizeof(Data_type);
88 elfcpp::Elf_Word
89 get_version() const
90 { return Convert32::convert_host(this->p_->version); }
92 elfcpp::Elf_Word
93 get_input_file_count() const
94 { return Convert32::convert_host(this->p_->input_file_count); }
96 elfcpp::Elf_Word
97 get_command_line_offset() const
98 { return Convert32::convert_host(this->p_->command_line_offset); }
100 elfcpp::Elf_Word
101 get_reserved() const
102 { return Convert32::convert_host(this->p_->reserved); }
104 private:
105 const Data_type* p_;
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
114 private:
115 typedef Incremental_inputs_header_data Data_type;
116 typedef elfcpp::Convert<32, big_endian> Convert32;
118 public:
119 Incremental_inputs_header_write(unsigned char *p)
120 : p_(reinterpret_cast<Data_type*>(p))
123 static const int data_size = sizeof(Data_type);
125 void
126 put_version(elfcpp::Elf_Word v)
127 { this->p_->version = Convert32::convert_host(v); }
129 void
130 put_input_file_count(elfcpp::Elf_Word v)
131 { this->p_->input_file_count = Convert32::convert_host(v); }
133 void
134 put_command_line_offset(elfcpp::Elf_Word v)
135 { this->p_->command_line_offset = Convert32::convert_host(v); }
137 void
138 put_reserved(elfcpp::Elf_Word v)
139 { this->p_->reserved = Convert32::convert_host(v); }
141 private:
142 Data_type* p_;
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;
164 // Padding.
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
173 private:
174 typedef Incremental_inputs_entry_data Data_type;
175 typedef elfcpp::Convert<32, big_endian> Convert32;
176 typedef elfcpp::Convert<64, big_endian> Convert64;
178 public:
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);
185 elfcpp::Elf_Word
186 get_filename_offset()
187 { return Convert32::convert_host(this->p_->filename_offset); }
189 elfcpp::Elf_Word
190 get_data_offset()
191 { return Convert32::convert_host(this->p_->data_offset); }
193 elfcpp::Elf_Xword
194 get_timestamp_sec()
195 { return Convert64::convert_host(this->p_->timestamp_sec); }
197 elfcpp::Elf_Word
198 get_timestamp_nsec()
199 { return Convert32::convert_host(this->p_->timestamp_nsec); }
201 elfcpp::Elf_Word
202 get_input_type()
203 { return Convert32::convert_host(this->p_->input_type); }
205 elfcpp::Elf_Word
206 get_reserved()
207 { return Convert32::convert_host(this->p_->reserved); }
209 private:
210 const Data_type* p_;
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
218 private:
219 typedef Incremental_inputs_entry_data Data_type;
220 typedef elfcpp::Convert<32, big_endian> Convert32;
221 typedef elfcpp::Convert<64, big_endian> Convert64;
223 public:
224 Incremental_inputs_entry_write(unsigned char *p)
225 : p_(reinterpret_cast<Data_type*>(p))
228 static const int data_size = sizeof(Data_type);
230 void
231 put_filename_offset(elfcpp::Elf_Word v)
232 { this->p_->filename_offset = Convert32::convert_host(v); }
234 void
235 put_data_offset(elfcpp::Elf_Word v)
236 { this->p_->data_offset = Convert32::convert_host(v); }
238 void
239 put_timestamp_sec(elfcpp::Elf_Xword v)
240 { this->p_->timestamp_sec = Convert64::convert_host(v); }
242 void
243 put_timestamp_nsec(elfcpp::Elf_Word v)
244 { this->p_->timestamp_nsec = Convert32::convert_host(v); }
246 void
247 put_input_type(elfcpp::Elf_Word v)
248 { this->p_->input_type = Convert32::convert_host(v); }
250 void
251 put_reserved(elfcpp::Elf_Word v)
252 { this->p_->reserved = Convert32::convert_host(v); }
254 private:
255 Data_type* p_;
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
266 public:
267 Incremental_binary(Output_file* output, Target* target)
268 : output_(output), target_(target)
271 virtual
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
277 // elfcpp::Elf_file.
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.
282 class View
284 public:
285 View(const unsigned char* p)
286 : p_(p)
289 const unsigned char*
290 data() const
291 { return this->p_; }
293 private:
294 const unsigned char* p_;
297 // Return a View.
298 View
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.
303 struct Location
305 off_t file_offset;
306 off_t data_size;
308 Location(off_t fo, section_size_type ds)
309 : file_offset(fo), data_size(ds)
312 Location()
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)); }
321 // Report an error.
322 void
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
327 // is not found.
328 bool
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.
339 virtual bool
340 check_inputs(Incremental_inputs* incremental_inputs)
341 { return do_check_inputs(incremental_inputs); }
343 protected:
344 // Find incremental inputs section.
345 virtual bool
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.
351 virtual bool
352 do_check_inputs(Incremental_inputs* incremental_inputs) = 0;
354 private:
355 // Edited output file object.
356 Output_file* output_;
357 // Target of the output file.
358 Target* target_;
361 template<int size, bool big_endian>
362 class Sized_incremental_binary : public Incremental_binary
364 public:
365 Sized_incremental_binary(Output_file* output,
366 const elfcpp::Ehdr<size, big_endian>& ehdr,
367 Target* target)
368 : Incremental_binary(output, target), elf_file_(this, ehdr)
371 protected:
372 virtual bool
373 do_find_incremental_inputs_section(Location* location,
374 unsigned int* strtab_shndx);
376 virtual bool
377 do_check_inputs(Incremental_inputs* incremental_inputs);
379 private:
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.
386 Incremental_binary*
387 open_incremental_binary(Output_file* file);
389 // Code invoked early during an incremental link that checks what files need
390 // to be relinked.
391 class Incremental_checker
393 public:
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.
406 bool
407 can_incrementally_link_output_file();
409 private:
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
422 public:
423 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.
430 void
431 report_command_line(int argc, const char* const* argv);
433 // Record the input arguments obtained from parsing the command line.
434 void
435 report_inputs(const Input_arguments& inputs)
436 { this->inputs_ = &inputs; }
438 // Record that the input argument INPUT is an archive ARCHIVE.
439 void
440 report_archive(const Input_argument* input, Archive* archive);
442 // Record that the input argument INPUT is to an object OBJ.
443 void
444 report_object(const Input_argument* input, Object* obj);
446 // Record that the input argument INPUT is to an script SCRIPT.
447 void
448 report_script(const Input_argument* input, Timespec mtime,
449 Script_info* script);
451 // Prepare for layout. Called from Layout::finalize.
452 void
453 finalize();
455 // Create the content of the .gnu_incremental_inputs section.
456 Output_section_data*
457 create_incremental_inputs_section_data();
459 // Return the .gnu_incremental_strtab stringpool.
460 Stringpool*
461 get_stringpool()
462 { return this->strtab_; }
464 // Return the canonical form of the command line, as will be stored in
465 // .gnu_incremental_strtab.
466 const std::string&
467 command_line()
468 { return this->command_line_; }
470 // Return the input files found in the command line.
471 const Input_arguments*
472 inputs()
473 { return this->inputs_; }
475 private:
476 // Code for each of the four possible variants of create_inputs_section_data.
477 template<int size, bool big_endian>
478 Output_section_data*
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.
485 void
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.
492 struct Input_info
494 Input_info()
495 : type(INCREMENTAL_INPUT_INVALID), archive(NULL), filename_key(0),
496 index(0)
499 // Type of the file pointed by this argument.
500 Incremental_input_type type;
502 union
504 // Present if type == INCREMENTAL_INPUT_ARCHIVE.
505 Archive* archive;
507 // Present if type == INCREMENTAL_INPUT_OBJECT or
508 // INCREMENTAL_INPUT_SHARED_LIBRARY.
509 Object* object;
511 // Present if type == INCREMENTAL_INPUT_SCRIPT.
512 Script_info* 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.
519 unsigned int index;
521 // Last modification time of the file.
522 Timespec mtime;
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.
529 Lock* lock_;
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.
546 Stringpool* strtab_;
549 } // End namespace gold.
551 #endif // !defined(GOLD_INCREMENTAL_H)