++Free_list::num_allocates;
+ // We usually want to drop free chunks smaller than 4 bytes.
+ // If we need to guarantee a minimum hole size, though, we need
+ // to keep track of all free chunks.
+ const int fuzz = this->min_hole_ > 0 ? 0 : 3;
+
for (Iterator p = this->list_.begin(); p != this->list_.end(); ++p)
{
++Free_list::num_allocate_visits;
this->length_ = end;
p->end_ = end;
}
- if (end <= p->end_)
+ if (end == p->end_ || (end <= p->end_ - this->min_hole_))
{
- if (p->start_ + 3 >= start && p->end_ <= end + 3)
+ if (p->start_ + fuzz >= start && p->end_ <= end + fuzz)
this->list_.erase(p);
- else if (p->start_ + 3 >= start)
+ else if (p->start_ + fuzz >= start)
p->start_ = end;
- else if (p->end_ <= end + 3)
+ else if (p->end_ <= end + fuzz)
p->end_ = start;
else
{
any_postprocessing_sections_(false),
resized_signatures_(false),
have_stabstr_section_(false),
+ section_ordering_specified_(false),
incremental_inputs_(NULL),
record_output_section_data_from_script_(false),
script_output_section_data_list_(),
segment_states_(NULL),
relaxation_debug_check_(NULL),
+ section_order_map_(),
+ input_section_position_(),
+ input_section_glob_(),
incremental_base_(NULL),
free_list_()
{
{
unsigned int sh_type = shdr.get_sh_type();
- // We preserve the layout of PROGBITS, NOBITS, and NOTE sections.
+ // We preserve the layout of PROGBITS, NOBITS, INIT_ARRAY, FINI_ARRAY,
+ // PRE_INIT_ARRAY, and NOTE sections.
// All others will be created from scratch and reallocated.
- if (sh_type != elfcpp::SHT_PROGBITS
- && sh_type != elfcpp::SHT_NOBITS
- && sh_type != elfcpp::SHT_NOTE)
+ if (!can_incremental_update(sh_type))
return NULL;
typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr();
&& order != ORDER_FINI
&& order != ORDER_RELRO_LAST
&& order != ORDER_NON_RELRO_FIRST
+ && strcmp(name, ".eh_frame") != 0
&& strcmp(name, ".ctors") != 0
&& strcmp(name, ".dtors") != 0
&& strcmp(name, ".jcr") != 0)
- os->set_is_patch_space_allowed();
+ {
+ os->set_is_patch_space_allowed();
+
+ // Certain sections require "holes" to be filled with
+ // specific fill patterns. These fill patterns may have
+ // a minimum size, so we must prevent allocations from the
+ // free list that leave a hole smaller than the minimum.
+ if (strcmp(name, ".debug_info") == 0)
+ os->set_free_space_fill(new Output_fill_debug_info(false));
+ else if (strcmp(name, ".debug_types") == 0)
+ os->set_free_space_fill(new Output_fill_debug_info(true));
+ else if (strcmp(name, ".debug_line") == 0)
+ os->set_free_space_fill(new Output_fill_debug_line());
+ }
// If we have already attached the sections to segments, then we
// need to attach this one now. This happens for sections created
false, ORDER_RELRO,
true);
- this->dynamic_symbol_ =
- symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED,
- this->dynamic_section_, 0, 0,
- elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
- elfcpp::STV_HIDDEN, 0, false, false);
+ // A linker script may discard .dynamic, so check for NULL.
+ if (this->dynamic_section_ != NULL)
+ {
+ this->dynamic_symbol_ =
+ symtab->define_in_output_data("_DYNAMIC", NULL,
+ Symbol_table::PREDEFINED,
+ this->dynamic_section_, 0, 0,
+ elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
+ elfcpp::STV_HIDDEN, 0, false, false);
- this->dynamic_data_ = new Output_data_dynamic(&this->dynpool_);
+ this->dynamic_data_ = new Output_data_dynamic(&this->dynpool_);
- this->dynamic_section_->add_output_section_data(this->dynamic_data_);
+ this->dynamic_section_->add_output_section_data(this->dynamic_data_);
+ }
}
// For each output section whose name can be represented as C symbol,
// If the user set the address of the text segment, that may not be
// compatible with putting the segment headers and file headers into
// that segment.
- if (parameters->options().user_set_Ttext())
- load_seg = NULL;
+ if (parameters->options().user_set_Ttext()
+ && parameters->options().Ttext() % target->common_pagesize() != 0)
+ {
+ load_seg = NULL;
+ phdr_seg = NULL;
+ }
gold_assert(phdr_seg == NULL
|| load_seg != NULL
}
// Read the sequence of input sections from the file specified with
-// --section-ordering-file.
+// option --section-ordering-file.
void
Layout::read_layout_from_file()
std::getline(in, line); // this chops off the trailing \n, if any
unsigned int position = 1;
+ this->set_section_ordering_specified();
while (in)
{
// We shouldn't get here--we shouldn't create segments which we
// can't distinguish. Unless of course we are using a weird linker
- // script.
- gold_assert(this->script_options_->saw_phdrs_clause());
+ // script or overlapping --section-start options.
+ gold_assert(this->script_options_->saw_phdrs_clause()
+ || parameters->options().any_section_start());
return false;
}
// the physical address.
addr = (*p)->paddr();
}
+ else if (parameters->options().user_set_Ttext()
+ && ((*p)->flags() & elfcpp::PF_W) == 0)
+ {
+ are_addresses_set = true;
+ }
else if (parameters->options().user_set_Tdata()
&& ((*p)->flags() & elfcpp::PF_W) != 0
&& (!parameters->options().user_set_Tbss()
ORDER_DYNAMIC_LINKER,
false);
- Output_section_data* odata = new Output_data_fixed_space(index * symsize,
- align,
- "** dynsym");
- dynsym->add_output_section_data(odata);
+ // Check for NULL as a linker script may discard .dynsym.
+ if (dynsym != NULL)
+ {
+ Output_section_data* odata = new Output_data_fixed_space(index * symsize,
+ align,
+ "** dynsym");
+ dynsym->add_output_section_data(odata);
- dynsym->set_info(local_symcount);
- dynsym->set_entsize(symsize);
- dynsym->set_addralign(align);
+ dynsym->set_info(local_symcount);
+ dynsym->set_entsize(symsize);
+ dynsym->set_addralign(align);
- this->dynsym_section_ = dynsym;
+ this->dynsym_section_ = dynsym;
+ }
Output_data_dynamic* const odyn = this->dynamic_data_;
- odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
- odyn->add_constant(elfcpp::DT_SYMENT, symsize);
+ if (odyn != NULL)
+ {
+ odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
+ odyn->add_constant(elfcpp::DT_SYMENT, symsize);
+ }
// If there are more than SHN_LORESERVE allocated sections, we
// create a .dynsym_shndx section. It is possible that we don't
elfcpp::SHF_ALLOC,
false, ORDER_DYNAMIC_LINKER, false);
- this->dynsym_xindex_ = new Output_symtab_xindex(index);
+ if (dynsym_xindex != NULL)
+ {
+ this->dynsym_xindex_ = new Output_symtab_xindex(index);
- dynsym_xindex->add_output_section_data(this->dynsym_xindex_);
+ dynsym_xindex->add_output_section_data(this->dynsym_xindex_);
- dynsym_xindex->set_link_section(dynsym);
- dynsym_xindex->set_addralign(4);
- dynsym_xindex->set_entsize(4);
+ dynsym_xindex->set_link_section(dynsym);
+ dynsym_xindex->set_addralign(4);
+ dynsym_xindex->set_entsize(4);
- dynsym_xindex->set_after_input_sections();
+ dynsym_xindex->set_after_input_sections();
- // This tells the driver code to wait until the symbol table has
- // written out before writing out the postprocessing sections,
- // including the .dynsym_shndx section.
- this->any_postprocessing_sections_ = true;
+ // This tells the driver code to wait until the symbol table
+ // has written out before writing out the postprocessing
+ // sections, including the .dynsym_shndx section.
+ this->any_postprocessing_sections_ = true;
+ }
}
// Create the dynamic string table section.
ORDER_DYNAMIC_LINKER,
false);
- Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
- dynstr->add_output_section_data(strdata);
+ if (dynstr != NULL)
+ {
+ Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
+ dynstr->add_output_section_data(strdata);
- dynsym->set_link_section(dynstr);
- this->dynamic_section_->set_link_section(dynstr);
+ if (dynsym != NULL)
+ dynsym->set_link_section(dynstr);
+ if (this->dynamic_section_ != NULL)
+ this->dynamic_section_->set_link_section(dynstr);
- odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
- odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
+ if (odyn != NULL)
+ {
+ odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
+ odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
+ }
- *pdynstr = dynstr;
+ *pdynstr = dynstr;
+ }
// Create the hash tables.
hashlen,
align,
"** hash");
- hashsec->add_output_section_data(hashdata);
+ if (hashsec != NULL && hashdata != NULL)
+ hashsec->add_output_section_data(hashdata);
- hashsec->set_link_section(dynsym);
- hashsec->set_entsize(4);
+ if (hashsec != NULL)
+ {
+ if (dynsym != NULL)
+ hashsec->set_link_section(dynsym);
+ hashsec->set_entsize(4);
+ }
- odyn->add_section_address(elfcpp::DT_HASH, hashsec);
+ if (odyn != NULL)
+ odyn->add_section_address(elfcpp::DT_HASH, hashsec);
}
if (strcmp(parameters->options().hash_style(), "gnu") == 0
hashlen,
align,
"** hash");
- hashsec->add_output_section_data(hashdata);
+ if (hashsec != NULL && hashdata != NULL)
+ hashsec->add_output_section_data(hashdata);
- hashsec->set_link_section(dynsym);
+ if (hashsec != NULL)
+ {
+ if (dynsym != NULL)
+ hashsec->set_link_section(dynsym);
- // For a 64-bit target, the entries in .gnu.hash do not have a
- // uniform size, so we only set the entry size for a 32-bit
- // target.
- if (parameters->target().get_size() == 32)
- hashsec->set_entsize(4);
+ // For a 64-bit target, the entries in .gnu.hash do not have
+ // a uniform size, so we only set the entry size for a
+ // 32-bit target.
+ if (parameters->target().get_size() == 32)
+ hashsec->set_entsize(4);
- odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
+ if (odyn != NULL)
+ odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
+ }
}
}
Layout::assign_local_dynsym_offsets(const Input_objects* input_objects)
{
Output_section* dynsym = this->dynsym_section_;
- gold_assert(dynsym != NULL);
+ if (dynsym == NULL)
+ return;
off_t off = dynsym->offset();
ORDER_DYNAMIC_LINKER,
false);
- unsigned char* vbuf;
- unsigned int vsize;
- versions->symbol_section_contents<size, big_endian>(symtab, &this->dynpool_,
- local_symcount,
- dynamic_symbols,
- &vbuf, &vsize);
+ // Check for NULL since a linker script may discard this section.
+ if (vsec != NULL)
+ {
+ unsigned char* vbuf;
+ unsigned int vsize;
+ versions->symbol_section_contents<size, big_endian>(symtab,
+ &this->dynpool_,
+ local_symcount,
+ dynamic_symbols,
+ &vbuf, &vsize);
- Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
- "** versions");
+ Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
+ "** versions");
- vsec->add_output_section_data(vdata);
- vsec->set_entsize(2);
- vsec->set_link_section(this->dynsym_section_);
+ vsec->add_output_section_data(vdata);
+ vsec->set_entsize(2);
+ vsec->set_link_section(this->dynsym_section_);
+ }
Output_data_dynamic* const odyn = this->dynamic_data_;
- odyn->add_section_address(elfcpp::DT_VERSYM, vsec);
+ if (odyn != NULL && vsec != NULL)
+ odyn->add_section_address(elfcpp::DT_VERSYM, vsec);
if (versions->any_defs())
{
Output_section* vdsec;
- vdsec= this->choose_output_section(NULL, ".gnu.version_d",
- elfcpp::SHT_GNU_verdef,
- elfcpp::SHF_ALLOC,
- false, ORDER_DYNAMIC_LINKER, false);
+ vdsec = this->choose_output_section(NULL, ".gnu.version_d",
+ elfcpp::SHT_GNU_verdef,
+ elfcpp::SHF_ALLOC,
+ false, ORDER_DYNAMIC_LINKER, false);
- unsigned char* vdbuf;
- unsigned int vdsize;
- unsigned int vdentries;
- versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
- &vdsize, &vdentries);
+ if (vdsec != NULL)
+ {
+ unsigned char* vdbuf;
+ unsigned int vdsize;
+ unsigned int vdentries;
+ versions->def_section_contents<size, big_endian>(&this->dynpool_,
+ &vdbuf, &vdsize,
+ &vdentries);
- Output_section_data* vddata =
- new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
+ Output_section_data* vddata =
+ new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
- vdsec->add_output_section_data(vddata);
- vdsec->set_link_section(dynstr);
- vdsec->set_info(vdentries);
+ vdsec->add_output_section_data(vddata);
+ vdsec->set_link_section(dynstr);
+ vdsec->set_info(vdentries);
- odyn->add_section_address(elfcpp::DT_VERDEF, vdsec);
- odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries);
+ if (odyn != NULL)
+ {
+ odyn->add_section_address(elfcpp::DT_VERDEF, vdsec);
+ odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries);
+ }
+ }
}
if (versions->any_needs())
elfcpp::SHF_ALLOC,
false, ORDER_DYNAMIC_LINKER, false);
- unsigned char* vnbuf;
- unsigned int vnsize;
- unsigned int vnentries;
- versions->need_section_contents<size, big_endian>(&this->dynpool_,
- &vnbuf, &vnsize,
- &vnentries);
+ if (vnsec != NULL)
+ {
+ unsigned char* vnbuf;
+ unsigned int vnsize;
+ unsigned int vnentries;
+ versions->need_section_contents<size, big_endian>(&this->dynpool_,
+ &vnbuf, &vnsize,
+ &vnentries);
- Output_section_data* vndata =
- new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs");
+ Output_section_data* vndata =
+ new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs");
- vnsec->add_output_section_data(vndata);
- vnsec->set_link_section(dynstr);
- vnsec->set_info(vnentries);
+ vnsec->add_output_section_data(vndata);
+ vnsec->set_link_section(dynstr);
+ vnsec->set_info(vnentries);
- odyn->add_section_address(elfcpp::DT_VERNEED, vnsec);
- odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries);
+ if (odyn != NULL)
+ {
+ odyn->add_section_address(elfcpp::DT_VERNEED, vnsec);
+ odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries);
+ }
+ }
}
}
elfcpp::SHF_ALLOC,
false, ORDER_INTERP,
false);
- osec->add_output_section_data(odata);
+ if (osec != NULL)
+ osec->add_output_section_data(odata);
}
// Add dynamic tags for the PLT and the dynamic relocs. This is
// some targets have multiple reloc sections in PLT_REL.
// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA,
-// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT.
+// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT. Again we use the output
+// section.
// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an
// executable.
if (dyn_rel != NULL && dyn_rel->output_section() != NULL)
{
odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
- dyn_rel);
- if (plt_rel != NULL && dynrel_includes_plt)
+ dyn_rel->output_section());
+ if (plt_rel != NULL
+ && plt_rel->output_section() != NULL
+ && dynrel_includes_plt)
odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
- dyn_rel, plt_rel);
+ dyn_rel->output_section(),
+ plt_rel->output_section());
else
odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
- dyn_rel);
+ dyn_rel->output_section());
const int size = parameters->target().get_size();
elfcpp::DT rel_tag;
int rel_size;
Layout::finish_dynamic_section(const Input_objects* input_objects,
const Symbol_table* symtab)
{
- if (!this->script_options_->saw_phdrs_clause())
+ if (!this->script_options_->saw_phdrs_clause()
+ && this->dynamic_section_ != NULL)
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
(elfcpp::PF_R
}
Output_data_dynamic* const odyn = this->dynamic_data_;
+ if (odyn == NULL)
+ return;
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
p != input_objects->dynobj_end();
flags |= elfcpp::DF_1_ORIGIN;
if (parameters->options().now())
flags |= elfcpp::DF_1_NOW;
+ if (parameters->options().Bgroup())
+ flags |= elfcpp::DF_1_GROUP;
if (flags != 0)
odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
}
Layout::set_dynamic_symbol_size(const Symbol_table* symtab)
{
Output_data_dynamic* const odyn = this->dynamic_data_;
+ if (odyn == NULL)
+ return;
odyn->finalize_data_size();
+ if (this->dynamic_symbol_ == NULL)
+ return;
off_t data_size = odyn->data_size();
const int size = parameters->target().get_size();
if (size == 32)