124 changes: 71 additions & 53 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,69 +42,87 @@ void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) {
m_compile_units.clear();
}

DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
if (m_cu_aranges_up == NULL && m_dwarf2Data) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));

m_cu_aranges_up.reset(new DWARFDebugAranges());
const DWARFDataExtractor &debug_aranges_data =
m_dwarf2Data->get_debug_aranges_data();
if (debug_aranges_data.GetByteSize() > 0) {
if (log)
log->Printf(
"DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from "
".debug_aranges",
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
m_cu_aranges_up->Extract(debug_aranges_data);
}
llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
if (m_cu_aranges_up)
return *m_cu_aranges_up;

assert(m_dwarf2Data);

Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));

m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>();
const DWARFDataExtractor &debug_aranges_data =
m_dwarf2Data->get_debug_aranges_data();
if (debug_aranges_data.GetByteSize() > 0) {
if (log)
log->Printf(
"DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from "
".debug_aranges",
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data);
if (error)
return std::move(error);
}

// Make a list of all CUs represented by the arange data in the file.
std::set<dw_offset_t> cus_with_data;
for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
if (offset != DW_INVALID_OFFSET)
cus_with_data.insert(offset);
}
// Make a list of all CUs represented by the arange data in the file.
std::set<dw_offset_t> cus_with_data;
for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
if (offset != DW_INVALID_OFFSET)
cus_with_data.insert(offset);
}

// Manually build arange data for everything that wasn't in the
// .debug_aranges table.
bool printed = false;
const size_t num_compile_units = GetNumCompileUnits();
for (size_t idx = 0; idx < num_compile_units; ++idx) {
DWARFUnit *cu = GetCompileUnitAtIndex(idx);

dw_offset_t offset = cu->GetOffset();
if (cus_with_data.find(offset) == cus_with_data.end()) {
if (log) {
if (!printed)
log->Printf(
"DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
printed = true;
}
cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_up.get());
// Manually build arange data for everything that wasn't in the
// .debug_aranges table.
bool printed = false;
const size_t num_compile_units = GetNumCompileUnits();
for (size_t idx = 0; idx < num_compile_units; ++idx) {
DWARFUnit *cu = GetCompileUnitAtIndex(idx);

dw_offset_t offset = cu->GetOffset();
if (cus_with_data.find(offset) == cus_with_data.end()) {
if (log) {
if (!printed)
log->Printf(
"DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
printed = true;
}
cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_up.get());
}

const bool minimize = true;
m_cu_aranges_up->Sort(minimize);
}

const bool minimize = true;
m_cu_aranges_up->Sort(minimize);
return *m_cu_aranges_up;
}

void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
if (m_compile_units.empty()) {
if (m_dwarf2Data != NULL) {
lldb::offset_t offset = 0;
DWARFUnitSP cu_sp;
const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
&offset))) {
m_compile_units.push_back(cu_sp);

offset = cu_sp->GetNextCompileUnitOffset();
}
if (!m_compile_units.empty())
return;
if (!m_dwarf2Data)
return;

lldb::offset_t offset = 0;
const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();

while (debug_info_data.ValidOffset(offset)) {
llvm::Expected<DWARFUnitSP> cu_sp =
DWARFCompileUnit::extract(m_dwarf2Data, debug_info_data, &offset);

if (!cu_sp) {
// FIXME: Propagate this error up.
llvm::consumeError(cu_sp.takeError());
return;
}

// If it didn't return an error, then it should be returning a valid
// CompileUnit.
assert(*cu_sp);

m_compile_units.push_back(*cu_sp);

offset = (*cu_sp)->GetNextCompileUnitOffset();
}
}

Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
#include <map>
#include <vector>

#include "DWARFUnit.h"
#include "DWARFDIE.h"
#include "DWARFUnit.h"
#include "SymbolFileDWARF.h"
#include "lldb/Core/STLUtils.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/Error.h"

typedef std::multimap<const char *, dw_offset_t, CStringCompareFunctionObject>
CStringToDIEMap;
Expand Down Expand Up @@ -50,7 +51,7 @@ class DWARFDebugInfo {
(1 << 2) // Show all parent DIEs when dumping single DIEs
};

DWARFDebugAranges &GetCompileUnitAranges();
llvm::Expected<DWARFDebugAranges &> GetCompileUnitAranges();

protected:
static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset,
Expand Down
14 changes: 12 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1758,8 +1758,18 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,

DWARFDebugInfo *debug_info = DebugInfo();
if (debug_info) {
const dw_offset_t cu_offset =
debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr);
llvm::Expected<DWARFDebugAranges &> aranges =
debug_info->GetCompileUnitAranges();
if (!aranges) {
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO |
DWARF_LOG_DEBUG_ARANGES);
LLDB_LOG_ERROR(log, aranges.takeError(),
"SymbolFileDWARF::ResolveSymbolContext failed to get cu "
"aranges. {0}");
return 0;
}

const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr);
if (cu_offset == DW_INVALID_OFFSET) {
// Global variables are not in the compile unit address ranges. The
// only way to currently find global variables is to iterate over the
Expand Down