diff options
author | Alan Modra <amodra@gmail.com> | 2013-02-27 23:11:56 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2013-02-27 23:11:56 +0000 |
commit | 9d5781f8a245086dcdd3cd8fcddcd5b19c3a1e49 (patch) | |
tree | e53d7aa78570b4f92a31db6d49bb0e0a31374b61 /gold/ehframe.cc | |
parent | 71091f23fd90c0f1d04a0471ec561f07120b702c (diff) | |
download | gdb-9d5781f8a245086dcdd3cd8fcddcd5b19c3a1e49.zip gdb-9d5781f8a245086dcdd3cd8fcddcd5b19c3a1e49.tar.gz gdb-9d5781f8a245086dcdd3cd8fcddcd5b19c3a1e49.tar.bz2 |
* target.h (Target::plt_fde_location, do_plt_fde_location): Declare.
* target.cc (Target::do_plt_fde_location): New function.
* ehframe.h (class FDE): Add post_map field to u_.from_linker,
accessor function, and constructor param.
(struct Post_fde, Post_fdes): Declare.
(Cie::write): Add post_fdes param.
* ehframe.cc (Fde::write): Use plt_fde_location.
(struct Post_fde): Define.
(Cie::write): Stash FDEs added post merge mapping.
(Eh_frame::add_ehframe_for_plt): Assert no new CIEs after mapping.
Adjust Fde constructor call. Bump final_data_size_ for post map FDEs.
(Eh_frame::do_sized_write): Arrange to write post map FDES after
other FDEs.
* powerpc.cc (Target_powerpc::do_plt_fde_location): New function.
(Target_powerpc::has_glink): New function.
(Target_powerpc::do_relax): Add eh_frame info for stubs.
(struct Eh_cie, eh_frame_cie, glink_eh_frame_fde_64,
glink_eh_frame_fde_32, default_fde): New data.
(Stub_table::eh_frame_added_): New var.
(Stub_table::find_long_branch_entry, stub_address, stub_offset):
Make const.
(Stub_table::add_eh_frame): New function.
(Output_data_glink::add_eh_frame): New function.
(Target_powerpc::make_glink_section): Call add_eh_frame.
Diffstat (limited to 'gold/ehframe.cc')
-rw-r--r-- | gold/ehframe.cc | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/gold/ehframe.cc b/gold/ehframe.cc index 1aaf346..82a6d6e 100644 --- a/gold/ehframe.cc +++ b/gold/ehframe.cc @@ -368,10 +368,13 @@ Fde::write(unsigned char* oview, section_offset_type offset, if (this->object_ == NULL) { gold_assert(memcmp(oview + offset + 8, "\0\0\0\0\0\0\0\0", 8) == 0); - Output_data* plt = this->u_.from_linker.plt; - uint64_t poffset = plt->address() - (address + offset + 8); + 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<int32_t>(poffset); - off_t psize = plt->data_size(); uint32_t upsize = static_cast<uint32_t>(psize); if (static_cast<uint64_t>(static_cast<int64_t>(spoffset)) != poffset || static_cast<off_t>(upsize) != psize) @@ -438,15 +441,30 @@ Cie::set_output_offset(section_offset_type output_offset, return output_offset + length; } -// Write the CIE to OVIEW starting at OFFSET. EH_FRAME_HDR is for FDE -// recording. Round up the bytes to ADDRALIGN. Return the new -// offset. +// A FDE plus some info from a CIE to allow later writing of the FDE. + +struct Post_fde +{ + Post_fde(Fde* f, section_offset_type cie_off, unsigned char encoding) + : fde(f), cie_offset(cie_off), fde_encoding(encoding) + { } + + Fde* fde; + section_offset_type cie_offset; + unsigned char fde_encoding; +}; + +// Write the CIE to OVIEW starting at OFFSET. 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<int size, bool big_endian> section_offset_type Cie::write(unsigned char* oview, section_offset_type offset, uint64_t address, unsigned int addralign, - Eh_frame_hdr* eh_frame_hdr) + Eh_frame_hdr* eh_frame_hdr, Post_fdes* post_fdes) { gold_assert((offset & (addralign - 1)) == 0); @@ -479,9 +497,14 @@ Cie::write(unsigned char* oview, section_offset_type offset, for (std::vector<Fde*>::const_iterator p = this->fdes_.begin(); p != this->fdes_.end(); ++p) - offset = (*p)->write<size, big_endian>(oview, offset, address, addralign, - cie_offset, fde_encoding, - eh_frame_hdr); + { + if ((*p)->post_map()) + post_fdes->push_back(new Post_fde(*p, cie_offset, fde_encoding)); + else + offset = (*p)->write<size, big_endian>(oview, offset, address, + addralign, cie_offset, + fde_encoding, eh_frame_hdr); + } return offset; } @@ -1039,12 +1062,16 @@ Eh_frame::add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data, 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); + 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()); } // Return the number of FDEs. @@ -1169,17 +1196,28 @@ Eh_frame::do_sized_write(unsigned char* oview) uint64_t address = this->address(); unsigned int addralign = this->addralign(); section_offset_type o = 0; + Post_fdes post_fdes; for (Unmergeable_cie_offsets::iterator p = this->unmergeable_cie_offsets_.begin(); p != this->unmergeable_cie_offsets_.end(); ++p) o = (*p)->write<size, big_endian>(oview, o, address, addralign, - this->eh_frame_hdr_); + this->eh_frame_hdr_, &post_fdes); for (Cie_offsets::iterator p = this->cie_offsets_.begin(); p != this->cie_offsets_.end(); ++p) o = (*p)->write<size, big_endian>(oview, o, address, addralign, - this->eh_frame_hdr_); + this->eh_frame_hdr_, &post_fdes); + for (Post_fdes::iterator p = post_fdes.begin(); + p != post_fdes.end(); + ++p) + { + o = (*p)->fde->write<size, big_endian>(oview, o, address, addralign, + (*p)->cie_offset, + (*p)->fde_encoding, + this->eh_frame_hdr_); + delete *p; + } } #ifdef HAVE_TARGET_32_LITTLE |