1 //===- DWARFDebugAbbrev.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/DWARFDebugAbbrev.h"
10 #include "llvm/Support/Format.h"
11 #include "llvm/Support/raw_ostream.h"
17 DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
21 void DWARFAbbreviationDeclarationSet::clear() {
27 Error
DWARFAbbreviationDeclarationSet::extract(DataExtractor Data
,
28 uint64_t *OffsetPtr
) {
30 const uint64_t BeginOffset
= *OffsetPtr
;
32 DWARFAbbreviationDeclaration AbbrDecl
;
33 uint32_t PrevAbbrCode
= 0;
35 Expected
<DWARFAbbreviationDeclaration::ExtractState
> ES
=
36 AbbrDecl
.extract(Data
, OffsetPtr
);
38 return ES
.takeError();
40 if (*ES
== DWARFAbbreviationDeclaration::ExtractState::Complete
)
43 if (FirstAbbrCode
== 0) {
44 FirstAbbrCode
= AbbrDecl
.getCode();
45 } else if (PrevAbbrCode
+ 1 != AbbrDecl
.getCode()) {
46 // Codes are not consecutive, can't do O(1) lookups.
47 FirstAbbrCode
= UINT32_MAX
;
49 PrevAbbrCode
= AbbrDecl
.getCode();
50 Decls
.push_back(std::move(AbbrDecl
));
52 return Error::success();
55 void DWARFAbbreviationDeclarationSet::dump(raw_ostream
&OS
) const {
56 for (const auto &Decl
: Decls
)
60 const DWARFAbbreviationDeclaration
*
61 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
62 uint32_t AbbrCode
) const {
63 if (FirstAbbrCode
== UINT32_MAX
) {
64 for (const auto &Decl
: Decls
) {
65 if (Decl
.getCode() == AbbrCode
)
70 if (AbbrCode
< FirstAbbrCode
|| AbbrCode
>= FirstAbbrCode
+ Decls
.size())
72 return &Decls
[AbbrCode
- FirstAbbrCode
];
75 std::string
DWARFAbbreviationDeclarationSet::getCodeRange() const {
76 // Create a sorted list of all abbrev codes.
77 std::vector
<uint32_t> Codes
;
78 Codes
.reserve(Decls
.size());
79 for (const auto &Decl
: Decls
)
80 Codes
.push_back(Decl
.getCode());
83 raw_string_ostream
Stream(Buffer
);
84 // Each iteration through this loop represents a single contiguous range in
86 for (auto Current
= Codes
.begin(), End
= Codes
.end(); Current
!= End
;) {
87 uint32_t RangeStart
= *Current
;
88 // Add the current range start.
90 uint32_t RangeEnd
= RangeStart
;
91 // Find the end of the current range.
92 while (++Current
!= End
&& *Current
== RangeEnd
+ 1)
94 // If there is more than one value in the range, add the range end too.
95 if (RangeStart
!= RangeEnd
)
96 Stream
<< "-" << RangeEnd
;
97 // If there is at least one more range, add a separator.
104 DWARFDebugAbbrev::DWARFDebugAbbrev(DataExtractor Data
)
105 : AbbrDeclSets(), PrevAbbrOffsetPos(AbbrDeclSets
.end()), Data(Data
) {}
107 Error
DWARFDebugAbbrev::parse() const {
109 return Error::success();
111 auto I
= AbbrDeclSets
.begin();
112 while (Data
->isValidOffset(Offset
)) {
113 while (I
!= AbbrDeclSets
.end() && I
->first
< Offset
)
115 uint64_t CUAbbrOffset
= Offset
;
116 DWARFAbbreviationDeclarationSet AbbrDecls
;
117 if (Error Err
= AbbrDecls
.extract(*Data
, &Offset
)) {
121 AbbrDeclSets
.insert(I
, std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)));
124 return Error::success();
127 void DWARFDebugAbbrev::dump(raw_ostream
&OS
) const {
128 if (Error Err
= parse())
129 // FIXME: We should propagate this error or otherwise display it.
130 llvm::consumeError(std::move(Err
));
132 if (AbbrDeclSets
.empty()) {
137 for (const auto &I
: AbbrDeclSets
) {
138 OS
<< format("Abbrev table for offset: 0x%8.8" PRIx64
"\n", I
.first
);
143 Expected
<const DWARFAbbreviationDeclarationSet
*>
144 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset
) const {
145 const auto End
= AbbrDeclSets
.end();
146 if (PrevAbbrOffsetPos
!= End
&& PrevAbbrOffsetPos
->first
== CUAbbrOffset
) {
147 return &PrevAbbrOffsetPos
->second
;
150 const auto Pos
= AbbrDeclSets
.find(CUAbbrOffset
);
152 PrevAbbrOffsetPos
= Pos
;
156 if (!Data
|| CUAbbrOffset
>= Data
->getData().size())
157 return make_error
<llvm::object::GenericBinaryError
>(
158 "the abbreviation offset into the .debug_abbrev section is not valid");
160 uint64_t Offset
= CUAbbrOffset
;
161 DWARFAbbreviationDeclarationSet AbbrDecls
;
162 if (Error Err
= AbbrDecls
.extract(*Data
, &Offset
))
163 return std::move(Err
);
166 AbbrDeclSets
.insert(std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)))
168 return &PrevAbbrOffsetPos
->second
;