resized_signatures_(false),
have_stabstr_section_(false),
section_ordering_specified_(false),
+ unique_segment_for_sections_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_(),
+ section_segment_map_(),
input_section_position_(),
input_section_glob_(),
incremental_base_(NULL),
case elfcpp::SHT_GROUP:
// If we are emitting relocations these should be handled
// elsewhere.
- gold_assert(!parameters->options().relocatable()
- && !parameters->options().emit_relocs());
+ gold_assert(!parameters->options().relocatable());
return false;
case elfcpp::SHT_PROGBITS:
}
}
+// Returns TRUE iff NAME (an input section from RELOBJ) will
+// be mapped to an output section that should be KEPT.
+
+bool
+Layout::keep_input_section(const Relobj* relobj, const char* name)
+{
+ if (! this->script_options_->saw_sections_clause())
+ return false;
+
+ Script_sections* ss = this->script_options_->script_sections();
+ const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
+ Output_section** output_section_slot;
+ Script_sections::Section_type script_section_type;
+ bool keep;
+
+ name = ss->output_section_name(file_name, name, &output_section_slot,
+ &script_section_type, &keep);
+ return name != NULL && keep;
+}
+
+// Clear the input section flags that should not be copied to the
+// output section.
+
+elfcpp::Elf_Xword
+Layout::get_output_section_flags(elfcpp::Elf_Xword input_section_flags)
+{
+ // Some flags in the input section should not be automatically
+ // copied to the output section.
+ input_section_flags &= ~ (elfcpp::SHF_INFO_LINK
+ | elfcpp::SHF_GROUP
+ | elfcpp::SHF_MERGE
+ | elfcpp::SHF_STRINGS);
+
+ // We only clear the SHF_LINK_ORDER flag in for
+ // a non-relocatable link.
+ if (!parameters->options().relocatable())
+ input_section_flags &= ~elfcpp::SHF_LINK_ORDER;
+
+ return input_section_flags;
+}
+
// Pick the output section to use for section NAME, in input file
// RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a
// linker created section. IS_INPUT_SECTION is true if we are
// sections to segments.
gold_assert(!is_input_section || !this->sections_are_attached_);
- // Some flags in the input section should not be automatically
- // copied to the output section.
- flags &= ~ (elfcpp::SHF_INFO_LINK
- | elfcpp::SHF_GROUP
- | elfcpp::SHF_MERGE
- | elfcpp::SHF_STRINGS);
-
- // We only clear the SHF_LINK_ORDER flag in for
- // a non-relocatable link.
- if (!parameters->options().relocatable())
- flags &= ~elfcpp::SHF_LINK_ORDER;
+ flags = this->get_output_section_flags(flags);
if (this->script_options_->saw_sections_clause())
{
Output_section** output_section_slot;
Script_sections::Section_type script_section_type;
const char* orig_name = name;
+ bool keep;
name = ss->output_section_name(file_name, name, &output_section_slot,
- &script_section_type);
+ &script_section_type, &keep);
+
if (name == NULL)
{
gold_debug(DEBUG_SCRIPT, _("Unable to create output section '%s' "
}
else
{
- os = this->choose_output_section(object, name, sh_type,
- shdr.get_sh_flags(), true,
- ORDER_INVALID, false);
+ // Plugins can choose to place one or more subsets of sections in
+ // unique segments and this is done by mapping these section subsets
+ // to unique output sections. Check if this section needs to be
+ // remapped to a unique output section.
+ Section_segment_map::iterator it
+ = this->section_segment_map_.find(Const_section_id(object, shndx));
+ if (it == this->section_segment_map_.end())
+ {
+ os = this->choose_output_section(object, name, sh_type,
+ shdr.get_sh_flags(), true,
+ ORDER_INVALID, false);
+ }
+ else
+ {
+ // We know the name of the output section, directly call
+ // get_output_section here by-passing choose_output_section.
+ elfcpp::Elf_Xword flags
+ = this->get_output_section_flags(shdr.get_sh_flags());
+
+ const char* os_name = it->second->name;
+ Stringpool::Key name_key;
+ os_name = this->namepool_.add(os_name, true, &name_key);
+ os = this->get_output_section(os_name, name_key, sh_type, flags,
+ ORDER_INVALID, false);
+ if (!os->is_unique_segment())
+ {
+ os->set_is_unique_segment();
+ os->set_extra_segment_flags(it->second->flags);
+ os->set_segment_alignment(it->second->align);
+ }
+ }
if (os == NULL)
return NULL;
}
return os;
}
+// Maps section SECN to SEGMENT s.
+void
+Layout::insert_section_segment_map(Const_section_id secn,
+ Unique_segment_info *s)
+{
+ gold_assert(this->unique_segment_for_sections_specified_);
+ this->section_segment_map_[secn] = s;
+}
+
// Handle a relocation section when doing a relocatable link.
template<int size, bool big_endian>
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
+ // If this output section's segment has extra flags that need to be set,
+ // coming from a linker plugin, do that.
+ seg_flags |= os->extra_segment_flags();
+
// Check for --section-start.
uint64_t addr;
bool is_address_set = parameters->options().section_start(os->name(), &addr);
// have to use a linker script.
Segment_list::const_iterator p;
- for (p = this->segment_list_.begin();
- p != this->segment_list_.end();
- ++p)
+ if (!os->is_unique_segment())
{
- if ((*p)->type() != elfcpp::PT_LOAD)
- continue;
- if (!parameters->options().omagic()
- && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
- continue;
- if ((target->isolate_execinstr() || parameters->options().rosegment())
- && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
- continue;
- // If -Tbss was specified, we need to separate the data and BSS
- // segments.
- if (parameters->options().user_set_Tbss())
- {
- if ((os->type() == elfcpp::SHT_NOBITS)
- == (*p)->has_any_data_sections())
- continue;
- }
- if (os->is_large_data_section() && !(*p)->is_large_data_segment())
- continue;
-
- if (is_address_set)
+ for (p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
{
- if ((*p)->are_addresses_set())
- continue;
-
- (*p)->add_initial_output_data(os);
- (*p)->update_flags_for_output_section(seg_flags);
- (*p)->set_addresses(addr, addr);
- break;
- }
-
- (*p)->add_output_section_to_load(this, os, seg_flags);
- break;
- }
-
- if (p == this->segment_list_.end())
+ if ((*p)->type() != elfcpp::PT_LOAD)
+ continue;
+ if ((*p)->is_unique_segment())
+ continue;
+ if (!parameters->options().omagic()
+ && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
+ continue;
+ if ((target->isolate_execinstr() || parameters->options().rosegment())
+ && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
+ continue;
+ // If -Tbss was specified, we need to separate the data and BSS
+ // segments.
+ if (parameters->options().user_set_Tbss())
+ {
+ if ((os->type() == elfcpp::SHT_NOBITS)
+ == (*p)->has_any_data_sections())
+ continue;
+ }
+ if (os->is_large_data_section() && !(*p)->is_large_data_segment())
+ continue;
+
+ if (is_address_set)
+ {
+ if ((*p)->are_addresses_set())
+ continue;
+
+ (*p)->add_initial_output_data(os);
+ (*p)->update_flags_for_output_section(seg_flags);
+ (*p)->set_addresses(addr, addr);
+ break;
+ }
+
+ (*p)->add_output_section_to_load(this, os, seg_flags);
+ break;
+ }
+ }
+
+ if (p == this->segment_list_.end()
+ || os->is_unique_segment())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
seg_flags);
oseg->add_output_section_to_load(this, os, seg_flags);
if (is_address_set)
oseg->set_addresses(addr, addr);
+ // Check if segment should be marked unique. For segments marked
+ // unique by linker plugins, set the new alignment if specified.
+ if (os->is_unique_segment())
+ {
+ oseg->set_is_unique_segment();
+ if (os->segment_alignment() != 0)
+ oseg->set_minimum_p_align(os->segment_alignment());
+ }
}
// If we see a loadable SHT_NOTE section, we create a PT_NOTE
// compatible with putting the segment headers and file headers into
// that segment.
if (parameters->options().user_set_Ttext()
- && parameters->options().Ttext() % target->common_pagesize() != 0)
+ && parameters->options().Ttext() % target->abi_pagesize() != 0)
{
load_seg = NULL;
phdr_seg = NULL;
// 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 or overlapping --section-start options.
+ // script or overlapping --section-start options. We could also get
+ // here if plugins want unique segments for subsets of sections.
gold_assert(this->script_options_->saw_phdrs_clause()
- || parameters->options().any_section_start());
+ || parameters->options().any_section_start()
+ || this->is_unique_segment_for_sections_specified());
return false;
}
if (!parameters->options().nmagic()
&& !parameters->options().omagic())
- (*p)->set_minimum_p_align(common_pagesize);
+ (*p)->set_minimum_p_align(abi_pagesize);
if (!are_addresses_set)
{