summaryrefslogtreecommitdiff
path: root/gold/ehframe.h
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2011-07-01 22:05:01 +0000
committerIan Lance Taylor <ian@airs.com>2011-07-01 22:05:01 +0000
commit07a60597350488f098508ee67717d549a8a0b579 (patch)
tree2476e48897011f57f41615892bdffda825fde6b2 /gold/ehframe.h
parenta931db6a07ac9ae2fec6c31c6d037716050292c5 (diff)
downloadbinutils-gdb-07a60597350488f098508ee67717d549a8a0b579.tar.gz
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.h88
1 files changed, 63 insertions, 25 deletions
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 <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;