LLVM  8.0.1
DWARFDebugAddr.cpp
Go to the documentation of this file.
1 //===- DWARFDebugAddr.cpp -------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
13 
14 using namespace llvm;
15 
17  HeaderData = {};
18  Addrs.clear();
20 }
21 
23  uint32_t *OffsetPtr,
24  uint16_t Version,
25  uint8_t AddrSize,
26  std::function<void(Error)> WarnCallback) {
27  clear();
28  HeaderOffset = *OffsetPtr;
29  // Read and verify the length field.
30  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
32  "section is not large enough to contain a "
33  ".debug_addr table length at offset 0x%"
34  PRIx32, *OffsetPtr);
35  uint16_t UnitVersion;
36  if (Version == 0) {
38  "DWARF version is not defined in CU,"
39  " assuming version 5"));
40  UnitVersion = 5;
41  } else {
42  UnitVersion = Version;
43  }
44  // TODO: Add support for DWARF64.
46  if (UnitVersion >= 5) {
47  HeaderData.Length = Data.getU32(OffsetPtr);
48  if (HeaderData.Length == 0xffffffffu) {
51  "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32,
52  HeaderOffset);
53  }
54  if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) {
55  uint32_t TmpLength = getLength();
58  ".debug_addr table at offset 0x%" PRIx32
59  " has too small length (0x%" PRIx32
60  ") to contain a complete header",
61  HeaderOffset, TmpLength);
62  }
63  uint32_t End = HeaderOffset + getLength();
64  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) {
65  uint32_t TmpLength = getLength();
68  "section is not large enough to contain a .debug_addr table "
69  "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
70  TmpLength, HeaderOffset);
71  }
72 
73  HeaderData.Version = Data.getU16(OffsetPtr);
74  HeaderData.AddrSize = Data.getU8(OffsetPtr);
75  HeaderData.SegSize = Data.getU8(OffsetPtr);
76  DataSize = getDataSize();
77  } else {
78  HeaderData.Version = UnitVersion;
79  HeaderData.AddrSize = AddrSize;
80  // TODO: Support for non-zero SegSize.
81  HeaderData.SegSize = 0;
82  DataSize = Data.size();
83  }
84 
85  // Perform basic validation of the remaining header fields.
86 
87  // We support DWARF version 5 for now as well as pre-DWARF5
88  // implementations of .debug_addr table, which doesn't contain a header
89  // and consists only of a series of addresses.
90  if (HeaderData.Version > 5) {
91  return createStringError(errc::not_supported, "version %" PRIu16
92  " of .debug_addr section at offset 0x%" PRIx32 " is not supported",
93  HeaderData.Version, HeaderOffset);
94  }
95  // FIXME: For now we just treat version mismatch as an error,
96  // however the correct way to associate a .debug_addr table
97  // with a .debug_info table is to look at the DW_AT_addr_base
98  // attribute in the info table.
99  if (HeaderData.Version != UnitVersion)
101  ".debug_addr table at offset 0x%" PRIx32
102  " has version %" PRIu16
103  " which is different from the version suggested"
104  " by the DWARF unit header: %" PRIu16,
105  HeaderOffset, HeaderData.Version, UnitVersion);
106  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
108  ".debug_addr table at offset 0x%" PRIx32
109  " has unsupported address size %" PRIu8,
110  HeaderOffset, HeaderData.AddrSize);
111  if (HeaderData.AddrSize != AddrSize && AddrSize != 0)
113  ".debug_addr table at offset 0x%" PRIx32
114  " has address size %" PRIu8
115  " which is different from CU address size %" PRIu8,
116  HeaderOffset, HeaderData.AddrSize, AddrSize);
117 
118  // TODO: add support for non-zero segment selector size.
119  if (HeaderData.SegSize != 0)
121  ".debug_addr table at offset 0x%" PRIx32
122  " has unsupported segment selector size %" PRIu8,
123  HeaderOffset, HeaderData.SegSize);
124  if (DataSize % HeaderData.AddrSize != 0) {
127  ".debug_addr table at offset 0x%" PRIx32
128  " contains data of size %" PRIu32
129  " which is not a multiple of addr size %" PRIu8,
130  HeaderOffset, DataSize, HeaderData.AddrSize);
131  }
132  Data.setAddressSize(HeaderData.AddrSize);
133  uint32_t AddrCount = DataSize / HeaderData.AddrSize;
134  for (uint32_t I = 0; I < AddrCount; ++I)
135  if (HeaderData.AddrSize == 4)
136  Addrs.push_back(Data.getU32(OffsetPtr));
137  else
138  Addrs.push_back(Data.getU64(OffsetPtr));
139  return Error::success();
140 }
141 
143  if (DumpOpts.Verbose)
144  OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
145  OS << format("Addr Section: length = 0x%8.8" PRIx32
146  ", version = 0x%4.4" PRIx16 ", "
147  "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n",
148  HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
149  HeaderData.SegSize);
150 
151  static const char *Fmt32 = "0x%8.8" PRIx64;
152  static const char *Fmt64 = "0x%16.16" PRIx64;
153  std::string AddrFmt = "\n";
154  std::string AddrFmtVerbose = " => ";
155  if (HeaderData.AddrSize == 4) {
156  AddrFmt.append(Fmt32);
157  AddrFmtVerbose.append(Fmt32);
158  }
159  else {
160  AddrFmt.append(Fmt64);
161  AddrFmtVerbose.append(Fmt64);
162  }
163 
164  if (Addrs.size() > 0) {
165  OS << "Addrs: [";
166  for (uint64_t Addr : Addrs) {
167  OS << format(AddrFmt.c_str(), Addr);
168  if (DumpOpts.Verbose)
169  OS << format(AddrFmtVerbose.c_str(),
170  Addr + HeaderOffset + sizeof(HeaderData));
171  }
172  OS << "\n]\n";
173  }
174 }
175 
177  if (Index < Addrs.size())
178  return Addrs[Index];
180  "Index %" PRIu32 " is out of range of the "
181  ".debug_addr table at offset 0x%" PRIx32,
182  Index, HeaderOffset);
183 }
184 
186  if (HeaderData.Length == 0)
187  return 0;
188  // TODO: DWARF64 support.
189  return HeaderData.Length + sizeof(uint32_t);
190 }
191 
193  if (DataSize != 0)
194  return DataSize;
195  if (getLength() == 0)
196  return 0;
197  return getLength() - getHeaderSize();
198 }
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.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint8_t getHeaderSize() const
Return the size of the table header including the length but not including the addresses.
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:159
Expected< uint64_t > getAddrEntry(uint32_t Index) const
Return the address based on a given index.
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const
Test the availability of length bytes of data from offset.
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize, std::function< void(Error)> WarnCallback)
Extract an entire table, including all addresses.
uint32_t Length
The total length of the entries for this table, not including the length field itself.
uint64_t getU64(uint32_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
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:327
uint32_t getLength() const
Returns the length of this table, including the length field, or 0 if the length has not been determi...
void setAddressSize(uint8_t Size)
Set the address size for this extractor.
Definition: DataExtractor.h:61
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:158
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
const uint64_t Version
Definition: InstrProf.h:895
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1164