LLVM  12.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));
21  if (AddrSize != 4 && AddrSize != 8)
23  "address table at offset 0x%" PRIx64
24  " has unsupported address size %" PRIu8
25  " (4 and 8 are supported)",
26  Offset, AddrSize);
27  if (DataSize % AddrSize != 0) {
28  invalidateLength();
30  "address table at offset 0x%" PRIx64
31  " contains data of size 0x%" PRIx64
32  " which is not a multiple of addr size %" PRIu8,
33  Offset, DataSize, AddrSize);
34  }
35  Addrs.clear();
36  size_t Count = DataSize / AddrSize;
37  Addrs.reserve(Count);
38  while (Count--)
39  Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
40  return Error::success();
41 }
42 
44  uint64_t *OffsetPtr, uint8_t CUAddrSize,
45  std::function<void(Error)> WarnCallback) {
46  Offset = *OffsetPtr;
48  std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
49  if (Err) {
50  invalidateLength();
52  "parsing address table at offset 0x%" PRIx64
53  ": %s",
54  Offset, toString(std::move(Err)).c_str());
55  }
56 
57  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
58  uint64_t DiagnosticLength = Length;
59  invalidateLength();
60  return createStringError(
62  "section is not large enough to contain an address table "
63  "at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
64  Offset, DiagnosticLength);
65  }
66  uint64_t EndOffset = *OffsetPtr + Length;
67  // Ensure that we can read the remaining header fields.
68  if (Length < 4) {
69  uint64_t DiagnosticLength = Length;
70  invalidateLength();
71  return createStringError(
73  "address table at offset 0x%" PRIx64
74  " has a unit_length value of 0x%" PRIx64
75  ", which is too small to contain a complete header",
76  Offset, DiagnosticLength);
77  }
78 
79  Version = Data.getU16(OffsetPtr);
80  AddrSize = Data.getU8(OffsetPtr);
81  SegSize = Data.getU8(OffsetPtr);
82 
83  // Perform a basic validation of the header fields.
84  if (Version != 5)
86  "address table at offset 0x%" PRIx64
87  " has unsupported version %" PRIu16,
88  Offset, Version);
89  // TODO: add support for non-zero segment selector size.
90  if (SegSize != 0)
92  "address table at offset 0x%" PRIx64
93  " has unsupported segment selector size %" PRIu8,
94  Offset, SegSize);
95 
96  if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
97  return Err;
98  if (CUAddrSize && AddrSize != CUAddrSize) {
99  WarnCallback(createStringError(
101  "address table at offset 0x%" PRIx64 " has address size %" PRIu8
102  " which is different from CU address size %" PRIu8,
103  Offset, AddrSize, CUAddrSize));
104  }
105  return Error::success();
106 }
107 
109  uint64_t *OffsetPtr,
110  uint16_t CUVersion,
111  uint8_t CUAddrSize) {
112  assert(CUVersion > 0 && CUVersion < 5);
113 
114  Offset = *OffsetPtr;
115  Length = 0;
116  Version = CUVersion;
117  AddrSize = CUAddrSize;
118  SegSize = 0;
119 
120  return extractAddresses(Data, OffsetPtr, Data.size());
121 }
122 
124  uint64_t *OffsetPtr,
125  uint16_t CUVersion,
126  uint8_t CUAddrSize,
127  std::function<void(Error)> WarnCallback) {
128  if (CUVersion > 0 && CUVersion < 5)
129  return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
130  if (CUVersion == 0)
132  "DWARF version is not defined in CU,"
133  " assuming version 5"));
134  return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
135 }
136 
138  if (DumpOpts.Verbose)
139  OS << format("0x%8.8" PRIx64 ": ", Offset);
140  if (Length) {
141  int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
142  OS << "Address table header: "
143  << format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)
144  << ", format = " << dwarf::FormatString(Format)
145  << format(", version = 0x%4.4" PRIx16, Version)
146  << format(", addr_size = 0x%2.2" PRIx8, AddrSize)
147  << format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";
148  }
149 
150  if (Addrs.size() > 0) {
151  const char *AddrFmt =
152  (AddrSize == 4) ? "0x%8.8" PRIx64 "\n" : "0x%16.16" PRIx64 "\n";
153  OS << "Addrs: [\n";
154  for (uint64_t Addr : Addrs)
155  OS << format(AddrFmt, Addr);
156  OS << "]\n";
157  }
158 }
159 
161  if (Index < Addrs.size())
162  return Addrs[Index];
164  "Index %" PRIu32 " is out of range of the "
165  "address table at offset 0x%" PRIx64,
166  Index, Offset);
167 }
168 
170  if (Length == 0)
171  return None;
172  return Length + dwarf::getUnitLengthFieldByteSize(Format);
173 }
174 
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:991
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
std::pair< uint64_t, dwarf::DwarfFormat > getInitialLength(uint64_t *Off, Error *Err=nullptr) const
Extracts the DWARF "initial length" field, which can either be a 32-bit value smaller than 0xfffffff0...
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and applies a relocation to the result if one exists for the given offset...
uint8_t getUnitLengthFieldByteSize(DwarfFormat Format)
Get the byte size of the unit length field depending on the DWARF format.
Definition: Dwarf.h:577
Error extractPreStandard(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint16_t CUVersion, uint8_t CUAddrSize)
Extract a pre-DWARFv5 address table.
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:181
Error extractV5(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint8_t CUAddrSize, std::function< void(Error)> WarnCallback)
Extract a DWARFv5 address table.
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:773
size_t size() const
Return the number of bytes in the underlying buffer.
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
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
This file contains constants used for implementing Dwarf debug support.
Optional< uint64_t > getFullLength() const
Return the full length of this table, including the length field.
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.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:541
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
print Print MemDeps of function
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202