Line data Source code
1 : //===- DWARFDebugRnglists.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/DWARFDebugRnglists.h"
11 : #include "llvm/BinaryFormat/Dwarf.h"
12 : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
13 : #include "llvm/Support/Errc.h"
14 : #include "llvm/Support/Error.h"
15 : #include "llvm/Support/Format.h"
16 : #include "llvm/Support/raw_ostream.h"
17 :
18 : using namespace llvm;
19 :
20 87 : Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
21 : uint32_t *OffsetPtr) {
22 87 : Offset = *OffsetPtr;
23 87 : SectionIndex = -1ULL;
24 : // The caller should guarantee that we have at least 1 byte available, so
25 : // we just assert instead of revalidate.
26 : assert(*OffsetPtr < End &&
27 : "not enough space to extract a rangelist encoding");
28 87 : uint8_t Encoding = Data.getU8(OffsetPtr);
29 :
30 87 : switch (Encoding) {
31 27 : case dwarf::DW_RLE_end_of_list:
32 27 : Value0 = Value1 = 0;
33 27 : break;
34 : // TODO: Support other encodings.
35 2 : case dwarf::DW_RLE_base_addressx:
36 : return createStringError(errc::not_supported,
37 : "unsupported rnglists encoding DW_RLE_base_addressx "
38 : "at offset 0x%" PRIx32,
39 4 : *OffsetPtr - 1);
40 2 : case dwarf::DW_RLE_startx_endx:
41 : return createStringError(errc::not_supported,
42 : "unsupported rnglists encoding DW_RLE_startx_endx at "
43 : "offset 0x%" PRIx32,
44 4 : *OffsetPtr - 1);
45 2 : case dwarf::DW_RLE_startx_length:
46 : return createStringError(errc::not_supported,
47 : "unsupported rnglists encoding DW_RLE_startx_length "
48 : "at offset 0x%" PRIx32,
49 4 : *OffsetPtr - 1);
50 17 : case dwarf::DW_RLE_offset_pair: {
51 17 : uint32_t PreviousOffset = *OffsetPtr - 1;
52 17 : Value0 = Data.getULEB128(OffsetPtr);
53 17 : Value1 = Data.getULEB128(OffsetPtr);
54 17 : if (End < *OffsetPtr)
55 : return createStringError(errc::invalid_argument,
56 : "read past end of table when reading "
57 : "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
58 0 : PreviousOffset);
59 17 : break;
60 : }
61 7 : case dwarf::DW_RLE_base_address: {
62 7 : if ((End - *OffsetPtr) < Data.getAddressSize())
63 : return createStringError(errc::invalid_argument,
64 : "insufficient space remaining in table for "
65 : "DW_RLE_base_address encoding at offset 0x%" PRIx32,
66 0 : *OffsetPtr - 1);
67 7 : Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
68 7 : break;
69 : }
70 14 : case dwarf::DW_RLE_start_end: {
71 14 : if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
72 : return createStringError(errc::invalid_argument,
73 : "insufficient space remaining in table for "
74 : "DW_RLE_start_end encoding "
75 : "at offset 0x%" PRIx32,
76 2 : *OffsetPtr - 1);
77 13 : Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
78 13 : Value1 = Data.getRelocatedAddress(OffsetPtr);
79 13 : break;
80 : }
81 15 : case dwarf::DW_RLE_start_length: {
82 15 : uint32_t PreviousOffset = *OffsetPtr - 1;
83 15 : Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
84 15 : Value1 = Data.getULEB128(OffsetPtr);
85 15 : if (End < *OffsetPtr)
86 : return createStringError(errc::invalid_argument,
87 : "read past end of table when reading "
88 : "DW_RLE_start_length encoding at offset 0x%" PRIx32,
89 1 : PreviousOffset);
90 14 : break;
91 : }
92 1 : default:
93 : return createStringError(errc::not_supported,
94 : "unknown rnglists encoding 0x%" PRIx32
95 : " at offset 0x%" PRIx32,
96 2 : uint32_t(Encoding), *OffsetPtr - 1);
97 : }
98 :
99 78 : EntryKind = Encoding;
100 : return Error::success();
101 : }
102 :
103 9 : DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
104 : llvm::Optional<BaseAddress> BaseAddr) const {
105 : DWARFAddressRangesVector Res;
106 29 : for (const RangeListEntry &RLE : Entries) {
107 29 : if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
108 : break;
109 20 : if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
110 4 : BaseAddr = {RLE.Value0, RLE.SectionIndex};
111 4 : continue;
112 : }
113 :
114 : DWARFAddressRange E;
115 16 : E.SectionIndex = RLE.SectionIndex;
116 16 : if (BaseAddr && E.SectionIndex == -1ULL)
117 8 : E.SectionIndex = BaseAddr->SectionIndex;
118 :
119 16 : switch (RLE.EntryKind) {
120 8 : case dwarf::DW_RLE_offset_pair:
121 8 : E.LowPC = RLE.Value0;
122 8 : E.HighPC = RLE.Value1;
123 8 : if (BaseAddr) {
124 8 : E.LowPC += BaseAddr->Address;
125 8 : E.HighPC += BaseAddr->Address;
126 : }
127 : break;
128 2 : case dwarf::DW_RLE_start_end:
129 2 : E.LowPC = RLE.Value0;
130 2 : E.HighPC = RLE.Value1;
131 2 : break;
132 6 : case dwarf::DW_RLE_start_length:
133 6 : E.LowPC = RLE.Value0;
134 6 : E.HighPC = E.LowPC + RLE.Value1;
135 6 : break;
136 0 : default:
137 : // Unsupported encodings should have been reported during extraction,
138 : // so we should not run into any here.
139 0 : llvm_unreachable("Unsupported range list encoding");
140 : }
141 16 : Res.push_back(E);
142 : }
143 9 : return Res;
144 : }
145 :
146 48 : void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
147 : uint8_t MaxEncodingStringLength,
148 : uint64_t &CurrentBase, DIDumpOptions DumpOpts) const {
149 : auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
150 : uint8_t AddrSize, DIDumpOptions DumpOpts) {
151 : if (DumpOpts.Verbose) {
152 : DumpOpts.DisplayRawContents = true;
153 : DWARFAddressRange(Entry.Value0, Entry.Value1)
154 : .dump(OS, AddrSize, DumpOpts);
155 : OS << " => ";
156 : }
157 : };
158 :
159 48 : if (DumpOpts.Verbose) {
160 : // Print the section offset in verbose mode.
161 58 : OS << format("0x%8.8" PRIx32 ":", Offset);
162 29 : auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
163 : // Unsupported encodings should have been reported during parsing.
164 : assert(!EncodingString.empty() && "Unknown range entry encoding");
165 29 : OS << format(" [%s%*c", EncodingString.data(),
166 87 : MaxEncodingStringLength - EncodingString.size() + 1, ']');
167 29 : if (EntryKind != dwarf::DW_RLE_end_of_list)
168 19 : OS << ": ";
169 : }
170 :
171 48 : switch (EntryKind) {
172 18 : case dwarf::DW_RLE_end_of_list:
173 26 : OS << (DumpOpts.Verbose ? "" : "<End of list>");
174 18 : break;
175 3 : case dwarf::DW_RLE_base_address:
176 : // In non-verbose mode we do not print anything for this entry.
177 3 : CurrentBase = Value0;
178 3 : if (!DumpOpts.Verbose)
179 1 : return;
180 4 : OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
181 2 : break;
182 8 : case dwarf::DW_RLE_start_length:
183 8 : PrintRawEntry(OS, *this, AddrSize, DumpOpts);
184 16 : DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
185 8 : break;
186 9 : case dwarf::DW_RLE_offset_pair:
187 9 : PrintRawEntry(OS, *this, AddrSize, DumpOpts);
188 9 : DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
189 9 : .dump(OS, AddrSize, DumpOpts);
190 9 : break;
191 10 : case dwarf::DW_RLE_start_end:
192 20 : DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
193 10 : break;
194 0 : default:
195 0 : llvm_unreachable("Unsupported range list encoding");
196 : }
197 47 : OS << "\n";
198 : }
|