1 //===- DWARFListTable.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFListTable.h"
10 #include "llvm/BinaryFormat/Dwarf.h"
11 #include "llvm/Support/Errc.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/raw_ostream.h"
18 Error
DWARFListTableHeader::extract(DWARFDataExtractor Data
,
19 uint64_t *OffsetPtr
) {
20 HeaderOffset
= *OffsetPtr
;
21 // Read and verify the length field.
22 if (!Data
.isValidOffsetForDataOfSize(*OffsetPtr
, sizeof(uint32_t)))
23 return createStringError(errc::invalid_argument
,
24 "section is not large enough to contain a "
25 "%s table length at offset 0x%" PRIx64
,
26 SectionName
.data(), *OffsetPtr
);
27 // TODO: Add support for DWARF64.
28 HeaderData
.Length
= Data
.getRelocatedValue(4, OffsetPtr
);
29 if (HeaderData
.Length
== dwarf::DW_LENGTH_DWARF64
)
30 return createStringError(errc::not_supported
,
31 "DWARF64 is not supported in %s at offset 0x%" PRIx64
,
32 SectionName
.data(), HeaderOffset
);
33 Format
= dwarf::DwarfFormat::DWARF32
;
34 if (HeaderData
.Length
+ sizeof(uint32_t) < sizeof(Header
))
35 return createStringError(errc::invalid_argument
,
36 "%s table at offset 0x%" PRIx64
37 " has too small length (0x%" PRIx32
38 ") to contain a complete header",
39 SectionName
.data(), HeaderOffset
, length());
40 uint64_t End
= HeaderOffset
+ length();
41 if (!Data
.isValidOffsetForDataOfSize(HeaderOffset
, End
- HeaderOffset
))
42 return createStringError(errc::invalid_argument
,
43 "section is not large enough to contain a %s table "
44 "of length 0x%" PRIx32
" at offset 0x%" PRIx64
,
45 SectionName
.data(), length(), HeaderOffset
);
47 HeaderData
.Version
= Data
.getU16(OffsetPtr
);
48 HeaderData
.AddrSize
= Data
.getU8(OffsetPtr
);
49 HeaderData
.SegSize
= Data
.getU8(OffsetPtr
);
50 HeaderData
.OffsetEntryCount
= Data
.getU32(OffsetPtr
);
52 // Perform basic validation of the remaining header fields.
53 if (HeaderData
.Version
!= 5)
54 return createStringError(errc::invalid_argument
,
55 "unrecognised %s table version %" PRIu16
56 " in table at offset 0x%" PRIx64
,
57 SectionName
.data(), HeaderData
.Version
, HeaderOffset
);
58 if (HeaderData
.AddrSize
!= 4 && HeaderData
.AddrSize
!= 8)
59 return createStringError(errc::not_supported
,
60 "%s table at offset 0x%" PRIx64
61 " has unsupported address size %" PRIu8
,
62 SectionName
.data(), HeaderOffset
, HeaderData
.AddrSize
);
63 if (HeaderData
.SegSize
!= 0)
64 return createStringError(errc::not_supported
,
65 "%s table at offset 0x%" PRIx64
66 " has unsupported segment selector size %" PRIu8
,
67 SectionName
.data(), HeaderOffset
, HeaderData
.SegSize
);
68 if (End
< HeaderOffset
+ sizeof(HeaderData
) +
69 HeaderData
.OffsetEntryCount
* sizeof(uint32_t))
70 return createStringError(errc::invalid_argument
,
71 "%s table at offset 0x%" PRIx64
" has more offset entries (%" PRIu32
72 ") than there is space for",
73 SectionName
.data(), HeaderOffset
, HeaderData
.OffsetEntryCount
);
74 Data
.setAddressSize(HeaderData
.AddrSize
);
75 for (uint32_t I
= 0; I
< HeaderData
.OffsetEntryCount
; ++I
)
76 Offsets
.push_back(Data
.getRelocatedValue(4, OffsetPtr
));
77 return Error::success();
80 void DWARFListTableHeader::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
82 OS
<< format("0x%8.8" PRIx64
": ", HeaderOffset
);
84 "%s list header: length = 0x%8.8" PRIx32
", version = 0x%4.4" PRIx16
", "
85 "addr_size = 0x%2.2" PRIx8
", seg_size = 0x%2.2" PRIx8
86 ", offset_entry_count = "
88 ListTypeString
.data(), HeaderData
.Length
, HeaderData
.Version
,
89 HeaderData
.AddrSize
, HeaderData
.SegSize
, HeaderData
.OffsetEntryCount
);
91 if (HeaderData
.OffsetEntryCount
> 0) {
93 for (const auto &Off
: Offsets
) {
94 OS
<< format("\n0x%8.8" PRIx32
, Off
);
96 OS
<< format(" => 0x%8.8" PRIx64
,
97 Off
+ HeaderOffset
+ sizeof(HeaderData
));
103 uint32_t DWARFListTableHeader::length() const {
104 if (HeaderData
.Length
== 0)
106 // TODO: DWARF64 support.
107 return HeaderData
.Length
+ sizeof(uint32_t);