xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- DWARFDebugAranges.cpp ---------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "DWARFDebugAranges.h"
10061da546Spatrick #include "DWARFDebugArangeSet.h"
11061da546Spatrick #include "DWARFUnit.h"
12be691f3bSpatrick #include "LogChannelDWARF.h"
13061da546Spatrick #include "lldb/Utility/Log.h"
14061da546Spatrick #include "lldb/Utility/Timer.h"
15061da546Spatrick 
16061da546Spatrick using namespace lldb;
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick 
19061da546Spatrick // Constructor
DWARFDebugAranges()20061da546Spatrick DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {}
21061da546Spatrick 
22061da546Spatrick // CountArangeDescriptors
23061da546Spatrick class CountArangeDescriptors {
24061da546Spatrick public:
CountArangeDescriptors(uint32_t & count_ref)25061da546Spatrick   CountArangeDescriptors(uint32_t &count_ref) : count(count_ref) {
26061da546Spatrick     //      printf("constructor CountArangeDescriptors()\n");
27061da546Spatrick   }
operator ()(const DWARFDebugArangeSet & set)28061da546Spatrick   void operator()(const DWARFDebugArangeSet &set) {
29061da546Spatrick     count += set.NumDescriptors();
30061da546Spatrick   }
31061da546Spatrick   uint32_t &count;
32061da546Spatrick };
33061da546Spatrick 
34061da546Spatrick // Extract
extract(const DWARFDataExtractor & debug_aranges_data)35be691f3bSpatrick void DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
36061da546Spatrick   lldb::offset_t offset = 0;
37061da546Spatrick 
38061da546Spatrick   DWARFDebugArangeSet set;
39061da546Spatrick   Range range;
40061da546Spatrick   while (debug_aranges_data.ValidOffset(offset)) {
41be691f3bSpatrick     const lldb::offset_t set_offset = offset;
42be691f3bSpatrick     if (llvm::Error error = set.extract(debug_aranges_data, &offset)) {
43*f6aab3d8Srobert       Log *log = GetLog(DWARFLog::DebugInfo);
44be691f3bSpatrick       LLDB_LOG_ERROR(log, std::move(error),
45be691f3bSpatrick                      "DWARFDebugAranges::extract failed to extract "
46be691f3bSpatrick                      ".debug_aranges set at offset %#" PRIx64,
47be691f3bSpatrick                      set_offset);
48be691f3bSpatrick     } else {
49061da546Spatrick       const uint32_t num_descriptors = set.NumDescriptors();
50061da546Spatrick       if (num_descriptors > 0) {
51061da546Spatrick         const dw_offset_t cu_offset = set.GetHeader().cu_offset;
52061da546Spatrick 
53061da546Spatrick         for (uint32_t i = 0; i < num_descriptors; ++i) {
54061da546Spatrick           const DWARFDebugArangeSet::Descriptor &descriptor =
55061da546Spatrick               set.GetDescriptorRef(i);
56061da546Spatrick           m_aranges.Append(RangeToDIE::Entry(descriptor.address,
57061da546Spatrick                                              descriptor.length, cu_offset));
58061da546Spatrick         }
59061da546Spatrick       }
60be691f3bSpatrick     }
61be691f3bSpatrick     // Always use the previous DWARFDebugArangeSet's information to calculate
62be691f3bSpatrick     // the offset of the next DWARFDebugArangeSet in case we entouncter an
63be691f3bSpatrick     // error in the current DWARFDebugArangeSet and our offset position is
64be691f3bSpatrick     // still in the middle of the data. If we do this, we can parse all valid
65be691f3bSpatrick     // DWARFDebugArangeSet objects without returning invalid errors.
66be691f3bSpatrick     offset = set.GetNextOffset();
67061da546Spatrick     set.Clear();
68061da546Spatrick   }
69061da546Spatrick }
70061da546Spatrick 
Dump(Log * log) const71061da546Spatrick void DWARFDebugAranges::Dump(Log *log) const {
72061da546Spatrick   if (log == nullptr)
73061da546Spatrick     return;
74061da546Spatrick 
75061da546Spatrick   const size_t num_entries = m_aranges.GetSize();
76061da546Spatrick   for (size_t i = 0; i < num_entries; ++i) {
77061da546Spatrick     const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i);
78061da546Spatrick     if (entry)
79061da546Spatrick       LLDB_LOGF(log, "0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data,
80061da546Spatrick                 entry->GetRangeBase(), entry->GetRangeEnd());
81061da546Spatrick   }
82061da546Spatrick }
83061da546Spatrick 
AppendRange(dw_offset_t offset,dw_addr_t low_pc,dw_addr_t high_pc)84061da546Spatrick void DWARFDebugAranges::AppendRange(dw_offset_t offset, dw_addr_t low_pc,
85061da546Spatrick                                     dw_addr_t high_pc) {
86061da546Spatrick   if (high_pc > low_pc)
87061da546Spatrick     m_aranges.Append(RangeToDIE::Entry(low_pc, high_pc - low_pc, offset));
88061da546Spatrick }
89061da546Spatrick 
Sort(bool minimize)90061da546Spatrick void DWARFDebugAranges::Sort(bool minimize) {
91be691f3bSpatrick   LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
92061da546Spatrick                      static_cast<void *>(this));
93061da546Spatrick 
94061da546Spatrick   m_aranges.Sort();
95061da546Spatrick   m_aranges.CombineConsecutiveEntriesWithEqualData();
96061da546Spatrick }
97061da546Spatrick 
98061da546Spatrick // FindAddress
FindAddress(dw_addr_t address) const99061da546Spatrick dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const {
100061da546Spatrick   const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
101061da546Spatrick   if (entry)
102061da546Spatrick     return entry->data;
103061da546Spatrick   return DW_INVALID_OFFSET;
104061da546Spatrick }
105