LLVM  10.0.0svn
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 
16  HeaderData = {};
17  Addrs.clear();
19 }
20 
22  uint64_t *OffsetPtr,
23  uint16_t Version,
24  uint8_t AddrSize,
25  std::function<void(Error)> WarnCallback) {
26  clear();
27  HeaderOffset = *OffsetPtr;
28  // Read and verify the length field.
29  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
31  "section is not large enough to contain a "
32  ".debug_addr table length at offset 0x%"
33  PRIx64, *OffsetPtr);
34  uint16_t UnitVersion;
35  if (Version == 0) {
37  "DWARF version is not defined in CU,"
38  " assuming version 5"));
39  UnitVersion = 5;
40  } else {
41  UnitVersion = Version;
42  }
43  // TODO: Add support for DWARF64.
45  if (UnitVersion >= 5) {
46  HeaderData.Length = Data.getU32(OffsetPtr);
47  if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) {
50  "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx64,
51  HeaderOffset);
52  }
53  if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) {
54  uint32_t TmpLength = getLength();
57  ".debug_addr table at offset 0x%" PRIx64
58  " has too small length (0x%" PRIx32
59  ") to contain a complete header",
60  HeaderOffset, TmpLength);
61  }
62  uint64_t End = HeaderOffset + getLength();
63  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) {
64  uint32_t TmpLength = getLength();
67  "section is not large enough to contain a .debug_addr table "
68  "of length 0x%" PRIx32 " at offset 0x%" PRIx64,
69  TmpLength, HeaderOffset);
70  }
71 
72  HeaderData.Version = Data.getU16(OffsetPtr);
73  HeaderData.AddrSize = Data.getU8(OffsetPtr);
74  HeaderData.SegSize = Data.getU8(OffsetPtr);
75  DataSize = getDataSize();
76  } else {
77  HeaderData.Version = UnitVersion;
78  HeaderData.AddrSize = AddrSize;
79  // TODO: Support for non-zero SegSize.
80  HeaderData.SegSize = 0;
81  DataSize = Data.size();
82  }
83 
84  // Perform basic validation of the remaining header fields.
85 
86  // We support DWARF version 5 for now as well as pre-DWARF5
87  // implementations of .debug_addr table, which doesn't contain a header
88  // and consists only of a series of addresses.
89  if (HeaderData.Version > 5) {
90  return createStringError(errc::not_supported, "version %" PRIu16
91  " of .debug_addr section at offset 0x%" PRIx64 " is not supported",
92  HeaderData.Version, HeaderOffset);
93  }
94  // FIXME: For now we just treat version mismatch as an error,
95  // however the correct way to associate a .debug_addr table
96  // with a .debug_info table is to look at the DW_AT_addr_base
97  // attribute in the info table.
98  if (HeaderData.Version != UnitVersion)
100  ".debug_addr table at offset 0x%" PRIx64
101  " has version %" PRIu16
102  " which is different from the version suggested"
103  " by the DWARF unit header: %" PRIu16,
104  HeaderOffset, HeaderData.Version, UnitVersion);
105  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
107  ".debug_addr table at offset 0x%" PRIx64
108  " has unsupported address size %" PRIu8,
109  HeaderOffset, HeaderData.AddrSize);
110  if (HeaderData.AddrSize != AddrSize && AddrSize != 0)
112  ".debug_addr table at offset 0x%" PRIx64
113  " has address size %" PRIu8
114  " which is different from CU address size %" PRIu8,
115  HeaderOffset, HeaderData.AddrSize, AddrSize);
116 
117  // TODO: add support for non-zero segment selector size.
118  if (HeaderData.SegSize != 0)
120  ".debug_addr table at offset 0x%" PRIx64
121  " has unsupported segment selector size %" PRIu8,
122  HeaderOffset, HeaderData.SegSize);
123  if (DataSize % HeaderData.AddrSize != 0) {
126  ".debug_addr table at offset 0x%" PRIx64
127  " contains data of size %" PRIu32
128  " which is not a multiple of addr size %" PRIu8,
129  HeaderOffset, DataSize, HeaderData.AddrSize);
130  }
131  Data.setAddressSize(HeaderData.AddrSize);
132  uint32_t AddrCount = DataSize / HeaderData.AddrSize;
133  for (uint32_t I = 0; I < AddrCount; ++I)
134  if (HeaderData.AddrSize == 4)
135  Addrs.push_back(Data.getU32(OffsetPtr));
136  else
137  Addrs.push_back(Data.getU64(OffsetPtr));
138  return Error::success();
139 }
140 
142  if (DumpOpts.Verbose)
143  OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
144  OS << format("Addr Section: length = 0x%8.8" PRIx32
145  ", version = 0x%4.4" PRIx16 ", "
146  "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n",
147  HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
148  HeaderData.SegSize);
149 
150  if (Addrs.size() > 0) {
151  const char *AddrFmt = (HeaderData.AddrSize == 4) ? "0x%8.8" PRIx64 "\n"
152  : "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  ".debug_addr table at offset 0x%" PRIx64,
166  Index, HeaderOffset);
167 }
168 
170  if (HeaderData.Length == 0)
171  return 0;
172  // TODO: DWARF64 support.
173  return HeaderData.Length + sizeof(uint32_t);
174 }
175 
177  if (DataSize != 0)
178  return DataSize;
179  if (getLength() == 0)
180  return 0;
181  return getLength() - getHeaderSize();
182 }
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint8_t AddrSize
The size in bytes of an address on the target architecture.
uint8_t SegSize
The size in bytes of a segment selector on the target architecture.
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
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
uint8_t getHeaderSize() const
Return the size of the table header including the length but not including the addresses.
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr, uint16_t Version, uint8_t AddrSize, std::function< void(Error)> WarnCallback)
Extract an entire table, including all addresses.
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:171
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
uint32_t Length
The total length of the entries for this table, not including the length field itself.
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:326
uint32_t getLength() const
Returns the length of this table, including the length field, or 0 if the length has not been determi...
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
void setAddressSize(uint8_t Size)
Set the address size for this extractor.
Definition: DataExtractor.h:98
This file contains constants used for implementing Dwarf debug support.
uint16_t Version
The DWARF version number.
uint32_t getDataSize() const
Returns the length of the array of addresses.
#define I(x, y, z)
Definition: MD5.cpp:58
void invalidateLength()
Invalidate Length field to stop further processing.
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:45
uint64_t getU64(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint64_t value from *offset_ptr.
print Print MemDeps of function
const uint64_t Version
Definition: InstrProf.h:984
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1177