1 //===- DWARFDebugAddr.cpp -------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
16 void DWARFDebugAddrTable::clear() {
22 Error
DWARFDebugAddrTable::extract(DWARFDataExtractor Data
,
26 std::function
<void(Error
)> WarnCallback
) {
28 HeaderOffset
= *OffsetPtr
;
29 // Read and verify the length field.
30 if (!Data
.isValidOffsetForDataOfSize(*OffsetPtr
, sizeof(uint32_t)))
31 return createStringError(errc::invalid_argument
,
32 "section is not large enough to contain a "
33 ".debug_addr table length at offset 0x%"
37 WarnCallback(createStringError(errc::invalid_argument
,
38 "DWARF version is not defined in CU,"
39 " assuming version 5"));
42 UnitVersion
= Version
;
44 // TODO: Add support for DWARF64.
45 Format
= dwarf::DwarfFormat::DWARF32
;
46 if (UnitVersion
>= 5) {
47 HeaderData
.Length
= Data
.getU32(OffsetPtr
);
48 if (HeaderData
.Length
== 0xffffffffu
) {
50 return createStringError(errc::not_supported
,
51 "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32
,
54 if (HeaderData
.Length
+ sizeof(uint32_t) < sizeof(Header
)) {
55 uint32_t TmpLength
= getLength();
57 return createStringError(errc::invalid_argument
,
58 ".debug_addr table at offset 0x%" PRIx32
59 " has too small length (0x%" PRIx32
60 ") to contain a complete header",
61 HeaderOffset
, TmpLength
);
63 uint32_t End
= HeaderOffset
+ getLength();
64 if (!Data
.isValidOffsetForDataOfSize(HeaderOffset
, End
- HeaderOffset
)) {
65 uint32_t TmpLength
= getLength();
67 return createStringError(errc::invalid_argument
,
68 "section is not large enough to contain a .debug_addr table "
69 "of length 0x%" PRIx32
" at offset 0x%" PRIx32
,
70 TmpLength
, HeaderOffset
);
73 HeaderData
.Version
= Data
.getU16(OffsetPtr
);
74 HeaderData
.AddrSize
= Data
.getU8(OffsetPtr
);
75 HeaderData
.SegSize
= Data
.getU8(OffsetPtr
);
76 DataSize
= getDataSize();
78 HeaderData
.Version
= UnitVersion
;
79 HeaderData
.AddrSize
= AddrSize
;
80 // TODO: Support for non-zero SegSize.
81 HeaderData
.SegSize
= 0;
82 DataSize
= Data
.size();
85 // Perform basic validation of the remaining header fields.
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
);
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
)
100 return createStringError(errc::invalid_argument
,
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)
107 return createStringError(errc::not_supported
,
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)
112 return createStringError(errc::invalid_argument
,
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
);
118 // TODO: add support for non-zero segment selector size.
119 if (HeaderData
.SegSize
!= 0)
120 return createStringError(errc::not_supported
,
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) {
126 return createStringError(errc::invalid_argument
,
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
);
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
));
138 Addrs
.push_back(Data
.getU64(OffsetPtr
));
139 return Error::success();
142 void DWARFDebugAddrTable::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
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
,
151 static const char *Fmt32
= "0x%8.8" PRIx32
;
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
);
160 AddrFmt
.append(Fmt64
);
161 AddrFmtVerbose
.append(Fmt64
);
164 if (Addrs
.size() > 0) {
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
));
176 Expected
<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index
) const {
177 if (Index
< Addrs
.size())
179 return createStringError(errc::invalid_argument
,
180 "Index %" PRIu32
" is out of range of the "
181 ".debug_addr table at offset 0x%" PRIx32
,
182 Index
, HeaderOffset
);
185 uint32_t DWARFDebugAddrTable::getLength() const {
186 if (HeaderData
.Length
== 0)
188 // TODO: DWARF64 support.
189 return HeaderData
.Length
+ sizeof(uint32_t);
192 uint32_t DWARFDebugAddrTable::getDataSize() const {
195 if (getLength() == 0)
197 return getLength() - getHeaderSize();