From 07a60597350488f098508ee67717d549a8a0b579 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 1 Jul 2011 22:05:01 +0000 Subject: 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. --- gold/ehframe.h | 88 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 25 deletions(-) (limited to 'gold/ehframe.h') diff --git a/gold/ehframe.h b/gold/ehframe.h index f626b1f1696..c3f82e937e1 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 . // 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(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(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 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 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; -- cgit v1.2.1