Both LLVM and LLDB implement DWARFAbbreviationDeclaration. As of
631ff46cbf, llvm's implementation of
DWARFAbbreviationDeclaration::extract behaves the same as LLDB's
implementation, making it easier to merge the implementations.
The only major difference between LLDB's implementation and LLVM's
implementation is that LLVM's DWARFAbbreviationDeclaration is slightly
larger. Specifically, it has some metadata that keeps track of the size
of a declaration (if it has a fixed size) so that it can potentially
optimize extraction in some scenarios. I think this increase in size
should be acceptable and possibly useful on the LLDB side.
Differential Revision: https://reviews.llvm.org/D150716
141 lines
4.5 KiB
C++
141 lines
4.5 KiB
C++
//===-- 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 "DWARFFormValue.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) {
|
|
llvm::DataExtractor llvm_data = data.GetAsLLVM();
|
|
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<llvm::DWARFAbbreviationDeclaration::ExtractState> es =
|
|
abbrevDeclaration.extract(llvm_data, offset_ptr);
|
|
if (!es)
|
|
return es.takeError();
|
|
if (*es == llvm::DWARFAbbreviationDeclaration::ExtractState::Complete)
|
|
break;
|
|
if (m_idx_offset == 0)
|
|
m_idx_offset = abbrevDeclaration.getCode();
|
|
else if (prev_abbr_code + 1 != abbrevDeclaration.getCode())
|
|
m_idx_offset = UINT32_MAX;
|
|
|
|
prev_abbr_code = abbrevDeclaration.getCode();
|
|
m_decls.push_back(abbrevDeclaration);
|
|
}
|
|
return llvm::ErrorSuccess();
|
|
}
|
|
|
|
// DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration()
|
|
const DWARFAbbreviationDeclaration *
|
|
DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(
|
|
uint32_t abbrCode) const {
|
|
if (m_idx_offset == UINT32_MAX) {
|
|
for (const auto &decl : m_decls) {
|
|
if (decl.getCode() == abbrCode)
|
|
return &decl;
|
|
}
|
|
return nullptr;
|
|
}
|
|
if (abbrCode < m_idx_offset || abbrCode >= m_idx_offset + m_decls.size())
|
|
return nullptr;
|
|
return &m_decls[abbrCode - m_idx_offset];
|
|
}
|
|
|
|
// DWARFAbbreviationDeclarationSet::GetUnsupportedForms()
|
|
void DWARFAbbreviationDeclarationSet::GetUnsupportedForms(
|
|
std::set<dw_form_t> &invalid_forms) const {
|
|
for (const auto &decl : m_decls) {
|
|
for (const auto &attr : decl.attributes()) {
|
|
if (!DWARFFormValue::FormIsSupported(attr.Form))
|
|
invalid_forms.insert(attr.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);
|
|
}
|