Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- DWARFDebugAddr.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/DWARFDebugAddr.h"
10
#include "llvm/BinaryFormat/Dwarf.h"
11
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
12
13
using namespace llvm;
14
15
42
void DWARFDebugAddrTable::clear() {
16
42
  HeaderData = {};
17
42
  Addrs.clear();
18
42
  invalidateLength();
19
42
}
20
21
Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data,
22
                                   uint32_t *OffsetPtr,
23
                                   uint16_t Version,
24
                                   uint8_t AddrSize,
25
42
                                   std::function<void(Error)> WarnCallback) {
26
42
  clear();
27
42
  HeaderOffset = *OffsetPtr;
28
42
  // Read and verify the length field.
29
42
  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
30
1
    return createStringError(errc::invalid_argument,
31
1
                       "section is not large enough to contain a "
32
1
                       ".debug_addr table length at offset 0x%"
33
1
                       PRIx32, *OffsetPtr);
34
41
  uint16_t UnitVersion;
35
41
  if (Version == 0) {
36
6
    WarnCallback(createStringError(errc::invalid_argument,
37
6
                       "DWARF version is not defined in CU,"
38
6
                       " assuming version 5"));
39
6
    UnitVersion = 5;
40
35
  } else {
41
35
    UnitVersion = Version;
42
35
  }
43
41
  // TODO: Add support for DWARF64.
44
41
  Format = dwarf::DwarfFormat::DWARF32;
45
41
  if (UnitVersion >= 5) {
46
31
    HeaderData.Length = Data.getU32(OffsetPtr);
47
31
    if (HeaderData.Length == 0xffffffffu) {
48
1
      invalidateLength();
49
1
      return createStringError(errc::not_supported,
50
1
          "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32,
51
1
          HeaderOffset);
52
1
    }
53
30
    if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) {
54
1
      uint32_t TmpLength = getLength();
55
1
      invalidateLength();
56
1
      return createStringError(errc::invalid_argument,
57
1
                         ".debug_addr table at offset 0x%" PRIx32
58
1
                         " has too small length (0x%" PRIx32
59
1
                         ") to contain a complete header",
60
1
                         HeaderOffset, TmpLength);
61
1
    }
62
29
    uint32_t End = HeaderOffset + getLength();
63
29
    if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) {
64
1
      uint32_t TmpLength = getLength();
65
1
      invalidateLength();
66
1
      return createStringError(errc::invalid_argument,
67
1
          "section is not large enough to contain a .debug_addr table "
68
1
          "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
69
1
          TmpLength, HeaderOffset);
70
1
    }
71
28
72
28
    HeaderData.Version = Data.getU16(OffsetPtr);
73
28
    HeaderData.AddrSize = Data.getU8(OffsetPtr);
74
28
    HeaderData.SegSize = Data.getU8(OffsetPtr);
75
28
    DataSize = getDataSize();
76
28
  } else {
77
10
    HeaderData.Version = UnitVersion;
78
10
    HeaderData.AddrSize = AddrSize;
79
10
    // TODO: Support for non-zero SegSize.
80
10
    HeaderData.SegSize = 0;
81
10
    DataSize = Data.size();
82
10
  }
83
41
84
41
  // Perform basic validation of the remaining header fields.
85
41
86
41
  // We support DWARF version 5 for now as well as pre-DWARF5
87
41
  // implementations of .debug_addr table, which doesn't contain a header
88
41
  // and consists only of a series of addresses.
89
41
  
if (38
HeaderData.Version > 538
) {
90
1
    return createStringError(errc::not_supported, "version %" PRIu16
91
1
        " of .debug_addr section at offset 0x%" PRIx32 " is not supported",
92
1
        HeaderData.Version, HeaderOffset);
93
1
  }
94
37
  // FIXME: For now we just treat version mismatch as an error,
95
37
  // however the correct way to associate a .debug_addr table
96
37
  // with a .debug_info table is to look at the DW_AT_addr_base
97
37
  // attribute in the info table.
98
37
  if (HeaderData.Version != UnitVersion)
