// gc.h -- garbage collection of unused sections

// Copyright (C) 2009-2016 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_GC_H
#define GOLD_GC_H

#include <vector>

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

namespace gold
{

class Object;

template<int size, bool big_endian>
class Sized_relobj_file;

class Output_section;
class General_options;
class Layout;

class Garbage_collection
{
 public:

  typedef Unordered_set<Section_id, Section_id_hash> Sections_reachable;
  typedef std::map<Section_id, Sections_reachable> Section_ref;
  typedef std::vector<Section_id> Worklist_type;
  // This maps the name of the section which can be represented as a C
  // identifier (cident) to the list of sections that have that name.
  // Different object files can have cident sections with the same name.
  typedef std::map<std::string, Sections_reachable> Cident_section_map;

  Garbage_collection()
  : is_worklist_ready_(false)
  { }

  // Accessor methods for the private members.

  Sections_reachable&
  referenced_list()
  { return referenced_list_; }

  Section_ref&
  section_reloc_map()
  { return this->section_reloc_map_; }

  Worklist_type&
  worklist()
  { return this->work_list_; }

  bool
  is_worklist_ready()
  { return this->is_worklist_ready_; }

  void
  worklist_ready()
  { this->is_worklist_ready_ = true; }

  void
  do_transitive_closure();

  bool
  is_section_garbage(Relobj* obj, unsigned int shndx)
  { return (this->referenced_list().find(Section_id(obj, shndx))
            == this->referenced_list().end()); }

  Cident_section_map*
  cident_sections()
  { return &cident_sections_; }

  void
  add_cident_section(std::string section_name,
		     Section_id secn)
  { this->cident_sections_[section_name].insert(secn); }

  // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to
  // DST_SHNDX-th section of DST_OBJECT.
  void
  add_reference(Relobj* src_object, unsigned int src_shndx,
		Relobj* dst_object, unsigned int dst_shndx)
  {
    Section_id src_id(src_object, src_shndx);
    Section_id dst_id(dst_object, dst_shndx);
    Sections_reachable& reachable = this->section_reloc_map_[src_id];
    reachable.insert(dst_id);
  }

 private:

