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