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 Format
= dwarf::DwarfFormat::DWARF32
;
28 uint8_t OffsetByteSize
= 4;
29 HeaderData
.Length
= Data
.getRelocatedValue(4, OffsetPtr
);
30 if (HeaderData
.Length
== dwarf::DW_LENGTH_DWARF64
) {
31 Format
= dwarf::DwarfFormat::DWARF64
;
33 HeaderData
.Length
= Data
.getU64(OffsetPtr
);
34 } else if (HeaderData
.Length
>= dwarf::DW_LENGTH_lo_reserved
) {
35 return createStringError(errc::invalid_argument
,
36 "%s table at offset 0x%" PRIx64
37 " has unsupported reserved unit length of value 0x%8.8" PRIx64
,
38 SectionName
.data(), HeaderOffset
, HeaderData
.Length
);
41 HeaderData
.Length
+ dwarf::getUnitLengthFieldByteSize(Format
);
42 assert(FullLength
== length());
43 if (FullLength
< getHeaderSize(Format
))
44 return createStringError(errc::invalid_argument
,
45 "%s table at offset 0x%" PRIx64
46 " has too small length (0x%" PRIx64
47 ") to contain a complete header",
48 SectionName
.data(), HeaderOffset
, FullLength
);
49 uint64_t End
= HeaderOffset
+ FullLength
;
50 if (!Data
.isValidOffsetForDataOfSize(HeaderOffset
, FullLength
))
51 return createStringError(errc::invalid_argument
,
52 "section is not large enough to contain a %s table "
53 "of length 0x%" PRIx64
" at offset 0x%" PRIx64
,
54 SectionName
.data(), FullLength
, HeaderOffset
);
56 HeaderData
.Version
= Data
.getU16(OffsetPtr
);
57 HeaderData
.AddrSize
= Data
.getU8(OffsetPtr
);
58 HeaderData
.SegSize
= Data
.getU8(OffsetPtr
);
59 HeaderData
.OffsetEntryCount
= Data
.getU32(OffsetPtr
);
61 // Perform basic validation of the remaining header fields.
62 if (HeaderData
.Version
!= 5)
63 return createStringError(errc::invalid_argument
,
64 "unrecognised %s table version %" PRIu16
65 " in table at offset 0x%" PRIx64
,
66 SectionName
.data(), HeaderData
.Version
, HeaderOffset
);
67 if (HeaderData
.AddrSize
!= 4 && HeaderData
.AddrSize
!= 8)
68 return createStringError(errc::not_supported
,
69 "%s table at offset 0x%" PRIx64
70 " has unsupported address size %" PRIu8
,
71 SectionName
.data(), HeaderOffset
, HeaderData
.AddrSize
);
72 if (HeaderData
.SegSize
!= 0)
73 return createStringError(errc::not_supported
,
74 "%s table at offset 0x%" PRIx64
75 " has unsupported segment selector size %" PRIu8
,
76 SectionName
.data(), HeaderOffset
, HeaderData
.SegSize
);
77 if (End
< HeaderOffset
+ getHeaderSize(Format
) +
78 HeaderData
.OffsetEntryCount
* OffsetByteSize
)
79 return createStringError(errc::invalid_argument
,
80 "%s table at offset 0x%" PRIx64
" has more offset entries (%" PRIu32
81 ") than there is space for",
82 SectionName
.data(), HeaderOffset
, HeaderData
.OffsetEntryCount
);
83 Data
.setAddressSize(HeaderData
.AddrSize
);
84 for (uint32_t I
= 0; I
< HeaderData
.OffsetEntryCount
; ++I
)
85 Offsets
.push_back(Data
.getRelocatedValue(OffsetByteSize
, OffsetPtr
));
86 return Error::success();
89 void DWARFListTableHeader::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
91 OS
<< format("0x%8.8" PRIx64
": ", HeaderOffset
);
93 "%s list header: length = 0x%8.8" PRIx64
", version = 0x%4.4" PRIx16
", "
94 "addr_size = 0x%2.2" PRIx8
", seg_size = 0x%2.2" PRIx8
95 ", offset_entry_count = "
97 ListTypeString
.data(), HeaderData
.Length
, HeaderData
.Version
,
98 HeaderData
.AddrSize
, HeaderData
.SegSize
, HeaderData
.OffsetEntryCount
);
100 if (HeaderData
.OffsetEntryCount
> 0) {
102 for (const auto &Off
: Offsets
) {
103 OS
<< format("\n0x%8.8" PRIx64
, Off
);
104 if (DumpOpts
.Verbose
)
105 OS
<< format(" => 0x%8.8" PRIx64
,
106 Off
+ HeaderOffset
+ getHeaderSize(Format
));
112 uint64_t DWARFListTableHeader::length() const {
113 if (HeaderData
.Length
== 0)
115 return HeaderData
.Length
+ dwarf::getUnitLengthFieldByteSize(Format
);