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 //---------------------------------------------------------------------- 18 // DWARFAbbreviationDeclarationSet::Clear() 19 //---------------------------------------------------------------------- 20 void DWARFAbbreviationDeclarationSet::Clear() { 21 m_idx_offset = 0; 22 m_decls.clear(); 23 } 24 25 //---------------------------------------------------------------------- 26 // DWARFAbbreviationDeclarationSet::Extract() 27 //---------------------------------------------------------------------- 28 llvm::Error 29 DWARFAbbreviationDeclarationSet::extract(const DWARFDataExtractor &data, 30 lldb::offset_t *offset_ptr) { 31 const lldb::offset_t begin_offset = *offset_ptr; 32 m_offset = begin_offset; 33 Clear(); 34 DWARFAbbreviationDeclaration abbrevDeclaration; 35 dw_uleb128_t prev_abbr_code = 0; 36 DWARFEnumState state = DWARFEnumState::MoreItems; 37 while (state == DWARFEnumState::MoreItems) { 38 llvm::Expected<DWARFEnumState> es = 39 abbrevDeclaration.extract(data, offset_ptr); 40 if (!es) 41 return es.takeError(); 42 43 state = *es; 44 m_decls.push_back(abbrevDeclaration); 45 if (m_idx_offset == 0) 46 m_idx_offset = abbrevDeclaration.Code(); 47 else { 48 if (prev_abbr_code + 1 != abbrevDeclaration.Code()) 49 m_idx_offset = 50 UINT32_MAX; // Out of order indexes, we can't do O(1) lookups... 51 } 52 prev_abbr_code = abbrevDeclaration.Code(); 53 } 54 return llvm::ErrorSuccess(); 55 } 56 57 //---------------------------------------------------------------------- 58 // DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration() 59 //---------------------------------------------------------------------- 60 const DWARFAbbreviationDeclaration * 61 DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration( 62 dw_uleb128_t abbrCode) const { 63 if (m_idx_offset == UINT32_MAX) { 64 DWARFAbbreviationDeclarationCollConstIter pos; 65 DWARFAbbreviationDeclarationCollConstIter end = m_decls.end(); 66 for (pos = m_decls.begin(); pos != end; ++pos) { 67 if (pos->Code() == abbrCode) 68 return &(*pos); 69 } 70 } else { 71 uint32_t idx = abbrCode - m_idx_offset; 72 if (idx < m_decls.size()) 73 return &m_decls[idx]; 74 } 75 return NULL; 76 } 77 78 //---------------------------------------------------------------------- 79 // DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential() 80 // 81 // Append an abbreviation declaration with a sequential code for O(n) lookups. 82 // Handy when creating an DWARFAbbreviationDeclarationSet. 83 //---------------------------------------------------------------------- 84 dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential( 85 const DWARFAbbreviationDeclaration &abbrevDecl) { 86 // Get the next abbreviation code based on our current array size 87 dw_uleb128_t code = m_decls.size() + 1; 88 89 // Push the new declaration on the back 90 m_decls.push_back(abbrevDecl); 91 92 // Update the code for this new declaration 93 m_decls.back().SetCode(code); 94 95 return code; // return the new abbreviation code! 96 } 97 98 //---------------------------------------------------------------------- 99 // DWARFAbbreviationDeclarationSet::GetUnsupportedForms() 100 //---------------------------------------------------------------------- 101 void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( 102 std::set<dw_form_t> &invalid_forms) const { 103 for (const auto &abbr_decl : m_decls) { 104 const size_t num_attrs = abbr_decl.NumAttributes(); 105 for (size_t i=0; i<num_attrs; ++i) { 106 dw_form_t form = abbr_decl.GetFormByIndex(i); 107 if (!DWARFFormValue::FormIsSupported(form)) 108 invalid_forms.insert(form); 109 } 110 } 111 } 112 113 //---------------------------------------------------------------------- 114 // Encode 115 // 116 // Encode the abbreviation table onto the end of the buffer provided into a 117 // byte representation as would be found in a ".debug_abbrev" debug information 118 // section. 119 //---------------------------------------------------------------------- 120 // void 121 // DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf) 122 // const 123 //{ 124 // DWARFAbbreviationDeclarationCollConstIter pos; 125 // DWARFAbbreviationDeclarationCollConstIter end = m_decls.end(); 126 // for (pos = m_decls.begin(); pos != end; ++pos) 127 // pos->Append(debug_abbrev_buf); 128 // debug_abbrev_buf.Append8(0); 129 //} 130 131 //---------------------------------------------------------------------- 132 // DWARFDebugAbbrev constructor 133 //---------------------------------------------------------------------- 134 DWARFDebugAbbrev::DWARFDebugAbbrev() 135 : m_abbrevCollMap(), m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {} 136 137 //---------------------------------------------------------------------- 138 // DWARFDebugAbbrev::Parse() 139 //---------------------------------------------------------------------- 140 llvm::Error DWARFDebugAbbrev::parse(const DWARFDataExtractor &data) { 141 lldb::offset_t offset = 0; 142 143 while (data.ValidOffset(offset)) { 144 uint32_t initial_cu_offset = offset; 145 DWARFAbbreviationDeclarationSet abbrevDeclSet; 146 147 llvm::Error error = abbrevDeclSet.extract(data, &offset); 148 if (error) 149 return error; 150 151 m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet; 152 } 153 m_prev_abbr_offset_pos = m_abbrevCollMap.end(); 154 return llvm::ErrorSuccess(); 155 } 156 157 //---------------------------------------------------------------------- 158 // DWARFDebugAbbrev::GetAbbreviationDeclarationSet() 159 //---------------------------------------------------------------------- 160 const DWARFAbbreviationDeclarationSet * 161 DWARFDebugAbbrev::GetAbbreviationDeclarationSet( 162 dw_offset_t cu_abbr_offset) const { 163 DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end(); 164 DWARFAbbreviationDeclarationCollMapConstIter pos; 165 if (m_prev_abbr_offset_pos != end && 166 m_prev_abbr_offset_pos->first == cu_abbr_offset) 167 return &(m_prev_abbr_offset_pos->second); 168 else { 169 pos = m_abbrevCollMap.find(cu_abbr_offset); 170 m_prev_abbr_offset_pos = pos; 171 } 172 173 if (pos != m_abbrevCollMap.end()) 174 return &(pos->second); 175 return NULL; 176 } 177 178 //---------------------------------------------------------------------- 179 // DWARFDebugAbbrev::GetUnsupportedForms() 180 //---------------------------------------------------------------------- 181 void DWARFDebugAbbrev::GetUnsupportedForms( 182 std::set<dw_form_t> &invalid_forms) const { 183 for (const auto &pair : m_abbrevCollMap) 184 pair.second.GetUnsupportedForms(invalid_forms); 185 } 186