Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- DWARFDebugRnglists.cpp ---------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
10
#include "llvm/BinaryFormat/Dwarf.h"
11
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
12
#include "llvm/Support/Errc.h"
13
#include "llvm/Support/Error.h"
14
#include "llvm/Support/Format.h"
15
#include "llvm/Support/raw_ostream.h"
16
17
using namespace llvm;
18
19
Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
20
119
                              uint32_t *OffsetPtr) {
21
119
  Offset = *OffsetPtr;
22
119
  SectionIndex = -1ULL;
23
119
  // The caller should guarantee that we have at least 1 byte available, so
24
119
  // we just assert instead of revalidate.
25
119
  assert(*OffsetPtr < End &&
26
119
         "not enough space to extract a rangelist encoding");
27
119
  uint8_t Encoding = Data.getU8(OffsetPtr);
28
119
29
119
  switch (Encoding) {
30
119
  case dwarf::DW_RLE_end_of_list:
31
39
    Value0 = Value1 = 0;
32
39
    break;
33
119
  // TODO: Support other encodings.
34
119
  case dwarf::DW_RLE_base_addressx: {
35
8
    uint32_t PreviousOffset = *OffsetPtr - 1;
36
8
    Value0 = Data.getULEB128(OffsetPtr);
37
8
    if (End < *OffsetPtr)
38
0
      return createStringError(
39
0
          errc::invalid_argument,
40
0
          "read past end of table when reading "
41
0
          "DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
42
0
          PreviousOffset);
43
8
    break;
44
8
  }
45
8
  case dwarf::DW_RLE_startx_endx:
46
2
    return createStringError(errc::not_supported,
47
2
                       "unsupported rnglists encoding DW_RLE_startx_endx at "
48
2
                       "offset 0x%" PRIx32,
49
2
                       *OffsetPtr - 1);
50
20
  case dwarf::DW_RLE_startx_length: {
51
20
    uint32_t PreviousOffset = *OffsetPtr - 1;
52
20
    Value0 = Data.getULEB128(OffsetPtr);
53
20
    Value1 = Data.getULEB128(OffsetPtr);
54
20
    if (End < *OffsetPtr)
55
0
      return createStringError(
56
0
          errc::invalid_argument,
57
0
          "read past end of table when reading "
58
0
          "DW_RLE_startx_length encoding at offset 0x%" PRIx32,
59
0
          PreviousOffset);
60
20
    break;
61
20
  }
62
23
  case dwarf::DW_RLE_offset_pair: {
63
23
    uint32_t PreviousOffset = *OffsetPtr - 1;
64
23
    Value0 = Data.getULEB128(OffsetPtr);
65
23
    Value1 = Data.getULEB128(OffsetPtr);
66
23
    if (End < *OffsetPtr)
67
0
      return createStringError(errc::invalid_argument,
68
0
                         "read past end of table when reading "
69
0
                         "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
70
0
                         PreviousOffset);
71
23
    break;
72
23
  }
73
23
  case dwarf::DW_RLE_base_address: {
74
5
    if ((End - *OffsetPtr) < Data.getAddressSize())
75
0
      return createStringError(errc::invalid_argument,
76
0
                         "insufficient space remaining in table for "
77
0
                         "DW_RLE_base_address encoding at offset 0x%" PRIx32,
78
0
                         *OffsetPtr - 1);
79
5
    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
80
5
    break;
81
5
  }
82
14
  case dwarf::DW_RLE_start_end: {
83
14
    if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
84
1
      return createStringError(errc::invalid_argument,
85
1
                         "insufficient space remaining in table for "
86
1
                         "DW_RLE_start_end encoding "
87
1
                         "at offset 0x%" PRIx32,
88
1
                         *OffsetPtr - 1);
89
13
    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
90
13
    Value1 = Data.getRelocatedAddress(OffsetPtr);
91
13
    break;
92
13
  }
93
13
  case dwarf::DW_RLE_start_length: {
94
7
    uint32_t PreviousOffset = *OffsetPtr - 1;
95
7
    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
96
7
    Value1 = Data.getULEB128(OffsetPtr);
97
7
    if (End < *OffsetPtr)
98
1
      return createStringError(errc::invalid_argument,
99
1
                         "read past end of table when reading "
100
1
                         "DW_RLE_start_length encoding at offset 0x%" PRIx32,
101
1
                         PreviousOffset);
102
6
    break;
103
6
  }
104
6
  default:
105
1
    return createStringError(errc::not_supported,
106
1
                       "unknown rnglists encoding 0x%" PRIx32
107
1
                       " at offset 0x%" PRIx32,
108
1
                       uint32_t(Encoding), *OffsetPtr - 1);
109
114
  }
110
114
111
114
  EntryKind = Encoding;
112
114
  return Error::success();
113
114
}
114
115
DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
116
14
    llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
117
14
  DWARFAddressRangesVector Res;
118
46
  for (const RangeListEntry &RLE : Entries) {
119
46
    if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
120
14
      break;
121
32
    if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
122
3
      BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
123
3
      if (!BaseAddr)
124
1
        BaseAddr = {RLE.Value0, -1ULL};
125
3
      continue;
126
3
    }
