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