summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
blob: 2c02fbe64f54ae5b610269baf0c40d0ac6dafc3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugAbbrev.h"
#include "DWARFDataExtractor.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

// DWARFAbbreviationDeclarationSet::Clear()
void DWARFAbbreviationDeclarationSet::Clear() {
  m_idx_offset = 0;
  m_decls.clear();
}

// DWARFAbbreviationDeclarationSet::Extract()
llvm::Error
DWARFAbbreviationDeclarationSet::extract(const DWARFDataExtractor &data,
                                         lldb::offset_t *offset_ptr) {
  const lldb::offset_t begin_offset = *offset_ptr;
  m_offset = begin_offset;
  Clear();
  DWARFAbbreviationDeclaration abbrevDeclaration;
  uint32_t prev_abbr_code = 0;
  while (true) {
    llvm::Expected<DWARFEnumState> es =
        abbrevDeclaration.extract(data, offset_ptr);
    if (!es)
      return es.takeError();
    if (*es == DWARFEnumState::Complete)
      break;
    m_decls.push_back(abbrevDeclaration);
    if (m_idx_offset == 0)
      m_idx_offset = abbrevDeclaration.Code();
    else if (prev_abbr_code + 1 != abbrevDeclaration.Code()) {
      // Out of order indexes, we can't do O(1) lookups...
      m_idx_offset = UINT32_MAX;
    }
    prev_abbr_code = abbrevDeclaration.Code();
  }
  return llvm::ErrorSuccess();
}

// DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration()
const DWARFAbbreviationDeclaration *
DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(
    uint32_t abbrCode) const {
  if (m_idx_offset == UINT32_MAX) {
    DWARFAbbreviationDeclarationCollConstIter pos;
    DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
    for (pos = m_decls.begin(); pos != end; ++pos) {
      if (pos->Code() == abbrCode)
        return &(*pos);
    }
  } else {
    uint32_t idx = abbrCode - m_idx_offset;
    if (idx < m_decls.size())
      return &m_decls[idx];
  }
  return nullptr;
}

// DWARFAbbreviationDeclarationSet::GetUnsupportedForms()
void DWARFAbbreviationDeclarationSet::GetUnsupportedForms(
    std::set<dw_form_t> &invalid_forms) const {
  for (const auto &abbr_decl : m_decls) {
    const size_t num_attrs = abbr_decl.NumAttributes();
    for (size_t i=0; i<num_attrs; ++i) {
      dw_form_t form = abbr_decl.GetFormByIndex(i);
      if (!DWARFFormValue::FormIsSupported(form))
        invalid_forms.insert(form);
    }
  }
}

// Encode
//
// Encode the abbreviation table onto the end of the buffer provided into a
// byte representation as would be found in a ".debug_abbrev" debug information
// section.
// void
// DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf)
// const
//{
//  DWARFAbbreviationDeclarationCollConstIter pos;
//  DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
//  for (pos = m_decls.begin(); pos != end; ++pos)
//      pos->Append(debug_abbrev_buf);
//  debug_abbrev_buf.Append8(0);
//}

// DWARFDebugAbbrev constructor
DWARFDebugAbbrev::DWARFDebugAbbrev()
    : m_abbrevCollMap(), m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {}

// DWARFDebugAbbrev::Parse()
llvm::Error DWARFDebugAbbrev::parse(const DWARFDataExtractor &data) {
  lldb::offset_t offset = 0;

  while (data.ValidOffset(offset)) {
    uint32_t initial_cu_offset = offset;
    DWARFAbbreviationDeclarationSet abbrevDeclSet;

    llvm::Error error = abbrevDeclSet.extract(data, &offset);
    if (error)
      return error;

    m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
  }
  m_prev_abbr_offset_pos = m_abbrevCollMap.end();
  return llvm::ErrorSuccess();
}

// DWARFDebugAbbrev::GetAbbreviationDeclarationSet()
const DWARFAbbreviationDeclarationSet *
DWARFDebugAbbrev::GetAbbreviationDeclarationSet(
    dw_offset_t cu_abbr_offset) const {
  DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
  DWARFAbbreviationDeclarationCollMapConstIter pos;
  if (m_prev_abbr_offset_pos != end &&
      m_prev_abbr_offset_pos->first == cu_abbr_offset)
    return &(m_prev_abbr_offset_pos->second);
  else {
    pos = m_abbrevCollMap.find(cu_abbr_offset);
    m_prev_abbr_offset_pos = pos;
  }

  if (pos != m_abbrevCollMap.end())
    return &(pos->second);
  return nullptr;
}

// DWARFDebugAbbrev::GetUnsupportedForms()
void DWARFDebugAbbrev::GetUnsupportedForms(
    std::set<dw_form_t> &invalid_forms) const {
  for (const auto &pair : m_abbrevCollMap)
    pair.second.GetUnsupportedForms(invalid_forms);
}