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

#include "SymbolFileDWARFDwp.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"

#include "SymbolFileDWARFDwoDwp.h"

static llvm::DWARFSectionKind
lldbSectTypeToLlvmSectionKind(lldb::SectionType type) {
  switch (type) {
  case lldb::eSectionTypeDWARFDebugInfo:
    return llvm::DW_SECT_INFO;
  // case lldb::eSectionTypeDWARFDebugTypes:
  //   return llvm::DW_SECT_TYPES;
  case lldb::eSectionTypeDWARFDebugAbbrev:
    return llvm::DW_SECT_ABBREV;
  case lldb::eSectionTypeDWARFDebugLine:
    return llvm::DW_SECT_LINE;
  case lldb::eSectionTypeDWARFDebugLoc:
    return llvm::DW_SECT_LOC;
  case lldb::eSectionTypeDWARFDebugStrOffsets:
    return llvm::DW_SECT_STR_OFFSETS;
  // case lldb::eSectionTypeDWARFDebugMacinfo:
  //   return llvm::DW_SECT_MACINFO;
  case lldb::eSectionTypeDWARFDebugMacro:
    return llvm::DW_SECT_MACRO;
  default:
    // Note: 0 is an invalid dwarf section kind.
    return llvm::DWARFSectionKind(0);
  }
}

std::unique_ptr<SymbolFileDWARFDwp>
SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp,
                           const lldb_private::FileSpec &file_spec) {
  const lldb::offset_t file_offset = 0;
  lldb::DataBufferSP file_data_sp;
  lldb::offset_t file_data_offset = 0;
  lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin(
      module_sp, &file_spec, file_offset, file_spec.GetByteSize(), file_data_sp,
      file_data_offset);
  if (obj_file == nullptr)
    return nullptr;

  std::unique_ptr<SymbolFileDWARFDwp> dwp_symfile(
      new SymbolFileDWARFDwp(module_sp, obj_file));

  lldb_private::DWARFDataExtractor debug_cu_index;
  if (!dwp_symfile->LoadRawSectionData(lldb::eSectionTypeDWARFDebugCuIndex,
                                       debug_cu_index))
    return nullptr;

  llvm::DataExtractor llvm_debug_cu_index(
      llvm::StringRef(debug_cu_index.PeekCStr(0), debug_cu_index.GetByteSize()),
      debug_cu_index.GetByteOrder() == lldb::eByteOrderLittle,
      debug_cu_index.GetAddressByteSize());
  if (!dwp_symfile->m_debug_cu_index.parse(llvm_debug_cu_index))
    return nullptr;
  dwp_symfile->InitDebugCUIndexMap();
  return dwp_symfile;
}

void SymbolFileDWARFDwp::InitDebugCUIndexMap() {
  m_debug_cu_index_map.clear();
  for (const auto &entry : m_debug_cu_index.getRows())
    m_debug_cu_index_map.emplace(entry.getSignature(), &entry);
}

SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp,
                                       lldb::ObjectFileSP obj_file)
    : m_obj_file(std::move(obj_file)), m_debug_cu_index(llvm::DW_SECT_INFO) 
{}

std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFUnit *dwarf_cu,
                                          uint64_t dwo_id) {
  return std::unique_ptr<SymbolFileDWARFDwo>(
      new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id));
}

bool SymbolFileDWARFDwp::LoadSectionData(
    uint64_t dwo_id, lldb::SectionType sect_type,
    lldb_private::DWARFDataExtractor &data) {
  lldb_private::DWARFDataExtractor section_data;
  if (!LoadRawSectionData(sect_type, section_data))
    return false;

  auto it = m_debug_cu_index_map.find(dwo_id);
  if (it == m_debug_cu_index_map.end())
    return false;

  auto *offsets =
      it->second->getOffset(lldbSectTypeToLlvmSectionKind(sect_type));
  if (offsets) {
    data.SetData(section_data, offsets->Offset, offsets->Length);
  } else {
    data.SetData(section_data, 0, section_data.GetByteSize());
  }
  return true;
}

bool SymbolFileDWARFDwp::LoadRawSectionData(
    lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) {
  std::lock_guard<std::mutex> lock(m_sections_mutex);

  auto it = m_sections.find(sect_type);
  if (it != m_sections.end()) {
    if (it->second.GetByteSize() == 0)
      return false;

    data = it->second;
    return true;
  }

  const lldb_private::SectionList *section_list =
      m_obj_file->GetSectionList(false /* update_module_section_list */);
  if (section_list) {
    lldb::SectionSP section_sp(
        section_list->FindSectionByType(sect_type, true));
    if (section_sp) {
      if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) {
        m_sections[sect_type] = data;
        return true;
      }
    }
  }
  m_sections[sect_type].Clear();
  return false;
}
