Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
35266 views
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/DWARFContext.h"
12
#include "llvm/Support/Errc.h"
13
14
using namespace llvm;
15
16
Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
17
uint64_t *OffsetPtr,
18
uint64_t EndOffset) {
19
assert(EndOffset >= *OffsetPtr);
20
uint64_t DataSize = EndOffset - *OffsetPtr;
21
assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
22
if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
23
AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
24
Offset))
25
return SizeErr;
26
if (DataSize % AddrSize != 0) {
27
invalidateLength();
28
return createStringError(errc::invalid_argument,
29
"address table at offset 0x%" PRIx64
30
" contains data of size 0x%" PRIx64
31
" which is not a multiple of addr size %" PRIu8,
32
Offset, DataSize, AddrSize);
33
}
34
Addrs.clear();
35
size_t Count = DataSize / AddrSize;
36
Addrs.reserve(Count);
37
while (Count--)
38
Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
39
return Error::success();
40
}
41
42
Error DWARFDebugAddrTable::extractV5(const DWARFDataExtractor &Data,
43
uint64_t *OffsetPtr, uint8_t CUAddrSize,
44
std::function<void(Error)> WarnCallback) {
45
Offset = *OffsetPtr;
46
llvm::Error Err = Error::success();
47
std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
48
if (Err) {
49
invalidateLength();
50
return createStringError(errc::invalid_argument,
51
"parsing address table at offset 0x%" PRIx64
52
": %s",
53
Offset, toString(std::move(Err)).c_str());
54
}
55
56
if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
57
uint64_t DiagnosticLength = Length;
58
invalidateLength();
59
return createStringError(
60
errc::invalid_argument,
61
"section is not large enough to contain an address table "
62
"at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
63
Offset, DiagnosticLength);
64
}
65
uint64_t EndOffset = *OffsetPtr + Length;
66
// Ensure that we can read the remaining header fields.
67
if (Length < 4) {
68
uint64_t DiagnosticLength = Length;
69
invalidateLength();
70
return createStringError(
71
errc::invalid_argument,
72
"address table at offset 0x%" PRIx64
73
" has a unit_length value of 0x%" PRIx64
74
", which is too small to contain a complete header",
75
Offset, DiagnosticLength);
76
}
77
78
Version = Data.getU16(OffsetPtr);
79
AddrSize = Data.getU8(OffsetPtr);
80
SegSize = Data.getU8(OffsetPtr);
81
82
// Perform a basic validation of the header fields.
83
if (Version != 5)
84
return createStringError(errc::not_supported,
85
"address table at offset 0x%" PRIx64
86
" has unsupported version %" PRIu16,
87
Offset, Version);
88
// TODO: add support for non-zero segment selector size.
89
if (SegSize != 0)
90
return createStringError(errc::not_supported,
91
"address table at offset 0x%" PRIx64
92
" has unsupported segment selector size %" PRIu8,
93
Offset, SegSize);
94
95
if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
96
return Err;
97
if (CUAddrSize && AddrSize != CUAddrSize) {
98
WarnCallback(createStringError(
99
errc::invalid_argument,
100
"address table at offset 0x%" PRIx64 " has address size %" PRIu8
101
" which is different from CU address size %" PRIu8,
102
Offset, AddrSize, CUAddrSize));
103
}
104
return Error::success();
105
}
106
107
Error DWARFDebugAddrTable::extractPreStandard(const DWARFDataExtractor &Data,
108
uint64_t *OffsetPtr,
109
uint16_t CUVersion,
110
uint8_t CUAddrSize) {
111
assert(CUVersion > 0 && CUVersion < 5);
112
113
Offset = *OffsetPtr;
114
Length = 0;
115
Version = CUVersion;
116
AddrSize = CUAddrSize;
117
SegSize = 0;
118
119
return extractAddresses(Data, OffsetPtr, Data.size());
120
}
121
122
Error DWARFDebugAddrTable::extract(const DWARFDataExtractor &Data,
123
uint64_t *OffsetPtr,
124
uint16_t CUVersion,
125
uint8_t CUAddrSize,
126
std::function<void(Error)> WarnCallback) {
127
if (CUVersion > 0 && CUVersion < 5)
128
return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
129
if (CUVersion == 0)
130
WarnCallback(createStringError(errc::invalid_argument,
131
"DWARF version is not defined in CU,"
132
" assuming version 5"));
133
return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
134
}
135
136
void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
137
if (DumpOpts.Verbose)
138
OS << format("0x%8.8" PRIx64 ": ", Offset);
139
if (Length) {
140
int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
141
OS << "Address table header: "
142
<< format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)
143
<< ", format = " << dwarf::FormatString(Format)
144
<< format(", version = 0x%4.4" PRIx16, Version)
145
<< format(", addr_size = 0x%2.2" PRIx8, AddrSize)
146
<< format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";
147
}
148
149
if (Addrs.size() > 0) {
150
const char *AddrFmt;
151
switch (AddrSize) {
152
case 2:
153
AddrFmt = "0x%4.4" PRIx64 "\n";
154
break;
155
case 4:
156
AddrFmt = "0x%8.8" PRIx64 "\n";
157
break;
158
case 8:
159
AddrFmt = "0x%16.16" PRIx64 "\n";
160
break;
161
default:
162
llvm_unreachable("unsupported address size");
163
}
164
OS << "Addrs: [\n";
165
for (uint64_t Addr : Addrs)
166
OS << format(AddrFmt, Addr);
167
OS << "]\n";
168
}
169
}
170
171
Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
172
if (Index < Addrs.size())
173
return Addrs[Index];
174
return createStringError(errc::invalid_argument,
175
"Index %" PRIu32 " is out of range of the "
176
"address table at offset 0x%" PRIx64,
177
Index, Offset);
178
}
179
180
std::optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {
181
if (Length == 0)
182
return std::nullopt;
183
return Length + dwarf::getUnitLengthFieldByteSize(Format);
184
}
185
186