]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / DWARF / DWARFDebugRnglists.cpp
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 Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
21                               uint32_t *OffsetPtr) {
22   Offset = *OffsetPtr;
23   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   uint8_t Encoding = Data.getU8(OffsetPtr);
29
30   switch (Encoding) {
31   case dwarf::DW_RLE_end_of_list:
32     Value0 = Value1 = 0;
33     break;
34   // TODO: Support other encodings.
35   case dwarf::DW_RLE_base_addressx: {
36     uint32_t PreviousOffset = *OffsetPtr - 1;
37     Value0 = Data.getULEB128(OffsetPtr);
38     if (End < *OffsetPtr)
39       return createStringError(
40           errc::invalid_argument,
41           "read past end of table when reading "
42           "DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
43           PreviousOffset);
44     break;
45   }
46   case dwarf::DW_RLE_startx_endx:
47     return createStringError(errc::not_supported,
48                        "unsupported rnglists encoding DW_RLE_startx_endx at "
49                        "offset 0x%" PRIx32,
50                        *OffsetPtr - 1);
51   case dwarf::DW_RLE_startx_length: {
52     uint32_t PreviousOffset = *OffsetPtr - 1;
53     Value0 = Data.getULEB128(OffsetPtr);
54     Value1 = Data.getULEB128(OffsetPtr);
55     if (End < *OffsetPtr)
56       return createStringError(
57           errc::invalid_argument,
58           "read past end of table when reading "
59           "DW_RLE_startx_length encoding at offset 0x%" PRIx32,
60           PreviousOffset);
61     break;
62   }
63   case dwarf::DW_RLE_offset_pair: {
64     uint32_t PreviousOffset = *OffsetPtr - 1;
65     Value0 = Data.getULEB128(OffsetPtr);
66     Value1 = Data.getULEB128(OffsetPtr);
67     if (End < *OffsetPtr)
68       return createStringError(errc::invalid_argument,
69                          "read past end of table when reading "
70                          "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
71                          PreviousOffset);
72     break;
73   }
74   case dwarf::DW_RLE_base_address: {
75     if ((End - *OffsetPtr) < Data.getAddressSize())
76       return createStringError(errc::invalid_argument,
77                          "insufficient space remaining in table for "
78                          "DW_RLE_base_address encoding at offset 0x%" PRIx32,
79                          *OffsetPtr - 1);
80     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
81     break;
82   }
83   case dwarf::DW_RLE_start_end: {
84     if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
85       return createStringError(errc::invalid_argument,
86                          "insufficient space remaining in table for "
87                          "DW_RLE_start_end encoding "
88                          "at offset 0x%" PRIx32,
89                          *OffsetPtr - 1);
90     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
91     Value1 = Data.getRelocatedAddress(OffsetPtr);
92     break;
93   }
94   case dwarf::DW_RLE_start_length: {
95     uint32_t PreviousOffset = *OffsetPtr - 1;
96     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
97     Value1 = Data.getULEB128(OffsetPtr);
98     if (End < *OffsetPtr)
99       return createStringError(errc::invalid_argument,
100                          "read past end of table when reading "
101                          "DW_RLE_start_length encoding at offset 0x%" PRIx32,
102                          PreviousOffset);
103     break;
104   }
105   default:
106     return createStringError(errc::not_supported,
107                        "unknown rnglists encoding 0x%" PRIx32
108                        " at offset 0x%" PRIx32,
109                        uint32_t(Encoding), *OffsetPtr - 1);
110   }
111
112   EntryKind = Encoding;
113   return Error::success();
114 }
115
116 DWARFAddressRangesVector
117 DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
118                                      DWARFUnit &U) const {
119   DWARFAddressRangesVector Res;
120   for (const RangeListEntry &RLE : Entries) {
121     if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
122       break;
123     if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
124       BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
125       if (!BaseAddr)
126         BaseAddr = {RLE.Value0, -1ULL};
127       continue;
128     }
129     if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
130       BaseAddr = {RLE.Value0, RLE.SectionIndex};
131       continue;
132     }
133
134     DWARFAddressRange E;
135     E.SectionIndex = RLE.SectionIndex;
136     if (BaseAddr && E.SectionIndex == -1ULL)
137       E.SectionIndex = BaseAddr->SectionIndex;
138
139     switch (RLE.EntryKind) {
140     case dwarf::DW_RLE_offset_pair:
141       E.LowPC = RLE.Value0;
142       E.HighPC = RLE.Value1;
143       if (BaseAddr) {
144         E.LowPC += BaseAddr->Address;
145         E.HighPC += BaseAddr->Address;
146       }
147       break;
148     case dwarf::DW_RLE_start_end:
149       E.LowPC = RLE.Value0;
150       E.HighPC = RLE.Value1;
151       break;
152     case dwarf::DW_RLE_start_length:
153       E.LowPC = RLE.Value0;
154       E.HighPC = E.LowPC + RLE.Value1;
155       break;
156     case dwarf::DW_RLE_startx_length: {
157       auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
158       if (!Start)
159         Start = {0, -1ULL};
160       E.SectionIndex = Start->SectionIndex;
161       E.LowPC = Start->Address;
162       E.HighPC = E.LowPC + RLE.Value1;
163       break;
164     }
165     default:
166       // Unsupported encodings should have been reported during extraction,
167       // so we should not run into any here.
168       llvm_unreachable("Unsupported range list encoding");
169     }
170     Res.push_back(E);
171   }
172   return Res;
173 }
174
175 void RangeListEntry::dump(
176     raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
177     uint64_t &CurrentBase, DIDumpOptions DumpOpts,
178     llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
179         LookupPooledAddress) const {
180   auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
181                           uint8_t AddrSize, DIDumpOptions DumpOpts) {
182     if (DumpOpts.Verbose) {
183       DumpOpts.DisplayRawContents = true;
184       DWARFAddressRange(Entry.Value0, Entry.Value1)
185           .dump(OS, AddrSize, DumpOpts);
186       OS << " => ";
187     }
188   };
189
190   if (DumpOpts.Verbose) {
191     // Print the section offset in verbose mode.
192     OS << format("0x%8.8" PRIx32 ":", Offset);
193     auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
194     // Unsupported encodings should have been reported during parsing.
195     assert(!EncodingString.empty() && "Unknown range entry encoding");
196     OS << format(" [%s%*c", EncodingString.data(),
197                  MaxEncodingStringLength - EncodingString.size() + 1, ']');
198     if (EntryKind != dwarf::DW_RLE_end_of_list)
199       OS << ": ";
200   }
201
202   switch (EntryKind) {
203   case dwarf::DW_RLE_end_of_list:
204     OS << (DumpOpts.Verbose ? "" : "<End of list>");
205     break;
206     //  case dwarf::DW_RLE_base_addressx:
207   case dwarf::DW_RLE_base_addressx: {
208     if (auto SA = LookupPooledAddress(Value0))
209       CurrentBase = SA->Address;
210     else
211       CurrentBase = Value0;
212     if (!DumpOpts.Verbose)
213       return;
214     OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
215     break;
216   }
217   case dwarf::DW_RLE_base_address:
218     // In non-verbose mode we do not print anything for this entry.
219     CurrentBase = Value0;
220     if (!DumpOpts.Verbose)
221       return;
222     OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
223     break;
224   case dwarf::DW_RLE_start_length:
225     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
226     DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
227     break;
228   case dwarf::DW_RLE_offset_pair:
229     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
230     DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
231         .dump(OS, AddrSize, DumpOpts);
232     break;
233   case dwarf::DW_RLE_start_end:
234     DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
235     break;
236   case dwarf::DW_RLE_startx_length: {
237     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
238     uint64_t Start = 0;
239     if (auto SA = LookupPooledAddress(Value0))
240       Start = SA->Address;
241     DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
242     break;
243   } break;
244   default:
245     llvm_unreachable("Unsupported range list encoding");
246   }
247   OS << "\n";
248 }