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