Line 419... |
Line 419... |
discarded_eh_frame_shndx_(-1U),
|
discarded_eh_frame_shndx_(-1U),
|
deferred_layout_(),
|
deferred_layout_(),
|
deferred_layout_relocs_(),
|
deferred_layout_relocs_(),
|
compressed_sections_()
|
compressed_sections_()
|
{
|
{
|
|
this->e_type_ = ehdr.get_e_type();
|
}
|
}
|
|
|
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
Sized_relobj_file<size, big_endian>::~Sized_relobj_file()
|
Sized_relobj_file<size, big_endian>::~Sized_relobj_file()
|
{
|
{
|
Line 509... |
Line 510... |
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
bool
|
bool
|
Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
|
Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
|
const elfcpp::Shdr<size, big_endian>* shdr) const
|
const elfcpp::Shdr<size, big_endian>* shdr) const
|
{
|
{
|
return (shdr->get_sh_type() == elfcpp::SHT_PROGBITS
|
elfcpp::Elf_Word sh_type = shdr->get_sh_type();
|
|
return ((sh_type == elfcpp::SHT_PROGBITS
|
|
|| sh_type == elfcpp::SHT_X86_64_UNWIND)
|
&& (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
|
&& (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
|
}
|
}
|
|
|
// Return whether there is a GNU .eh_frame section, given the section
|
// Return whether there is a GNU .eh_frame section, given the section
|
// headers and the section names.
|
// headers and the section names.
|
Line 744... |
Line 747... |
// The first word contains flags. We only care about COMDAT section
|
// The first word contains flags. We only care about COMDAT section
|
// groups. Other section groups are always included in the link
|
// groups. Other section groups are always included in the link
|
// just like ordinary sections.
|
// just like ordinary sections.
|
elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword);
|
elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword);
|
|
|
// Look up the group signature, which is the name of a symbol. This
|
// Look up the group signature, which is the name of a symbol. ELF
|
// is a lot of effort to go to to read a string. Why didn't they
|
// uses a symbol name because some group signatures are long, and
|
// just have the group signature point into the string table, rather
|
// the name is generally already in the symbol table, so it makes
|
// than indirect through a symbol?
|
// sense to put the long string just once in .strtab rather than in
|
|
// both .strtab and .shstrtab.
|
|
|
// Get the appropriate symbol table header (this will normally be
|
// Get the appropriate symbol table header (this will normally be
|
// the single SHT_SYMTAB section, but in principle it need not be).
|
// the single SHT_SYMTAB section, but in principle it need not be).
|
const unsigned int link = this->adjust_shndx(shdr.get_sh_link());
|
const unsigned int link = this->adjust_shndx(shdr.get_sh_link());
|
typename This::Shdr symshdr(this, this->elf_file_.section_header(link));
|
typename This::Shdr symshdr(this, this->elf_file_.section_header(link));
|
Line 1014... |
Line 1018... |
|
|
// Layout an input section.
|
// Layout an input section.
|
|
|
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
inline void
|
inline void
|
Sized_relobj_file<size, big_endian>::layout_section(Layout* layout,
|
Sized_relobj_file<size, big_endian>::layout_section(
|
|
Layout* layout,
|
unsigned int shndx,
|
unsigned int shndx,
|
const char* name,
|
const char* name,
|
typename This::Shdr& shdr,
|
const typename This::Shdr& shdr,
|
unsigned int reloc_shndx,
|
unsigned int reloc_shndx,
|
unsigned int reloc_type)
|
unsigned int reloc_type)
|
{
|
{
|
off_t offset;
|
off_t offset;
|
Output_section* os = layout->layout(this, shndx, name, shdr,
|
Output_section* os = layout->layout(this, shndx, name, shdr,
|
Line 1038... |
Line 1043... |
// before we apply the relocs.
|
// before we apply the relocs.
|
if (offset == -1 && reloc_shndx != 0)
|
if (offset == -1 && reloc_shndx != 0)
|
this->set_relocs_must_follow_section_writes();
|
this->set_relocs_must_follow_section_writes();
|
}
|
}
|
|
|
|
// Layout an input .eh_frame section.
|
|
|
|
template<int size, bool big_endian>
|
|
void
|
|
Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
|
|
Layout* layout,
|
|
const unsigned char* symbols_data,
|
|
section_size_type symbols_size,
|
|
const unsigned char* symbol_names_data,
|
|
section_size_type symbol_names_size,
|
|
unsigned int shndx,
|
|
const typename This::Shdr& shdr,
|
|
unsigned int reloc_shndx,
|
|
unsigned int reloc_type)
|
|
{
|
|
gold_assert(this->has_eh_frame_);
|
|
|
|
off_t offset;
|
|
Output_section* os = layout->layout_eh_frame(this,
|
|
symbols_data,
|
|
symbols_size,
|
|
symbol_names_data,
|
|
symbol_names_size,
|
|
shndx,
|
|
shdr,
|
|
reloc_shndx,
|
|
reloc_type,
|
|
&offset);
|
|
this->output_sections()[shndx] = os;
|
|
if (os == NULL || offset == -1)
|
|
{
|
|
// An object can contain at most one section holding exception
|
|
// frame information.
|
|
gold_assert(this->discarded_eh_frame_shndx_ == -1U);
|
|
this->discarded_eh_frame_shndx_ = shndx;
|
|
this->section_offsets()[shndx] = invalid_address;
|
|
}
|
|
else
|
|
this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);
|
|
|
|
// If this section requires special handling, and if there are
|
|
// relocs that aply to it, then we must do the special handling
|
|
// before we apply the relocs.
|
|
if (os != NULL && offset == -1 && reloc_shndx != 0)
|
|
this->set_relocs_must_follow_section_writes();
|
|
}
|
|
|
// Lay out the input sections. We walk through the sections and check
|
// Lay out the input sections. We walk through the sections and check
|
// whether they should be included in the link. If they should, we
|
// whether they should be included in the link. If they should, we
|
// pass them to the Layout object, which will return an output section
|
// pass them to the Layout object, which will return an output section
|
// and an offset.
|
// and an offset.
|
// During garbage collection (--gc-sections) and identical code folding
|
// During garbage collection (--gc-sections) and identical code folding
|
Line 1241... |
Line 1293... |
|
|
if (!is_gc_pass_two)
|
if (!is_gc_pass_two)
|
{
|
{
|
if (this->handle_gnu_warning_section(name, i, symtab))
|
if (this->handle_gnu_warning_section(name, i, symtab))
|
{
|
{
|
if (!relocatable)
|
if (!relocatable && !parameters->options().shared())
|
omit[i] = true;
|
omit[i] = true;
|
}
|
}
|
|
|
// The .note.GNU-stack section is special. It gives the
|
// The .note.GNU-stack section is special. It gives the
|
// protection flags that this object file requires for the stack
|
// protection flags that this object file requires for the stack
|
Line 1260... |
Line 1312... |
// The .note.GNU-split-stack section is also special. It
|
// The .note.GNU-split-stack section is also special. It
|
// indicates that the object was compiled with
|
// indicates that the object was compiled with
|
// -fsplit-stack.
|
// -fsplit-stack.
|
if (this->handle_split_stack_section(name))
|
if (this->handle_split_stack_section(name))
|
{
|
{
|
if (!parameters->options().relocatable()
|
if (!relocatable && !parameters->options().shared())
|
&& !parameters->options().shared())
|
|
omit[i] = true;
|
omit[i] = true;
|
}
|
}
|
|
|
// Skip attributes section.
|
// Skip attributes section.
|
if (parameters->target().is_attributes_section(name))
|
if (parameters->target().is_attributes_section(name))
|
Line 1364... |
Line 1415... |
if (is_gc_pass_one)
|
if (is_gc_pass_one)
|
{
|
{
|
out_sections[i] = reinterpret_cast<Output_section*>(1);
|
out_sections[i] = reinterpret_cast<Output_section*>(1);
|
out_section_offsets[i] = invalid_address;
|
out_section_offsets[i] = invalid_address;
|
}
|
}
|
|
else if (should_defer_layout)
|
|
this->deferred_layout_.push_back(Deferred_layout(i, name,
|
|
pshdrs,
|
|
reloc_shndx[i],
|
|
reloc_type[i]));
|
else
|
else
|
eh_frame_sections.push_back(i);
|
eh_frame_sections.push_back(i);
|
continue;
|
continue;
|
}
|
}
|
|
|
Line 1524... |
Line 1580... |
gold_assert(!is_gc_pass_one || eh_frame_sections.empty());
|
gold_assert(!is_gc_pass_one || eh_frame_sections.empty());
|
for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
|
for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
|
p != eh_frame_sections.end();
|
p != eh_frame_sections.end();
|
++p)
|
++p)
|
{
|
{
|
gold_assert(this->has_eh_frame_);
|
|
gold_assert(external_symbols_offset != 0);
|
gold_assert(external_symbols_offset != 0);
|
|
|
unsigned int i = *p;
|
unsigned int i = *p;
|
const unsigned char* pshdr;
|
const unsigned char* pshdr;
|
pshdr = section_headers_data + i * This::shdr_size;
|
pshdr = section_headers_data + i * This::shdr_size;
|
typename This::Shdr shdr(pshdr);
|
typename This::Shdr shdr(pshdr);
|
|
|
off_t offset;
|
this->layout_eh_frame_section(layout,
|
Output_section* os = layout->layout_eh_frame(this,
|
|
symbols_data,
|
symbols_data,
|
symbols_size,
|
symbols_size,
|
symbol_names_data,
|
symbol_names_data,
|
symbol_names_size,
|
symbol_names_size,
|
i, shdr,
|
i,
|
|
shdr,
|
reloc_shndx[i],
|
reloc_shndx[i],
|
reloc_type[i],
|
reloc_type[i]);
|
&offset);
|
|
out_sections[i] = os;
|
|
if (os == NULL || offset == -1)
|
|
{
|
|
// An object can contain at most one section holding exception
|
|
// frame information.
|
|
gold_assert(this->discarded_eh_frame_shndx_ == -1U);
|
|
this->discarded_eh_frame_shndx_ = i;
|
|
out_section_offsets[i] = invalid_address;
|
|
}
|
|
else
|
|
out_section_offsets[i] = convert_types<Address, off_t>(offset);
|
|
|
|
// If this section requires special handling, and if there are
|
|
// relocs that apply to it, then we must do the special handling
|
|
// before we apply the relocs.
|
|
if (os != NULL && offset == -1 && reloc_shndx[i] != 0)
|
|
this->set_relocs_must_follow_section_writes();
|
|
}
|
}
|
|
|
if (is_gc_pass_two)
|
if (is_gc_pass_two)
|
{
|
{
|
delete[] gc_sd->section_headers_data;
|
delete[] gc_sd->section_headers_data;
|
Line 1597... |
Line 1634... |
// If the section is not included, it is because the garbage collector
|
// If the section is not included, it is because the garbage collector
|
// decided it is not needed. Avoid reverting that decision.
|
// decided it is not needed. Avoid reverting that decision.
|
if (!this->is_section_included(deferred->shndx_))
|
if (!this->is_section_included(deferred->shndx_))
|
continue;
|
continue;
|
|
|
|
if (parameters->options().relocatable()
|
|
|| deferred->name_ != ".eh_frame"
|
|
|| !this->check_eh_frame_flags(&shdr))
|
this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
|
this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
|
shdr, deferred->reloc_shndx_, deferred->reloc_type_);
|
shdr, deferred->reloc_shndx_,
|
|
deferred->reloc_type_);
|
|
else
|
|
{
|
|
// Reading the symbols again here may be slow.
|
|
Read_symbols_data sd;
|
|
this->read_symbols(&sd);
|
|
this->layout_eh_frame_section(layout,
|
|
sd.symbols->data(),
|
|
sd.symbols_size,
|
|
sd.symbol_names->data(),
|
|
sd.symbol_names_size,
|
|
deferred->shndx_,
|
|
shdr,
|
|
deferred->reloc_shndx_,
|
|
deferred->reloc_type_);
|
|
}
|
}
|
}
|
|
|
this->deferred_layout_.clear();
|
this->deferred_layout_.clear();
|
|
|
// Now handle the deferred relocation sections.
|
// Now handle the deferred relocation sections.
|