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

// Copyright 2008 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 <vector>

namespace gold
{

void
write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value)
{
  do
    {
      unsigned char current_byte = value & 0x7f;
      value >>= 7;
      if (value != 0)
        {
          current_byte |= 0x80;
        }
      buffer->push_back(current_byte);
    }
  while (value != 0);
}

size_t
get_length_as_unsigned_LEB_128(uint64_t value)
{
  size_t length = 0;
  do
    {
      unsigned char current_byte = value & 0x7f;
      value >>= 7;
      if (value != 0)
        {
          current_byte |= 0x80;
        }
      length++;
    }
  while (value != 0);
  return length;
}

template <int valsize>
void Insert_into_vector(std::vector<unsigned char>* destination,
                        typename elfcpp::Valtype_base<valsize>::Valtype value)
{
  union
    {
      unsigned char buffer[valsize / 8];
      long long align;
    } u;
  if (parameters->target().is_big_endian())
    elfcpp::Swap<valsize, true>::writeval(u.buffer, value);
  else
    elfcpp::Swap<valsize, false>::writeval(u.buffer, value);
  destination->insert(destination->end(), u.buffer, u.buffer + valsize / 8);
}

template <int valsize>
typename elfcpp::Valtype_base<valsize>::Valtype
read_from_pointer(unsigned char** source)
{
  typename elfcpp::Valtype_base<valsize>::Valtype return_value;
  if (parameters->target().is_big_endian())
    return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source);
  else
    return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source);
  *source += valsize / 8;
  return return_value;
}

// 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:
            break;
          case elfcpp::DW_FORM_strp:
            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:
            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:
            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_string:
            {
              size_t length = strlen(reinterpret_cast<char*>(die));
              die += length + 1;
              break;
            }
          case elfcpp::DW_FORM_sdata:
          case elfcpp::DW_FORM_indirect:
            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 reducting 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.
