gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / ehframe.h
index 2f45b23c1ee39e06007655596dd61a4ee0b2265d..3fe96002dc94dd3ab57a853081f2976d364565bf 100644 (file)
@@ -1,6 +1,6 @@
 // ehframe.h -- handle exception frame sections for gold  -*- C++ -*-
 
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 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:
@@ -67,6 +63,7 @@ class Eh_frame_hdr : public Output_section_data
       this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
   }
 
+ protected:
   // Set the final data size.
   void
   set_final_data_size();
@@ -75,6 +72,11 @@ class Eh_frame_hdr : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** eh_frame_hdr")); }
+
  private:
   // Write the data to the file with the right endianness.
   template<int size, bool big_endian>
@@ -164,9 +166,22 @@ 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,
+      bool post_map)
+    : object_(NULL),
+      contents_(reinterpret_cast<const char*>(contents), length)
+  {
+    this->u_.from_linker.plt = plt;
+    this->u_.from_linker.post_map = post_map;
+  }
 
   // Return the length of this FDE.  Add 4 for the length and 4 for
   // the offset to the CIE.
@@ -174,35 +189,84 @@ 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
+  add_mapping(section_offset_type output_offset,
+              Output_section_data* output_data) const
   {
-    merge_map->add_mapping(this->object_, this->shndx_,
-                          this->input_offset_, this->length(),
-                          output_offset);
+    if (this->object_ != NULL)
+      this->object_->add_merge_mapping(output_data, this->u_.from_object.shndx,
+                            this->u_.from_object.input_offset, this->length(),
+                            output_offset);
   }
 
+  // Return whether this FDE was added after merge mapping.
+  bool
+  post_map() const
+  { return this->object_ == NULL && this->u_.from_linker.post_map; }
+
+  // Return whether this FDE was added for the PLT after merge mapping.
+  bool
+  post_map(const Output_data* plt) const
+  { return this->post_map() && this->u_.from_linker.plt == plt; }
+
   // Write the FDE to OVIEW starting at OFFSET.  FDE_ENCODING is the
-  // encoding, from the CIE.  Record the FDE in EH_FRAME_HDR.  Return
-  // the new offset.
+  // encoding, from the CIE.  Round up the bytes to ADDRALIGN if
+  // 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,
+  write(unsigned char* oview, section_offset_type output_section_offset,
+       section_offset_type offset, 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;
+      // Set if the FDE was added after merge mapping.
+      bool post_map;
+    } from_linker;
+  } u_;
   // FDE data.
   std::string contents_;
 };
 
+// A FDE plus some info from a CIE to allow later writing of the FDE.
+
+struct Post_fde
+{
+  Post_fde(Fde* f, section_offset_type cie_off, unsigned char encoding)
+    : fde(f), cie_offset(cie_off), fde_encoding(encoding)
+  { }
+
+  Fde* fde;
+  section_offset_type cie_offset;
+  unsigned char fde_encoding;
+};
+
+typedef std::vector<Post_fde> Post_fdes;
+
 // This class holds a CIE.
 
 class Cie
@@ -239,6 +303,16 @@ class Cie
   add_fde(Fde* fde)
   { this->fdes_.push_back(fde); }
 
+  // Remove the last FDE associated with this CIE.
+  void
+  remove_fde()
+  { this->fdes_.pop_back(); }
+
+  // Access the last FDE associated with this CIE.
+  const Fde*
+  last_fde() const
+  { return this->fdes_.back(); }
+
   // Return the number of FDEs.
   unsigned int
   fde_count() const
@@ -250,14 +324,24 @@ class Cie
   // mapping.  It returns the new output offset.
   section_offset_type
   set_output_offset(section_offset_type output_offset, unsigned int addralign,
-                   Merge_map*);
+                   Output_section_data*);
 
-  // Write the CIE to OVIEW starting at OFFSET.  EH_FRAME_HDR is the
-  // exception frame header for FDE recording.  Return the new offset.
+  // Write the CIE to OVIEW starting at OFFSET.  Round up the bytes to
+  // ADDRALIGN.  ADDRESS is the virtual address of OVIEW.
+  // EH_FRAME_HDR is the exception frame header for FDE recording.
+  // POST_FDES stashes FDEs created after mappings were done, for later
+  // writing.  Return the new offset.
   template<int size, bool big_endian>
   section_offset_type
