(root)/
binutils-2.41/
gold/
ehframe.h
       1  // ehframe.h -- handle exception frame sections for gold  -*- C++ -*-
       2  
       3  // Copyright (C) 2006-2023 Free Software Foundation, Inc.
       4  // Written by Ian Lance Taylor <iant@google.com>.
       5  
       6  // This file is part of gold.
       7  
       8  // This program is free software; you can redistribute it and/or modify
       9  // it under the terms of the GNU General Public License as published by
      10  // the Free Software Foundation; either version 3 of the License, or
      11  // (at your option) any later version.
      12  
      13  // This program is distributed in the hope that it will be useful,
      14  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      15  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16  // GNU General Public License for more details.
      17  
      18  // You should have received a copy of the GNU General Public License
      19  // along with this program; if not, write to the Free Software
      20  // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21  // MA 02110-1301, USA.
      22  
      23  #ifndef GOLD_EHFRAME_H
      24  #define GOLD_EHFRAME_H
      25  
      26  #include <map>
      27  #include <set>
      28  #include <vector>
      29  
      30  #include "output.h"
      31  #include "merge.h"
      32  
      33  namespace gold
      34  {
      35  
      36  template<int size, bool big_endian>
      37  class Track_relocs;
      38  
      39  class Eh_frame;
      40  
      41  // This class manages the .eh_frame_hdr section, which holds the data
      42  // for the PT_GNU_EH_FRAME segment.  gcc's unwind support code uses
      43  // the PT_GNU_EH_FRAME segment to find the list of FDEs.  This saves
      44  // the time required to register the exception handlers at startup
      45  // time and when a shared object is loaded, and the time required to
      46  // deregister the exception handlers when a shared object is unloaded.
      47  
      48  class Eh_frame_hdr : public Output_section_data
      49  {
      50   public:
      51    Eh_frame_hdr(Output_section* eh_frame_section, const Eh_frame*);
      52  
      53    // Record that we found an unrecognized .eh_frame section.
      54    void
      55    found_unrecognized_eh_frame_section()
      56    { this->any_unrecognized_eh_frame_sections_ = true; }
      57  
      58    // Record an FDE.
      59    void
      60    record_fde(section_offset_type fde_offset, unsigned char fde_encoding)
      61    {
      62      if (!this->any_unrecognized_eh_frame_sections_)
      63        this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
      64    }
      65  
      66   protected:
      67    // Set the final data size.
      68    void
      69    set_final_data_size();
      70  
      71    // Write the data to the file.
      72    void
      73    do_write(Output_file*);
      74  
      75    // Write to a map file.
      76    void
      77    do_print_to_mapfile(Mapfile* mapfile) const
      78    { mapfile->print_output_data(this, _("** eh_frame_hdr")); }
      79  
      80   private:
      81    // Write the data to the file with the right endianness.
      82    template<int size, bool big_endian>
      83    void
      84    do_sized_write(Output_file*);
      85  
      86    // The data we record for one FDE: the offset of the FDE within the
      87    // .eh_frame section, and the FDE encoding.
      88    typedef std::pair<section_offset_type, unsigned char> Fde_offset;
      89  
      90    // The list of information we record for an FDE.
      91    typedef std::vector<Fde_offset> Fde_offsets;
      92  
      93    // When writing out the header, we convert the FDE offsets into FDE
      94    // addresses.  This is a list of pairs of the offset from the header
      95    // to the FDE PC and to the FDE itself.
      96    template<int size>
      97    class Fde_addresses
      98    {
      99     public:
     100      typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
     101      typedef typename std::pair<Address, Address> Fde_address;
     102      typedef typename std::vector<Fde_address> Fde_address_list;
     103      typedef typename Fde_address_list::iterator iterator;
     104  
     105      Fde_addresses(unsigned int reserve)
     106        : fde_addresses_()
     107      { this->fde_addresses_.reserve(reserve); }
     108  
     109      void
     110      push_back(Address pc_address, Address fde_address)
     111      {
     112        this->fde_addresses_.push_back(std::make_pair(pc_address, fde_address));
     113      }
     114  
     115      iterator
     116      begin()
     117      { return this->fde_addresses_.begin(); }
     118  
     119      iterator
     120      end()
     121      { return this->fde_addresses_.end(); }
     122  
     123     private:
     124      Fde_address_list fde_addresses_;
     125    };
     126  
     127    // Compare Fde_address objects.
     128    template<int size>
     129    struct Fde_address_compare
     130    {
     131      bool
     132      operator()(const typename Fde_addresses<size>::Fde_address& f1,
     133  	       const typename Fde_addresses<size>::Fde_address& f2) const
     134      { return f1.first < f2.first; }
     135    };
     136  
     137    // Return the PC to which an FDE refers.
     138    template<int size, bool big_endian>
     139    typename elfcpp::Elf_types<size>::Elf_Addr
     140    get_fde_pc(typename elfcpp::Elf_types<size>::Elf_Addr eh_frame_address,
     141  	     const unsigned char* eh_frame_contents,
     142  	     section_offset_type fde_offset, unsigned char fde_encoding);
     143  
     144    // Convert Fde_offsets to Fde_addresses.
     145    template<int size, bool big_endian>
     146    void
     147    get_fde_addresses(Output_file* of,
     148  		    const Fde_offsets* fde_offsets,
     149  		    Fde_addresses<size>* fde_addresses);
     150  
     151    // The .eh_frame section.
     152    Output_section* eh_frame_section_;
     153    // The .eh_frame section data.
     154    const Eh_frame* eh_frame_data_;
     155    // Data from the FDEs in the .eh_frame sections.
     156    Fde_offsets fde_offsets_;
     157    // Whether we found any .eh_frame sections which we could not
     158    // process.
     159    bool any_unrecognized_eh_frame_sections_;
     160  };
     161  
     162  // This class holds an FDE.
     163  
     164  class Fde
     165  {
     166   public:
     167    Fde(Relobj* object, unsigned int shndx, section_offset_type input_offset,
     168        const unsigned char* contents, size_t length)
     169      : object_(object),
     170        contents_(reinterpret_cast<const char*>(contents), length)
     171    {
     172      this->u_.from_object.shndx = shndx;
     173      this->u_.from_object.input_offset = input_offset;
     174    }
     175  
     176    // Create an FDE associated with a PLT.
     177    Fde(Output_data* plt, const unsigned char* contents, size_t length,
     178        bool post_map)
     179      : object_(NULL),
     180        contents_(reinterpret_cast<const char*>(contents), length)
     181    {
     182      this->u_.from_linker.plt = plt;
     183      this->u_.from_linker.post_map = post_map;
     184    }
     185  
     186    // Return the length of this FDE.  Add 4 for the length and 4 for
     187    // the offset to the CIE.
     188    size_t
     189    length() const
     190    { return this->contents_.length() + 8; }
     191  
     192    // Add a mapping for this FDE to MERGE_MAP, so that relocations
     193    // against the FDE are applied to right part of the output file.
     194    void
     195    add_mapping(section_offset_type output_offset,
     196                Output_section_data* output_data) const
     197    {
     198      if (this->object_ != NULL)
     199        this->object_->add_merge_mapping(output_data, this->u_.from_object.shndx,
     200  			     this->u_.from_object.input_offset, this->length(),
     201  			     output_offset);
     202    }
     203  
     204    // Return whether this FDE was added after merge mapping.
     205    bool
     206    post_map() const
     207    { return this->object_ == NULL && this->u_.from_linker.post_map; }
     208  
     209    // Return whether this FDE was added for the PLT after merge mapping.
     210    bool
     211    post_map(const Output_data* plt) const
     212    { return this->post_map() && this->u_.from_linker.plt == plt; }
     213  
     214    // Write the FDE to OVIEW starting at OFFSET.  FDE_ENCODING is the
     215    // encoding, from the CIE.  Round up the bytes to ADDRALIGN if
     216    // necessary.  ADDRESS is the virtual address of OVIEW.  Record the
     217    // FDE in EH_FRAME_HDR.  Return the new offset.
     218    template<int size, bool big_endian>
     219    section_offset_type
     220    write(unsigned char* oview, section_offset_type output_section_offset,
     221  	section_offset_type offset, uint64_t address, unsigned int addralign,
     222  	section_offset_type cie_offset, unsigned char fde_encoding,
     223  	Eh_frame_hdr* eh_frame_hdr);
     224  
     225   private:
     226    // The object in which this FDE was seen.  This will be NULL for a
     227    // linker generated FDE.
     228    Relobj* object_;
     229    union
     230    {
     231      // These fields are used if the FDE is from an input object (the
     232      // object_ field is not NULL).
     233      struct
     234      {
     235        // Input section index for this FDE.
     236        unsigned int shndx;
     237        // Offset within the input section for this FDE.
     238        section_offset_type input_offset;
     239      } from_object;
     240      // This field is used if the FDE is generated by the linker (the
     241      // object_ field is NULL).
     242      struct
     243      {
     244        // The only linker generated FDEs are for PLT sections, and this
     245        // points to the PLT section.
     246        Output_data* plt;
     247        // Set if the FDE was added after merge mapping.
     248        bool post_map;
     249      } from_linker;
     250    } u_;
     251    // FDE data.
     252    std::string contents_;
     253  };
     254  
     255  // A FDE plus some info from a CIE to allow later writing of the FDE.
     256  
     257  struct Post_fde
     258  {
     259    Post_fde(Fde* f, section_offset_type cie_off, unsigned char encoding)
     260      : fde(f), cie_offset(cie_off), fde_encoding(encoding)
     261    { }
     262  
     263    Fde* fde;
     264    section_offset_type cie_offset;
     265    unsigned char fde_encoding;
     266  };
     267  
     268  typedef std::vector<Post_fde> Post_fdes;
     269  
     270  // This class holds a CIE.
     271  
     272  class Cie
     273  {
     274   public:
     275    Cie(Relobj* object, unsigned int shndx, section_offset_type input_offset,
     276        unsigned char fde_encoding, const char* personality_name,
     277        const unsigned char* contents, size_t length)
     278      : object_(object),
     279        shndx_(shndx),
     280        input_offset_(input_offset),
     281        fde_encoding_(fde_encoding),
     282        personality_name_(personality_name),
     283        fdes_(),
     284        contents_(reinterpret_cast<const char*>(contents), length)
     285    { }
     286  
     287    ~Cie();
     288  
     289    // We permit copying a CIE when there are no FDEs.  This is
     290    // convenient in the code which creates them.
     291    Cie(const Cie& cie)
     292      : object_(cie.object_),
     293        shndx_(cie.shndx_),
     294        input_offset_(cie.input_offset_),
     295        fde_encoding_(cie.fde_encoding_),
     296        personality_name_(cie.personality_name_),
     297        fdes_(),
     298        contents_(cie.contents_)
     299    { gold_assert(cie.fdes_.empty()); }
     300  
     301    // Add an FDE associated with this CIE.
     302    void
     303    add_fde(Fde* fde)
     304    { this->fdes_.push_back(fde); }
     305  
     306    // Remove the last FDE associated with this CIE.
     307    void
     308    remove_fde()
     309    { this->fdes_.pop_back(); }
     310  
     311    // Access the last FDE associated with this CIE.
     312    const Fde*
     313    last_fde() const
     314    { return this->fdes_.back(); }
     315  
     316    // Return the number of FDEs.
     317    unsigned int
     318    fde_count() const
     319    { return this->fdes_.size(); }
     320  
     321    // Set the output offset of this CIE to OUTPUT_OFFSET.  It will be
     322    // followed by all its FDEs.  ADDRALIGN is the required address
     323    // alignment, typically 4 or 8.  This updates MERGE_MAP with the
     324    // mapping.  It returns the new output offset.
     325    section_offset_type
     326    set_output_offset(section_offset_type output_offset, unsigned int addralign,
     327  		    Output_section_data*);
     328  
     329    // Write the CIE to OVIEW starting at OFFSET.  Round up the bytes to
     330    // ADDRALIGN.  ADDRESS is the virtual address of OVIEW.
     331    // EH_FRAME_HDR is the exception frame header for FDE recording.
     332    // POST_FDES stashes FDEs created after mappings were done, for later
     333    // writing.  Return the new offset.
     334    template<int size, bool big_endian>
     335    section_offset_type
     336    write(unsigned char* oview, section_offset_type output_section_offset,
     337  	section_offset_type offset, uint64_t address,
     338  	unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
     339  	Post_fdes* post_fdes);
     340  
     341    // Return the FDE encoding.
     342    unsigned char
     343    fde_encoding() const
     344    { return this->fde_encoding_; }
     345  
     346    friend bool operator<(const Cie&, const Cie&);
     347    friend bool operator==(const Cie&, const Cie&);
     348  
     349   private:
     350    // The class is not assignable.
     351    Cie& operator=(const Cie&);
     352  
     353    // The object in which this CIE was first seen.  This will be NULL
     354    // for a linker generated CIE.
     355    Relobj* object_;
     356    // Input section index for this CIE.  This will be 0 for a linker
     357    // generated CIE.
     358    unsigned int shndx_;
     359    // Offset within the input section for this CIE.  This will be 0 for
     360    // a linker generated CIE.
     361    section_offset_type input_offset_;
     362    // The encoding of the FDE.  This is a DW_EH_PE code.
     363    unsigned char fde_encoding_;
     364    // The name of the personality routine.  This will be the name of a
     365    // global symbol, or will be the empty string.
     366    std::string personality_name_;
     367    // List of FDEs.
     368    std::vector<Fde*> fdes_;
     369    // CIE data.
     370    std::string contents_;
     371  };
     372  
     373  extern bool operator<(const Cie&, const Cie&);
     374  extern bool operator==(const Cie&, const Cie&);
     375  
     376  // This class manages .eh_frame sections.  It discards duplicate
     377  // exception information.
     378  
     379  class Eh_frame : public Output_section_data
     380  {
     381   public:
     382    enum Eh_frame_section_disposition
     383    {
     384      EH_EMPTY_SECTION,
     385      EH_UNRECOGNIZED_SECTION,
     386      EH_OPTIMIZABLE_SECTION,
     387      EH_END_MARKER_SECTION
     388    };
     389  
     390    Eh_frame();
     391  
     392    // Record the associated Eh_frame_hdr, if any.
     393    void
     394    set_eh_frame_hdr(Eh_frame_hdr* hdr)
     395    { this->eh_frame_hdr_ = hdr; }
     396  
     397    // Add the input section SHNDX in OBJECT.  SYMBOLS is the contents
     398    // of the symbol table section (size SYMBOLS_SIZE), SYMBOL_NAMES is
     399    // the symbol names section (size SYMBOL_NAMES_SIZE).  RELOC_SHNDX
     400    // is the relocation section if any (0 for none, -1U for multiple).
     401    // RELOC_TYPE is the type of the relocation section if any.  This
     402    // returns whether the section was incorporated into the .eh_frame
     403    // data.
     404    template<int size, bool big_endian>
     405    Eh_frame_section_disposition
     406    add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
     407  			    const unsigned char* symbols,
     408  			    section_size_type symbols_size,
     409  			    const unsigned char* symbol_names,
     410  			    section_size_type symbol_names_size,
     411  			    unsigned int shndx, unsigned int reloc_shndx,
     412  			    unsigned int reloc_type);
     413  
     414    // Add a CIE and an FDE for a PLT section, to permit unwinding
     415    // through a PLT.  The FDE data should start with 8 bytes of zero,
     416    // which will be replaced by a 4 byte PC relative reference to the
     417    // address of PLT and a 4 byte size of PLT.
     418    void
     419    add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
     420  		      size_t cie_length, const unsigned char* fde_data,
     421  		      size_t fde_length);
     422  
     423    // Remove all post-map unwind information for a PLT.
     424    void
     425    remove_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
     426  			 size_t cie_length);
     427  
     428    // Return the number of FDEs.
     429    unsigned int
     430    fde_count() const;
     431  
     432   protected:
     433    // Set the final data size.
     434    void
     435    set_final_data_size();
     436  
     437    // Return the output address for an input address.
     438    bool
     439    do_output_offset(const Relobj*, unsigned int shndx,
     440  		   section_offset_type offset,
     441  		   section_offset_type* poutput) const;
     442  
     443    // Write the data to the file.
     444    void
     445    do_write(Output_file*);
     446  
     447    // Write to a map file.
     448    void
     449    do_print_to_mapfile(Mapfile* mapfile) const
     450    { mapfile->print_output_data(this, _("** eh_frame")); }
     451  
     452   private:
     453    // The comparison routine for the CIE map.
     454    struct Cie_less
     455    {
     456      bool
     457      operator()(const Cie* cie1, const Cie* cie2) const
     458      { return *cie1 < *cie2; }
     459    };
     460  
     461    // A set of unique CIEs.
     462    typedef std::set<Cie*, Cie_less> Cie_offsets;
     463  
     464    // A list of unmergeable CIEs.
     465    typedef std::vector<Cie*> Unmergeable_cie_offsets;
     466  
     467    // A mapping from offsets to CIEs.  This is used while reading an
     468    // input section.
     469    typedef std::map<uint64_t, Cie*> Offsets_to_cie;
     470  
     471    // A list of CIEs, and a bool indicating whether the CIE is
     472    // mergeable.
     473    typedef std::vector<std::pair<Cie*, bool> > New_cies;
     474  
     475    // Skip an LEB128.
     476    static bool
     477    skip_leb128(const unsigned char**, const unsigned char*);
     478  
     479    // The implementation of add_ehframe_input_section.
     480    template<int size, bool big_endian>
     481    bool
     482    do_add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
     483  			       const unsigned char* symbols,
     484  			       section_size_type symbols_size,
     485  			       const unsigned char* symbol_names,
     486  			       section_size_type symbol_names_size,
     487  			       unsigned int shndx,
     488  			       unsigned int reloc_shndx,
     489  			       unsigned int reloc_type,
     490  			       const unsigned char* pcontents,
     491  			       section_size_type contents_len,
     492  			       New_cies*);
     493  
     494    // Read a CIE.
     495    template<int size, bool big_endian>
     496    bool
     497    read_cie(Sized_relobj_file<size, big_endian>* object,
     498  	   unsigned int shndx,
     499  	   const unsigned char* symbols,
     500  	   section_size_type symbols_size,
     501  	   const unsigned char* symbol_names,
     502  	   section_size_type symbol_names_size,
     503  	   const unsigned char* pcontents,
     504  	   const unsigned char* pcie,
     505  	   const unsigned char* pcieend,
     506  	   Track_relocs<size, big_endian>* relocs,
     507  	   Offsets_to_cie* cies,
     508  	   New_cies* new_cies);
     509  
     510    // Read an FDE.
     511    template<int size, bool big_endian>
     512    bool
     513    read_fde(Sized_relobj_file<size, big_endian>* object,
     514  	   unsigned int shndx,
     515  	   const unsigned char* symbols,
     516  	   section_size_type symbols_size,
     517  	   const unsigned char* pcontents,
     518  	   unsigned int offset,
     519  	   const unsigned char* pfde,
     520  	   const unsigned char* pfdeend,
     521  	   Track_relocs<size, big_endian>* relocs,
     522  	   Offsets_to_cie* cies);
     523  
     524    // Template version of write function.
     525    template<int size, bool big_endian>
     526    void
     527    do_sized_write(unsigned char* oview);
     528  
     529    // The exception frame header, if any.
     530    Eh_frame_hdr* eh_frame_hdr_;
     531    // A mapping from all unique CIEs to their offset in the output
     532    // file.
     533    Cie_offsets cie_offsets_;
     534    // A mapping from unmergeable CIEs to their offset in the output
     535    // file.
     536    Unmergeable_cie_offsets unmergeable_cie_offsets_;
     537    // Whether we have created the mappings to the output section.
     538    bool mappings_are_done_;
     539    // The final data size.  This is only set if mappings_are_done_ is
     540    // true.
     541    section_size_type final_data_size_;
     542  };
     543  
     544  } // End namespace gold.
     545  
     546  #endif // !defined(GOLD_EHFRAME_H)