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

// Copyright 2009, 2010 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 <queue>
#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;

template<int sh_type, int size, bool big_endian>
class Reloc_types;

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::queue<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(Object* 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(Object* src_object, unsigned int src_shndx,
		Object* dst_object, unsigned int dst_shndx)
  {
    Section_id src_id(src_object, src_shndx);
    Section_id dst_id(dst_object, dst_shndx);
    Section_ref::iterator p = this->section_reloc_map_.find(src_id);
    if (p == this->section_reloc_map_.end())
      this->section_reloc_map_[src_id].insert(dst_id);
    else
      p->second.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 sh_type, int r_type, Relobj* obj)
{
  if (sh_type != elfcpp::SHT_REL)
    return 0;
  Classify_reloc classify_reloc;
  return classify_reloc.get_size_for_reloc(r_type, obj);
}

// 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, int sh_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)
{
  Object* dst_obj;
  unsigned int dst_indx;
  Scan scan;

  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::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);
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
      unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
      typename elfcpp::Elf_types<size>::Elf_Swxword addend =
      Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc);

      if (r_sym < local_count)
        {
          gold_assert(plocal_syms != NULL);
          typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
                                                      + r_sym * sym_size);
          unsigned int shndx = lsym.get_st_shndx();
          bool is_ordinary;
          shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
          dst_obj = src_obj;
          dst_indx = shndx;
          if (is_icf_tracked)
            {
	      if (is_ordinary) 
                (*secvec).push_back(Section_id(dst_obj, dst_indx));
	      else
                (*secvec).push_back(Section_id(NULL, 0));
              (*symvec).push_back(NULL);
              long long symvalue = static_cast<long long>(lsym.get_st_value());
              (*addendvec).push_back(std::make_pair(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>(sh_type, 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 || shndx == 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)
            {
              dst_obj = gsym->object();
              dst_indx = gsym->shndx(&is_ordinary);
            }

	  // 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
              && gsym->type() != elfcpp::STT_OBJECT
              && (!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)
            {
              if (is_ordinary && gsym->source() == Symbol::FROM_OBJECT)
                (*secvec).push_back(Section_id(dst_obj, dst_indx));
	      else
                (*secvec).push_back(Section_id(NULL, 0));
              (*symvec).push_back(gsym);
              Sized_symbol<size>* sized_gsym =
                        static_cast<Sized_symbol<size>* >(gsym);
              long long symvalue =
                        static_cast<long long>(sized_gsym->value());
              (*addendvec).push_back(std::make_pair(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>(sh_type, r_type,
                                                         src_obj));
	    }

          if (gsym->source() != Symbol::FROM_OBJECT)
            continue;
          if (!is_ordinary)
            continue;
        }
      if (parameters->options().gc_sections())
        {
	  symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
          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
