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"
18 DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
22 void DWARFAbbreviationDeclarationSet::clear() {
28 Error
DWARFAbbreviationDeclarationSet::extract(DataExtractor Data
,
29 uint64_t *OffsetPtr
) {
31 const uint64_t BeginOffset
= *OffsetPtr
;
33 DWARFAbbreviationDeclaration AbbrDecl
;
34 uint32_t PrevAbbrCode
= 0;
36 Expected
<DWARFAbbreviationDeclaration::ExtractState
> ES
=
37 AbbrDecl
.extract(Data
, OffsetPtr
);
39 return ES
.takeError();
41 if (*ES
== DWARFAbbreviationDeclaration::ExtractState::Complete
)
44 if (FirstAbbrCode
== 0) {
45 FirstAbbrCode
= AbbrDecl
.getCode();
46 } else if (PrevAbbrCode
+ 1 != AbbrDecl
.getCode()) {
47 // Codes are not consecutive, can't do O(1) lookups.
48 FirstAbbrCode
= UINT32_MAX
;
50 PrevAbbrCode
= AbbrDecl
.getCode();
51 Decls
.push_back(std::move(AbbrDecl
));
53 return Error::success();
56 void DWARFAbbreviationDeclarationSet::dump(raw_ostream
&OS
) const {
57 for (const auto &Decl
: Decls
)
61 const DWARFAbbreviationDeclaration
*
62 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
63 uint32_t AbbrCode
) const {
64 if (FirstAbbrCode
== UINT32_MAX
) {
65 for (const auto &Decl
: Decls
) {
66 if (Decl
.getCode() == AbbrCode
)
71 if (AbbrCode
< FirstAbbrCode
|| AbbrCode
>= FirstAbbrCode
+ Decls
.size())
73 return &Decls
[AbbrCode
- FirstAbbrCode
];
76 std::string
DWARFAbbreviationDeclarationSet::getCodeRange() const {
77 // Create a sorted list of all abbrev codes.
78 std::vector
<uint32_t> Codes
;
79 Codes
.reserve(Decls
.size());
80 for (const auto &Decl
: Decls
)
81 Codes
.push_back(Decl
.getCode());
84 raw_string_ostream
Stream(Buffer
);
85 // Each iteration through this loop represents a single contiguous range in
87 for (auto Current
= Codes
.begin(), End
= Codes
.end(); Current
!= End
;) {
88 uint32_t RangeStart
= *Current
;
89 // Add the current range start.
91 uint32_t RangeEnd
= RangeStart
;
92 // Find the end of the current range.
93 while (++Current
!= End
&& *Current
== RangeEnd
+ 1)
95 // If there is more than one value in the range, add the range end too.
96 if (RangeStart
!= RangeEnd
)
97 Stream
<< "-" << RangeEnd
;
98 // If there is at least one more range, add a separator.
105 DWARFDebugAbbrev::DWARFDebugAbbrev(DataExtractor Data
)
106 : AbbrDeclSets(), PrevAbbrOffsetPos(AbbrDeclSets
.end()), Data(Data
) {}
108 Error
DWARFDebugAbbrev::parse() const {
110 return Error::success();
112 auto I
= AbbrDeclSets
.begin();
113 while (Data
->isValidOffset(Offset
)) {
114 while (I
!= AbbrDeclSets
.end() && I
->first
< Offset
)
116 uint64_t CUAbbrOffset
= Offset
;
117 DWARFAbbreviationDeclarationSet AbbrDecls
;
118 if (Error Err
= AbbrDecls
.extract(*Data
, &Offset
)) {
122 AbbrDeclSets
.insert(I
, std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)));
125 return Error::success();
128 void DWARFDebugAbbrev::dump(raw_ostream
&OS
) const {
129 if (Error Err
= parse())
130 // FIXME: We should propagate this error or otherwise display it.
131 llvm::consumeError(std::move(Err
));
133 if (AbbrDeclSets
.empty()) {
138 for (const auto &I
: AbbrDeclSets
) {
139 OS
<< format("Abbrev table for offset: 0x%8.8" PRIx64
"\n", I
.first
);
144 Expected
<const DWARFAbbreviationDeclarationSet
*>
145 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset
) const {
146 const auto End
= AbbrDeclSets
.end();
147 if (PrevAbbrOffsetPos
!= End
&& PrevAbbrOffsetPos
->first
== CUAbbrOffset
) {
148 return &PrevAbbrOffsetPos
->second
;
151 const auto Pos
= AbbrDeclSets
.find(CUAbbrOffset
);
153 PrevAbbrOffsetPos
= Pos
;
157 if (!Data
|| CUAbbrOffset
>= Data
->getData().size())
158 return make_error
<llvm::object::GenericBinaryError
>(
159 "the abbreviation offset into the .debug_abbrev section is not valid");
161 uint64_t Offset
= CUAbbrOffset
;
162 DWARFAbbreviationDeclarationSet AbbrDecls
;
163 if (Error Err
= AbbrDecls
.extract(*Data
, &Offset
))
164 return std::move(Err
);
167 AbbrDeclSets
.insert(std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)))
169 return &PrevAbbrOffsetPos
->second
;