diff options
author | Ian Lance Taylor <ian@airs.com> | 2011-07-01 22:05:01 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2011-07-01 22:05:01 +0000 |
commit | 07a60597350488f098508ee67717d549a8a0b579 (patch) | |
tree | 2476e48897011f57f41615892bdffda825fde6b2 /gold/ehframe.h | |
parent | a931db6a07ac9ae2fec6c31c6d037716050292c5 (diff) | |
download | gdb-07a60597350488f098508ee67717d549a8a0b579.zip gdb-07a60597350488f098508ee67717d549a8a0b579.tar.gz gdb-07a60597350488f098508ee67717d549a8a0b579.tar.bz2 |
PR gold/12571
* options.h (class General_options): Add
--ld-generated-unwind-info.
* ehframe.cc (Fde::write): Add address parameter. Change all
callers. If associated with PLT, fill in address and size.
(Cie::set_output_offset): Only add merge mapping if there is an
object.
(Cie::write): Add address parameter. Change all callers.
(Eh_frame::add_ehframe_for_plt): New function.
* ehframe.h (class Fde): Update declarations. Move shndx_ and
input_offset_ fields into union u_, with new plt field.
(Fde::Fde): Adjust for new union field.
(Fde::Fde) [Output_data version]: New constructor.
(Fde::add_mapping): Only add merge mapping if there is an object.
(class Cie): Update declarations.
(class Eh_frame): Declare add_ehframe_for_plt.
* layout.cc (Layout::layout_eh_frame): Break out code into
make_eh_frame_section, and call it.
(Layout::make_eh_frame_section): New function.
(Layout::add_eh_frame_for_plt): New function.
* layout.h (class Layout): Update declarations.
* merge.cc (Merge_map::add_mapping): Add assertion.
* i386.cc: Include "dwarf.h".
(class Output_data_plt_i386): Make first_plt_entry,
dyn_first_plt_entry, exec_plt_entry, and dyn_plt_entry const. Add
plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie,
and plt_eh_frame_fde.
(Output_data_plt_i386::Output_data_plt_i386): Align to 16-byte
boundary. Call add_eh_frame_for_plt if appropriate.
* x86_64.cc: Include "dwarf.h".
(class Output_data_plt_x86_64): Align to 16-byte boundary. Make
first_plt_entry, plt_entry and tlsdesc_plt_entry const. Add
plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie,
and plt_eh_frame_fde.
(Output_data_plt_x86_64::init): Call add_eh_frame_for_plt if
appropriate.
Diffstat (limited to 'gold/ehframe.h')
-rw-r--r-- | gold/ehframe.h | 88 |
1 files changed, 63 insertions, 25 deletions
diff --git a/gold/ehframe.h b/gold/ehframe.h index f626b1f..c3f82e9 100644 --- a/gold/ehframe.h +++ b/gold/ehframe.h @@ -1,6 +1,6 @@ // ehframe.h -- handle exception frame sections for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -45,10 +45,6 @@ class Eh_frame; // time and when a shared object is loaded, and the time required to // deregister the exception handlers when a shared object is unloaded. -// FIXME: gcc supports using storing a sorted lookup table for the -// FDEs in the PT_GNU_EH_FRAME segment, but we do not yet generate -// that. - class Eh_frame_hdr : public Output_section_data { public: @@ -170,9 +166,18 @@ class Fde public: Fde(Relobj* object, unsigned int shndx, section_offset_type input_offset, const unsigned char* contents, size_t length) - : object_(object), shndx_(shndx), input_offset_(input_offset), + : object_(object), contents_(reinterpret_cast<const char*>(contents), length) - { } + { + this->u_.from_object.shndx = shndx; + this->u_.from_object.input_offset = input_offset; + } + + // Create an FDE associated with a PLT. + Fde(Output_data* plt, const unsigned char* contents, size_t length) + : object_(NULL), + contents_(reinterpret_cast<const char*>(contents), length) + { this->u_.from_linker.plt = plt; } // Return the length of this FDE. Add 4 for the length and 4 for // the offset to the CIE. @@ -180,32 +185,52 @@ class Fde length() const { return this->contents_.length() + 8; } - // Add a mapping for this FDE to MERGE_MAP. + // Add a mapping for this FDE to MERGE_MAP, so that relocations + // against the FDE are applied to right part of the output file. void add_mapping(section_offset_type output_offset, Merge_map* merge_map) const { - merge_map->add_mapping(this->object_, this->shndx_, - this->input_offset_, this->length(), - output_offset); + if (this->object_ != NULL) + merge_map->add_mapping(this->object_, this->u_.from_object.shndx, + this->u_.from_object.input_offset, this->length(), + output_offset); } // Write the FDE to OVIEW starting at OFFSET. FDE_ENCODING is the // encoding, from the CIE. Round up the bytes to ADDRALIGN if - // necessary. Record the FDE in EH_FRAME_HDR. Return the new - // offset. + // necessary. ADDRESS is the virtual address of OVIEW. Record the + // FDE in EH_FRAME_HDR. Return the new offset. template<int size, bool big_endian> section_offset_type write(unsigned char* oview, section_offset_type offset, - unsigned int addralign, section_offset_type cie_offset, - unsigned char fde_encoding, Eh_frame_hdr* eh_frame_hdr); + uint64_t address, unsigned int addralign, + section_offset_type cie_offset, unsigned char fde_encoding, + Eh_frame_hdr* eh_frame_hdr); private: - // The object in which this FDE was seen. + // The object in which this FDE was seen. This will be NULL for a + // linker generated FDE. Relobj* object_; - // Input section index for this FDE. - unsigned int shndx_; - // Offset within the input section for this FDE. - section_offset_type input_offset_; + union + { + // These fields are used if the FDE is from an input object (the + // object_ field is not NULL). + struct + { + // Input section index for this FDE. + unsigned int shndx; + // Offset within the input section for this FDE. + section_offset_type input_offset; + } from_object; + // This field is used if the FDE is generated by the linker (the + // object_ field is NULL). + struct + { + // The only linker generated FDEs are for PLT sections, and this + // points to the PLT section. + Output_data* plt; + } from_linker; + } u_; // FDE data. std::string contents_; }; @@ -261,10 +286,11 @@ class Cie // Write the CIE to OVIEW starting at OFFSET. EH_FRAME_HDR is the // exception frame header for FDE recording. Round up the bytes to - // ADDRALIGN. Return the new offset. + // ADDRALIGN. ADDRESS is the virtual address of OVIEW. Return the + // new offset. template<int size, bool big_endian> section_offset_type - write(unsigned char* oview, section_offset_type offset, + write(unsigned char* oview, section_offset_type offset, uint64_t address, unsigned int addralign, Eh_frame_hdr* eh_frame_hdr); friend bool operator<(const Cie&, const Cie&); @@ -274,11 +300,14 @@ class Cie // The class is not assignable. Cie& operator=(const Cie&); - // The object in which this CIE was first seen. + // The object in which this CIE was first seen. This will be NULL + // for a linker generated CIE. Relobj* object_; - // Input section index for this CIE. + // Input section index for this CIE. This will be 0 for a linker + // generated CIE. unsigned int shndx_; - // Offset within the input section for this CIE. + // Offset within the input section for this CIE. This will be 0 for + // a linker generated CIE. section_offset_type input_offset_; // The encoding of the FDE. This is a DW_EH_PE code. unsigned char fde_encoding_; @@ -324,6 +353,15 @@ class Eh_frame : public Output_section_data unsigned int shndx, unsigned int reloc_shndx, unsigned int reloc_type); + // Add a CIE and an FDE for a PLT section, to permit unwinding + // through a PLT. The FDE data should start with 8 bytes of zero, + // which will be replaced by a 4 byte PC relative reference to the + // address of PLT and a 4 byte size of PLT. + void + 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); + // Return the number of FDEs. unsigned int fde_count() const; |