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