  Worklist_type work_list_;
  bool is_worklist_ready_;
  Section_ref section_reloc_map_;
  Sections_reachable referenced_list_;
  Cident_section_map cident_sections_;
};

// Data to pass between successive invocations of do_layout
// in object.cc while garbage collecting.  This data structure
// is filled by using the data from Read_symbols_data.

struct Symbols_data
{
  // Section headers.
  unsigned char* section_headers_data;
  // Section names.
  unsigned char* section_names_data;
  // Size of section name data in bytes.
  section_size_type section_names_size;
  // Symbol data.
  unsigned char* symbols_data;
  // Size of symbol data in bytes.
  section_size_type symbols_size;
  // Offset of external symbols within symbol data.  This structure
  // sometimes contains only external symbols, in which case this will
  // be zero.  Sometimes it contains all symbols.
  section_offset_type external_symbols_offset;
  // Symbol names.
  unsigned char* symbol_names_data;
  // Size of symbol name data in bytes.
  section_size_type symbol_names_size;
};

// Relocations of type SHT_REL store the addend value in their bytes.
// This function returns the size of the embedded addend which is
// nothing but the size of the relocation.

template<typename Classify_reloc>
inline unsigned int
get_embedded_addend_size(int r_type, Relobj* obj)
{
  if (Classify_reloc::sh_type == elfcpp::SHT_REL)
    return Classify_reloc::get_size_for_reloc(r_type, obj);
  return 0;
}

// This function implements the generic part of reloc
// processing to map a section to all the sections it
// references through relocs.  It is called only during
// garbage collection (--gc-sections) and identical code
// folding (--icf).

template<int size, bool big_endian, typename Target_type,
	 typename Scan, typename Classify_reloc>
inline void
gc_process_relocs(
    Symbol_table* symtab,
    Layout*,
    Target_type* target,
    Sized_relobj_file<size, big_endian>* src_obj,
    unsigned int src_indx,
    const unsigned char* prelocs,
    size_t reloc_count,
    Output_section*,
    bool,
    size_t local_count,
    const unsigned char* plocal_syms)
{
  Scan scan;

  typedef typename Classify_reloc::Reltype Reltype;
  const int reloc_size = Classify_reloc::reloc_size;
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;

  Icf::Sections_reachable_info* secvec = NULL;
  Icf::Symbol_info* symvec = NULL;
  Icf::Addend_info* addendvec = NULL;
  Icf::Offset_info* offsetvec = NULL;
  Icf::Reloc_addend_size_info* reloc_addend_size_vec = NULL;
  bool is_icf_tracked = false;
  const char* cident_section_name = NULL;

  std::string src_section_name = (parameters->options().icf_enabled()
                                  ? src_obj->section_name(src_indx)
                                  : "");

  bool check_section_for_function_pointers = false;

  if (parameters->options().icf_enabled()
      && is_section_foldable_candidate(src_section_name.c_str()))
    {
      is_icf_tracked = true;
      Section_id src_id(src_obj, src_indx);
      Icf::Reloc_info* reloc_info =
        &symtab->icf()->reloc_info_list()[src_id];
      secvec = &reloc_info->section_info;
      symvec = &reloc_info->symbol_info;
      addendvec = &reloc_info->addend_info;
      offsetvec = &reloc_info->offset_info;
      reloc_addend_size_vec = &reloc_info->reloc_addend_size_info;
    }

  check_section_for_function_pointers =
    symtab->icf()->check_section_for_function_pointers(src_section_name,
                                                       target);

  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
    {
      Reltype reloc(prelocs);
      unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
      unsigned int r_type = Classify_reloc::get_r_type(&reloc);
      typename elfcpp::Elf_types<size>::Elf_Swxword addend =
	  Classify_reloc::get_r_addend(&reloc);
      Relobj* dst_obj;
      unsigned int dst_indx;
      typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
      Address dst_off;

      if (r_sym < local_count)
        {
          gold_assert(plocal_syms != NULL);
          typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
                                                      + r_sym * sym_size);
	  dst_indx = lsym.get_st_shndx();
          bool is_ordinary;
	  dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary);
          dst_obj = src_obj;
	  dst_off = lsym.get_st_value() + addend;

          if (is_icf_tracked)
            {
	      Address symvalue = dst_off - addend;
	      if (is_ordinary) 
		(*secvec).push_back(Section_id(src_obj, dst_indx));
	      else
                (*secvec).push_back(Section_id(NULL, 0));
              (*symvec).push_back(NULL);
	      (*addendvec).push_back(std::make_pair(
					static_cast<long long>(symvalue),
					static_cast<long long>(addend)));
              uint64_t reloc_offset =
                convert_to_section_size_type(reloc.get_r_offset());
	      (*offsetvec).push_back(reloc_offset);
              (*reloc_addend_size_vec).push_back(
                get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
            }

	  // When doing safe folding, check to see if this relocation is that
	  // of a function pointer being taken.
	  if (is_ordinary
	      && check_section_for_function_pointers
              && lsym.get_st_type() != elfcpp::STT_OBJECT
 	      && scan.local_reloc_may_be_function_pointer(symtab, NULL, NULL,
							  src_obj, src_indx,
			                       		  NULL, reloc, r_type,
							  lsym))
            symtab->icf()->set_section_has_function_pointers(
              src_obj, lsym.get_st_shndx());

          if (!is_ordinary || dst_indx == src_indx)
            continue;
        }
      else
        {
          Symbol* gsym = src_obj->global_symbol(r_sym);
          gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = symtab->resolve_forwards(gsym);

          dst_obj = NULL;
          dst_indx = 0;
          bool is_ordinary = false;
          if (gsym->source() == Symbol::FROM_OBJECT
	      && !gsym->object()->is_dynamic())
            {
              dst_obj = static_cast<Relobj*>(gsym->object());
              dst_indx = gsym->shndx(&is_ordinary);
            }
	  dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value();
	  dst_off += addend;

	  // When doing safe folding, check to see if this relocation is that
	  // of a function pointer being taken.
	  if (gsym->source() == Symbol::FROM_OBJECT
              && check_section_for_function_pointers
              && dst_obj != NULL
              && (!is_ordinary
                  || scan.global_reloc_may_be_function_pointer(
                       symtab, NULL, NULL, src_obj, src_indx, NULL, reloc,
                       r_type, gsym)))
            symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx);

          // If the symbol name matches '__start_XXX' then the section with
          // the C identifier like name 'XXX' should not be garbage collected.
          // A similar treatment to symbols with the name '__stop_XXX'.
          if (is_prefix_of(cident_section_start_prefix, gsym->name()))
            {
              cident_section_name = (gsym->name() 
                                     + strlen(cident_section_start_prefix));
            }
          else if (is_prefix_of(cident_section_stop_prefix, gsym->name()))
            {
              cident_section_name = (gsym->name() 
                                     + strlen(cident_section_stop_prefix));
            }
          if (is_icf_tracked)
            {
	      Address symvalue = dst_off - addend;
              if (is_ordinary && dst_obj != NULL)
		(*secvec).push_back(Section_id(dst_obj, dst_indx));
	      else
                (*secvec).push_back(Section_id(NULL, 0));
              (*symvec).push_back(gsym);
	      (*addendvec).push_back(std::make_pair(
					static_cast<long long>(symvalue),
					static_cast<long long>(addend)));
              uint64_t reloc_offset =
                convert_to_section_size_type(reloc.get_r_offset());
	      (*offsetvec).push_back(reloc_offset);
              (*reloc_addend_size_vec).push_back(
                get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
	    }

          if (dst_obj == NULL)
            continue;
          if (!is_ordinary)
            continue;
        }
      if (parameters->options().gc_sections())
        {
	  symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
	  parameters->sized_target<size, big_endian>()
	    ->gc_add_reference(symtab, src_obj, src_indx, dst_obj, dst_indx,
			       dst_off);
          if (cident_section_name != NULL)
            {
              Garbage_collection::Cident_section_map::iterator ele =
                symtab->gc()->cident_sections()->find(std::string(cident_section_name));
              if (ele == symtab->gc()->cident_sections()->end())
                continue;
	      Section_id src_id(src_obj, src_indx);
              Garbage_collection::Sections_reachable&
                v(symtab->gc()->section_reloc_map()[src_id]);
              Garbage_collection::Sections_reachable& cident_secn(ele->second);
              for (Garbage_collection::Sections_reachable::iterator it_v
                     = cident_secn.begin();
                   it_v != cident_secn.end();
                   ++it_v)
                {
                  v.insert(*it_v);
                }
            }
        }
    }
  return;
}

} // End of namespace gold.

#endif
