Summary: The DWP (DWARF package) format is used to pack multiple dwo files generated by split-dwarf into a single ELF file to make distributing them easier. It is part of the DWARFv5 spec and can be generated by dwp or llvm-dwp from a set of dwo files. Caviats: * Only the new version of the dwp format is supported (v2 in GNU numbering schema and v5 in the DWARF spec). The old version (v1) is already deprecated but binutils 2.24 still generates that one. * Combining DWP files with module debugging is not yet supported. Subscribers: emaste, mgorny, aprantl Differential Revision: https://reviews.llvm.org/D36062 llvm-svn: 311775
139 lines
4.5 KiB
C++
139 lines
4.5 KiB
C++
//===-- SymbolFileDWARFDwp.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "SymbolFileDWARFDwp.h"
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Core/Section.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "SymbolFileDWARFDwoDwp.h"
|
|
|
|
static llvm::DWARFSectionKind
|
|
lldbSectTypeToLlvmSectionKind(lldb::SectionType type) {
|
|
switch (type) {
|
|
case lldb::eSectionTypeDWARFDebugInfo:
|
|
return llvm::DW_SECT_INFO;
|
|
// case lldb::eSectionTypeDWARFDebugTypes:
|
|
// return llvm::DW_SECT_TYPES;
|
|
case lldb::eSectionTypeDWARFDebugAbbrev:
|
|
return llvm::DW_SECT_ABBREV;
|
|
case lldb::eSectionTypeDWARFDebugLine:
|
|
return llvm::DW_SECT_LINE;
|
|
case lldb::eSectionTypeDWARFDebugLoc:
|
|
return llvm::DW_SECT_LOC;
|
|
case lldb::eSectionTypeDWARFDebugStrOffsets:
|
|
return llvm::DW_SECT_STR_OFFSETS;
|
|
// case lldb::eSectionTypeDWARFDebugMacinfo:
|
|
// return llvm::DW_SECT_MACINFO;
|
|
case lldb::eSectionTypeDWARFDebugMacro:
|
|
return llvm::DW_SECT_MACRO;
|
|
default:
|
|
// Note: 0 is an invalid dwarf section kind.
|
|
return llvm::DWARFSectionKind(0);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<SymbolFileDWARFDwp>
|
|
SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp,
|
|
const lldb_private::FileSpec &file_spec) {
|
|
const lldb::offset_t file_offset = 0;
|
|
lldb::DataBufferSP file_data_sp;
|
|
lldb::offset_t file_data_offset = 0;
|
|
lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin(
|
|
module_sp, &file_spec, file_offset, file_spec.GetByteSize(), file_data_sp,
|
|
file_data_offset);
|
|
if (obj_file == nullptr)
|
|
return nullptr;
|
|
|
|
std::unique_ptr<SymbolFileDWARFDwp> dwp_symfile(
|
|
new SymbolFileDWARFDwp(module_sp, obj_file));
|
|
|
|
lldb_private::DWARFDataExtractor debug_cu_index;
|
|
if (!dwp_symfile->LoadRawSectionData(lldb::eSectionTypeDWARFDebugCuIndex,
|
|
debug_cu_index))
|
|
return nullptr;
|
|
|
|
llvm::DataExtractor llvm_debug_cu_index(
|
|
llvm::StringRef(debug_cu_index.PeekCStr(0), debug_cu_index.GetByteSize()),
|
|
debug_cu_index.GetByteOrder() == lldb::eByteOrderLittle,
|
|
debug_cu_index.GetAddressByteSize());
|
|
if (!dwp_symfile->m_debug_cu_index.parse(llvm_debug_cu_index))
|
|
return nullptr;
|
|
return dwp_symfile;
|
|
}
|
|
|
|
SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp,
|
|
lldb::ObjectFileSP obj_file)
|
|
: m_obj_file(std::move(obj_file)), m_debug_cu_index(llvm::DW_SECT_INFO) {
|
|
for (const auto &entry : m_debug_cu_index.getRows()) {
|
|
m_debug_cu_index_map.emplace(entry.getSignature(), &entry);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<SymbolFileDWARFDwo>
|
|
SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu,
|
|
uint64_t dwo_id) {
|
|
return std::unique_ptr<SymbolFileDWARFDwo>(
|
|
new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id));
|
|
}
|
|
|
|
bool SymbolFileDWARFDwp::LoadSectionData(
|
|
uint64_t dwo_id, lldb::SectionType sect_type,
|
|
lldb_private::DWARFDataExtractor &data) {
|
|
lldb_private::DWARFDataExtractor section_data;
|
|
if (!LoadRawSectionData(sect_type, section_data))
|
|
return false;
|
|
|
|
auto it = m_debug_cu_index_map.find(dwo_id);
|
|
if (it == m_debug_cu_index_map.end())
|
|
return false;
|
|
|
|
auto *offsets =
|
|
it->second->getOffset(lldbSectTypeToLlvmSectionKind(sect_type));
|
|
if (offsets) {
|
|
data.SetData(section_data, offsets->Offset, offsets->Length);
|
|
} else {
|
|
data.SetData(section_data, 0, section_data.GetByteSize());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SymbolFileDWARFDwp::LoadRawSectionData(
|
|
lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) {
|
|
std::lock_guard<std::mutex> lock(m_sections_mutex);
|
|
|
|
auto it = m_sections.find(sect_type);
|
|
if (it != m_sections.end()) {
|
|
if (it->second.GetByteSize() == 0)
|
|
return false;
|
|
|
|
data = it->second;
|
|
return true;
|
|
}
|
|
|
|
const lldb_private::SectionList *section_list =
|
|
m_obj_file->GetSectionList(false /* update_module_section_list */);
|
|
if (section_list) {
|
|
lldb::SectionSP section_sp(
|
|
section_list->FindSectionByType(sect_type, true));
|
|
if (section_sp) {
|
|
if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) {
|
|
m_sections[sect_type] = data;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
m_sections[sect_type].Clear();
|
|
return false;
|
|
}
|