Combine read-only .eh_frame sections with read-write .eh_frame

sections.
This commit is contained in:
Ian Lance Taylor 2008-03-12 04:38:42 +00:00
parent e00eeb0a11
commit 1650c4ff50
5 changed files with 89 additions and 4 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 (this->find_eh_frame(pshdrs, names, sd->section_names_size))
this->has_eh_frame_ = true;
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;

View File

@ -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.

View File

@ -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