-  write(unsigned char* oview, section_offset_type offset,
-       Eh_frame_hdr* eh_frame_hdr);
+  write(unsigned char* oview, section_offset_type output_section_offset,
+       section_offset_type offset, uint64_t address,
+       unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
+       Post_fdes* post_fdes);
+
+  // Return the FDE encoding.
+  unsigned char
+  fde_encoding() const
+  { return this->fde_encoding_; }
 
   friend bool operator<(const Cie&, const Cie&);
   friend bool operator==(const Cie&, const Cie&);
@@ -266,11 +350,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_;
@@ -292,6 +379,14 @@ extern bool operator==(const Cie&, const Cie&);
 class Eh_frame : public Output_section_data
 {
  public:
+  enum Eh_frame_section_disposition
+  {
+    EH_EMPTY_SECTION,
+    EH_UNRECOGNIZED_SECTION,
+    EH_OPTIMIZABLE_SECTION,
+    EH_END_MARKER_SECTION
+  };
+
   Eh_frame();
 
   // Record the associated Eh_frame_hdr, if any.
@@ -307,8 +402,8 @@ class Eh_frame : public Output_section_data
   // returns whether the section was incorporated into the .eh_frame
   // data.
   template<int size, bool big_endian>
-  bool
-  add_ehframe_input_section(Sized_relobj<size, big_endian>* object,
+  Eh_frame_section_disposition
+  add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
                            const unsigned char* symbols,
                            section_size_type symbols_size,
                            const unsigned char* symbol_names,
@@ -316,10 +411,25 @@ 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);
+
+  // Remove all post-map unwind information for a PLT.
+  void
+  remove_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
+                        size_t cie_length);
+
   // Return the number of FDEs.
   unsigned int
   fde_count() const;
 
+ protected:
   // Set the final data size.
   void
   set_final_data_size();
@@ -330,14 +440,15 @@ class Eh_frame : public Output_section_data
                   section_offset_type offset,
                   section_offset_type* poutput) const;
 
-  // Return whether this is the merge section for an input section.
-  bool
-  do_is_merge_section_for(const Relobj*, unsigned int shndx) const;
-
   // Write the data to the file.
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** eh_frame")); }
+
  private:
   // The comparison routine for the CIE map.
   struct Cie_less
@@ -368,7 +479,7 @@ class Eh_frame : public Output_section_data
   // The implementation of add_ehframe_input_section.
   template<int size, bool big_endian>
   bool
-  do_add_ehframe_input_section(Sized_relobj<size, big_endian>* object,
+  do_add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
                               const unsigned char* symbols,
                               section_size_type symbols_size,
                               const unsigned char* symbol_names,
@@ -383,7 +494,7 @@ class Eh_frame : public Output_section_data
   // Read a CIE.
   template<int size, bool big_endian>
   bool
-  read_cie(Sized_relobj<size, big_endian>* object,
+  read_cie(Sized_relobj_file<size, big_endian>* object,
           unsigned int shndx,
           const unsigned char* symbols,
           section_size_type symbols_size,
@@ -391,7 +502,7 @@ class Eh_frame : public Output_section_data
           section_size_type symbol_names_size,
           const unsigned char* pcontents,
           const unsigned char* pcie,
-          const unsigned char *pcieend,
+          const unsigned charpcieend,
           Track_relocs<size, big_endian>* relocs,
           Offsets_to_cie* cies,
           New_cies* new_cies);
@@ -399,14 +510,14 @@ class Eh_frame : public Output_section_data
   // Read an FDE.
   template<int size, bool big_endian>
   bool
-  read_fde(Sized_relobj<size, big_endian>* object,
+  read_fde(Sized_relobj_file<size, big_endian>* object,
           unsigned int shndx,
           const unsigned char* symbols,
           section_size_type symbols_size,
           const unsigned char* pcontents,
           unsigned int offset,
           const unsigned char* pfde,
-          const unsigned char *pfdeend,
+          const unsigned charpfdeend,
           Track_relocs<size, big_endian>* relocs,
           Offsets_to_cie* cies);
 
@@ -423,8 +534,11 @@ class Eh_frame : public Output_section_data
   // A mapping from unmergeable CIEs to their offset in the output
   // file.
   Unmergeable_cie_offsets unmergeable_cie_offsets_;
-  // A mapping from input sections to the output section.
-  Merge_map merge_map_;
+  // Whether we have created the mappings to the output section.
+  bool mappings_are_done_;
+  // The final data size.  This is only set if mappings_are_done_ is
+  // true.
+  section_size_type final_data_size_;
 };
 
 } // End namespace gold.
This page took 0.028166 seconds and 4 git commands to generate.