Combine read-only .eh_frame sections with read-write .eh_frame
sections.
This commit is contained in:
parent
e00eeb0a11
commit
1650c4ff50
@ -520,7 +520,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
||||
off_t* off)
|
||||
{
|
||||
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
|
||||
gold_assert(shdr.get_sh_flags() == elfcpp::SHF_ALLOC);
|
||||
gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
|
||||
|
||||
const char* const name = ".eh_frame";
|
||||
Output_section* os = this->choose_output_section(object,
|
||||
@ -531,6 +531,16 @@ 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;
|
||||
@ -778,6 +788,41 @@ Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags)
|
||||
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
|
||||
|
@ -477,6 +477,10 @@ class Layout
|
||||
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);
|
||||
|
||||
// Set the final file offsets of all the segments.
|
||||
off_t
|
||||
set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);
|
||||
|
@ -226,7 +226,7 @@ Sized_relobj<size, big_endian>::check_eh_frame_flags(
|
||||
{
|
||||
return (shdr->get_sh_size() > 0
|
||||
&& shdr->get_sh_type() == elfcpp::SHT_PROGBITS
|
||||
&& shdr->get_sh_flags() == elfcpp::SHF_ALLOC);
|
||||
&& (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
|
||||
}
|
||||
|
||||
// Return whether there is a GNU .eh_frame section, given the section
|
||||
@ -275,8 +275,11 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
|
||||
const unsigned char* namesu = sd->section_names->data();
|
||||
const char* names = reinterpret_cast<const char*>(namesu);
|
||||
if (memmem(names, sd->section_names_size, ".eh_frame", 10) != NULL)
|
||||
{
|
||||
if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
|
||||
this->has_eh_frame_ = true;
|
||||
}
|
||||
|
||||
sd->symbols = NULL;
|
||||
sd->symbols_size = 0;
|
||||
|
@ -2376,6 +2376,27 @@ Output_segment::add_output_section(Output_section* os,
|
||||
pdl->push_back(os);
|
||||
}
|
||||
|
||||
// Remove an Output_section from this segment. It is an error if it
|
||||
// is not present.
|
||||
|
||||
void
|
||||
Output_segment::remove_output_section(Output_section* os)
|
||||
{
|
||||
// We only need this for SHT_PROGBITS.
|
||||
gold_assert(os->type() == elfcpp::SHT_PROGBITS);
|
||||
for (Output_data_list::iterator p = this->output_data_.begin();
|
||||
p != this->output_data_.end();
|
||||
++p)
|
||||
{
|
||||
if (*p == os)
|
||||
{
|
||||
this->output_data_.erase(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Add an Output_data (which is not an Output_section) to the start of
|
||||
// a segment.
|
||||
|
||||
|
@ -1714,6 +1714,13 @@ class Output_section : public Output_data
|
||||
flags() const
|
||||
{ return this->flags_; }
|
||||
|
||||
// Set the section flags. This may only be used with the Layout
|
||||
// code when it is prepared to move the section to a different
|
||||
// segment.
|
||||
void
|
||||
set_flags(elfcpp::Elf_Xword flags)
|
||||
{ this->flags_ = flags; }
|
||||
|
||||
// Return the entsize field.
|
||||
uint64_t
|
||||
entsize() const
|
||||
@ -2523,6 +2530,11 @@ class Output_segment
|
||||
add_initial_output_section(Output_section* os, elfcpp::Elf_Word seg_flags)
|
||||
{ this->add_output_section(os, seg_flags, true); }
|
||||
|
||||
// Remove an Output_section from this segment. It is an error if it
|
||||
// is not present.
|
||||
void
|
||||
remove_output_section(Output_section* os);
|
||||
|
||||
// Add an Output_data (which is not an Output_section) to the start
|
||||
// of this segment.
|
||||
void
|
||||
|
Loading…
x
Reference in New Issue
Block a user