Line 1... |
Line 1... |
// ehframe.h -- handle exception frame sections for gold -*- C++ -*-
|
// 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>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
|
|
// This file is part of gold.
|
// This file is part of gold.
|
|
|
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
Line 43... |
Line 43... |
// the PT_GNU_EH_FRAME segment to find the list of FDEs. This saves
|
// the PT_GNU_EH_FRAME segment to find the list of FDEs. This saves
|
// the time required to register the exception handlers at startup
|
// the time required to register the exception handlers at startup
|
// time and when a shared object is loaded, and the time required to
|
// time and when a shared object is loaded, and the time required to
|
// deregister the exception handlers when a shared object is unloaded.
|
// 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
|
class Eh_frame_hdr : public Output_section_data
|
{
|
{
|
public:
|
public:
|
Eh_frame_hdr(Output_section* eh_frame_section, const Eh_frame*);
|
Eh_frame_hdr(Output_section* eh_frame_section, const Eh_frame*);
|
|
|
Line 168... |
Line 164... |
class Fde
|
class Fde
|
{
|
{
|
public:
|
public:
|
Fde(Relobj* object, unsigned int shndx, section_offset_type input_offset,
|
Fde(Relobj* object, unsigned int shndx, section_offset_type input_offset,
|
const unsigned char* contents, size_t length)
|
const unsigned char* contents, size_t length)
|
: object_(object), shndx_(shndx), input_offset_(input_offset),
|
: object_(object),
|
contents_(reinterpret_cast<const char*>(contents), length)
|
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
|
// Return the length of this FDE. Add 4 for the length and 4 for
|
// the offset to the CIE.
|
// the offset to the CIE.
|
size_t
|
size_t
|
length() const
|
length() const
|
{ return this->contents_.length() + 8; }
|
{ 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
|
void
|
add_mapping(section_offset_type output_offset, Merge_map* merge_map) const
|
add_mapping(section_offset_type output_offset, Merge_map* merge_map) const
|
{
|
{
|
merge_map->add_mapping(this->object_, this->shndx_,
|
if (this->object_ != NULL)
|
this->input_offset_, this->length(),
|
merge_map->add_mapping(this->object_, this->u_.from_object.shndx,
|
|
this->u_.from_object.input_offset, this->length(),
|
output_offset);
|
output_offset);
|
}
|
}
|
|
|
// Write the FDE to OVIEW starting at OFFSET. FDE_ENCODING is the
|
// Write the FDE to OVIEW starting at OFFSET. FDE_ENCODING is the
|
// encoding, from the CIE. Round up the bytes to ADDRALIGN if
|
// encoding, from the CIE. Round up the bytes to ADDRALIGN if
|
// necessary. Record the FDE in EH_FRAME_HDR. Return the new
|
// necessary. ADDRESS is the virtual address of OVIEW. Record the
|
// offset.
|
// FDE in EH_FRAME_HDR. Return the new offset.
|
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
section_offset_type
|
section_offset_type
|
write(unsigned char* oview, section_offset_type offset,
|
write(unsigned char* oview, section_offset_type offset,
|
unsigned int addralign, section_offset_type cie_offset,
|
uint64_t address, unsigned int addralign,
|
unsigned char fde_encoding, Eh_frame_hdr* eh_frame_hdr);
|
section_offset_type cie_offset, unsigned char fde_encoding,
|
|
Eh_frame_hdr* eh_frame_hdr);
|
|
|
private:
|
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_;
|
Relobj* object_;
|
|
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.
|
// Input section index for this FDE.
|
unsigned int shndx_;
|
unsigned int shndx;
|
// Offset within the input section for this FDE.
|
// Offset within the input section for this FDE.
|
section_offset_type input_offset_;
|
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.
|
// FDE data.
|
std::string contents_;
|
std::string contents_;
|
};
|
};
|
|
|
// This class holds a CIE.
|
// This class holds a CIE.
|
Line 259... |
Line 284... |
set_output_offset(section_offset_type output_offset, unsigned int addralign,
|
set_output_offset(section_offset_type output_offset, unsigned int addralign,
|
Merge_map*);
|
Merge_map*);
|
|
|
// Write the CIE to OVIEW starting at OFFSET. EH_FRAME_HDR is the
|
// Write the CIE to OVIEW starting at OFFSET. EH_FRAME_HDR is the
|
// exception frame header for FDE recording. Round up the bytes to
|
// 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>
|
template<int size, bool big_endian>
|
section_offset_type
|
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);
|
unsigned int addralign, Eh_frame_hdr* eh_frame_hdr);
|
|
|
friend bool operator<(const Cie&, const Cie&);
|
friend bool operator<(const Cie&, const Cie&);
|
friend bool operator==(const Cie&, const Cie&);
|
friend bool operator==(const Cie&, const Cie&);
|
|
|
private:
|
private:
|
// The class is not assignable.
|
// The class is not assignable.
|
Cie& operator=(const Cie&);
|
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_;
|
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_;
|
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_;
|
section_offset_type input_offset_;
|
// The encoding of the FDE. This is a DW_EH_PE code.
|
// The encoding of the FDE. This is a DW_EH_PE code.
|
unsigned char fde_encoding_;
|
unsigned char fde_encoding_;
|
// The name of the personality routine. This will be the name of a
|
// The name of the personality routine. This will be the name of a
|
// global symbol, or will be the empty string.
|
// global symbol, or will be the empty string.
|
Line 322... |
Line 351... |
const unsigned char* symbol_names,
|
const unsigned char* symbol_names,
|
section_size_type symbol_names_size,
|
section_size_type symbol_names_size,
|
unsigned int shndx, unsigned int reloc_shndx,
|
unsigned int shndx, unsigned int reloc_shndx,
|
unsigned int reloc_type);
|
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.
|
// Return the number of FDEs.
|
unsigned int
|
unsigned int
|
fde_count() const;
|
fde_count() const;
|
|
|
protected:
|
protected:
|