1//===-- SymbolFileDWARFDwp.cpp ----------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SymbolFileDWARFDwp.h"
10
11#include "lldb/Core/Section.h"
12#include "lldb/Symbol/ObjectFile.h"
13
14#include "SymbolFileDWARFDwoDwp.h"
15
16static llvm::DWARFSectionKind
17lldbSectTypeToLlvmSectionKind(lldb::SectionType type) {
18  switch (type) {
19  case lldb::eSectionTypeDWARFDebugInfo:
20    return llvm::DW_SECT_INFO;
21  // case lldb::eSectionTypeDWARFDebugTypes:
22  //   return llvm::DW_SECT_TYPES;
23  case lldb::eSectionTypeDWARFDebugAbbrev:
24    return llvm::DW_SECT_ABBREV;
25  case lldb::eSectionTypeDWARFDebugLine:
26    return llvm::DW_SECT_LINE;
27  case lldb::eSectionTypeDWARFDebugLoc:
28    return llvm::DW_SECT_LOC;
29  case lldb::eSectionTypeDWARFDebugStrOffsets:
30    return llvm::DW_SECT_STR_OFFSETS;
31  // case lldb::eSectionTypeDWARFDebugMacinfo:
32  //   return llvm::DW_SECT_MACINFO;
33  case lldb::eSectionTypeDWARFDebugMacro:
34    return llvm::DW_SECT_MACRO;
35  default:
36    // Note: 0 is an invalid dwarf section kind.
37    return llvm::DWARFSectionKind(0);
38  }
39}
40
41std::unique_ptr<SymbolFileDWARFDwp>
42SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp,
43                           const lldb_private::FileSpec &file_spec) {
44  const lldb::offset_t file_offset = 0;
45  lldb::DataBufferSP file_data_sp;
46  lldb::offset_t file_data_offset = 0;
47  lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin(
48      module_sp, &file_spec, file_offset,
49      lldb_private::FileSystem::Instance().GetByteSize(file_spec), file_data_sp,
50      file_data_offset);
51  if (obj_file == nullptr)
52    return nullptr;
53
54  std::unique_ptr<SymbolFileDWARFDwp> dwp_symfile(
55      new SymbolFileDWARFDwp(module_sp, obj_file));
56
57  lldb_private::DWARFDataExtractor debug_cu_index;
58  if (!dwp_symfile->LoadRawSectionData(lldb::eSectionTypeDWARFDebugCuIndex,
59                                       debug_cu_index))
60    return nullptr;
61
62  llvm::DataExtractor llvm_debug_cu_index(
63      llvm::StringRef(debug_cu_index.PeekCStr(0), debug_cu_index.GetByteSize()),
64      debug_cu_index.GetByteOrder() == lldb::eByteOrderLittle,
65      debug_cu_index.GetAddressByteSize());
66  if (!dwp_symfile->m_debug_cu_index.parse(llvm_debug_cu_index))
67    return nullptr;
68  dwp_symfile->InitDebugCUIndexMap();
69  return dwp_symfile;
70}
71
72void SymbolFileDWARFDwp::InitDebugCUIndexMap() {
73  m_debug_cu_index_map.clear();
74  for (const auto &entry : m_debug_cu_index.getRows())
75    m_debug_cu_index_map.emplace(entry.getSignature(), &entry);
76}
77
78SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp,
79                                       lldb::ObjectFileSP obj_file)
80    : m_obj_file(std::move(obj_file)), m_debug_cu_index(llvm::DW_SECT_INFO)
81{}
82
83std::unique_ptr<SymbolFileDWARFDwo>
84SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit &dwarf_cu,
85                                          uint64_t dwo_id) {
86  return std::unique_ptr<SymbolFileDWARFDwo>(
87      new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id));
88}
89
90bool SymbolFileDWARFDwp::LoadSectionData(
91    uint64_t dwo_id, lldb::SectionType sect_type,
92    lldb_private::DWARFDataExtractor &data) {
93  lldb_private::DWARFDataExtractor section_data;
94  if (!LoadRawSectionData(sect_type, section_data))
95    return false;
96
97  auto it = m_debug_cu_index_map.find(dwo_id);
98  if (it == m_debug_cu_index_map.end())
99    return false;
100
101  auto *offsets =
102      it->second->getOffset(lldbSectTypeToLlvmSectionKind(sect_type));
103  if (offsets) {
104    data.SetData(section_data, offsets->Offset, offsets->Length);
105  } else {
106    data.SetData(section_data, 0, section_data.GetByteSize());
107  }
108  return true;
109}
110
111bool SymbolFileDWARFDwp::LoadRawSectionData(
112    lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) {
113  std::lock_guard<std::mutex> lock(m_sections_mutex);
114
115  auto it = m_sections.find(sect_type);
116  if (it != m_sections.end()) {
117    if (it->second.GetByteSize() == 0)
118      return false;
119
120    data = it->second;
121    return true;
122  }
123
124  const lldb_private::SectionList *section_list =
125      m_obj_file->GetSectionList(false /* update_module_section_list */);
126  if (section_list) {
127    lldb::SectionSP section_sp(
128        section_list->FindSectionByType(sect_type, true));
129    if (section_sp) {
130      if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) {
131        m_sections[sect_type] = data;
132        return true;
133      }
134    }
135  }
136  m_sections[sect_type].Clear();
137  return false;
138}
139