99
1
    return createStringError(errc::invalid_argument,
100
1
                       ".debug_addr table at offset 0x%" PRIx32
101
1
                       " has version %" PRIu16
102
1
                       " which is different from the version suggested"
103
1
                       " by the DWARF unit header: %" PRIu16,
104
1
                       HeaderOffset, HeaderData.Version, UnitVersion);
105
36
  if (HeaderData.AddrSize != 4 && 
HeaderData.AddrSize != 826
)
106
1
    return createStringError(errc::not_supported,
107
1
                       ".debug_addr table at offset 0x%" PRIx32
108
1
                       " has unsupported address size %" PRIu8,
109
1
                       HeaderOffset, HeaderData.AddrSize);
110
35
  if (HeaderData.AddrSize != AddrSize && 
AddrSize != 03
)
111
1
    return createStringError(errc::invalid_argument,
112
1
                       ".debug_addr table at offset 0x%" PRIx32
113
1
                       " has address size %" PRIu8
114
1
                       " which is different from CU address size %" PRIu8,
115
1
                       HeaderOffset, HeaderData.AddrSize, AddrSize);
116
34
117
34
  // TODO: add support for non-zero segment selector size.
118
34
  if (HeaderData.SegSize != 0)
119
1
    return createStringError(errc::not_supported,
120
1
                       ".debug_addr table at offset 0x%" PRIx32
121
1
                       " has unsupported segment selector size %" PRIu8,
122
1
                       HeaderOffset, HeaderData.SegSize);
123
33
  if (DataSize % HeaderData.AddrSize != 0) {
124
1
    invalidateLength();
125
1
    return createStringError(errc::invalid_argument,
126
1
                       ".debug_addr table at offset 0x%" PRIx32
127
1
                       " contains data of size %" PRIu32
128
1
                       " which is not a multiple of addr size %" PRIu8,
129
1
                       HeaderOffset, DataSize, HeaderData.AddrSize);
130
1
  }
131
32
  Data.setAddressSize(HeaderData.AddrSize);
132
32
  uint32_t AddrCount = DataSize / HeaderData.AddrSize;
133
119
  for (uint32_t I = 0; I < AddrCount; 
++I87
)
134
87
    if (HeaderData.AddrSize == 4)
135
14
      Addrs.push_back(Data.getU32(OffsetPtr));
136
73
    else
137
73
      Addrs.push_back(Data.getU64(OffsetPtr));
138
32
  return Error::success();
139
32
}
140
141
32
void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
142
32
  if (DumpOpts.Verbose)
143
24
    OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
144
32
  OS << format("Addr Section: length = 0x%8.8" PRIx32
145
32
               ", version = 0x%4.4" PRIx16 ", "
146
32
               "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n",
147
32
               HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
148
32
               HeaderData.SegSize);
149
32
150
32
  if (Addrs.size() > 0) {
151
31
    const char *AddrFmt = (HeaderData.AddrSize == 4) ? 
"0x%8.8" PRIx64 "\n"7
152
31
                                                     : 
"0x%16.16" PRIx64 "\n"24
;
153
31
    OS << "Addrs: [\n";
154
31
    for (uint64_t Addr : Addrs)
155
87
      OS << format(AddrFmt, Addr);
156
31
    OS << "]\n";
157
31
  }
158
32
}
159
160
0
Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
161
0
  if (Index < Addrs.size())
162
0
    return Addrs[Index];
163
0
  return createStringError(errc::invalid_argument,
164
0
                           "Index %" PRIu32 " is out of range of the "
165
0
                           ".debug_addr table at offset 0x%" PRIx32,
166
0
                           Index, HeaderOffset);
167
0
}
168
169
102
uint32_t DWARFDebugAddrTable::getLength() const {
170
102
  if (HeaderData.Length == 0)
171
5
    return 0;
172
97
  // TODO: DWARF64 support.
173
97
  return HeaderData.Length + sizeof(uint32_t);
174
97
}
175
176
28
uint32_t DWARFDebugAddrTable::getDataSize() const {
177
28
  if (DataSize != 0)
178
0
    return DataSize;
179
28
  if (getLength() == 0)
180
0
    return 0;
181
28
  return getLength() - getHeaderSize();
182
28
}