1254721Semaste//===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "SymbolFileDWARF.h"
10254721Semaste
11254721Semaste#include <algorithm>
12254721Semaste#include <set>
13254721Semaste
14314564Sdim#include "lldb/Host/PosixApi.h"
15254721Semaste#include "lldb/Symbol/ObjectFile.h"
16321369Sdim#include "lldb/Utility/RegularExpression.h"
17321369Sdim#include "lldb/Utility/Stream.h"
18353358Sdim#include "llvm/Support/Casting.h"
19254721Semaste
20314564Sdim#include "DWARFCompileUnit.h"
21353358Sdim#include "DWARFContext.h"
22254721Semaste#include "DWARFDebugAranges.h"
23254721Semaste#include "DWARFDebugInfo.h"
24254721Semaste#include "DWARFDebugInfoEntry.h"
25254721Semaste#include "DWARFFormValue.h"
26353358Sdim#include "DWARFTypeUnit.h"
27254721Semaste
28254721Semasteusing namespace lldb;
29254721Semasteusing namespace lldb_private;
30254721Semasteusing namespace std;
31254721Semaste
32254721Semaste// Constructor
33353358SdimDWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf,
34353358Sdim                               lldb_private::DWARFContext &context)
35353358Sdim    : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {}
36254721Semaste
37353358Sdimllvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
38353358Sdim  if (m_cu_aranges_up)
39353358Sdim    return *m_cu_aranges_up;
40353358Sdim
41360784Sdim  m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
42353358Sdim  const DWARFDataExtractor &debug_aranges_data =
43353358Sdim      m_context.getOrLoadArangesData();
44353358Sdim  if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data))
45353358Sdim    return std::move(error);
46353358Sdim
47353358Sdim  // Make a list of all CUs represented by the arange data in the file.
48353358Sdim  std::set<dw_offset_t> cus_with_data;
49353358Sdim  for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
50353358Sdim    dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
51353358Sdim    if (offset != DW_INVALID_OFFSET)
52353358Sdim      cus_with_data.insert(offset);
53353358Sdim  }
54353358Sdim
55353358Sdim  // Manually build arange data for everything that wasn't in the
56353358Sdim  // .debug_aranges table.
57353358Sdim  const size_t num_units = GetNumUnits();
58353358Sdim  for (size_t idx = 0; idx < num_units; ++idx) {
59353358Sdim    DWARFUnit *cu = GetUnitAtIndex(idx);
60353358Sdim
61353358Sdim    dw_offset_t offset = cu->GetOffset();
62353358Sdim    if (cus_with_data.find(offset) == cus_with_data.end())
63353358Sdim      cu->BuildAddressRangeTable(m_cu_aranges_up.get());
64353358Sdim  }
65353358Sdim
66353358Sdim  const bool minimize = true;
67353358Sdim  m_cu_aranges_up->Sort(minimize);
68353358Sdim  return *m_cu_aranges_up;
69254721Semaste}
70254721Semaste
71353358Sdimvoid DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) {
72353358Sdim  DWARFDataExtractor data = section == DIERef::Section::DebugTypes
73353358Sdim                                ? m_context.getOrLoadDebugTypesData()
74353358Sdim                                : m_context.getOrLoadDebugInfoData();
75353358Sdim  lldb::offset_t offset = 0;
76353358Sdim  while (data.ValidOffset(offset)) {
77353358Sdim    llvm::Expected<DWARFUnitSP> unit_sp =
78353358Sdim        DWARFUnit::extract(m_dwarf, m_units.size(), data, section, &offset);
79254721Semaste
80353358Sdim    if (!unit_sp) {
81353358Sdim      // FIXME: Propagate this error up.
82353358Sdim      llvm::consumeError(unit_sp.takeError());
83353358Sdim      return;
84314564Sdim    }
85254721Semaste
86353358Sdim    // If it didn't return an error, then it should be returning a valid Unit.
87353358Sdim    assert(*unit_sp);
88353358Sdim    m_units.push_back(*unit_sp);
89353358Sdim    offset = (*unit_sp)->GetNextUnitOffset();
90258054Semaste
91353358Sdim    if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) {
92353358Sdim      m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(),
93353358Sdim                                             unit_sp.get()->GetID());
94314564Sdim    }
95314564Sdim  }
96254721Semaste}
97254721Semaste
98353358Sdimvoid DWARFDebugInfo::ParseUnitHeadersIfNeeded() {
99353358Sdim  if (!m_units.empty())
100353358Sdim    return;
101254721Semaste
102353358Sdim  ParseUnitsFor(DIERef::Section::DebugInfo);
103353358Sdim  ParseUnitsFor(DIERef::Section::DebugTypes);
104353358Sdim  llvm::sort(m_type_hash_to_unit_index, llvm::less_first());
105254721Semaste}
106254721Semaste
107353358Sdimsize_t DWARFDebugInfo::GetNumUnits() {
108353358Sdim  ParseUnitHeadersIfNeeded();
109353358Sdim  return m_units.size();
110254721Semaste}
111254721Semaste
112353358SdimDWARFUnit *DWARFDebugInfo::GetUnitAtIndex(user_id_t idx) {
113353358Sdim  DWARFUnit *cu = nullptr;
114353358Sdim  if (idx < GetNumUnits())
115353358Sdim    cu = m_units[idx].get();
116314564Sdim  return cu;
117254721Semaste}
118254721Semaste
119353358Sdimuint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section,
120353358Sdim                                       dw_offset_t offset) {
121353358Sdim  ParseUnitHeadersIfNeeded();
122314564Sdim
123353358Sdim  // llvm::lower_bound is not used as for DIE offsets it would still return
124353358Sdim  // index +1 and GetOffset() returning index itself would be a special case.
125353358Sdim  auto pos = llvm::upper_bound(
126353358Sdim      m_units, std::make_pair(section, offset),
127353358Sdim      [](const std::pair<DIERef::Section, dw_offset_t> &lhs,
128353358Sdim         const DWARFUnitSP &rhs) {
129353358Sdim        return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset());
130353358Sdim      });
131353358Sdim  uint32_t idx = std::distance(m_units.begin(), pos);
132353358Sdim  if (idx == 0)
133353358Sdim    return DW_INVALID_OFFSET;
134353358Sdim  return idx - 1;
135254721Semaste}
136254721Semaste
137353358SdimDWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section,
138353358Sdim                                           dw_offset_t cu_offset,
139353358Sdim                                           uint32_t *idx_ptr) {
140353358Sdim  uint32_t idx = FindUnitIndex(section, cu_offset);
141353358Sdim  DWARFUnit *result = GetUnitAtIndex(idx);
142353358Sdim  if (result && result->GetOffset() != cu_offset) {
143353358Sdim    result = nullptr;
144353358Sdim    idx = DW_INVALID_INDEX;
145314564Sdim  }
146314564Sdim  if (idx_ptr)
147353358Sdim    *idx_ptr = idx;
148353358Sdim  return result;
149254721Semaste}
150254721Semaste
151353358SdimDWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) {
152353358Sdim  return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset());
153309124Sdim}
154296417Sdim
155341825SdimDWARFUnit *
156353358SdimDWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section,
157353358Sdim                                           dw_offset_t die_offset) {
158353358Sdim  uint32_t idx = FindUnitIndex(section, die_offset);
159353358Sdim  DWARFUnit *result = GetUnitAtIndex(idx);
160353358Sdim  if (result && !result->ContainsDIEOffset(die_offset))
161353358Sdim    return nullptr;
162353358Sdim  return result;
163353358Sdim}
164309124Sdim
165353358SdimDWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) {
166353358Sdim  auto pos = llvm::lower_bound(m_type_hash_to_unit_index,
167353358Sdim                               std::make_pair(hash, 0u), llvm::less_first());
168353358Sdim  if (pos == m_type_hash_to_unit_index.end() || pos->first != hash)
169353358Sdim    return nullptr;
170353358Sdim  return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second));
171353358Sdim}
172309124Sdim
173353358Sdimbool DWARFDebugInfo::ContainsTypeUnits() {
174353358Sdim  ParseUnitHeadersIfNeeded();
175353358Sdim  return !m_type_hash_to_unit_index.empty();
176254721Semaste}
177254721Semaste
178309124SdimDWARFDIE
179353358SdimDWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section,
180353358Sdim                                   dw_offset_t die_offset) {
181353358Sdim  DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset);
182314564Sdim  if (cu)
183314564Sdim    return cu->GetDIE(die_offset);
184314564Sdim  return DWARFDIE();
185309124Sdim}
186309124Sdim
187254721Semaste// GetDIE()
188254721Semaste//
189254721Semaste// Get the DIE (Debug Information Entry) with the specified offset.
190296417SdimDWARFDIE
191314564SdimDWARFDebugInfo::GetDIE(const DIERef &die_ref) {
192353358Sdim  DWARFUnit *cu = GetUnit(die_ref);
193314564Sdim  if (cu)
194353358Sdim    return cu->GetDIE(die_ref.die_offset());
195314564Sdim  return DWARFDIE(); // Not found
196254721Semaste}
197254721Semaste
198