180814287SRaphael Isemann //===-- DWARFDebugAranges.cpp ---------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
930fdc8d8SChris Lattner #include "DWARFDebugAranges.h"
10fe79fbc9SPavel Labath #include "DWARFDebugArangeSet.h"
11c4d65751SJan Kratochvil #include "DWARFUnit.h"
12eee30906SGreg Clayton #include "LogChannelDWARF.h"
13fe79fbc9SPavel Labath #include "lldb/Utility/Log.h"
14fe79fbc9SPavel Labath #include "lldb/Utility/Timer.h"
1530fdc8d8SChris Lattner
1621f2a491SGreg Clayton using namespace lldb;
1730fdc8d8SChris Lattner using namespace lldb_private;
1830fdc8d8SChris Lattner
1930fdc8d8SChris Lattner // Constructor
DWARFDebugAranges()20b9c1b51eSKate Stone DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {}
2130fdc8d8SChris Lattner
2230fdc8d8SChris Lattner // CountArangeDescriptors
23b9c1b51eSKate Stone class CountArangeDescriptors {
2430fdc8d8SChris Lattner public:
CountArangeDescriptors(uint32_t & count_ref)25b9c1b51eSKate Stone CountArangeDescriptors(uint32_t &count_ref) : count(count_ref) {
2630fdc8d8SChris Lattner // printf("constructor CountArangeDescriptors()\n");
2730fdc8d8SChris Lattner }
operator ()(const DWARFDebugArangeSet & set)28b9c1b51eSKate Stone void operator()(const DWARFDebugArangeSet &set) {
2930fdc8d8SChris Lattner count += set.NumDescriptors();
3030fdc8d8SChris Lattner }
3130fdc8d8SChris Lattner uint32_t &count;
3230fdc8d8SChris Lattner };
3330fdc8d8SChris Lattner
3430fdc8d8SChris Lattner // Extract
extract(const DWARFDataExtractor & debug_aranges_data)35eee30906SGreg Clayton void DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
36c7bece56SGreg Clayton lldb::offset_t offset = 0;
3730fdc8d8SChris Lattner
3830fdc8d8SChris Lattner DWARFDebugArangeSet set;
3930fdc8d8SChris Lattner Range range;
401cbbab92SZachary Turner while (debug_aranges_data.ValidOffset(offset)) {
41eee30906SGreg Clayton const lldb::offset_t set_offset = offset;
42eee30906SGreg Clayton if (llvm::Error error = set.extract(debug_aranges_data, &offset)) {
43*2d75f627SPavel Labath Log *log = GetLog(DWARFLog::DebugInfo);
44eee30906SGreg Clayton LLDB_LOG_ERROR(log, std::move(error),
45eee30906SGreg Clayton "DWARFDebugAranges::extract failed to extract "
46eee30906SGreg Clayton ".debug_aranges set at offset %#" PRIx64,
47eee30906SGreg Clayton set_offset);
48eee30906SGreg Clayton } else {
49c26e4454SGreg Clayton const uint32_t num_descriptors = set.NumDescriptors();
50b9c1b51eSKate Stone if (num_descriptors > 0) {
51611d1f98SZachary Turner const dw_offset_t cu_offset = set.GetHeader().cu_offset;
5230fdc8d8SChris Lattner
53b9c1b51eSKate Stone for (uint32_t i = 0; i < num_descriptors; ++i) {
54b9c1b51eSKate Stone const DWARFDebugArangeSet::Descriptor &descriptor =
55b9c1b51eSKate Stone set.GetDescriptorRef(i);
56b9c1b51eSKate Stone m_aranges.Append(RangeToDIE::Entry(descriptor.address,
57b9c1b51eSKate Stone descriptor.length, cu_offset));
58c26e4454SGreg Clayton }
59c26e4454SGreg Clayton }
60eee30906SGreg Clayton }
61eee30906SGreg Clayton // Always use the previous DWARFDebugArangeSet's information to calculate
62eee30906SGreg Clayton // the offset of the next DWARFDebugArangeSet in case we entouncter an
63eee30906SGreg Clayton // error in the current DWARFDebugArangeSet and our offset position is
64eee30906SGreg Clayton // still in the middle of the data. If we do this, we can parse all valid
65eee30906SGreg Clayton // DWARFDebugArangeSet objects without returning invalid errors.
66eee30906SGreg Clayton offset = set.GetNextOffset();
67c26e4454SGreg Clayton set.Clear();
68c26e4454SGreg Clayton }
6930fdc8d8SChris Lattner }
7030fdc8d8SChris Lattner
Dump(Log * log) const71b9c1b51eSKate Stone void DWARFDebugAranges::Dump(Log *log) const {
72248a1305SKonrad Kleine if (log == nullptr)
73d4a2b370SGreg Clayton return;
74c26e4454SGreg Clayton
75ea3e7d5cSGreg Clayton const size_t num_entries = m_aranges.GetSize();
76b9c1b51eSKate Stone for (size_t i = 0; i < num_entries; ++i) {
77c26e4454SGreg Clayton const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i);
7828eb5711SJim Ingham if (entry)
7963e5fb76SJonas Devlieghere LLDB_LOGF(log, "0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data,
80b9c1b51eSKate Stone entry->GetRangeBase(), entry->GetRangeEnd());
81d4a2b370SGreg Clayton }
8230fdc8d8SChris Lattner }
8330fdc8d8SChris Lattner
AppendRange(dw_offset_t offset,dw_addr_t low_pc,dw_addr_t high_pc)84b9c1b51eSKate Stone void DWARFDebugAranges::AppendRange(dw_offset_t offset, dw_addr_t low_pc,
85b9c1b51eSKate Stone dw_addr_t high_pc) {
86c26e4454SGreg Clayton if (high_pc > low_pc)
87c26e4454SGreg Clayton m_aranges.Append(RangeToDIE::Entry(low_pc, high_pc - low_pc, offset));
88016a95ebSGreg Clayton }
89016a95ebSGreg Clayton
Sort(bool minimize)90b9c1b51eSKate Stone void DWARFDebugAranges::Sort(bool minimize) {
915c1c8443SJonas Devlieghere LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
92b9c1b51eSKate Stone static_cast<void *>(this));
93d2ddabacSJohnny Chen
94c26e4454SGreg Clayton m_aranges.Sort();
95c26e4454SGreg Clayton m_aranges.CombineConsecutiveEntriesWithEqualData();
96016a95ebSGreg Clayton }
97016a95ebSGreg Clayton
9830fdc8d8SChris Lattner // FindAddress
FindAddress(dw_addr_t address) const99b9c1b51eSKate Stone dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const {
100c26e4454SGreg Clayton const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
101c26e4454SGreg Clayton if (entry)
102c26e4454SGreg Clayton return entry->data;
10330fdc8d8SChris Lattner return DW_INVALID_OFFSET;
10430fdc8d8SChris Lattner }
105