// icf.h --  Identical Code Folding

// Copyright (C) 2009-2021 Free Software Foundation, Inc.
// Written by Sriraman Tallam <tmsriram@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#ifndef GOLD_ICF_H
#define GOLD_ICF_H

#include <vector>

#include "elfcpp.h"
#include "symtab.h"
#include "object.h"

namespace gold
{

class Object;
class Input_objects;
class Symbol_table;

class Icf
{
 public:
  typedef std::vector<Section_id> Sections_reachable_info;
  typedef std::vector<Symbol*> Symbol_info;
  typedef std::vector<std::pair<long long, long long> > Addend_info;
  typedef std::vector<uint64_t> Offset_info;
  typedef std::vector<unsigned int> Reloc_addend_size_info;
  typedef Unordered_map<Section_id,
                        unsigned int,
                        Section_id_hash> Uniq_secn_id_map;
  typedef Unordered_set<Section_id, Section_id_hash> Secn_fptr_taken_set;

  typedef struct
  {
    // This stores the section corresponding to the reloc.
    Sections_reachable_info section_info;
    // This stores the symbol corresponding to the reloc.
    Symbol_info symbol_info;
    // This stores the symbol value and the addend for a reloc.
    Addend_info addend_info;
    Offset_info offset_info;
    Reloc_addend_size_info reloc_addend_size_info;
  } Reloc_info;

  typedef Unordered_map<Section_id, Reloc_info,
                        Section_id_hash> Reloc_info_list;

  // A region of some other section that should be considered part of
  // a section for ICF purposes. This is used to avoid folding sections
  // that have identical text and relocations but different .eh_frame
  // information.
  typedef struct
  {
	Section_id section;
	section_offset_type offset;
	section_size_type length;
  } Extra_identity_info;

  typedef std::multimap<Section_id, Extra_identity_info> Extra_identity_list;

  Icf()
  : id_section_(), section_id_(), kept_section_id_(),
    fptr_section_id_(),
    icf_ready_(false),
    reloc_info_list_()
  { }

  // Returns the kept folded identical section corresponding to
  // dup_obj and dup_shndx.
  Section_id
  get_folded_section(Relobj* dup_obj, unsigned int dup_shndx);

  // Forms groups of identical sections where the first member
  // of each group is the kept section during folding.
  void
  find_identical_sections(const Input_objects* input_objects,
                          Symbol_table* symtab);

  // This is set when ICF has been run and the groups of
  // identical sections have been formed.
  void
  icf_ready()
  { this->icf_ready_ = true; }

  // Returns true if ICF has been run.
  bool
  is_icf_ready()
  { return this->icf_ready_; }

  // Unfolds the section denoted by OBJ and SHNDX if folded.
  void
  unfold_section(Relobj* obj, unsigned int shndx);

  // Returns the kept section corresponding to the
  // given section.
  bool
  is_section_folded(Relobj* obj, unsigned int shndx);

  // Given an object and a section index, this returns true if the
  // pointer of the function defined in this section is taken.
  bool
  section_has_function_pointers(Relobj* obj, unsigned int shndx)
  {
    return (this->fptr_section_id_.find(Section_id(obj, shndx))
            != this->fptr_section_id_.end());
  }

  // Records that a pointer of the function defined in this section
  // is taken.
  void
  set_section_has_function_pointers(Relobj* obj, unsigned int shndx)
  {
    this->fptr_section_id_.insert(Section_id(obj, shndx));
  }

  // Checks if the section_name should be searched for relocs
  // corresponding to taken function pointers.  Ignores eh_frame
  // and vtable sections.
  inline bool
  check_section_for_function_pointers(const std::string& section_name,
                                      Target* target)
  {
    return (parameters->options().icf_safe_folding()
	    && target->can_check_for_function_pointers()
	    && target->section_may_have_icf_unsafe_pointers(
	        section_name.c_str()));
  }

  // Returns a map of a section to info (Reloc_info) about its relocations.
  Reloc_info_list&
  reloc_info_list()
  { return this->reloc_info_list_; }

  // Returns a map from section to region of a different section that should
  // be considered part of the key section for ICF purposes.
  Extra_identity_list&
  extra_identity_list()
  { return this->extra_identity_list_; }

  // Returns a mapping of each section to a unique integer.
  Uniq_secn_id_map&
  section_to_int_map()
  { return this->section_id_; }

 private:

  bool
  add_ehframe_links(Relobj* object, unsigned int ehframe_shndx,
		    Reloc_info& ehframe_relocs);

  // Maps integers to sections.
  std::vector<Section_id> id_section_;
  // Does the reverse.
  Uniq_secn_id_map section_id_;
  // Given a section id, this maps it to the id of the kept
  // section.  If the id's are the same then this section is
  // not folded.
  std::vector<unsigned int> kept_section_id_;
  // Given a section id, this says if the pointer to this
  // function is taken in which case it is dangerous to fold
  // this function.
  Secn_fptr_taken_set fptr_section_id_;
  // Flag to indicate if ICF has been run.
  bool icf_ready_;
  // This list is populated by gc_process_relocs in gc.h.
  Reloc_info_list reloc_info_list_;
  // Regions of other sections that should be considered part of
  // each section for ICF purposes.
  Extra_identity_list extra_identity_list_;
};

// This function returns true if this section corresponds to a function that
// should be considered by icf as a possible candidate for folding.  Some
// earlier gcc versions, like 4.0.3, put constructors and destructors in
// .gnu.linkonce.t sections and hence should be included too.
// The mechanism used to safely fold functions referenced by .eh_frame
// requires folding .gcc_except_table sections as well; see "Notes regarding
// C++ exception handling" at the top of icf.cc for an explanation why.
inline bool
is_section_foldable_candidate(const std::string& section_name)
{
  const char* section_name_cstr = section_name.c_str();
  return (is_prefix_of(".text", section_name_cstr)
          || is_prefix_of(".gcc_except_table", section_name_cstr)
          || is_prefix_of(".gnu.linkonce.t", section_name_cstr));
}

} // End of namespace gold.

#endif
