Xamarin Public Jenkins (auto-signing) 468663ddbb Imported Upstream version 6.10.0.49
Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
2020-01-16 16:38:04 +00:00

256 lines
8.2 KiB
C++

//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DWARFDebugPubnames.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugInfo.h"
#include "DWARFFormValue.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
using namespace lldb;
using namespace lldb_private;
DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
bool DWARFDebugPubnames::Extract(const DWARFDataExtractor &data) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
"DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
(uint64_t)data.GetByteSize());
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
if (log)
log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
(uint64_t)data.GetByteSize());
if (data.ValidOffset(0)) {
lldb::offset_t offset = 0;
DWARFDebugPubnamesSet set;
while (data.ValidOffset(offset)) {
if (set.Extract(data, &offset)) {
m_sets.push_back(set);
offset = set.GetOffsetOfNextEntry();
} else
break;
}
if (log)
Dump(log);
return true;
}
return false;
}
bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
"DWARFDebugPubnames::GeneratePubnames (data = %p)",
static_cast<void *>(dwarf2Data));
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
if (log)
log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
static_cast<void *>(dwarf2Data));
m_sets.clear();
DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
if (debug_info) {
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
DWARFFormValue::FixedFormSizes fixed_form_sizes =
DWARFFormValue::GetFixedFormSizesForAddressSize(
cu->GetAddressByteSize(), cu->IsDWARF64());
bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
DWARFDIECollection dies;
const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
cu->AppendDIEsWithTag(DW_TAG_variable, dies);
dw_offset_t cu_offset = cu->GetOffset();
DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
cu->GetNextCompileUnitOffset() -
cu_offset);
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx) {
DWARFDIE die = dies.GetDIEAtIndex(die_idx);
DWARFAttributes attributes;
const char *name = NULL;
const char *mangled = NULL;
bool add_die = false;
const size_t num_attributes = die.GetDIE()->GetAttributes(
die.GetCU(), fixed_form_sizes, attributes);
if (num_attributes > 0) {
uint32_t i;
dw_tag_t tag = die.Tag();
for (i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
switch (attr) {
case DW_AT_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
name = form_value.AsCString();
break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
mangled = form_value.AsCString();
break;
case DW_AT_low_pc:
case DW_AT_ranges:
case DW_AT_entry_pc:
if (tag == DW_TAG_subprogram)
add_die = true;
break;
case DW_AT_location:
if (tag == DW_TAG_variable) {
DWARFDIE parent_die = die.GetParent();
while (parent_die) {
switch (parent_die.Tag()) {
case DW_TAG_subprogram:
case DW_TAG_lexical_block:
case DW_TAG_inlined_subroutine:
// Even if this is a function level static, we don't add it.
// We could theoretically
// add these if we wanted to by introspecting into the
// DW_AT_location and seeing
// if the location describes a hard coded address, but we
// don't want the performance
// penalty of that right now.
add_die = false;
parent_die.Clear(); // Terminate the while loop.
break;
case DW_TAG_compile_unit:
add_die = true;
parent_die.Clear(); // Terminate the while loop.
break;
default:
parent_die =
parent_die.GetParent(); // Keep going in the while loop.
break;
}
}
}
break;
}
}
}
if (add_die && (name || mangled)) {
pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
mangled ? mangled : name);
}
}
if (pubnames_set.NumDescriptors() > 0) {
m_sets.push_back(pubnames_set);
}
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if (clear_dies)
cu->ClearDIEs(true);
}
}
if (m_sets.empty())
return false;
if (log)
Dump(log);
return true;
}
bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
m_sets.clear();
DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
if (debug_info) {
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
DWARFDIECollection dies;
const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_base_type, dies);
dw_offset_t cu_offset = cu->GetOffset();
DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
cu->GetNextCompileUnitOffset() -
cu_offset);
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx) {
DWARFDIE die = dies.GetDIEAtIndex(die_idx);
const char *name = die.GetName();
if (name)
pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
}
if (pubnames_set.NumDescriptors() > 0) {
m_sets.push_back(pubnames_set);
}
}
}
return !m_sets.empty();
}
void DWARFDebugPubnames::Dump(Log *s) const {
if (m_sets.empty())
s->PutCString("< EMPTY >\n");
else {
const_iterator pos;
const_iterator end = m_sets.end();
for (pos = m_sets.begin(); pos != end; ++pos)
(*pos).Dump(s);
}
}
bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
std::vector<dw_offset_t> &die_offsets) const {
const_iterator pos;
const_iterator end = m_sets.end();
die_offsets.clear();
for (pos = m_sets.begin(); pos != end; ++pos) {
(*pos).Find(name, ignore_case, die_offsets);
}
return !die_offsets.empty();
}
bool DWARFDebugPubnames::Find(const RegularExpression &regex,
std::vector<dw_offset_t> &die_offsets) const {
const_iterator pos;
const_iterator end = m_sets.end();
die_offsets.clear();
for (pos = m_sets.begin(); pos != end; ++pos) {
(*pos).Find(regex, die_offsets);
}
return !die_offsets.empty();
}