127
29
    if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
128
3
      BaseAddr = {RLE.Value0, RLE.SectionIndex};
129
3
      continue;
130
3
    }
131
26
132
26
    DWARFAddressRange E;
133
26
    E.SectionIndex = RLE.SectionIndex;
134
26
    if (BaseAddr && 
E.SectionIndex == -1ULL22
)
135
22
      E.SectionIndex = BaseAddr->SectionIndex;
136
26
137
26
    switch (RLE.EntryKind) {
138
26
    case dwarf::DW_RLE_offset_pair:
139
11
      E.LowPC = RLE.Value0;
140
11
      E.HighPC = RLE.Value1;
141
11
      if (BaseAddr) {
142
11
        E.LowPC += BaseAddr->Address;
143
11
        E.HighPC += BaseAddr->Address;
144
11
      }
145
11
      break;
146
26
    case dwarf::DW_RLE_start_end:
147
2
      E.LowPC = RLE.Value0;
148
2
      E.HighPC = RLE.Value1;
149
2
      break;
150
26
    case dwarf::DW_RLE_start_length:
151
2
      E.LowPC = RLE.Value0;
152
2
      E.HighPC = E.LowPC + RLE.Value1;
153
2
      break;
154
26
    case dwarf::DW_RLE_startx_length: {
155
11
      auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
156
11
      if (!Start)
157
3
        Start = {0, -1ULL};
158
11
      E.SectionIndex = Start->SectionIndex;
159
11
      E.LowPC = Start->Address;
160
11
      E.HighPC = E.LowPC + RLE.Value1;
161
11
      break;
162
26
    }
163
26
    default:
164
0
      // Unsupported encodings should have been reported during extraction,
165
0
      // so we should not run into any here.
166
0
      llvm_unreachable("Unsupported range list encoding");
167
26
    }
168
26
    Res.push_back(E);
169
26
  }
170
14
  return Res;
171
14
}
172
173
void RangeListEntry::dump(
174
    raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
175
    uint64_t &CurrentBase, DIDumpOptions DumpOpts,
176
    llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
177
67
        LookupPooledAddress) const {
178
67
  auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
179
67
                          uint8_t AddrSize, DIDumpOptions DumpOpts) {
180
25
    if (DumpOpts.Verbose) {
181
20
      DumpOpts.DisplayRawContents = true;
182
20
      DWARFAddressRange(Entry.Value0, Entry.Value1)
183
20
          .dump(OS, AddrSize, DumpOpts);
184
20
      OS << " => ";
185
20
    }
186
25
  };
187
67
188
67
  if (DumpOpts.Verbose) {
189
44
    // Print the section offset in verbose mode.
190
44
    OS << format("0x%8.8" PRIx32 ":", Offset);
191
44
    auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
192
44
    // Unsupported encodings should have been reported during parsing.
193
44
    assert(!EncodingString.empty() && "Unknown range entry encoding");
194
44
    OS << format(" [%s%*c", EncodingString.data(),
195
44
                 MaxEncodingStringLength - EncodingString.size() + 1, ']');
196
44
    if (EntryKind != dwarf::DW_RLE_end_of_list)
197
29
      OS << ": ";
198
44
  }
199
67
200
67
  switch (EntryKind) {
201
67
  case dwarf::DW_RLE_end_of_list:
202
25
    OS << (DumpOpts.Verbose ? 
""15
:
"<End of list>"10
);
203
25
    break;
204
67
  case dwarf::DW_RLE_base_addressx: {
205
5
    if (auto SA = LookupPooledAddress(Value0))
206
2
      CurrentBase = SA->Address;
207
3
    else
208
3
      CurrentBase = Value0;
209
5
    if (!DumpOpts.Verbose)
210
1
      return;
211
4
    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
212
4
    break;
213
4
  }
214
4
  case dwarf::DW_RLE_base_address:
215
2
    // In non-verbose mode we do not print anything for this entry.
216
2
    CurrentBase = Value0;
217
2
    if (!DumpOpts.Verbose)
218
1
      return;
219
1
    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
220
1
    break;
221
4
  case dwarf::DW_RLE_start_length:
222
4
    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
223
4
    DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
224
4
    break;
225
12
  case dwarf::DW_RLE_offset_pair:
226
12
    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
227
12
    DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
228
12
        .dump(OS, AddrSize, DumpOpts);
229
12
    break;
230
10
  case dwarf::DW_RLE_start_end:
231
10
    DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
232
10
    break;
233
9
  case dwarf::DW_RLE_startx_length: {
234
9
    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
235
9
    uint64_t Start = 0;
236
9
    if (auto SA = LookupPooledAddress(Value0))
237
6
      Start = SA->Address;
238
9
    DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
239
9
    break;
240
1
  }
241
1
  default:
242
0
    llvm_unreachable("Unsupported range list encoding");
243
65
  }
244
65
  OS << "\n";
245
65
}