to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
215 lines
6.6 KiB
C++
215 lines
6.6 KiB
C++
//===-- SymbolFileBreakpad.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// 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 "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
|
|
#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
|
|
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Core/Section.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
#include "lldb/Symbol/TypeMap.h"
|
|
#include "lldb/Utility/Log.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::breakpad;
|
|
|
|
namespace {
|
|
class LineIterator {
|
|
public:
|
|
// begin iterator for sections of given type
|
|
LineIterator(ObjectFile &obj, ConstString section_type)
|
|
: m_obj(&obj), m_section_type(section_type), m_next_section_idx(0) {
|
|
++*this;
|
|
}
|
|
|
|
// end iterator
|
|
explicit LineIterator(ObjectFile &obj)
|
|
: m_obj(&obj),
|
|
m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)) {}
|
|
|
|
friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs) {
|
|
assert(lhs.m_obj == rhs.m_obj);
|
|
if (lhs.m_next_section_idx != rhs.m_next_section_idx)
|
|
return true;
|
|
if (lhs.m_next_text.data() != rhs.m_next_text.data())
|
|
return true;
|
|
assert(lhs.m_current_text == rhs.m_current_text);
|
|
assert(rhs.m_next_text == rhs.m_next_text);
|
|
return false;
|
|
}
|
|
|
|
const LineIterator &operator++();
|
|
llvm::StringRef operator*() const { return m_current_text; }
|
|
|
|
private:
|
|
ObjectFile *m_obj;
|
|
ConstString m_section_type;
|
|
uint32_t m_next_section_idx;
|
|
llvm::StringRef m_current_text;
|
|
llvm::StringRef m_next_text;
|
|
};
|
|
} // namespace
|
|
|
|
const LineIterator &LineIterator::operator++() {
|
|
const SectionList &list = *m_obj->GetSectionList();
|
|
size_t num_sections = list.GetNumSections(0);
|
|
while (m_next_text.empty() && m_next_section_idx < num_sections) {
|
|
Section § = *list.GetSectionAtIndex(m_next_section_idx++);
|
|
if (sect.GetName() != m_section_type)
|
|
continue;
|
|
DataExtractor data;
|
|
m_obj->ReadSectionData(§, data);
|
|
m_next_text =
|
|
llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
|
|
data.GetByteSize());
|
|
}
|
|
std::tie(m_current_text, m_next_text) = m_next_text.split('\n');
|
|
return *this;
|
|
}
|
|
|
|
static llvm::iterator_range<LineIterator> lines(ObjectFile &obj,
|
|
ConstString section_type) {
|
|
return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj));
|
|
}
|
|
|
|
void SymbolFileBreakpad::Initialize() {
|
|
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
|
GetPluginDescriptionStatic(), CreateInstance,
|
|
DebuggerInitialize);
|
|
}
|
|
|
|
void SymbolFileBreakpad::Terminate() {
|
|
PluginManager::UnregisterPlugin(CreateInstance);
|
|
}
|
|
|
|
ConstString SymbolFileBreakpad::GetPluginNameStatic() {
|
|
static ConstString g_name("breakpad");
|
|
return g_name;
|
|
}
|
|
|
|
uint32_t SymbolFileBreakpad::CalculateAbilities() {
|
|
if (!m_obj_file)
|
|
return 0;
|
|
if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic())
|
|
return 0;
|
|
|
|
return CompileUnits | Functions;
|
|
}
|
|
|
|
uint32_t SymbolFileBreakpad::GetNumCompileUnits() {
|
|
// TODO
|
|
return 0;
|
|
}
|
|
|
|
CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
|
|
// TODO
|
|
return nullptr;
|
|
}
|
|
|
|
size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) {
|
|
// TODO
|
|
return 0;
|
|
}
|
|
|
|
bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {
|
|
// TODO
|
|
return 0;
|
|
}
|
|
|
|
uint32_t
|
|
SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
|
|
SymbolContextItem resolve_scope,
|
|
SymbolContext &sc) {
|
|
// TODO
|
|
return 0;
|
|
}
|
|
|
|
uint32_t SymbolFileBreakpad::FindFunctions(
|
|
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
|
|
FunctionNameType name_type_mask, bool include_inlines, bool append,
|
|
SymbolContextList &sc_list) {
|
|
// TODO
|
|
if (!append)
|
|
sc_list.Clear();
|
|
return sc_list.GetSize();
|
|
}
|
|
|
|
uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex,
|
|
bool include_inlines, bool append,
|
|
SymbolContextList &sc_list) {
|
|
// TODO
|
|
if (!append)
|
|
sc_list.Clear();
|
|
return sc_list.GetSize();
|
|
}
|
|
|
|
uint32_t SymbolFileBreakpad::FindTypes(
|
|
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
|
|
bool append, uint32_t max_matches,
|
|
llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
|
|
if (!append)
|
|
types.Clear();
|
|
return types.GetSize();
|
|
}
|
|
|
|
size_t
|
|
SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context,
|
|
bool append, TypeMap &types) {
|
|
if (!append)
|
|
types.Clear();
|
|
return types.GetSize();
|
|
}
|
|
|
|
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
|
|
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
|
|
Module &module = *m_obj_file->GetModule();
|
|
addr_t base = module.GetObjectFile()->GetBaseAddress().GetFileAddress();
|
|
if (base == LLDB_INVALID_ADDRESS) {
|
|
LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping "
|
|
"symtab population.");
|
|
return;
|
|
}
|
|
|
|
const SectionList &list = *module.GetSectionList();
|
|
for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) {
|
|
auto record = PublicRecord::parse(line);
|
|
if (!record) {
|
|
LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line);
|
|
continue;
|
|
}
|
|
addr_t file_address = base + record->getAddress();
|
|
|
|
SectionSP section_sp = list.FindSectionContainingFileAddress(file_address);
|
|
if (!section_sp) {
|
|
LLDB_LOG(log,
|
|
"Ignoring symbol {0}, whose address ({1}) is outside of the "
|
|
"object file. Mismatched symbol file?",
|
|
record->getName(), file_address);
|
|
continue;
|
|
}
|
|
|
|
symtab.AddSymbol(Symbol(
|
|
/*symID*/ 0, Mangled(record->getName(), /*is_mangled*/ false),
|
|
eSymbolTypeCode,
|
|
/*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false,
|
|
/*is_artificial*/ false,
|
|
AddressRange(section_sp, file_address - section_sp->GetFileAddress(),
|
|
0),
|
|
/*size_is_valid*/ 0, /*contains_linker_annotations*/ false,
|
|
/*flags*/ 0));
|
|
}
|
|
|
|
// TODO: Process FUNC records as well.
|
|
|
|
symtab.CalculateSymbolSizes();
|
|
}
|