* layout.cc (Layout::Layout): Initialize sections_are_attached_.
(Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR in the name/type/flags to section mapping. Don't call allocate_output_section. (Layout::choose_output_section): Change parameter from adjust_name to is_input_section. Don't permit input sections after sections are attached to segments. Don't call allocate_output_section. (Layout::layout_eh_frame): Call update_flags_for_input_section, not write_enable_output_section. (Layout::make_output_section): Don't push to unattached_section_list_ nor call attach_to_segment. Call attach_section_to_segment if sections are attached. (Layout::attach_sections_to_segments): New function. (Layout::attach_section_to_segment): New function. (Layout::attach_allocated_section_to_segment): Rename from attach_to_segment. Remove flags parameter. (Layout::allocate_output_section): Remove function. (Layout::write_enable_output_section): Remove function. * layout.h (class Layout): Update for above changes. Add new field sections_are_attached_. * output.h (Output_section::update_flags_for_input_section): New function. * output.cc (Output_section::add_input_section): Call update_flags_for_input_section. * gold.cc (queue_middle_tasks): Call attach_sections_to_segments.
This commit is contained in:
parent
9380031c3f
commit
154e0e9aa7
@ -1,3 +1,31 @@
|
||||
2008-04-14 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* layout.cc (Layout::Layout): Initialize sections_are_attached_.
|
||||
(Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR
|
||||
in the name/type/flags to section mapping. Don't call
|
||||
allocate_output_section.
|
||||
(Layout::choose_output_section): Change parameter from adjust_name
|
||||
to is_input_section. Don't permit input sections after sections
|
||||
are attached to segments. Don't call allocate_output_section.
|
||||
(Layout::layout_eh_frame): Call update_flags_for_input_section,
|
||||
not write_enable_output_section.
|
||||
(Layout::make_output_section): Don't push to
|
||||
unattached_section_list_ nor call attach_to_segment. Call
|
||||
attach_section_to_segment if sections are attached.
|
||||
(Layout::attach_sections_to_segments): New function.
|
||||
(Layout::attach_section_to_segment): New function.
|
||||
(Layout::attach_allocated_section_to_segment): Rename from
|
||||
attach_to_segment. Remove flags parameter.
|
||||
(Layout::allocate_output_section): Remove function.
|
||||
(Layout::write_enable_output_section): Remove function.
|
||||
* layout.h (class Layout): Update for above changes. Add new
|
||||
field sections_are_attached_.
|
||||
* output.h (Output_section::update_flags_for_input_section): New
|
||||
function.
|
||||
* output.cc (Output_section::add_input_section): Call
|
||||
update_flags_for_input_section.
|
||||
* gold.cc (queue_middle_tasks): Call attach_sections_to_segments.
|
||||
|
||||
2008-04-11 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* i386.cc (Target_i386::got_mod_index_entry): Restore code previously
|
||||
|
@ -212,6 +212,9 @@ queue_middle_tasks(const General_options& options,
|
||||
// Define symbols from any linker scripts.
|
||||
layout->define_script_symbols(symtab);
|
||||
|
||||
// Attach sections to segments.
|
||||
layout->attach_sections_to_segments();
|
||||
|
||||
if (!parameters->options().relocatable())
|
||||
{
|
||||
// Predefine standard symbols.
|
||||
|
158
gold/layout.cc
158
gold/layout.cc
@ -79,10 +79,10 @@ Layout::Layout(const General_options& options, Script_options* script_options)
|
||||
: options_(options), script_options_(script_options), namepool_(),
|
||||
sympool_(), dynpool_(), signatures_(),
|
||||
section_name_map_(), segment_list_(), section_list_(),
|
||||
unattached_section_list_(), special_output_list_(),
|
||||
section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
|
||||
dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
|
||||
eh_frame_section_(NULL), eh_frame_data_(NULL),
|
||||
unattached_section_list_(), sections_are_attached_(false),
|
||||
special_output_list_(), section_headers_(NULL), tls_segment_(NULL),
|
||||
symtab_section_(NULL), dynsym_section_(NULL), dynamic_section_(NULL),
|
||||
dynamic_data_(NULL), eh_frame_section_(NULL), eh_frame_data_(NULL),
|
||||
added_eh_frame_data_(false), eh_frame_hdr_section_(NULL),
|
||||
build_id_note_(NULL), group_signatures_(), output_file_size_(-1),
|
||||
input_requires_executable_stack_(false),
|
||||
@ -234,7 +234,15 @@ Output_section*
|
||||
Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
||||
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
|
||||
{
|
||||
const Key key(name_key, std::make_pair(type, flags));
|
||||
elfcpp::Elf_Xword lookup_flags = flags;
|
||||
|
||||
// Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
|
||||
// read-write with read-only sections. Some other ELF linkers do
|
||||
// not do this. FIXME: Perhaps there should be an option
|
||||
// controlling this.
|
||||
lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
|
||||
|
||||
const Key key(name_key, std::make_pair(type, lookup_flags));
|
||||
const std::pair<Key, Output_section*> v(key, NULL);
|
||||
std::pair<Section_name_map::iterator, bool> ins(
|
||||
this->section_name_map_.insert(v));
|
||||
@ -268,11 +276,7 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
||||
Section_name_map::iterator p =
|
||||
this->section_name_map_.find(zero_key);
|
||||
if (p != this->section_name_map_.end())
|
||||
{
|
||||
os = p->second;
|
||||
if ((flags & elfcpp::SHF_ALLOC) != 0)
|
||||
this->allocate_output_section(os, flags);
|
||||
}
|
||||
os = p->second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,17 +289,22 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
||||
|
||||
// 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. ADJUST_NAME is true if we should apply the
|
||||
// standard name mappings in Layout::output_section_name. This will
|
||||
// return NULL if the input section should be discarded.
|
||||
// linker created section. IS_INPUT_SECTION is true if we are
|
||||
// choosing an output section for an input section found in a input
|
||||
// file. This will return NULL if the input section should be
|
||||
// discarded.
|
||||
|
||||
Output_section*
|
||||
Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
||||
bool adjust_name)
|
||||
bool is_input_section)
|
||||
{
|
||||
// We should ignore some flags. FIXME: This will need some
|
||||
// adjustment for ld -r.
|
||||
// We should not see any input sections after we have attached
|
||||
// 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_LINK_ORDER
|
||||
| elfcpp::SHF_GROUP
|
||||
@ -324,17 +333,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||
if (output_section_slot != NULL)
|
||||
{
|
||||
if (*output_section_slot != NULL)
|
||||
{
|
||||
// If the output section was created unallocated, and we
|
||||
// are now allocating it, then we need to clear the
|
||||
// address set in the constructor and remove it from the
|
||||
// unattached section list.
|
||||
if (((*output_section_slot)->flags() & elfcpp::SHF_ALLOC) == 0
|
||||
&& (flags & elfcpp::SHF_ALLOC) != 0)
|
||||
this->allocate_output_section(*output_section_slot, flags);
|
||||
|
||||
return *output_section_slot;
|
||||
}
|
||||
return *output_section_slot;
|
||||
|
||||
// We don't put sections found in the linker script into
|
||||
// SECTION_NAME_MAP_. That keeps us from getting confused
|
||||
@ -356,7 +355,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||
// output section.
|
||||
|
||||
size_t len = strlen(name);
|
||||
if (adjust_name && !parameters->options().relocatable())
|
||||
if (is_input_section && !parameters->options().relocatable())
|
||||
name = Layout::output_section_name(name, &len);
|
||||
|
||||
Stringpool::Key name_key;
|
||||
@ -550,16 +549,6 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||
if (os == NULL)
|
||||
return NULL;
|
||||
|
||||
// On some targets gcc assumes that a read-only .eh_frame section
|
||||
// will be merged with a read-write .eh_frame section.
|
||||
if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0
|
||||
&& (os->flags() & elfcpp::SHF_WRITE) == 0)
|
||||
{
|
||||
elfcpp::Elf_Xword new_flags = os->flags() | elfcpp::SHF_WRITE;
|
||||
this->write_enable_output_section(os, new_flags);
|
||||
os->set_flags(new_flags);
|
||||
}
|
||||
|
||||
if (this->eh_frame_section_ == NULL)
|
||||
{
|
||||
this->eh_frame_section_ = os;
|
||||
@ -606,6 +595,8 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||
reloc_shndx,
|
||||
reloc_type))
|
||||
{
|
||||
os->update_flags_for_input_section(shdr.get_sh_flags());
|
||||
|
||||
// We found a .eh_frame section we are going to optimize, so now
|
||||
// we can add the set of optimized sections to the output
|
||||
// section. We need to postpone adding this until we've found a
|
||||
@ -689,11 +680,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
||||
|
||||
this->section_list_.push_back(os);
|
||||
|
||||
if ((flags & elfcpp::SHF_ALLOC) == 0)
|
||||
this->unattached_section_list_.push_back(os);
|
||||
else
|
||||
this->attach_to_segment(os, flags);
|
||||
|
||||
// The GNU linker by default sorts some sections by priority, so we
|
||||
// do the same. We need to know that this might happen before we
|
||||
// attach any input sections.
|
||||
@ -704,14 +690,46 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
||||
|| strcmp(name, ".fini_array") == 0))
|
||||
os->set_may_sort_attached_input_sections();
|
||||
|
||||
// If we have already attached the sections to segments, then we
|
||||
// need to attach this one now. This happens for sections created
|
||||
// directly by the linker.
|
||||
if (this->sections_are_attached_)
|
||||
this->attach_section_to_segment(os);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
// Attach output sections to segments. This is called after we have
|
||||
// seen all the input sections.
|
||||
|
||||
void
|
||||
Layout::attach_sections_to_segments()
|
||||
{
|
||||
for (Section_list::iterator p = this->section_list_.begin();
|
||||
p != this->section_list_.end();
|
||||
++p)
|
||||
this->attach_section_to_segment(*p);
|
||||
|
||||
this->sections_are_attached_ = true;
|
||||
}
|
||||
|
||||
// Attach an output section to a segment.
|
||||
|
||||
void
|
||||
Layout::attach_section_to_segment(Output_section* os)
|
||||
{
|
||||
if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
|
||||
this->unattached_section_list_.push_back(os);
|
||||
else
|
||||
this->attach_allocated_section_to_segment(os);
|
||||
}
|
||||
|
||||
// Attach an allocated output section to a segment.
|
||||
|
||||
void
|
||||
Layout::attach_to_segment(Output_section* os, elfcpp::Elf_Xword flags)
|
||||
Layout::attach_allocated_section_to_segment(Output_section* os)
|
||||
{
|
||||
elfcpp::Elf_Xword flags = os->flags();
|
||||
gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
|
||||
|
||||
if (parameters->options().relocatable())
|
||||
@ -811,58 +829,6 @@ Layout::make_output_section_for_script(const char* name)
|
||||
return os;
|
||||
}
|
||||
|
||||
// We have to move an existing output section from the unallocated
|
||||
// list to the allocated list.
|
||||
|
||||
void
|
||||
Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags)
|
||||
{
|
||||
os->reset_address_and_file_offset();
|
||||
|
||||
Section_list::iterator p = std::find(this->unattached_section_list_.begin(),
|
||||
this->unattached_section_list_.end(),
|
||||
os);
|
||||
gold_assert(p != this->unattached_section_list_.end());
|
||||
this->unattached_section_list_.erase(p);
|
||||
|
||||
this->attach_to_segment(os, flags);
|
||||
}
|
||||
|
||||
// We have to move an existing output section from the read-only
|
||||
// segment to the writable segment.
|
||||
|
||||
void
|
||||
Layout::write_enable_output_section(Output_section* os,
|
||||
elfcpp::Elf_Xword flags)
|
||||
{
|
||||
gold_assert((os->flags() & elfcpp::SHF_WRITE) == 0);
|
||||
gold_assert(os->type() == elfcpp::SHT_PROGBITS);
|
||||
gold_assert((flags & elfcpp::SHF_WRITE) != 0);
|
||||
gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
|
||||
|
||||
if (parameters->options().relocatable())
|
||||
return;
|
||||
|
||||
if (this->script_options_->saw_sections_clause())
|
||||
return;
|
||||
|
||||
Segment_list::iterator p;
|
||||
for (p = this->segment_list_.begin();
|
||||
p != this->segment_list_.end();
|
||||
++p)
|
||||
{
|
||||
if ((*p)->type() == elfcpp::PT_LOAD
|
||||
&& ((*p)->flags() & elfcpp::PF_W) == 0)
|
||||
{
|
||||
(*p)->remove_output_section(os);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gold_assert(p != this->segment_list_.end());
|
||||
|
||||
this->attach_to_segment(os, flags);
|
||||
}
|
||||
|
||||
// Return the number of segments we expect to see.
|
||||
|
||||
size_t
|
||||
|
@ -340,6 +340,10 @@ class Layout
|
||||
static elfcpp::Elf_Word
|
||||
section_flags_to_segment(elfcpp::Elf_Xword flags);
|
||||
|
||||
// Attach sections to segments.
|
||||
void
|
||||
attach_sections_to_segments();
|
||||
|
||||
private:
|
||||
Layout(const Layout&);
|
||||
Layout& operator=(const Layout&);
|
||||
@ -475,7 +479,7 @@ class Layout
|
||||
Output_section*
|
||||
choose_output_section(const Relobj* relobj, const char* name,
|
||||
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
||||
bool adjust_name);
|
||||
bool is_input_section);
|
||||
|
||||
// Create a new Output_section.
|
||||
Output_section*
|
||||
@ -484,15 +488,11 @@ class Layout
|
||||
|
||||
// Attach a section to a segment.
|
||||
void
|
||||
attach_to_segment(Output_section*, elfcpp::Elf_Xword flags);
|
||||
attach_section_to_segment(Output_section*);
|
||||
|
||||
// Allocate a previously unallocated output section.
|
||||
// Attach an allocated section to a segment.
|
||||
void
|
||||
allocate_output_section(Output_section*, elfcpp::Elf_Xword flags);
|
||||
|
||||
// Turn a read-only output section into a read-write output section.
|
||||
void
|
||||
write_enable_output_section(Output_section*, elfcpp::Elf_Xword flags);
|
||||
attach_allocated_section_to_segment(Output_section*);
|
||||
|
||||
// Set the final file offsets of all the segments.
|
||||
off_t
|
||||
@ -578,6 +578,8 @@ class Layout
|
||||
// The list of output sections which are not attached to any output
|
||||
// segment.
|
||||
Section_list unattached_section_list_;
|
||||
// Whether we have attached the sections to the segments.
|
||||
bool sections_are_attached_;
|
||||
// The list of unattached Output_data objects which require special
|
||||
// handling because they are not Output_sections.
|
||||
Data_list special_output_list_;
|
||||
|
@ -1673,10 +1673,7 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
||||
this->addralign_ = addralign;
|
||||
|
||||
typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
|
||||
this->flags_ |= (sh_flags
|
||||
& (elfcpp::SHF_WRITE
|
||||
| elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_EXECINSTR));
|
||||
this->update_flags_for_input_section(sh_flags);
|
||||
|
||||
uint64_t entsize = shdr.get_sh_entsize();
|
||||
|
||||
|
@ -1714,6 +1714,16 @@ class Output_section : public Output_data
|
||||
set_flags(elfcpp::Elf_Xword flags)
|
||||
{ this->flags_ = flags; }
|
||||
|
||||
// Update the output section flags based on input section flags.
|
||||
void
|
||||
update_flags_for_input_section(elfcpp::Elf_Xword flags)
|
||||
{
|
||||
this->flags_ |= (flags
|
||||
& (elfcpp::SHF_WRITE
|
||||
| elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_EXECINSTR));
|
||||
}
|
||||
|
||||
// Return the entsize field.
|
||||
uint64_t
|
||||
entsize() const
|
||||
|
Loading…
Reference in New Issue
Block a user