LLVM  14.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 
13 using namespace llvm;
14 
15 Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
16  uint64_t *OffsetPtr,
17  uint64_t EndOffset) {
18  assert(EndOffset >= *OffsetPtr);
19  uint64_t DataSize = EndOffset - *OffsetPtr;
20  assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
22  AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
23  Offset))
24  return SizeErr;
25  if (DataSize % AddrSize != 0) {
26  invalidateLength();
28  "address table at offset 0x%" PRIx64
29  " contains data of size 0x%" PRIx64
30  " which is not a multiple of addr size %" PRIu8,
31  Offset, DataSize, AddrSize);
32  }
33  Addrs.clear();
34  size_t Count = DataSize / AddrSize;
35  Addrs.reserve(Count);
36  while (Count--)
37  Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
38  return Error::success();
39 }
40 
42  uint64_t *OffsetPtr, uint8_t CUAddrSize,
43  std::function<void(Error)> WarnCallback) {
44  Offset = *OffsetPtr;
46  std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
47  if (Err) {
48  invalidateLength();
50  "parsing address table at offset 0x%" PRIx64
51  ": %s",
52  Offset, toString(std::move(Err)).c_str());
53  }
54 
55  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
56  uint64_t DiagnosticLength = Length;
57  invalidateLength();
58  return createStringError(
60  "section is not large enough to contain an address table "
61  "at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
62  Offset, DiagnosticLength);
63  }
64  uint64_t EndOffset = *OffsetPtr + Length;
65  // Ensure that we can read the remaining header fields.
66  if (Length < 4) {
67  uint64_t DiagnosticLength = Length;
68  invalidateLength();
69  return createStringError(
71  "address table at offset 0x%" PRIx64
72  " has a unit_length value of 0x%" PRIx64
73  ", which is too small to contain a complete header",
74  Offset, DiagnosticLength);
75  }
76 
77  Version = Data.getU16(OffsetPtr);
78  AddrSize = Data.getU8(OffsetPtr);
79  SegSize = Data.getU8(OffsetPtr);
80 
81  // Perform a basic validation of the header fields.
82  if (Version != 5)
84  "address table at offset 0x%" PRIx64
85  " has unsupported version %" PRIu16,
86  Offset, Version);
87  // TODO: add support for non-zero segment selector size.
88  if (SegSize != 0)
90  "address table at offset 0x%" PRIx64
91  " has unsupported segment selector size %" PRIu8,
92  Offset, SegSize);
93 
94  if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
95  return Err;
96  if (CUAddrSize && AddrSize != CUAddrSize) {
97  WarnCallback(createStringError(
99  "address table at offset 0x%" PRIx64 " has address size %" PRIu8
100  " which is different from CU address size %" PRIu8,
101  Offset, AddrSize, CUAddrSize));
102  }
103  return Error::success();
104 }
105 
107  uint64_t *OffsetPtr,
108  uint16_t CUVersion,
109  uint8_t CUAddrSize) {
110  assert(CUVersion > 0 && CUVersion < 5);
111 
112  Offset = *OffsetPtr;
113  Length = 0;
114  Version = CUVersion;
115  AddrSize = CUAddrSize;
116  SegSize = 0;
117 
118  return extractAddresses(Data, OffsetPtr, Data.size());
119 }
120 
122  uint64_t *OffsetPtr,
123  uint16_t CUVersion,
124  uint8_t CUAddrSize,
125  std::function<void(Error)> WarnCallback) {
126  if (CUVersion > 0 && CUVersion < 5)
127  return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
128  if (CUVersion == 0)
130  "DWARF version is not defined in CU,"
131  " assuming version 5"));
132  return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
133 }
134 
136  if (DumpOpts.Verbose)
137  OS << format("0x%8.8" PRIx64 ": ", Offset);
138  if (Length) {
139  int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
140  OS << "Address table header: "
141  << format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)
142  << ", format = " << dwarf::FormatString(Format)
143  << format(", version = 0x%4.4" PRIx16, Version)
144  << format(", addr_size = 0x%2.2" PRIx8, AddrSize)
145  << format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";
146  }
147 
148  if (Addrs.size() > 0) {
149  const char *AddrFmt;
150  switch (AddrSize) {
151  case 2:
152  AddrFmt = "0x%4.4" PRIx64 "\n";
153  break;
154  case 4:
155  AddrFmt = "0x%8.8" PRIx64 "\n";
156  break;
157  case 8:
158  AddrFmt = "0x%16.16" PRIx64 "\n";
159  break;
160  default:
161  llvm_unreachable("unsupported address size");
162  }
163  OS << "Addrs: [\n";
164  for (uint64_t Addr : Addrs)
165  OS << format(AddrFmt, Addr);
166  OS << "]\n";
167  }
168 }
169 
171  if (Index < Addrs.size())
172  return Addrs[Index];
174  "Index %" PRIu32 " is out of range of the "
175  "address table at offset 0x%" PRIx64,
176  Index, Offset);
177 }
178 
180  if (Length == 0)
181  return None;
182  return Length + dwarf::getUnitLengthFieldByteSize(Format);
183 }
184 
llvm::errc::invalid_argument
@ invalid_argument
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1029
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
DWARFContext.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:121
llvm::DWARFDebugAddrTable::getFullLength
Optional< uint64_t > getFullLength() const
Return the full length of this table, including the length field.
Definition: DWARFDebugAddr.cpp:179
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
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:106
llvm::DIDumpOptions::Verbose
bool Verbose
Definition: DIContext.h:191
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:23
Index
uint32_t Index
Definition: ELFObjHandler.cpp:83
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
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:674
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:83
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:134
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:1240
llvm::DWARFDebugAddrTable::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts={}) const
Definition: DWARFDebugAddr.cpp:135
uint16_t
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
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:41
llvm::DWARFDebugAddrTable::getAddrEntry
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
Definition: DWARFDebugAddr.cpp:170
llvm::dwarf::getDwarfOffsetByteSize
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:635
DWARFDebugAddr.h
llvm::DIDumpOptions
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:180