LLVM 20.0.0git
DWARFDebugAddr.cpp
Go to the documentation of this file.
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
12#include "llvm/Support/Errc.h"
13
14using namespace llvm;
15
16Error 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));
23 AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
24 Offset))
25 return SizeErr;
26 if (DataSize % AddrSize != 0) {
27 invalidateLength();
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
43 uint64_t *OffsetPtr, uint8_t CUAddrSize,
44 std::function<void(Error)> WarnCallback) {
45 Offset = *OffsetPtr;
47 std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
48 if (Err) {
49 invalidateLength();
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(
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(
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)
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)
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(
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
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
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)
131 "DWARF version is not defined in CU,"
132 " assuming version 5"));
133 return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
134}
135
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
172 if (Index < Addrs.size())
173 return Addrs[Index];
175 "Index %" PRIu32 " is out of range of the "
176 "address table at offset 0x%" PRIx64,
177 Index, Offset);
178}
179
180std::optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {
181 if (Length == 0)
182 return std::nullopt;
183 return Length + dwarf::getUnitLengthFieldByteSize(Format);
184}
This file contains constants used for implementing Dwarf debug support.
uint64_t Addr
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static Error checkAddressSizeSupported(unsigned AddressSize, std::error_code EC, char const *Fmt, const Ts &...Vals)
Definition: DWARFContext.h:414
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
void dump(raw_ostream &OS, DIDumpOptions DumpOpts={}) const
Error extract(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint16_t CUVersion, uint8_t CUAddrSize, std::function< void(Error)> WarnCallback)
Extract the entire table, including all addresses.
Error extractV5(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint8_t CUAddrSize, std::function< void(Error)> WarnCallback)
Extract a DWARFv5 address table.
Error extractPreStandard(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint16_t CUVersion, uint8_t CUAddrSize)
Extract a pre-DWARFv5 address table.
std::optional< uint64_t > getFullLength() const
Return the full length of this table, including the length field.
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:868
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint8_t getUnitLengthFieldByteSize(DwarfFormat Format)
Get the byte size of the unit length field depending on the DWARF format.
Definition: Dwarf.h:1103
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:1064
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:480
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1286
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:196