blob: 90f3b45af377b618b272e1d490063e32014b9a6d [file] [log] [blame]
Eugene Zelenko28db7e62017-03-01 01:14:23 +00001//===- DWARFDebugLoc.cpp --------------------------------------------------===//
David Blaikie18e73502013-06-19 21:37:13 +00002//
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
Chandler Carruth6bda14b2017-06-06 11:49:48 +000010#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
Eugene Zelenko28db7e62017-03-01 01:14:23 +000011#include "llvm/ADT/StringRef.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000012#include "llvm/BinaryFormat/Dwarf.h"
George Rimarf8a96422017-04-21 09:12:18 +000013#include "llvm/DebugInfo/DWARF/DWARFContext.h"
Reid Klecknera0587362017-08-29 21:41:21 +000014#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
Eugene Zelenko28db7e62017-03-01 01:14:23 +000015#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
Reid Klecknera0587362017-08-29 21:41:21 +000016#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
17#include "llvm/Support/Compiler.h"
David Blaikie18e73502013-06-19 21:37:13 +000018#include "llvm/Support/Format.h"
19#include "llvm/Support/raw_ostream.h"
Eugene Zelenko28db7e62017-03-01 01:14:23 +000020#include <algorithm>
21#include <cinttypes>
22#include <cstdint>
David Blaikie18e73502013-06-19 21:37:13 +000023
24using namespace llvm;
25
Reid Klecknera0587362017-08-29 21:41:21 +000026// 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.
31static 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);
Pavel Labath54ca2d62018-04-06 08:49:57 +000036 DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI);
Reid Klecknera0587362017-08-29 21:41:21 +000037}
38
39void 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);
Jonas Devlieghere6f24c872018-01-16 11:17:57 +000046 OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
47 E.Begin)
48 << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, E.End);
49 OS << ": ";
Reid Klecknera0587362017-08-29 21:41:21 +000050
51 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
52 }
53}
54
Jonas Devlieghere622c5632017-09-27 09:33:36 +000055DWARFDebugLoc::LocationList const *
56DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
57 auto It = std::lower_bound(
58 Locations.begin(), Locations.end(), Offset,
59 [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
60 if (It != Locations.end() && It->Offset == Offset)
61 return &(*It);
62 return nullptr;
63}
64
65void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
66 Optional<uint64_t> Offset) const {
67 auto DumpLocationList = [&](const LocationList &L) {
Alexey Samsonov1eabf982014-03-13 07:52:54 +000068 OS << format("0x%8.8x: ", L.Offset);
Reid Klecknera0587362017-08-29 21:41:21 +000069 L.dump(OS, IsLittleEndian, AddressSize, MRI, 12);
70 OS << "\n\n";
Jonas Devlieghere622c5632017-09-27 09:33:36 +000071 };
72
73 if (Offset) {
74 if (auto *L = getLocationListAtOffset(*Offset))
75 DumpLocationList(*L);
76 return;
77 }
78
79 for (const LocationList &L : Locations) {
80 DumpLocationList(L);
Reid Klecknera0587362017-08-29 21:41:21 +000081 }
82}
83
84Optional<DWARFDebugLoc::LocationList>
85DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
86 LocationList LL;
87 LL.Offset = *Offset;
88
89 // 2.6.2 Location Lists
90 // A location list entry consists of:
91 while (true) {
92 Entry E;
93 if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
94 llvm::errs() << "Location list overflows the debug_loc section.\n";
95 return None;
David Blaikie18e73502013-06-19 21:37:13 +000096 }
Reid Klecknera0587362017-08-29 21:41:21 +000097
98 // 1. A beginning address offset. ...
99 E.Begin = Data.getRelocatedAddress(Offset);
100
101 // 2. An ending address offset. ...
102 E.End = Data.getRelocatedAddress(Offset);
103
104 // The end of any given location list is marked by an end of list entry,
105 // which consists of a 0 for the beginning address offset and a 0 for the
106 // ending address offset.
107 if (E.Begin == 0 && E.End == 0)
108 return LL;
109
110 if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
111 llvm::errs() << "Location list overflows the debug_loc section.\n";
112 return None;
113 }
114
115 unsigned Bytes = Data.getU16(Offset);
116 if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
117 llvm::errs() << "Location list overflows the debug_loc section.\n";
118 return None;
119 }
120 // A single location description describing the location of the object...
121 StringRef str = Data.getData().substr(*Offset, Bytes);
122 *Offset += Bytes;
123 E.Loc.reserve(str.size());
124 std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
125 LL.Entries.push_back(std::move(E));
David Blaikie18e73502013-06-19 21:37:13 +0000126 }
127}
128
Paul Robinson17536b92017-06-29 16:52:08 +0000129void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
Reid Klecknera0587362017-08-29 21:41:21 +0000130 IsLittleEndian = data.isLittleEndian();
131 AddressSize = data.getAddressSize();
132
David Blaikie18e73502013-06-19 21:37:13 +0000133 uint32_t Offset = 0;
Reid Klecknera0587362017-08-29 21:41:21 +0000134 while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
135 if (auto LL = parseOneLocationList(data, &Offset))
136 Locations.push_back(std::move(*LL));
137 else
138 break;
David Blaikie18e73502013-06-19 21:37:13 +0000139 }
Adrian Prantl6f84d312014-02-11 21:22:53 +0000140 if (data.isValidOffset(Offset))
Eugene Zelenko28db7e62017-03-01 01:14:23 +0000141 errs() << "error: failed to consume entire .debug_loc section\n";
David Blaikie18e73502013-06-19 21:37:13 +0000142}
David Blaikie9c550ac2014-03-25 01:44:02 +0000143
Reid Klecknera0587362017-08-29 21:41:21 +0000144Optional<DWARFDebugLocDWO::LocationList>
145DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
146 LocationList LL;
147 LL.Offset = *Offset;
148
149 // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
150 while (auto Kind =
151 static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
152 if (Kind != dwarf::DW_LLE_startx_length) {
153 llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
154 << " not implemented\n";
155 return None;
156 }
157
158 Entry E;
159 E.Start = Data.getULEB128(Offset);
160 E.Length = Data.getU32(Offset);
161
162 unsigned Bytes = Data.getU16(Offset);
163 // A single location description describing the location of the object...
164 StringRef str = Data.getData().substr(*Offset, Bytes);
165 *Offset += Bytes;
166 E.Loc.resize(str.size());
167 std::copy(str.begin(), str.end(), E.Loc.begin());
168
169 LL.Entries.push_back(std::move(E));
170 }
171 return LL;
172}
173
David Blaikie9c550ac2014-03-25 01:44:02 +0000174void DWARFDebugLocDWO::parse(DataExtractor data) {
Reid Klecknera0587362017-08-29 21:41:21 +0000175 IsLittleEndian = data.isLittleEndian();
176 AddressSize = data.getAddressSize();
177
David Blaikie9c550ac2014-03-25 01:44:02 +0000178 uint32_t Offset = 0;
179 while (data.isValidOffset(Offset)) {
Reid Klecknera0587362017-08-29 21:41:21 +0000180 if (auto LL = parseOneLocationList(data, &Offset))
181 Locations.push_back(std::move(*LL));
182 else
183 return;
David Blaikie9c550ac2014-03-25 01:44:02 +0000184 }
185}
186
Jonas Devlieghere622c5632017-09-27 09:33:36 +0000187DWARFDebugLocDWO::LocationList const *
188DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const {
189 auto It = std::lower_bound(
190 Locations.begin(), Locations.end(), Offset,
191 [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
192 if (It != Locations.end() && It->Offset == Offset)
193 return &(*It);
194 return nullptr;
195}
196
Reid Klecknera0587362017-08-29 21:41:21 +0000197void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
198 unsigned AddressSize,
199 const MCRegisterInfo *MRI,
200 unsigned Indent) const {
201 for (const Entry &E : Entries) {
202 OS << '\n';
203 OS.indent(Indent);
204 OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
205 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
206 }
207}
208
Jonas Devlieghere622c5632017-09-27 09:33:36 +0000209void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
210 Optional<uint64_t> Offset) const {
211 auto DumpLocationList = [&](const LocationList &L) {
David Blaikie9c550ac2014-03-25 01:44:02 +0000212 OS << format("0x%8.8x: ", L.Offset);
Reid Klecknera0587362017-08-29 21:41:21 +0000213 L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
214 OS << "\n\n";
Jonas Devlieghere622c5632017-09-27 09:33:36 +0000215 };
216
217 if (Offset) {
218 if (auto *L = getLocationListAtOffset(*Offset))
219 DumpLocationList(*L);
220 return;
221 }
222
223 for (const LocationList &L : Locations) {
224 DumpLocationList(L);
David Blaikie9c550ac2014-03-25 01:44:02 +0000225 }
226}