//===-- DWARFCompileUnit.cpp ----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
#include "DWARFFormValue.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace dwarf;

DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const {
  return DataExtractor(Context.getInfoSection(),
                       Context.isLittleEndian(), getAddressByteSize());
}

bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
  clear();

  Offset = *offset_ptr;

  if (debug_info.isValidOffset(*offset_ptr)) {
    uint64_t abbrOffset;
    const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev();
    Length = debug_info.getU32(offset_ptr);
    Version = debug_info.getU16(offset_ptr);
    abbrOffset = debug_info.getU32(offset_ptr);
    AddrSize = debug_info.getU8(offset_ptr);

    bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1);
    bool versionOK = DWARFContext::isSupportedVersion(Version);
    bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset;
    bool addrSizeOK = AddrSize == 4 || AddrSize == 8;

    if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) {
      Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset);
      return true;
    }

    // reset the offset to where we tried to parse from if anything went wrong
    *offset_ptr = Offset;
  }

  return false;
}

uint32_t
DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
                          const DWARFAbbreviationDeclarationSet *abbrevs) {
  clear();

  Offset = offset;

  if (debug_info_data.isValidOffset(offset)) {
    Length = debug_info_data.getU32(&offset);
    Version = debug_info_data.getU16(&offset);
    bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset();
    Abbrevs = abbrevs;
    AddrSize = debug_info_data.getU8 (&offset);

    bool versionOK = DWARFContext::isSupportedVersion(Version);
    bool addrSizeOK = AddrSize == 4 || AddrSize == 8;

    if (versionOK && addrSizeOK && abbrevsOK &&
        debug_info_data.isValidOffset(offset))
      return offset;
  }
  return 0;
}

void DWARFCompileUnit::clear() {
  Offset = 0;
  Length = 0;
  Version = 0;
  Abbrevs = 0;
  AddrSize = 0;
  BaseAddr = 0;
  DieArray.clear();
}

void DWARFCompileUnit::dump(raw_ostream &OS) {
  OS << format("0x%08x", Offset) << ": Compile Unit:"
     << " length = " << format("0x%08x", Length)
     << " version = " << format("0x%04x", Version)
     << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset())
     << " addr_size = " << format("0x%02x", AddrSize)
     << " (next CU at " << format("0x%08x", getNextCompileUnitOffset())
     << ")\n";

  getCompileUnitDIE(false)->dump(OS, this, -1U);
}

void DWARFCompileUnit::setDIERelations() {
  if (DieArray.empty())
    return;
  DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
  DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
  DWARFDebugInfoEntryMinimal *curr_die;
  // We purposely are skipping the last element in the array in the loop below
  // so that we can always have a valid next item
  for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
    // Since our loop doesn't include the last element, we can always
    // safely access the next die in the array.
    DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;

    const DWARFAbbreviationDeclaration *curr_die_abbrev =
      curr_die->getAbbreviationDeclarationPtr();

    if (curr_die_abbrev) {
      // Normal DIE
      if (curr_die_abbrev->hasChildren())
        next_die->setParent(curr_die);
      else
        curr_die->setSibling(next_die);
    } else {
      // NULL DIE that terminates a sibling chain
      DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
      if (parent)
        parent->setSibling(next_die);
    }
  }

  // Since we skipped the last element, we need to fix it up!
  if (die_array_begin < die_array_end)
    curr_die->setParent(die_array_begin);
}

size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
  const size_t initial_die_array_size = DieArray.size();
  if ((cu_die_only && initial_die_array_size > 0) ||
      initial_die_array_size > 1)
    return 0; // Already parsed

  // Set the offset to that of the first DIE and calculate the start of the
  // next compilation unit header.
  uint32_t offset = getFirstDIEOffset();
  uint32_t next_cu_offset = getNextCompileUnitOffset();

  DWARFDebugInfoEntryMinimal die;
  // Keep a flat array of the DIE for binary lookup by DIE offset
  uint32_t depth = 0;
  // We are in our compile unit, parse starting at the offset
  // we were told to parse

  const uint8_t *fixed_form_sizes =
    DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize());

  while (offset < next_cu_offset &&
         die.extractFast(this, fixed_form_sizes, &offset)) {

    if (depth == 0) {
      uint64_t base_addr =
        die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
      if (base_addr == -1U)
        base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
      setBaseAddress(base_addr);
    }

    if (cu_die_only) {
      addDIE(die);
      return 1;
    }
    else if (depth == 0 && initial_die_array_size == 1) {
      // Don't append the CU die as we already did that
    } else {
      addDIE (die);
    }

    const DWARFAbbreviationDeclaration *abbrDecl =
      die.getAbbreviationDeclarationPtr();
    if (abbrDecl) {
      // Normal DIE
      if (abbrDecl->hasChildren())
        ++depth;
    } else {
      // NULL DIE.
      if (depth > 0)
        --depth;
      if (depth == 0)
        break;  // We are done with this compile unit!
    }

  }

  // Give a little bit of info if we encounter corrupt DWARF (our offset
  // should always terminate at or before the start of the next compilation
  // unit header).
  if (offset > next_cu_offset) {
    fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
  }

  setDIERelations();
  return DieArray.size();
}

void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) {
  if (DieArray.size() > 1) {
    // std::vectors never get any smaller when resized to a smaller size,
    // or when clear() or erase() are called, the size will report that it
    // is smaller, but the memory allocated remains intact (call capacity()
    // to see this). So we need to create a temporary vector and swap the
    // contents which will cause just the internal pointers to be swapped
    // so that when "tmp_array" goes out of scope, it will destroy the
    // contents.

    // Save at least the compile unit DIE
    std::vector<DWARFDebugInfoEntryMinimal> tmpArray;
    DieArray.swap(tmpArray);
    if (keep_compile_unit_die)
      DieArray.push_back(tmpArray.front());
  }
}

void
DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
                                         bool clear_dies_if_already_not_parsed){
  // This function is usually called if there in no .debug_aranges section
  // in order to produce a compile unit level set of address ranges that
  // is accurate. If the DIEs weren't parsed, then we don't want all dies for
  // all compile units to stay loaded when they weren't needed. So we can end
  // up parsing the DWARF and then throwing them all away to keep memory usage
  // down.
  const bool clear_dies = extractDIEsIfNeeded(false) > 1;

  DieArray[0].buildAddressRangeTable(this, debug_aranges);

  // Keep memory down by clearing DIEs if this generate function
  // caused them to be parsed.
  if (clear_dies)
    clearDIEs(true);
}
