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 DWARFAddressRange::dump(raw_ostream &OS, uint32_t AddressSize) const {
21 
22   OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, LowPC)
23      << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, HighPC);
24 }
25 
26 raw_ostream &llvm::operator<<(raw_ostream &OS, const DWARFAddressRange &R) {
27   R.dump(OS, /* AddressSize */ 8);
28   return OS;
29 }
30 
31 void DWARFDebugRangeList::clear() {
32   Offset = -1U;
33   AddressSize = 0;
34   Entries.clear();
35 }
36 
37 bool DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
38                                   uint32_t *offset_ptr) {
39   clear();
40   if (!data.isValidOffset(*offset_ptr))
41     return false;
42   AddressSize = data.getAddressSize();
43   if (AddressSize != 4 && AddressSize != 8)
44     return false;
45   Offset = *offset_ptr;
46   while (true) {
47     RangeListEntry Entry;
48     Entry.SectionIndex = -1ULL;
49 
50     uint32_t prev_offset = *offset_ptr;
51     Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
52     Entry.EndAddress =
53         data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
54 
55     // Check that both values were extracted correctly.
56     if (*offset_ptr != prev_offset + 2 * AddressSize) {
57       clear();
58       return false;
59     }
60     if (Entry.isEndOfListEntry())
61       break;
62     Entries.push_back(Entry);
63   }
64   return true;
65 }
66 
67 void DWARFDebugRangeList::dump(raw_ostream &OS) const {
68   for (const RangeListEntry &RLE : Entries) {
69     const char *format_str = (AddressSize == 4
70                               ? "%08x %08"  PRIx64 " %08"  PRIx64 "\n"
71                               : "%08x %016" PRIx64 " %016" PRIx64 "\n");
72     OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
73   }
74   OS << format("%08x <End of list>\n", Offset);
75 }
76 
77 DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
78     llvm::Optional<BaseAddress> BaseAddr) const {
79   DWARFAddressRangesVector Res;
80   for (const RangeListEntry &RLE : Entries) {
81     if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
82       BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
83       continue;
84     }
85 
86     DWARFAddressRange E;
87     E.LowPC = RLE.StartAddress;
88     E.HighPC = RLE.EndAddress;
89     E.SectionIndex = RLE.SectionIndex;
90     // Base address of a range list entry is determined by the closest preceding
91     // base address selection entry in the same range list. It defaults to the
92     // base address of the compilation unit if there is no such entry.
93     if (BaseAddr) {
94       E.LowPC += BaseAddr->Address;
95       E.HighPC += BaseAddr->Address;
96       if (E.SectionIndex == -1ULL)
97         E.SectionIndex = BaseAddr->SectionIndex;
98     }
99     Res.push_back(E);
100   }
101   return Res;
102 }
103