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