LLVM  15.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 
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));
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 
181  if (Length == 0)
182  return None;
183  return Length + dwarf::getUnitLengthFieldByteSize(Format);
184 }
185 
llvm::errc::invalid_argument
@ invalid_argument
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
DWARFContext.h
Errc.h
llvm::Optional< uint64_t >
llvm::DWARFDebugAddrTable::extract
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.
Definition: DWARFDebugAddr.cpp:122
llvm::DWARFDebugAddrTable::getFullLength
Optional< uint64_t > getFullLength() const
Return the full length of this table, including the length field.
Definition: DWARFDebugAddr.cpp:180
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::DWARFDataExtractor
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
Definition: DWARFDataExtractor.h:21
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::DWARFDebugAddrTable::extractPreStandard
Error extractPreStandard(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint16_t CUVersion, uint8_t CUAddrSize)
Extract a pre-DWARFv5 address table.
Definition: DWARFDebugAddr.cpp:107
llvm::DIDumpOptions::Verbose
bool Verbose
Definition: DIContext.h:199
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::dwarf::FormatString
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:790
llvm::DWARFContext::checkAddressSizeSupported
static Error checkAddressSizeSupported(unsigned AddressSize, std::error_code EC, char const *Fmt, const Ts &...Vals)
Definition: DWARFContext.h:392
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::None
const NoneType None
Definition: None.h:24
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::dwarf::getUnitLengthFieldByteSize
uint8_t getUnitLengthFieldByteSize(DwarfFormat Format)
Get the byte size of the unit length field depending on the DWARF format.
Definition: Dwarf.h:679
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
Dwarf.h
llvm::errc::not_supported
@ not_supported
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
uint32_t
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::DWARFDebugAddrTable::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts={}) const
Definition: DWARFDebugAddr.cpp:136
uint16_t
llvm::toString
const char * toString(DWARFSectionKind Kind)
Definition: DWARFUnitIndex.h:67
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::c_str
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
Definition: WindowsSupport.h:193
llvm::DWARFDebugAddrTable::extractV5
Error extractV5(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint8_t CUAddrSize, std::function< void(Error)> WarnCallback)
Extract a DWARFv5 address table.
Definition: DWARFDebugAddr.cpp:42
llvm::DWARFDebugAddrTable::getAddrEntry
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
Definition: DWARFDebugAddr.cpp:171
llvm::dwarf::getDwarfOffsetByteSize
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:640
DWARFDebugAddr.h
llvm::DIDumpOptions
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:188