1 //===- DWARFDebugRangesList.cpp -------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include <cinttypes>
15 #include <cstdint>
16 #include <utility>
17 
18 using namespace llvm;
19 
20 void DWARFDebugRangeList::clear() {
21   Offset = -1U;
22   AddressSize = 0;
23   Entries.clear();
24 }
25 
26 bool DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
27                                   uint32_t *offset_ptr) {
28   clear();
29   if (!data.isValidOffset(*offset_ptr))
30     return false;
31   AddressSize = data.getAddressSize();
32   if (AddressSize != 4 && AddressSize != 8)
33     return false;
34   Offset = *offset_ptr;
35   while (true) {
36     RangeListEntry Entry;
37     Entry.SectionIndex = -1ULL;
38 
39     uint32_t prev_offset = *offset_ptr;
40     Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
41     Entry.EndAddress =
42         data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
43 
44     // Check that both values were extracted correctly.
45     if (*offset_ptr != prev_offset + 2 * AddressSize) {
46       clear();
47       return false;
48     }
49     if (Entry.isEndOfListEntry())
50       break;
51     Entries.push_back(Entry);
52   }
53   return true;
54 }
55 
56 void DWARFDebugRangeList::dump(raw_ostream &OS) const {
57   for (const RangeListEntry &RLE : Entries) {
58     const char *format_str = (AddressSize == 4
59                               ? "%08x %08"  PRIx64 " %08"  PRIx64 "\n"
60                               : "%08x %016" PRIx64 " %016" PRIx64 "\n");
61     OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
62   }
63   OS << format("%08x <End of list>\n", Offset);
64 }
65 
66 DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
67     llvm::Optional<BaseAddress> BaseAddr) const {
68   DWARFAddressRangesVector Res;
69   for (const RangeListEntry &RLE : Entries) {
70     if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
71       BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
72       continue;
73     }
74 
75     DWARFAddressRange E;
76     E.LowPC = RLE.StartAddress;
77     E.HighPC = RLE.EndAddress;
78     E.SectionIndex = RLE.SectionIndex;
79     // Base address of a range list entry is determined by the closest preceding
80     // base address selection entry in the same range list. It defaults to the
81     // base address of the compilation unit if there is no such entry.
82     if (BaseAddr) {
83       E.LowPC += BaseAddr->Address;
84       E.HighPC += BaseAddr->Address;
85       if (E.SectionIndex == -1ULL)
86         E.SectionIndex = BaseAddr->SectionIndex;
87     }
88     Res.push_back(E);
89   }
90   return Res;
91 }
92