X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fehframe.cc;h=c9feb28793d50b43f4eb551ee4226d4eb3a39071;hb=b899eb3bb807be1094fde9a2f1c8628232bc0743;hp=b2406b4f7e1f4da356f4d6927dbebb84f3993e8a;hpb=a9a60db6891083f0afc4df6353a0c7ef80508874;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/ehframe.cc b/gold/ehframe.cc index b2406b4f7e..c9feb28793 100644 --- a/gold/ehframe.cc +++ b/gold/ehframe.cc @@ -1,6 +1,6 @@ // ehframe.cc -- handle exception frame sections for gold -// Copyright 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -104,51 +104,36 @@ Eh_frame_hdr::set_final_data_size() this->set_data_size(data_size); } -// Write the data to the flie. +// Write the data to the file. void Eh_frame_hdr::do_write(Output_file* of) { - if (parameters->get_size() == 32) + switch (parameters->size_and_endianness()) { - if (!parameters->is_big_endian()) - { #ifdef HAVE_TARGET_32_LITTLE - this->do_sized_write<32, false>(of); -#else - gold_unreachable(); + case Parameters::TARGET_32_LITTLE: + this->do_sized_write<32, false>(of); + break; #endif - } - else - { #ifdef HAVE_TARGET_32_BIG - this->do_sized_write<32, true>(of); -#else - gold_unreachable(); + case Parameters::TARGET_32_BIG: + this->do_sized_write<32, true>(of); + break; #endif - } - } - else if (parameters->get_size() == 64) - { - if (!parameters->is_big_endian()) - { #ifdef HAVE_TARGET_64_LITTLE - this->do_sized_write<64, false>(of); -#else - gold_unreachable(); + case Parameters::TARGET_64_LITTLE: + this->do_sized_write<64, false>(of); + break; #endif - } - else - { #ifdef HAVE_TARGET_64_BIG - this->do_sized_write<64, true>(of); -#else - gold_unreachable(); + case Parameters::TARGET_64_BIG: + this->do_sized_write<64, true>(of); + break; #endif - } + default: + gold_unreachable(); } - else - gold_unreachable(); } // Write the data to the file with the right endianness. @@ -281,7 +266,7 @@ Eh_frame_hdr::get_fde_pc( gold_unreachable(); } - switch (fde_encoding & 0xf0) + switch (fde_encoding & 0x70) { case 0: break; @@ -290,12 +275,18 @@ Eh_frame_hdr::get_fde_pc( pc += eh_frame_address + fde_offset + 8; break; + case elfcpp::DW_EH_PE_datarel: + pc += parameters->target().ehframe_datarel_base(); + break; + default: // If other cases arise, then we have to handle them, or we have // to reject them by returning false in Eh_frame::read_cie. gold_unreachable(); } + gold_assert((fde_encoding & elfcpp::DW_EH_PE_indirect) == 0); + return pc; } @@ -335,22 +326,32 @@ Eh_frame_hdr::get_fde_addresses(Output_file* of, // Class Fde. // Write the FDE to OVIEW starting at OFFSET. CIE_OFFSET is the -// offset of the CIE in OVIEW. FDE_ENCODING is the encoding, from the -// CIE. Record the FDE pc for EH_FRAME_HDR. Return the new offset. +// offset of the CIE in OVIEW. OUTPUT_OFFSET is the offset of the +// Eh_frame section within the output section. FDE_ENCODING is the +// encoding, from the CIE. ADDRALIGN is the required alignment. +// ADDRESS is the virtual address of OVIEW. Record the FDE pc for +// EH_FRAME_HDR. Return the new offset. template section_offset_type -Fde::write(unsigned char* oview, section_offset_type offset, +Fde::write(unsigned char* oview, section_offset_type output_offset, + section_offset_type offset, uint64_t address, unsigned int addralign, section_offset_type cie_offset, unsigned char fde_encoding, Eh_frame_hdr* eh_frame_hdr) { + gold_assert((offset & (addralign - 1)) == 0); + size_t length = this->contents_.length(); + // We add 8 when getting the aligned length to account for the + // length word and the CIE offset. + size_t aligned_full_length = align_address(length + 8, addralign); + // Write the length of the FDE as a 32-bit word. The length word // does not include the four bytes of the length word itself, but it // does include the offset to the CIE. elfcpp::Swap<32, big_endian>::writeval(oview + offset, - length + 4); + aligned_full_length - 4); // Write the offset to the CIE as a 32-bit word. This is the // difference between the address of the offset word itself and the @@ -363,11 +364,35 @@ Fde::write(unsigned char* oview, section_offset_type offset, // will later be applied to the FDE data. memcpy(oview + offset + 8, this->contents_.data(), length); + // If this FDE is associated with a PLT, fill in the PLT's address + // and size. + if (this->object_ == NULL) + { + gold_assert(memcmp(oview + offset + 8, "\0\0\0\0\0\0\0\0", 8) == 0); + uint64_t paddress; + off_t psize; + parameters->target().plt_fde_location(this->u_.from_linker.plt, + oview + offset + 8, + &paddress, &psize); + uint64_t poffset = paddress - (address + offset + 8); + int32_t spoffset = static_cast(poffset); + uint32_t upsize = static_cast(psize); + if (static_cast(static_cast(spoffset)) != poffset + || static_cast(upsize) != psize) + gold_warning(_("overflow in PLT unwind data; " + "unwinding through PLT may fail")); + elfcpp::Swap<32, big_endian>::writeval(oview + offset + 8, spoffset); + elfcpp::Swap<32, big_endian>::writeval(oview + offset + 12, upsize); + } + + if (aligned_full_length > length + 8) + memset(oview + offset + length + 8, 0, aligned_full_length - (length + 8)); + // Tell the exception frame header about this FDE. if (eh_frame_hdr != NULL) - eh_frame_hdr->record_fde(offset, fde_encoding); + eh_frame_hdr->record_fde(output_offset + offset, fde_encoding); - return offset + length + 8; + return offset + aligned_full_length; } // Class Cie. @@ -387,60 +412,90 @@ Cie::~Cie() section_offset_type Cie::set_output_offset(section_offset_type output_offset, unsigned int addralign, - Merge_map* merge_map) + Output_section_data *output_data) { size_t length = this->contents_.length(); - gold_assert((length & (addralign - 1)) == 0); + // Add 4 for length and 4 for zero CIE identifier tag. length += 8; - merge_map->add_mapping(this->object_, this->shndx_, this->input_offset_, - length, output_offset); + if (this->object_ != NULL) + { + // Add a mapping so that relocations are applied correctly. + this->object_->add_merge_mapping(output_data, this->shndx_, + this->input_offset_, length, + output_offset); + } + + length = align_address(length, addralign); for (std::vector::const_iterator p = this->fdes_.begin(); p != this->fdes_.end(); ++p) { - (*p)->add_mapping(output_offset + length, merge_map); + (*p)->add_mapping(output_offset + length, output_data); size_t fde_length = (*p)->length(); - gold_assert((fde_length & (addralign - 1)) == 0); + fde_length = align_address(fde_length, addralign); length += fde_length; } return output_offset + length; } -// Write the CIE to OVIEW starting at OFFSET. EH_FRAME_HDR is for FDE -// recording. Return the new offset. +// Write the CIE to OVIEW starting at OFFSET. OUTPUT_OFFSET is the +// offset of the Eh_frame section within the output section. Round up +// the bytes to ADDRALIGN. ADDRESS is the virtual address of OVIEW. +// EH_FRAME_HDR is the exception frame header for FDE recording. +// POST_FDES stashes FDEs created after mappings were done, for later +// writing. Return the new offset. template section_offset_type -Cie::write(unsigned char* oview, section_offset_type offset, - Eh_frame_hdr* eh_frame_hdr) +Cie::write(unsigned char* oview, section_offset_type output_offset, + section_offset_type offset, uint64_t address, + unsigned int addralign, Eh_frame_hdr* eh_frame_hdr, + Post_fdes* post_fdes) { + gold_assert((offset & (addralign - 1)) == 0); + section_offset_type cie_offset = offset; size_t length = this->contents_.length(); + // We add 8 when getting the aligned length to account for the + // length word and the CIE tag. + size_t aligned_full_length = align_address(length + 8, addralign); + // Write the length of the CIE as a 32-bit word. The length word // does not include the four bytes of the length word itself. - elfcpp::Swap<32, big_endian>::writeval(oview + offset, length + 4); + elfcpp::Swap<32, big_endian>::writeval(oview + offset, + aligned_full_length - 4); // Write the tag which marks this as a CIE: a 32-bit zero. elfcpp::Swap<32, big_endian>::writeval(oview + offset + 4, 0); // Write out the CIE data. memcpy(oview + offset + 8, this->contents_.data(), length); - offset += length + 8; + + if (aligned_full_length > length + 8) + memset(oview + offset + length + 8, 0, aligned_full_length - (length + 8)); + + offset += aligned_full_length; // Write out the associated FDEs. unsigned char fde_encoding = this->fde_encoding_; for (std::vector::const_iterator p = this->fdes_.begin(); p != this->fdes_.end(); ++p) - offset = (*p)->write(oview, offset, cie_offset, - fde_encoding, eh_frame_hdr); + { + if ((*p)->post_map()) + post_fdes->push_back(Post_fde(*p, cie_offset, fde_encoding)); + else + offset = (*p)->write(oview, output_offset, offset, + address, addralign, cie_offset, + fde_encoding, eh_frame_hdr); + } return offset; } @@ -477,7 +532,8 @@ Eh_frame::Eh_frame() eh_frame_hdr_(NULL), cie_offsets_(), unmergeable_cie_offsets_(), - merge_map_() + mappings_are_done_(false), + final_data_size_(0) { } @@ -511,9 +567,9 @@ Eh_frame::skip_leb128(const unsigned char** pp, const unsigned char* pend) // section. template -bool +Eh_frame::Eh_frame_section_disposition Eh_frame::add_ehframe_input_section( - Sized_relobj* object, + Sized_relobj_file* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names, @@ -528,7 +584,7 @@ Eh_frame::add_ehframe_input_section( &contents_len, false); if (contents_len == 0) - return false; + return EH_EMPTY_SECTION; // If this is the marker section for the end of the data, then // return false to force it to be handled as an ordinary input @@ -536,7 +592,7 @@ Eh_frame::add_ehframe_input_section( // of unrecognized .eh_frame sections. if (contents_len == 4 && elfcpp::Swap<32, big_endian>::readval(pcontents) == 0) - return false; + return EH_END_MARKER_SECTION; New_cies new_cies; if (!this->do_add_ehframe_input_section(object, symbols, symbols_size, @@ -545,14 +601,15 @@ Eh_frame::add_ehframe_input_section( reloc_type, pcontents, contents_len, &new_cies)) { - this->eh_frame_hdr_->found_unrecognized_eh_frame_section(); + if (this->eh_frame_hdr_ != NULL) + this->eh_frame_hdr_->found_unrecognized_eh_frame_section(); for (New_cies::iterator p = new_cies.begin(); p != new_cies.end(); ++p) delete p->first; - return false; + return EH_UNRECOGNIZED_SECTION; } // Now that we know we are using this section, record any new CIEs @@ -561,15 +618,13 @@ Eh_frame::add_ehframe_input_section( p != new_cies.end(); ++p) { - uint64_t zero = 0; if (p->second) - this->cie_offsets_.insert(std::make_pair(p->first, zero)); + this->cie_offsets_.insert(p->first); else - this->unmergeable_cie_offsets_.push_back(std::make_pair(p->first, - zero)); + this->unmergeable_cie_offsets_.push_back(p->first); } - return true; + return EH_OPTIMIZABLE_SECTION; } // The bulk of the implementation of add_ehframe_input_section. @@ -577,7 +632,7 @@ Eh_frame::add_ehframe_input_section( template bool Eh_frame::do_add_ehframe_input_section( - Sized_relobj* object, + Sized_relobj_file* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names, @@ -589,7 +644,6 @@ Eh_frame::do_add_ehframe_input_section( section_size_type contents_len, New_cies* new_cies) { - typedef typename elfcpp::Elf_types::Elf_Addr Address; Track_relocs relocs; const unsigned char* p = pcontents; @@ -664,7 +718,7 @@ Eh_frame::do_add_ehframe_input_section( template bool -Eh_frame::read_cie(Sized_relobj* object, +Eh_frame::read_cie(Sized_relobj_file* object, unsigned int shndx, const unsigned char* symbols, section_size_type symbols_size, @@ -672,7 +726,7 @@ Eh_frame::read_cie(Sized_relobj* object, section_size_type symbol_names_size, const unsigned char* pcontents, const unsigned char* pcie, - const unsigned char *pcieend, + const unsigned char* pcieend, Track_relocs* relocs, Offsets_to_cie* cies, New_cies* new_cies) @@ -875,7 +929,7 @@ Eh_frame::read_cie(Sized_relobj* object, { Cie_offsets::iterator find_cie = this->cie_offsets_.find(&cie); if (find_cie != this->cie_offsets_.end()) - cie_pointer = find_cie->first; + cie_pointer = *find_cie; else { // See if we already saw this CIE in this object file. @@ -904,8 +958,8 @@ Eh_frame::read_cie(Sized_relobj* object, // know for sure that we are doing a special mapping for this // input section, but that's OK--if we don't do a special // mapping, nobody will ever ask for the mapping we add here. - this->merge_map_.add_mapping(object, shndx, (pcie - 8) - pcontents, - pcieend - (pcie - 8), -1); + object->add_merge_mapping(this, shndx, (pcie - 8) - pcontents, + pcieend - (pcie - 8), -1); } // Record this CIE plus the offset in the input section. @@ -918,14 +972,14 @@ Eh_frame::read_cie(Sized_relobj* object, template bool -Eh_frame::read_fde(Sized_relobj* object, +Eh_frame::read_fde(Sized_relobj_file* object, unsigned int shndx, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* pcontents, unsigned int offset, const unsigned char* pfde, - const unsigned char *pfdeend, + const unsigned char* pfdeend, Track_relocs* relocs, Offsets_to_cie* cies) { @@ -938,13 +992,68 @@ Eh_frame::read_fde(Sized_relobj* object, return false; Cie* cie = pcie->second; + int pc_size = 0; + switch (cie->fde_encoding() & 7) + { + case elfcpp::DW_EH_PE_udata2: + pc_size = 2; + break; + case elfcpp::DW_EH_PE_udata4: + pc_size = 4; + break; + case elfcpp::DW_EH_PE_udata8: + gold_assert(size == 64); + pc_size = 8; + break; + case elfcpp::DW_EH_PE_absptr: + pc_size = size == 32 ? 4 : 8; + break; + default: + // All other cases were rejected in Eh_frame::read_cie. + gold_unreachable(); + } + // The FDE should start with a reloc to the start of the code which // it describes. if (relocs->advance(pfde - pcontents) > 0) return false; - if (relocs->next_offset() != pfde - pcontents) - return false; + { + // In an object produced by a relocatable link, gold may have + // discarded a COMDAT group in the previous link, but not the + // corresponding FDEs. In that case, gold will have discarded + // the relocations, so the FDE will have a non-relocatable zero + // (regardless of whether the PC encoding is absolute, pc-relative, + // or data-relative) instead of a pointer to the start of the code. + + uint64_t pc_value = 0; + switch (pc_size) + { + case 2: + pc_value = elfcpp::Swap<16, big_endian>::readval(pfde); + break; + case 4: + pc_value = elfcpp::Swap<32, big_endian>::readval(pfde); + break; + case 8: + pc_value = elfcpp::Swap_unaligned<64, big_endian>::readval(pfde); + break; + default: + gold_unreachable(); + } + + if (pc_value == 0) + { + // This FDE applies to a discarded function. We + // can discard this FDE. + object->add_merge_mapping(this, shndx, (pfde - 8) - pcontents, + pfdeend - (pfde - 8), -1); + return true; + } + + // Otherwise, reject the FDE. + return false; + } unsigned int symndx = relocs->next_symndx(); if (symndx == -1U) @@ -956,21 +1065,48 @@ Eh_frame::read_fde(Sized_relobj* object, // pointer to a PC relative offset when generating a shared library. relocs->advance(pfdeend - pcontents); + // Find the section index for code that this FDE describes. + // If we have discarded the section, we can also discard the FDE. unsigned int fde_shndx; const int sym_size = elfcpp::Elf_sizes::sym_size; if (symndx >= symbols_size / sym_size) return false; elfcpp::Sym sym(symbols + symndx * sym_size); - fde_shndx = sym.get_st_shndx(); + bool is_ordinary; + fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(), + &is_ordinary); + bool is_discarded = (is_ordinary + && fde_shndx != elfcpp::SHN_UNDEF + && fde_shndx < object->shnum() + && !object->is_section_included(fde_shndx)); + + // Fetch the address range field from the FDE. The offset and size + // of the field depends on the PC encoding given in the CIE, but + // it is always an absolute value. If the address range is 0, this + // FDE corresponds to a function that was discarded during optimization + // (too late to discard the corresponding FDE). + uint64_t address_range = 0; + switch (pc_size) + { + case 2: + address_range = elfcpp::Swap<16, big_endian>::readval(pfde + 2); + break; + case 4: + address_range = elfcpp::Swap<32, big_endian>::readval(pfde + 4); + break; + case 8: + address_range = elfcpp::Swap_unaligned<64, big_endian>::readval(pfde + 8); + break; + default: + gold_unreachable(); + } - if (fde_shndx != elfcpp::SHN_UNDEF - && fde_shndx < object->shnum() - && !object->is_section_included(fde_shndx)) + if (is_discarded || address_range == 0) { - // This FDE applies to a section which we are discarding. We + // This FDE applies to a discarded function. We // can discard this FDE. - this->merge_map_.add_mapping(object, shndx, (pfde - 8) - pcontents, - pfdeend - (pfde - 8), -1); + object->add_merge_mapping(this, shndx, (pfde - 8) - pcontents, + pfdeend - (pfde - 8), -1); return true; } @@ -980,6 +1116,60 @@ Eh_frame::read_fde(Sized_relobj* object, return true; } +// Add unwind information for a PLT. + +void +Eh_frame::add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data, + size_t cie_length, const unsigned char* fde_data, + size_t fde_length) +{ + Cie cie(NULL, 0, 0, elfcpp::DW_EH_PE_pcrel | elfcpp::DW_EH_PE_sdata4, "", + cie_data, cie_length); + Cie_offsets::iterator find_cie = this->cie_offsets_.find(&cie); + Cie* pcie; + if (find_cie != this->cie_offsets_.end()) + pcie = *find_cie; + else + { + gold_assert(!this->mappings_are_done_); + pcie = new Cie(cie); + this->cie_offsets_.insert(pcie); + } + + Fde* fde = new Fde(plt, fde_data, fde_length, this->mappings_are_done_); + pcie->add_fde(fde); + + if (this->mappings_are_done_) + this->final_data_size_ += align_address(fde_length + 8, this->addralign()); +} + +// Remove all post-map unwind information for a PLT. + +void +Eh_frame::remove_ehframe_for_plt(Output_data* plt, + const unsigned char* cie_data, + size_t cie_length) +{ + if (!this->mappings_are_done_) + return; + + Cie cie(NULL, 0, 0, elfcpp::DW_EH_PE_pcrel | elfcpp::DW_EH_PE_sdata4, "", + cie_data, cie_length); + Cie_offsets::iterator find_cie = this->cie_offsets_.find(&cie); + gold_assert (find_cie != this->cie_offsets_.end()); + Cie* pcie = *find_cie; + + while (pcie->fde_count() != 0) + { + const Fde* fde = pcie->last_fde(); + if (!fde->post_map(plt)) + break; + size_t length = fde->length(); + this->final_data_size_ -= align_address(length + 8, this->addralign()); + pcie->remove_fde(); + } +} + // Return the number of FDEs. unsigned int @@ -990,11 +1180,11 @@ Eh_frame::fde_count() const this->unmergeable_cie_offsets_.begin(); p != this->unmergeable_cie_offsets_.end(); ++p) - ret += p->first->fde_count(); + ret += (*p)->fde_count(); for (Cie_offsets::const_iterator p = this->cie_offsets_.begin(); p != this->cie_offsets_.end(); ++p) - ret += p->first->fde_count(); + ret += (*p)->fde_count(); return ret; } @@ -1003,32 +1193,40 @@ Eh_frame::fde_count() const void Eh_frame::set_final_data_size() { - off_t start_file_offset = this->offset(); - section_offset_type output_offset = 0; + // We can be called more than once if Layout::set_segment_offsets + // finds a better mapping. We don't want to add all the mappings + // again. + if (this->mappings_are_done_) + { + this->set_data_size(this->final_data_size_); + return; + } + + section_offset_type output_start = 0; + if (this->is_offset_valid()) + output_start = this->offset() - this->output_section()->offset(); + section_offset_type output_offset = output_start; for (Unmergeable_cie_offsets::iterator p = this->unmergeable_cie_offsets_.begin(); p != this->unmergeable_cie_offsets_.end(); ++p) - { - p->second = start_file_offset + output_offset; - output_offset = p->first->set_output_offset(output_offset, - this->addralign(), - &this->merge_map_); - } + output_offset = (*p)->set_output_offset(output_offset, + this->addralign(), + this); for (Cie_offsets::iterator p = this->cie_offsets_.begin(); p != this->cie_offsets_.end(); ++p) - { - p->second = start_file_offset + output_offset; - output_offset = p->first->set_output_offset(output_offset, - this->addralign(), - &this->merge_map_); - } + output_offset = (*p)->set_output_offset(output_offset, + this->addralign(), + this); + + this->mappings_are_done_ = true; + this->final_data_size_ = output_offset - output_start; gold_assert((output_offset & (this->addralign() - 1)) == 0); - this->set_data_size(output_offset); + this->set_data_size(this->final_data_size_); } // Return an output offset for an input offset. @@ -1038,16 +1236,7 @@ Eh_frame::do_output_offset(const Relobj* object, unsigned int shndx, section_offset_type offset, section_offset_type* poutput) const { - return this->merge_map_.get_output_offset(object, shndx, offset, poutput); -} - -// Return whether this is the merge section for an input section. - -bool -Eh_frame::do_is_merge_section_for(const Relobj* object, - unsigned int shndx) const -{ - return this->merge_map_.is_merge_section_for(object, shndx); + return object->merge_output_offset(shndx, offset, poutput); } // Write the data to the output file. @@ -1059,46 +1248,31 @@ Eh_frame::do_write(Output_file* of) const off_t oview_size = this->data_size(); unsigned char* const oview = of->get_output_view(offset, oview_size); - if (parameters->get_size() == 32) + switch (parameters->size_and_endianness()) { - if (!parameters->is_big_endian()) - { #ifdef HAVE_TARGET_32_LITTLE - this->do_sized_write<32, false>(oview); -#else - gold_unreachable(); + case Parameters::TARGET_32_LITTLE: + this->do_sized_write<32, false>(oview); + break; #endif - } - else - { #ifdef HAVE_TARGET_32_BIG - this->do_sized_write<32, true>(oview); -#else - gold_unreachable(); + case Parameters::TARGET_32_BIG: + this->do_sized_write<32, true>(oview); + break; #endif - } - } - else if (parameters->get_size() == 64) - { - if (!parameters->is_big_endian()) - { #ifdef HAVE_TARGET_64_LITTLE - this->do_sized_write<64, false>(oview); -#else - gold_unreachable(); + case Parameters::TARGET_64_LITTLE: + this->do_sized_write<64, false>(oview); + break; #endif - } - else - { #ifdef HAVE_TARGET_64_BIG - this->do_sized_write<64, true>(oview); -#else - gold_unreachable(); + case Parameters::TARGET_64_BIG: + this->do_sized_write<64, true>(oview); + break; #endif - } + default: + gold_unreachable(); } - else - gold_unreachable(); of->write_output_view(offset, oview_size, oview); } @@ -1109,23 +1283,38 @@ template void Eh_frame::do_sized_write(unsigned char* oview) { + uint64_t address = this->address(); + unsigned int addralign = this->addralign(); section_offset_type o = 0; + const off_t output_offset = this->offset() - this->output_section()->offset(); + Post_fdes post_fdes; for (Unmergeable_cie_offsets::iterator p = this->unmergeable_cie_offsets_.begin(); p != this->unmergeable_cie_offsets_.end(); ++p) - o = p->first->write(oview, o, this->eh_frame_hdr_); + o = (*p)->write(oview, output_offset, o, address, + addralign, this->eh_frame_hdr_, + &post_fdes); for (Cie_offsets::iterator p = this->cie_offsets_.begin(); p != this->cie_offsets_.end(); ++p) - o = p->first->write(oview, o, this->eh_frame_hdr_); + o = (*p)->write(oview, output_offset, o, address, + addralign, this->eh_frame_hdr_, + &post_fdes); + for (Post_fdes::iterator p = post_fdes.begin(); + p != post_fdes.end(); + ++p) + o = (*p).fde->write(oview, output_offset, o, address, + addralign, (*p).cie_offset, + (*p).fde_encoding, + this->eh_frame_hdr_); } #ifdef HAVE_TARGET_32_LITTLE template -bool +Eh_frame::Eh_frame_section_disposition Eh_frame::add_ehframe_input_section<32, false>( - Sized_relobj<32, false>* object, + Sized_relobj_file<32, false>* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names, @@ -1137,9 +1326,9 @@ Eh_frame::add_ehframe_input_section<32, false>( #ifdef HAVE_TARGET_32_BIG template -bool +Eh_frame::Eh_frame_section_disposition Eh_frame::add_ehframe_input_section<32, true>( - Sized_relobj<32, true>* object, + Sized_relobj_file<32, true>* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names, @@ -1151,9 +1340,9 @@ Eh_frame::add_ehframe_input_section<32, true>( #ifdef HAVE_TARGET_64_LITTLE template -bool +Eh_frame::Eh_frame_section_disposition Eh_frame::add_ehframe_input_section<64, false>( - Sized_relobj<64, false>* object, + Sized_relobj_file<64, false>* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names, @@ -1165,9 +1354,9 @@ Eh_frame::add_ehframe_input_section<64, false>( #ifdef HAVE_TARGET_64_BIG template -bool +Eh_frame::Eh_frame_section_disposition Eh_frame::add_ehframe_input_section<64, true>( - Sized_relobj<64, true>* object, + Sized_relobj_file<64, true>* object, const unsigned char* symbols, section_size_type symbols_size, const unsigned char* symbol_names,