LLVM 23.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"
15
16using namespace llvm;
17
18Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
19 uint64_t *OffsetPtr,
20 uint64_t EndOffset) {
21 assert(EndOffset >= *OffsetPtr);
22 uint64_t DataSize = EndOffset - *OffsetPtr;
23 assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
25 AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
26 Offset))
27 return SizeErr;
28 if (DataSize % AddrSize != 0) {
29 invalidateLength();
31 "address table at offset 0x%" PRIx64
32 " contains data of size 0x%" PRIx64
33 " which is not a multiple of addr size %" PRIu8,
34 Offset, DataSize, AddrSize);
35 }
36 Addrs.clear();
37 size_t Count = DataSize / AddrSize;
38 Addrs.reserve(Count);
39 while (Count--)
40 Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
41 return Error::success();
42}
43
45 uint64_t *OffsetPtr, uint8_t CUAddrSize,
46 std::function<void(Error)> WarnCallback) {
47 Offset = *OffsetPtr;
49 std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
50 if (Err) {
51 invalidateLength();
53 "parsing address table at offset 0x%" PRIx64
54 ": %s",
55 Offset, toString(std::move(Err)).c_str());
56 }
57
58 if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
59 uint64_t DiagnosticLength = Length;
60 invalidateLength();
61 return createStringError(
63 "section is not large enough to contain an address table "
64 "at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
65 Offset, DiagnosticLength);
66 }
67 uint64_t EndOffset = *OffsetPtr + Length;
68 // Ensure that we can read the remaining header fields.
69 if (Length < 4) {
70 uint64_t DiagnosticLength = Length;
71 invalidateLength();
72 return createStringError(
74 "address table at offset 0x%" PRIx64
75 " has a unit_length value of 0x%" PRIx64
76 ", which is too small to contain a complete header",
77 Offset, DiagnosticLength);
78 }
79
80 Version = Data.getU16(OffsetPtr);
81 AddrSize = Data.getU8(OffsetPtr);
82 SegSize = Data.getU8(OffsetPtr);
83
84 // Perform a basic validation of the header fields.
85 if (Version != 5)
87 "address table at offset 0x%" PRIx64
88 " has unsupported version %" PRIu16,
89 Offset, Version);
90 // TODO: add support for non-zero segment selector size.
91 if (SegSize != 0)
93 "address table at offset 0x%" PRIx64
94 " has unsupported segment selector size %" PRIu8,
95 Offset, SegSize);
96
97 if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
98 return Err;
99 if (CUAddrSize && AddrSize != CUAddrSize) {
100 WarnCallback(createStringError(
102 "address table at offset 0x%" PRIx64 " has address size %" PRIu8
103 " which is different from CU address size %" PRIu8,
104 Offset, AddrSize, CUAddrSize));
105 }
106 return Error::success();
107}
108
110 uint64_t *OffsetPtr,
111 uint16_t CUVersion,
112 uint8_t CUAddrSize) {
113 assert(CUVersion > 0 && CUVersion < 5);
114
115 Offset = *OffsetPtr;
116 Length = 0;
117 Version = CUVersion;
118 AddrSize = CUAddrSize;
119 SegSize = 0;
120
121 return extractAddresses(Data, OffsetPtr, Data.size());
122}
123
125 uint64_t *OffsetPtr,
126 uint16_t CUVersion,
127 uint8_t CUAddrSize,
128 std::function<void(Error)> WarnCallback) {
129 if (CUVersion > 0 && CUVersion < 5)
130 return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
131 if (CUVersion == 0)
133 "DWARF version is not defined in CU,"
134 " assuming version 5"));
135 return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
136}
137
139 if (DumpOpts.Verbose)
140 OS << formatv("{0:x+8}: ", Offset);
141 if (Length) {
142 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
143 OS << "Address table header: "
144 << formatv("length = 0x{0:x-}",
145 fmt_align(Length, AlignStyle::Right, OffsetDumpWidth, '0'))
146 << ", format = " << dwarf::FormatString(Format)
147 << formatv(", version = {0:x+4}", Version)
148 << formatv(", addr_size = {0:x+2}", AddrSize)
149 << formatv(", seg_size = {0:x+2}", SegSize) << "\n";
150 }
151
152 if (Addrs.size() > 0) {
153 const char *AddrFmt;
154 switch (AddrSize) {
155 case 2:
156 AddrFmt = "{0:x+4}\n";
157 break;
158 case 4:
159 AddrFmt = "{0:x+8}\n";
160 break;
161 case 8:
162 AddrFmt = "{0:x+16}\n";
163 break;
164 default:
165 llvm_unreachable("unsupported address size");
166 }
167 OS << "Addrs: [\n";
168 for (uint64_t Addr : Addrs)
169 OS << formatv(AddrFmt, Addr);
170 OS << "]\n";
171 }
172}
173
175 if (Index < Addrs.size())
176 return Addrs[Index];
178 "Index %" PRIu32 " is out of range of the "
179 "address table at offset 0x%" PRIx64,
180 Index, Offset);
181}
182
183std::optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {
184 if (Length == 0)
185 return std::nullopt;
186 return Length + dwarf::getUnitLengthFieldByteSize(Format);
187}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains constants used for implementing Dwarf debug support.
static Error checkAddressSizeSupported(unsigned AddressSize, std::error_code EC, char const *Fmt, const Ts &...Vals)
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
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:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1023
#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:1139
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1097
This is an optimization pass for GlobalISel generic memory operations.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
Definition InstrProf.h:299
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ not_supported
Definition Errc.h:69
@ invalid_argument
Definition Errc.h:56
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196