1 //===-- DWARFDebugAranges.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 "DWARFDebugAranges.h"
10 
11 #include <assert.h>
12 #include <stdio.h>
13 
14 #include <algorithm>
15 
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/Timer.h"
19 
20 #include "DWARFUnit.h"
21 #include "DWARFDebugInfo.h"
22 #include "SymbolFileDWARF.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 // Constructor
28 DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {}
29 
30 // CountArangeDescriptors
31 class CountArangeDescriptors {
32 public:
33   CountArangeDescriptors(uint32_t &count_ref) : count(count_ref) {
34     //      printf("constructor CountArangeDescriptors()\n");
35   }
36   void operator()(const DWARFDebugArangeSet &set) {
37     count += set.NumDescriptors();
38   }
39   uint32_t &count;
40 };
41 
42 // Extract
43 llvm::Error
44 DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
45   assert(debug_aranges_data.ValidOffset(0));
46 
47   lldb::offset_t offset = 0;
48 
49   DWARFDebugArangeSet set;
50   Range range;
51   while (debug_aranges_data.ValidOffset(offset)) {
52     llvm::Error error = set.extract(debug_aranges_data, &offset);
53     if (!error)
54       return error;
55 
56     const uint32_t num_descriptors = set.NumDescriptors();
57     if (num_descriptors > 0) {
58       const dw_offset_t cu_offset = set.GetHeader().cu_offset;
59 
60       for (uint32_t i = 0; i < num_descriptors; ++i) {
61         const DWARFDebugArangeSet::Descriptor &descriptor =
62             set.GetDescriptorRef(i);
63         m_aranges.Append(RangeToDIE::Entry(descriptor.address,
64                                            descriptor.length, cu_offset));
65       }
66     }
67     set.Clear();
68     }
69     return llvm::ErrorSuccess();
70 }
71 
72 void DWARFDebugAranges::Dump(Log *log) const {
73   if (log == NULL)
74     return;
75 
76   const size_t num_entries = m_aranges.GetSize();
77   for (size_t i = 0; i < num_entries; ++i) {
78     const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i);
79     if (entry)
80       log->Printf("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data,
81                   entry->GetRangeBase(), entry->GetRangeEnd());
82   }
83 }
84 
85 void DWARFDebugAranges::AppendRange(dw_offset_t offset, dw_addr_t low_pc,
86                                     dw_addr_t high_pc) {
87   if (high_pc > low_pc)
88     m_aranges.Append(RangeToDIE::Entry(low_pc, high_pc - low_pc, offset));
89 }
90 
91 void DWARFDebugAranges::Sort(bool minimize) {
92   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
93   Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
94                      static_cast<void *>(this));
95 
96   m_aranges.Sort();
97   m_aranges.CombineConsecutiveEntriesWithEqualData();
98 }
99 
100 // FindAddress
101 dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const {
102   const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
103   if (entry)
104     return entry->data;
105   return DW_INVALID_OFFSET;
106 }
107