#include "reduced_debug_output.h"
#include "reloc.h"
#include "descriptors.h"
-#include "layout.h"
#include "plugin.h"
+#include "incremental.h"
+#include "layout.h"
namespace gold
{
// Layout methods.
-Layout::Layout(const General_options& options, Script_options* script_options)
- : options_(options),
+Layout::Layout(int number_of_input_files, Script_options* script_options)
+ : number_of_input_files_(number_of_input_files),
script_options_(script_options),
namepool_(),
sympool_(),
segment_list_(),
section_list_(),
unattached_section_list_(),
- sections_are_attached_(false),
special_output_list_(),
section_headers_(NULL),
tls_segment_(NULL),
debug_info_(NULL),
group_signatures_(),
output_file_size_(-1),
+ sections_are_attached_(false),
input_requires_executable_stack_(false),
input_with_gnu_stack_note_(false),
input_without_gnu_stack_note_(false),
has_static_tls_(false),
- any_postprocessing_sections_(false)
+ any_postprocessing_sections_(false),
+ resized_signatures_(false),
+ incremental_inputs_(NULL)
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
// We expect two unattached Output_data objects: the file header and
// the segment headers.
this->special_output_list_.reserve(2);
+
+ // Initialize structure needed for an incremental build.
+ if (parameters->options().incremental())
+ this->incremental_inputs_ = new Incremental_inputs;
}
// Hash a key we use to look up an output section mapping.
os->set_info_symndx(sym);
else
{
+ // Reserve some space to minimize reallocations.
+ if (this->group_signatures_.empty())
+ this->group_signatures_.reserve(this->number_of_input_files_ * 16);
+
// We will wind up using a symbol whose name is the signature.
// So just put the signature in the symbol name pool to save it.
signature = symtab->canonicalize_name(signature);
this->eh_frame_section_ = os;
this->eh_frame_data_ = new Eh_frame();
- if (this->options_.eh_frame_hdr())
+ if (parameters->options().eh_frame_hdr())
{
Output_section* hdr_os =
this->choose_output_section(NULL,
{
Output_section* os;
if ((flags & elfcpp::SHF_ALLOC) == 0
- && strcmp(this->options_.compress_debug_sections(), "none") != 0
+ && strcmp(parameters->options().compress_debug_sections(), "none") != 0
&& is_compressible_debug_section(name))
- os = new Output_compressed_section(&this->options_, name, type, flags);
+ os = new Output_compressed_section(¶meters->options(), name, type,
+ flags);
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && this->options_.strip_debug_non_line()
+ && parameters->options().strip_debug_non_line()
&& strcmp(".debug_abbrev", name) == 0)
{
os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
this->debug_info_->set_abbreviations(this->debug_abbrev_);
}
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && this->options_.strip_debug_non_line()
+ && parameters->options().strip_debug_non_line()
&& strcmp(".debug_info", name) == 0)
{
os = this->debug_info_ = new Output_reduced_debug_info_section(
{
// If -Tbss was specified, we need to separate the data
// and BSS segments.
- if (this->options_.user_set_Tbss())
+ if (parameters->options().user_set_Tbss())
{
if ((os->type() == elfcpp::SHT_NOBITS)
== (*p)->has_any_data_sections())
this->create_version_sections(&versions, symtab, local_dynamic_count,
dynamic_symbols, dynstr);
}
+
+ if (this->incremental_inputs_)
+ {
+ this->incremental_inputs_->finalize();
+ this->create_incremental_info_sections();
+ }
// If there is a SECTIONS clause, put all the input sections into
// the required order.
else
load_seg = this->find_first_load_seg();
- if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+ if (parameters->options().oformat_enum()
+ != General_options::OBJECT_FORMAT_ELF)
load_seg = NULL;
gold_assert(phdr_seg == NULL || load_seg != NULL);
// Lay out the file header.
Output_file_header* file_header;
file_header = new Output_file_header(target, symtab, segment_headers,
- this->options_.entry());
+ parameters->options().entry());
if (load_seg != NULL)
load_seg->add_initial_output_data(file_header);
// *TRAILING_PADDING to the number of trailing zero bytes required.
Output_section*
-Layout::create_note(const char* name, int note_type, size_t descsz,
+Layout::create_note(const char* name, int note_type,
+ const char* section_name, size_t descsz,
bool allocate, size_t* trailing_padding)
{
// Authorities all agree that the values in a .note field should
memcpy(buffer + 3 * (size / 8), name, namesz);
- const char* note_name = this->namepool_.add(".note", false, NULL);
+ const char *note_name = this->namepool_.add(section_name, false, NULL);
elfcpp::Elf_Xword flags = 0;
if (allocate)
flags = elfcpp::SHF_ALLOC;
size_t trailing_padding;
Output_section *os = this->create_note("GNU", elfcpp::NT_GNU_GOLD_VERSION,
- desc.size(), false, &trailing_padding);
+ ".note.gnu.gold-version", desc.size(),
+ false, &trailing_padding);
Output_section_data* posd = new Output_data_const(desc, 4);
os->add_output_section_data(posd);
Layout::create_executable_stack_info(const Target* target)
{
bool is_stack_executable;
- if (this->options_.is_execstack_set())
- is_stack_executable = this->options_.is_stack_executable();
+ if (parameters->options().is_execstack_set())
+ is_stack_executable = parameters->options().is_stack_executable();
else if (!this->input_with_gnu_stack_note_)
return;
else
// Create the note.
size_t trailing_padding;
Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_BUILD_ID,
- descsz, true, &trailing_padding);
+ ".note.gnu.build-id", descsz, true,
+ &trailing_padding);
if (!desc.empty())
{
}
}
+// Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+// for the next run of incremental linking to check what has changed.
+
+void
+Layout::create_incremental_info_sections()
+{
+ gold_assert(this->incremental_inputs_ != NULL);
+
+ // Add the .gnu_incremental_inputs section.
+ const char *incremental_inputs_name =
+ this->namepool_.add(".gnu_incremental_inputs", false, NULL);
+ Output_section* inputs_os =
+ this->make_output_section(incremental_inputs_name,
+ elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
+ Output_section_data* posd =
+ this->incremental_inputs_->create_incremental_inputs_section_data();
+ inputs_os->add_output_section_data(posd);
+
+ // Add the .gnu_incremental_strtab section.
+ const char *incremental_strtab_name =
+ this->namepool_.add(".gnu_incremental_strtab", false, NULL);
+ Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
+ elfcpp::SHT_STRTAB,
+ 0);
+ Output_data_strtab* strtab_data =
+ new Output_data_strtab(this->incremental_inputs_->get_stringpool());
+ strtab_os->add_output_section_data(strtab_data);
+
+ inputs_os->set_link_section(strtab_data);
+}
+
// Return whether SEG1 should be before SEG2 in the output file. This
// is based entirely on the segment type and flags. When this is
// called the segment addresses has normally not yet been set.
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
uint64_t addr;
- if (this->options_.user_set_Ttext())
- addr = this->options_.Ttext();
+ if (parameters->options().user_set_Ttext())
+ addr = parameters->options().Ttext();
else if (parameters->options().shared())
addr = 0;
else
// the physical address.
addr = (*p)->paddr();
}
- else if (this->options_.user_set_Tdata()
+ else if (parameters->options().user_set_Tdata()
&& ((*p)->flags() & elfcpp::PF_W) != 0
- && (!this->options_.user_set_Tbss()
+ && (!parameters->options().user_set_Tbss()
|| (*p)->has_any_data_sections()))
{
- addr = this->options_.Tdata();
+ addr = parameters->options().Tdata();
are_addresses_set = true;
}
- else if (this->options_.user_set_Tbss()
+ else if (parameters->options().user_set_Tbss()
&& ((*p)->flags() & elfcpp::PF_W) != 0
&& !(*p)->has_any_data_sections())
{
- addr = this->options_.Tbss();
+ addr = parameters->options().Tbss();
are_addresses_set = true;
}
void
Layout::create_interp(const Target* target)
{
- const char* interp = this->options_.dynamic_linker();
+ const char* interp = parameters->options().dynamic_linker();
if (interp == NULL)
{
interp = target->dynamic_linker();
if (parameters->options().shared())
{
- const char* soname = this->options_.soname();
+ const char* soname = parameters->options().soname();
if (soname != NULL)
odyn->add_string(elfcpp::DT_SONAME, soname);
}
// FIXME: Support DT_INIT_ARRAY and DT_FINI_ARRAY.
// Add a DT_RPATH entry if needed.
- const General_options::Dir_list& rpath(this->options_.rpath());
+ const General_options::Dir_list& rpath(parameters->options().rpath());
if (!rpath.empty())
{
std::string rpath_val;
// initial '.', we use the name unchanged (i.e., "mysection" and
// ".text" are unchanged).
+ // If the name starts with '.note', we keep it unchanged (e.g. to
+ // avoid truncating '.note.ABI-tag' to '.note').
+
// If the name starts with ".data.rel.ro.local" we use
// ".data.rel.ro.local".
const char* sdot = strchr(s, '.');
if (sdot == NULL)
return name;
+ if (strncmp(name, ".note.", 6) == 0)
+ return name;
const char* const data_rel_ro_local = ".data.rel.ro.local";
if (strncmp(name, data_rel_ro_local, strlen(data_rel_ro_local)) == 0)
// CANDIDATE.
bool
-Layout::find_or_add_kept_section(const std::string name,
+Layout::find_or_add_kept_section(const std::string& name,
Kept_section* candidate,
Kept_section** kept_section)
{
+ // It's normal to see a couple of entries here, for the x86 thunk
+ // sections. If we see more than a few, we're linking a C++
+ // program, and we resize to get more space to minimize rehashing.
+ if (this->signatures_.size() > 4
+ && !this->resized_signatures_)
+ {
+ reserve_unordered_map(&this->signatures_,
+ this->number_of_input_files_ * 64);
+ this->resized_signatures_ = true;
+ }
+
std::pair<Signatures::iterator, bool> ins(
this->signatures_.insert(std::make_pair(name, *candidate)));
void
Layout::write_binary(Output_file* in) const
{
- gold_assert(this->options_.oformat_enum()
+ gold_assert(parameters->options().oformat_enum()
== General_options::OBJECT_FORMAT_BINARY);
// Get the size of the binary file.