// reduced_debug_output.cc -- output reduced debugging information to save space

// Copyright 2008, 2010 Free Software Foundation, Inc.
// Written by Caleb Howe <cshowe@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.

#include "gold.h"

#include "parameters.h"
#include "options.h"
#include "dwarf.h"
#include "dwarf_reader.h"
#include "reduced_debug_output.h"
#include "int_encoding.h"

#include <vector>

namespace gold
{

// Given a pointer to the beginning of a die and the beginning of the associated
// abbreviation fills in die_end with the end of the information entry.  If
// successful returns true.  Get_die_end also takes a pointer to the end of the
// buffer containing the die.  If die_end would be beyond the end of the
// buffer, or if an unsupported dwarf form is encountered returns false.
bool
Output_reduced_debug_info_section::get_die_end(
    unsigned char* die, unsigned char* abbrev, unsigned char** die_end,
    unsigned char* buffer_end, int address_size, bool is64)
{
  size_t LEB_size;
  uint64_t LEB_decoded;
  for(;;)
    {
      uint64_t attribute = read_unsigned_LEB_128(abbrev, &LEB_size);
      abbrev += LEB_size;
      elfcpp::DW_FORM form =
          static_cast<elfcpp::DW_FORM>(read_unsigned_LEB_128(abbrev,
                                                             &LEB_size));
      abbrev += LEB_size;
      if (!(attribute || form))
        break;
      if (die >= buffer_end)
        return false;
      switch(form)
        {
          case elfcpp::DW_FORM_null:
          case elfcpp::DW_FORM_flag_present:
            break;
          case elfcpp::DW_FORM_strp:
          case elfcpp::DW_FORM_sec_offset:
            die += is64 ? 8 : 4;
            break;
          case elfcpp::DW_FORM_addr:
          case elfcpp::DW_FORM_ref_addr:
            die += address_size;
            break;
          case elfcpp::DW_FORM_block1:
            die += *die;
            die += 1;
            break;
          case elfcpp::DW_FORM_block2:
            {
              uint16_t block_size;
              block_size = read_from_pointer<16>(&die);
              die += block_size;
              break;
            }
          case elfcpp::DW_FORM_block4:
            {
              uint32_t block_size;
              block_size = read_from_pointer<32>(&die);
              die += block_size;
              break;
            }
          case elfcpp::DW_FORM_block:
          case elfcpp::DW_FORM_exprloc:
            LEB_decoded = read_unsigned_LEB_128(die, &LEB_size);
            die += (LEB_decoded + LEB_size);
            break;
          case elfcpp::DW_FORM_data1:
          case elfcpp::DW_FORM_ref1:
          case elfcpp::DW_FORM_flag:
            die += 1;
            break;
          case elfcpp::DW_FORM_data2:
          case elfcpp::DW_FORM_ref2:
            die += 2;
            break;
          case elfcpp::DW_FORM_data4:
          case elfcpp::DW_FORM_ref4:
            die += 4;
            break;
          case elfcpp::DW_FORM_data8:
          case elfcpp::DW_FORM_ref8:
          case elfcpp::DW_FORM_ref_sig8:
            die += 8;
            break;
          case elfcpp::DW_FORM_ref_udata:
          case elfcpp::DW_FORM_udata:
            read_unsigned_LEB_128(die, &LEB_size);
            die += LEB_size;
            break;
          case elfcpp::DW_FORM_sdata:
            read_signed_LEB_128(die, &LEB_size);
            die += LEB_size;
            break;
          case elfcpp::DW_FORM_string:
            {
              size_t length = strlen(reinterpret_cast<char*>(die));
              die += length + 1;
              break;
            }
          case elfcpp::DW_FORM_indirect:
          case elfcpp::DW_FORM_GNU_ref_index:
          case elfcpp::DW_FORM_GNU_addr_index:
          case elfcpp::DW_FORM_GNU_str_index:
            return false;
      }
    }
  *die_end = die;
  return true;
}

void
Output_reduced_debug_abbrev_section::set_final_data_size()
{
  if (this->sized_ || this->failed_)
    return;

  uint64_t abbrev_number;
  size_t LEB_size;
  unsigned char* abbrev_data = this->postprocessing_buffer();
  unsigned char* abbrev_end = this->postprocessing_buffer() +
                              this->postprocessing_buffer_size();
  this->write_to_postprocessing_buffer();
  while(abbrev_data < abbrev_end)
    {
      uint64_t abbrev_offset = abbrev_data - this->postprocessing_buffer();
      while((abbrev_number = read_unsigned_LEB_128(abbrev_data, &LEB_size)))
        {
          if (abbrev_data >= abbrev_end)
            {
              failed("Debug abbreviations extend beyond .debug_abbrev "
                     "section; failed to reduce debug abbreviations");
              return;
            }
          abbrev_data += LEB_size;

          // Together with the abbreviation number these fields make up
          // the header for each abbreviation.
          uint64_t abbrev_type = read_unsigned_LEB_128(abbrev_data, &LEB_size);
          abbrev_data += LEB_size;

          // This would ordinarily be the has_children field of the
          // abbreviation.  But it's going to be false after reducing the
          // information, so there's no point in storing it.
          abbrev_data++;

          // Read to the end of the current abbreviation.
          // This is indicated by two zero unsigned LEBs in a row.  We don't
          // need to parse the data yet, so we just scan through the data
          // looking for two consecutive 0 bytes indicating the end of the
          // abbreviation.
          unsigned char* current_abbrev;
          for (current_abbrev = abbrev_data;
               current_abbrev[0] || current_abbrev[1];
               current_abbrev++)
            {
              if (current_abbrev >= abbrev_end)
                {
                  this->failed(_("Debug abbreviations extend beyond "
				 ".debug_abbrev section; failed to reduce "
				 "debug abbreviations"));
                  return;
                }
            }
          // Account for the two nulls and advance to the start of the
          // next abbreviation.
          current_abbrev += 2;

          // We're eliminating every entry except for compile units, so we
          // only need to store abbreviations that describe them
          if (abbrev_type == elfcpp::DW_TAG_compile_unit)
            {
              write_unsigned_LEB_128(&this->data_, ++this->abbrev_count_);
              write_unsigned_LEB_128(&this->data_, abbrev_type);
              // has_children is false for all entries
              this->data_.push_back(0);
              this->abbrev_mapping_[std::make_pair(abbrev_offset,
                                                   abbrev_number)] =
                  std::make_pair(abbrev_count_, this->data_.size());
              this->data_.insert(this->data_.end(), abbrev_data,
                                 current_abbrev);
            }
          abbrev_data = current_abbrev;
        }
      gold_assert(LEB_size == 1);
      abbrev_data += LEB_size;
    }
  // Null terminate the list of abbreviations
  this->data_.push_back(0);
  this->set_data_size(data_.size());
  this->sized_ = true;
}

void
Output_reduced_debug_abbrev_section::do_write(Output_file* of)
{
  off_t offset = this->offset();
  off_t data_size = this->data_size();
  unsigned char* view = of->get_output_view(offset, data_size);
  if (this->failed_)
    memcpy(view, this->postprocessing_buffer(),
           this->postprocessing_buffer_size());
  else
    memcpy(view, &this->data_.front(), data_size);
  of->write_output_view(offset, data_size, view);
}

// Locates the abbreviation with abbreviation_number abbrev_number in the
// abbreviation table at offset abbrev_offset.  abbrev_number is updated with
// its new abbreviation number and a pointer to the beginning of the
// abbreviation is returned.
unsigned char*
Output_reduced_debug_abbrev_section::get_new_abbrev(
  uint64_t* abbrev_number, uint64_t abbrev_offset)
{
  set_final_data_size();
  std::pair<uint64_t, uint64_t> abbrev_info =
      this->abbrev_mapping_[std::make_pair(abbrev_offset, *abbrev_number)];
  *abbrev_number = abbrev_info.first;
  return &this->data_[abbrev_info.second];
}

void Output_reduced_debug_info_section::set_final_data_size()
{
  if (this->failed_)
    return;
  unsigned char* debug_info = this->postprocessing_buffer();
  unsigned char* debug_info_end = (this->postprocessing_buffer()
				   + this->postprocessing_buffer_size());
  unsigned char* next_compile_unit;
  this->write_to_postprocessing_buffer();

  while (debug_info < debug_info_end)
    {
      uint32_t compile_unit_start = read_from_pointer<32>(&debug_info);
      // The first 4 bytes of each compile unit determine whether or
      // not we're using dwarf32 or dwarf64.  This is not necessarily
      // related to whether the binary is 32 or 64 bits.
      if (compile_unit_start == 0xFFFFFFFF)
        {
          // Technically the size can be up to 96 bits.  Rather than handle
          // 96/128 bit integers we just truncate the size at 64 bits.
          if (0 != read_from_pointer<32>(&debug_info))
            {
              this->failed(_("Extremely large compile unit in debug info; "
			     "failed to reduce debug info"));
              return;
            }
          const int dwarf64_header_size = sizeof(uint64_t) + sizeof(uint16_t) +
                                          sizeof(uint64_t) + sizeof(uint8_t);
          if (debug_info + dwarf64_header_size >= debug_info_end)
            {
              this->failed(_("Debug info extends beyond .debug_info section;"
			     "failed to reduce debug info"));
              return;
            }

          uint64_t compile_unit_size = read_from_pointer<64>(&debug_info);
          next_compile_unit = debug_info + compile_unit_size;
          uint16_t version = read_from_pointer<16>(&debug_info);
          uint64_t abbrev_offset = read_from_pointer<64>(&debug_info);
          uint8_t address_size = read_from_pointer<8>(&debug_info);
          size_t LEB_size;
          uint64_t abbreviation_number = read_unsigned_LEB_128(debug_info,
                                                               &LEB_size);
          debug_info += LEB_size;
          unsigned char* die_abbrev = this->associated_abbrev_->get_new_abbrev(
              &abbreviation_number, abbrev_offset);
          unsigned char* die_end;
          if (!this->get_die_end(debug_info, die_abbrev, &die_end,
                                 debug_info_end, address_size, true))
            {
              this->failed(_("Invalid DIE in debug info; "
			     "failed to reduce debug info"));
              return;
            }

          insert_into_vector<32>(&this->data_, 0xFFFFFFFF);
          insert_into_vector<32>(&this->data_, 0);
          insert_into_vector<64>(
              &this->data_,
              (11 + get_length_as_unsigned_LEB_128(abbreviation_number)
	       + die_end - debug_info));
          insert_into_vector<16>(&this->data_, version);
          insert_into_vector<64>(&this->data_, 0);
          insert_into_vector<8>(&this->data_, address_size);
          write_unsigned_LEB_128(&this->data_, abbreviation_number);
          this->data_.insert(this->data_.end(), debug_info, die_end);
        }
      else
        {
          const int dwarf32_header_size =
              sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t);
          if (debug_info + dwarf32_header_size >= debug_info_end)
            {
              this->failed(_("Debug info extends beyond .debug_info section; "
			     "failed to reduce debug info"));
              return;
            }
          uint32_t compile_unit_size = compile_unit_start;
          next_compile_unit = debug_info + compile_unit_size;
          uint16_t version = read_from_pointer<16>(&debug_info);
          uint32_t abbrev_offset = read_from_pointer<32>(&debug_info);
          uint8_t address_size = read_from_pointer<8>(&debug_info);
          size_t LEB_size;
          uint64_t abbreviation_number = read_unsigned_LEB_128(debug_info,
                                                               &LEB_size);
          debug_info += LEB_size;
          unsigned char* die_abbrev = this->associated_abbrev_->get_new_abbrev(
              &abbreviation_number, abbrev_offset);
          unsigned char* die_end;
          if (!this->get_die_end(debug_info, die_abbrev, &die_end,
                                 debug_info_end, address_size, false))
            {
              this->failed(_("Invalid DIE in debug info; "
			     "failed to reduce debug info"));
              return;
            }

          insert_into_vector<32>(
              &this->data_,
              (7 + get_length_as_unsigned_LEB_128(abbreviation_number)
	       + die_end - debug_info));
          insert_into_vector<16>(&this->data_, version);
          insert_into_vector<32>(&this->data_, 0);
          insert_into_vector<8>(&this->data_, address_size);
          write_unsigned_LEB_128(&this->data_, abbreviation_number);
          this->data_.insert(this->data_.end(), debug_info, die_end);
        }
      debug_info = next_compile_unit;
    }
  this->set_data_size(data_.size());
}

void Output_reduced_debug_info_section::do_write(Output_file* of)
{
  off_t offset = this->offset();
  off_t data_size = this->data_size();
  unsigned char* view = of->get_output_view(offset, data_size);
  if (this->failed_)
    memcpy(view, this->postprocessing_buffer(),
           this->postprocessing_buffer_size());
  else
    memcpy(view, &this->data_.front(), data_size);
  of->write_output_view(offset, data_size, view);
}

} // End namespace gold.
