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 bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data
,
29 uint64_t *OffsetPtr
) {
31 const uint64_t BeginOffset
= *OffsetPtr
;
33 DWARFAbbreviationDeclaration AbbrDecl
;
34 uint32_t PrevAbbrCode
= 0;
35 while (AbbrDecl
.extract(Data
, OffsetPtr
)) {
36 if (FirstAbbrCode
== 0) {
37 FirstAbbrCode
= AbbrDecl
.getCode();
39 if (PrevAbbrCode
+ 1 != AbbrDecl
.getCode()) {
40 // Codes are not consecutive, can't do O(1) lookups.
41 FirstAbbrCode
= UINT32_MAX
;
44 PrevAbbrCode
= AbbrDecl
.getCode();
45 Decls
.push_back(std::move(AbbrDecl
));
47 return BeginOffset
!= *OffsetPtr
;
50 void DWARFAbbreviationDeclarationSet::dump(raw_ostream
&OS
) const {
51 for (const auto &Decl
: Decls
)
55 const DWARFAbbreviationDeclaration
*
56 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
57 uint32_t AbbrCode
) const {
58 if (FirstAbbrCode
== UINT32_MAX
) {
59 for (const auto &Decl
: Decls
) {
60 if (Decl
.getCode() == AbbrCode
)
65 if (AbbrCode
< FirstAbbrCode
|| AbbrCode
>= FirstAbbrCode
+ Decls
.size())
67 return &Decls
[AbbrCode
- FirstAbbrCode
];
70 std::string
DWARFAbbreviationDeclarationSet::getCodeRange() const {
71 // Create a sorted list of all abbrev codes.
72 std::vector
<uint32_t> Codes
;
73 Codes
.reserve(Decls
.size());
74 for (const auto &Decl
: Decls
)
75 Codes
.push_back(Decl
.getCode());
77 std::string Buffer
= "";
78 raw_string_ostream
Stream(Buffer
);
79 // Each iteration through this loop represents a single contiguous range in
81 for (auto Current
= Codes
.begin(), End
= Codes
.end(); Current
!= End
;) {
82 uint32_t RangeStart
= *Current
;
83 // Add the current range start.
85 uint32_t RangeEnd
= RangeStart
;
86 // Find the end of the current range.
87 while (++Current
!= End
&& *Current
== RangeEnd
+ 1)
89 // If there is more than one value in the range, add the range end too.
90 if (RangeStart
!= RangeEnd
)
91 Stream
<< "-" << RangeEnd
;
92 // If there is at least one more range, add a separator.
99 DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); }
101 void DWARFDebugAbbrev::clear() {
102 AbbrDeclSets
.clear();
103 PrevAbbrOffsetPos
= AbbrDeclSets
.end();
106 void DWARFDebugAbbrev::extract(DataExtractor Data
) {
111 void DWARFDebugAbbrev::parse() const {
115 auto I
= AbbrDeclSets
.begin();
116 while (Data
->isValidOffset(Offset
)) {
117 while (I
!= AbbrDeclSets
.end() && I
->first
< Offset
)
119 uint64_t CUAbbrOffset
= Offset
;
120 DWARFAbbreviationDeclarationSet AbbrDecls
;
121 if (!AbbrDecls
.extract(*Data
, &Offset
))
123 AbbrDeclSets
.insert(I
, std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)));
128 void DWARFDebugAbbrev::dump(raw_ostream
&OS
) const {
131 if (AbbrDeclSets
.empty()) {
136 for (const auto &I
: AbbrDeclSets
) {
137 OS
<< format("Abbrev table for offset: 0x%8.8" PRIx64
"\n", I
.first
);
142 const DWARFAbbreviationDeclarationSet
*
143 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset
) const {
144 const auto End
= AbbrDeclSets
.end();
145 if (PrevAbbrOffsetPos
!= End
&& PrevAbbrOffsetPos
->first
== CUAbbrOffset
) {
146 return &(PrevAbbrOffsetPos
->second
);
149 const auto Pos
= AbbrDeclSets
.find(CUAbbrOffset
);
151 PrevAbbrOffsetPos
= Pos
;
152 return &(Pos
->second
);
155 if (Data
&& CUAbbrOffset
< Data
->getData().size()) {
156 uint64_t Offset
= CUAbbrOffset
;
157 DWARFAbbreviationDeclarationSet AbbrDecls
;
158 if (!AbbrDecls
.extract(*Data
, &Offset
))
161 AbbrDeclSets
.insert(std::make_pair(CUAbbrOffset
, std::move(AbbrDecls
)))
163 return &PrevAbbrOffsetPos
->second
;