xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1 //===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DWARFDebugAbbrev.h"
10 #include "DWARFDataExtractor.h"
11 #include "lldb/Utility/Stream.h"
12 
13 using namespace lldb;
14 using namespace lldb_private;
15 
16 // DWARFAbbreviationDeclarationSet::Clear()
Clear()17 void DWARFAbbreviationDeclarationSet::Clear() {
18   m_idx_offset = 0;
19   m_decls.clear();
20 }
21 
22 // DWARFAbbreviationDeclarationSet::Extract()
23 llvm::Error
extract(const DWARFDataExtractor & data,lldb::offset_t * offset_ptr)24 DWARFAbbreviationDeclarationSet::extract(const DWARFDataExtractor &data,
25                                          lldb::offset_t *offset_ptr) {
26   const lldb::offset_t begin_offset = *offset_ptr;
27   m_offset = begin_offset;
28   Clear();
29   DWARFAbbreviationDeclaration abbrevDeclaration;
30   dw_uleb128_t prev_abbr_code = 0;
31   while (true) {
32     llvm::Expected<DWARFEnumState> es =
33         abbrevDeclaration.extract(data, offset_ptr);
34     if (!es)
35       return es.takeError();
36     if (*es == DWARFEnumState::Complete)
37       break;
38     m_decls.push_back(abbrevDeclaration);
39     if (m_idx_offset == 0)
40       m_idx_offset = abbrevDeclaration.Code();
41     else if (prev_abbr_code + 1 != abbrevDeclaration.Code()) {
42       // Out of order indexes, we can't do O(1) lookups...
43       m_idx_offset = UINT32_MAX;
44     }
45     prev_abbr_code = abbrevDeclaration.Code();
46   }
47   return llvm::ErrorSuccess();
48 }
49 
50 // DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration()
51 const DWARFAbbreviationDeclaration *
GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const52 DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(
53     dw_uleb128_t abbrCode) const {
54   if (m_idx_offset == UINT32_MAX) {
55     DWARFAbbreviationDeclarationCollConstIter pos;
56     DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
57     for (pos = m_decls.begin(); pos != end; ++pos) {
58       if (pos->Code() == abbrCode)
59         return &(*pos);
60     }
61   } else {
62     uint32_t idx = abbrCode - m_idx_offset;
63     if (idx < m_decls.size())
64       return &m_decls[idx];
65   }
66   return nullptr;
67 }
68 
69 
70 // DWARFAbbreviationDeclarationSet::GetUnsupportedForms()
GetUnsupportedForms(std::set<dw_form_t> & invalid_forms) const71 void DWARFAbbreviationDeclarationSet::GetUnsupportedForms(
72     std::set<dw_form_t> &invalid_forms) const {
73   for (const auto &abbr_decl : m_decls) {
74     const size_t num_attrs = abbr_decl.NumAttributes();
75     for (size_t i=0; i<num_attrs; ++i) {
76       dw_form_t form = abbr_decl.GetFormByIndex(i);
77       if (!DWARFFormValue::FormIsSupported(form))
78         invalid_forms.insert(form);
79     }
80   }
81 }
82 
83 // Encode
84 //
85 // Encode the abbreviation table onto the end of the buffer provided into a
86 // byte representation as would be found in a ".debug_abbrev" debug information
87 // section.
88 // void
89 // DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf)
90 // const
91 //{
92 //  DWARFAbbreviationDeclarationCollConstIter pos;
93 //  DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
94 //  for (pos = m_decls.begin(); pos != end; ++pos)
95 //      pos->Append(debug_abbrev_buf);
96 //  debug_abbrev_buf.Append8(0);
97 //}
98 
99 // DWARFDebugAbbrev constructor
DWARFDebugAbbrev()100 DWARFDebugAbbrev::DWARFDebugAbbrev()
101     : m_abbrevCollMap(), m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {}
102 
103 // DWARFDebugAbbrev::Parse()
parse(const DWARFDataExtractor & data)104 llvm::Error DWARFDebugAbbrev::parse(const DWARFDataExtractor &data) {
105   lldb::offset_t offset = 0;
106 
107   while (data.ValidOffset(offset)) {
108     uint32_t initial_cu_offset = offset;
109     DWARFAbbreviationDeclarationSet abbrevDeclSet;
110 
111     llvm::Error error = abbrevDeclSet.extract(data, &offset);
112     if (error)
113       return error;
114 
115     m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
116   }
117   m_prev_abbr_offset_pos = m_abbrevCollMap.end();
118   return llvm::ErrorSuccess();
119 }
120 
121 // DWARFDebugAbbrev::GetAbbreviationDeclarationSet()
122 const DWARFAbbreviationDeclarationSet *
GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const123 DWARFDebugAbbrev::GetAbbreviationDeclarationSet(
124     dw_offset_t cu_abbr_offset) const {
125   DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
126   DWARFAbbreviationDeclarationCollMapConstIter pos;
127   if (m_prev_abbr_offset_pos != end &&
128       m_prev_abbr_offset_pos->first == cu_abbr_offset)
129     return &(m_prev_abbr_offset_pos->second);
130   else {
131     pos = m_abbrevCollMap.find(cu_abbr_offset);
132     m_prev_abbr_offset_pos = pos;
133   }
134 
135   if (pos != m_abbrevCollMap.end())
136     return &(pos->second);
137   return nullptr;
138 }
139 
140 // DWARFDebugAbbrev::GetUnsupportedForms()
GetUnsupportedForms(std::set<dw_form_t> & invalid_forms) const141 void DWARFDebugAbbrev::GetUnsupportedForms(
142     std::set<dw_form_t> &invalid_forms) const {
143   for (const auto &pair : m_abbrevCollMap)
144     pair.second.GetUnsupportedForms(invalid_forms);
145 }
146