]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
Merge ^/head r327150 through r327164.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / DWARF / DWARFDebugLoc.cpp
1 //===- DWARFDebugLoc.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/DWARFDebugLoc.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
15 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
16 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <algorithm>
21 #include <cinttypes>
22 #include <cstdint>
23
24 using namespace llvm;
25
26 // When directly dumping the .debug_loc without a compile unit, we have to guess
27 // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
28 // expression that LLVM doesn't produce. Guessing the wrong version means we
29 // won't be able to pretty print expressions in DWARF2 binaries produced by
30 // non-LLVM tools.
31 static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
32                            bool IsLittleEndian, unsigned AddressSize,
33                            const MCRegisterInfo *MRI) {
34   DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
35                                IsLittleEndian, AddressSize);
36   DWARFExpression(Extractor, AddressSize, dwarf::DWARF_VERSION).print(OS, MRI);
37 }
38
39 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
40                                        unsigned AddressSize,
41                                        const MCRegisterInfo *MRI,
42                                        unsigned Indent) const {
43   for (const Entry &E : Entries) {
44     OS << '\n';
45     OS.indent(Indent);
46     OS << format("0x%016" PRIx64, E.Begin) << " - "
47        << format("0x%016" PRIx64, E.End) << ": ";
48
49     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
50   }
51 }
52
53 DWARFDebugLoc::LocationList const *
54 DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
55   auto It = std::lower_bound(
56       Locations.begin(), Locations.end(), Offset,
57       [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
58   if (It != Locations.end() && It->Offset == Offset)
59     return &(*It);
60   return nullptr;
61 }
62
63 void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
64                          Optional<uint64_t> Offset) const {
65   auto DumpLocationList = [&](const LocationList &L) {
66     OS << format("0x%8.8x: ", L.Offset);
67     L.dump(OS, IsLittleEndian, AddressSize, MRI, 12);
68     OS << "\n\n";
69   };
70
71   if (Offset) {
72     if (auto *L = getLocationListAtOffset(*Offset))
73       DumpLocationList(*L);
74     return;
75   }
76
77   for (const LocationList &L : Locations) {
78     DumpLocationList(L);
79   }
80 }
81
82 Optional<DWARFDebugLoc::LocationList>
83 DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
84   LocationList LL;
85   LL.Offset = *Offset;
86
87   // 2.6.2 Location Lists
88   // A location list entry consists of:
89   while (true) {
90     Entry E;
91     if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
92       llvm::errs() << "Location list overflows the debug_loc section.\n";
93       return None;
94     }
95
96     // 1. A beginning address offset. ...
97     E.Begin = Data.getRelocatedAddress(Offset);
98
99     // 2. An ending address offset. ...
100     E.End = Data.getRelocatedAddress(Offset);
101
102     // The end of any given location list is marked by an end of list entry,
103     // which consists of a 0 for the beginning address offset and a 0 for the
104     // ending address offset.
105     if (E.Begin == 0 && E.End == 0)
106       return LL;
107
108     if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
109       llvm::errs() << "Location list overflows the debug_loc section.\n";
110       return None;
111     }
112
113     unsigned Bytes = Data.getU16(Offset);
114     if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
115       llvm::errs() << "Location list overflows the debug_loc section.\n";
116       return None;
117     }
118     // A single location description describing the location of the object...
119     StringRef str = Data.getData().substr(*Offset, Bytes);
120     *Offset += Bytes;
121     E.Loc.reserve(str.size());
122     std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
123     LL.Entries.push_back(std::move(E));
124   }
125 }
126
127 void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
128   IsLittleEndian = data.isLittleEndian();
129   AddressSize = data.getAddressSize();
130
131   uint32_t Offset = 0;
132   while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
133     if (auto LL = parseOneLocationList(data, &Offset))
134       Locations.push_back(std::move(*LL));
135     else
136       break;
137   }
138   if (data.isValidOffset(Offset))
139     errs() << "error: failed to consume entire .debug_loc section\n";
140 }
141
142 Optional<DWARFDebugLocDWO::LocationList>
143 DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
144   LocationList LL;
145   LL.Offset = *Offset;
146
147   // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
148   while (auto Kind =
149              static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
150     if (Kind != dwarf::DW_LLE_startx_length) {
151       llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
152                    << " not implemented\n";
153       return None;
154     }
155
156     Entry E;
157     E.Start = Data.getULEB128(Offset);
158     E.Length = Data.getU32(Offset);
159
160     unsigned Bytes = Data.getU16(Offset);
161     // A single location description describing the location of the object...
162     StringRef str = Data.getData().substr(*Offset, Bytes);
163     *Offset += Bytes;
164     E.Loc.resize(str.size());
165     std::copy(str.begin(), str.end(), E.Loc.begin());
166
167     LL.Entries.push_back(std::move(E));
168   }
169   return LL;
170 }
171
172 void DWARFDebugLocDWO::parse(DataExtractor data) {
173   IsLittleEndian = data.isLittleEndian();
174   AddressSize = data.getAddressSize();
175
176   uint32_t Offset = 0;
177   while (data.isValidOffset(Offset)) {
178     if (auto LL = parseOneLocationList(data, &Offset))
179       Locations.push_back(std::move(*LL));
180     else
181       return;
182   }
183 }
184
185 DWARFDebugLocDWO::LocationList const *
186 DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const {
187   auto It = std::lower_bound(
188       Locations.begin(), Locations.end(), Offset,
189       [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
190   if (It != Locations.end() && It->Offset == Offset)
191     return &(*It);
192   return nullptr;
193 }
194
195 void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
196                                           unsigned AddressSize,
197                                           const MCRegisterInfo *MRI,
198                                           unsigned Indent) const {
199   for (const Entry &E : Entries) {
200     OS << '\n';
201     OS.indent(Indent);
202     OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
203     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
204   }
205 }
206
207 void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
208                             Optional<uint64_t> Offset) const {
209   auto DumpLocationList = [&](const LocationList &L) {
210     OS << format("0x%8.8x: ", L.Offset);
211     L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
212     OS << "\n\n";
213   };
214
215   if (Offset) {
216     if (auto *L = getLocationListAtOffset(*Offset))
217       DumpLocationList(*L);
218     return;
219   }
220
221   for (const LocationList &L : Locations) {
222     DumpLocationList(L);
223   }
224 }