This is the behavior expected by DWARF. It also requires some fixups to algorithms which were storing the addresses of some objects (Blocks and Variables) relative to the beginning of the function. There are plenty of things that still don't work in this setups, but this change is sufficient for the expression evaluator to correctly recognize the entry point of a function in this case.
259 lines
9.0 KiB
C++
259 lines
9.0 KiB
C++
//===-- SymbolFileSymtab.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 "SymbolFileSymtab.h"
|
|
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Symbol/CompileUnit.h"
|
|
#include "lldb/Symbol/Function.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
#include "lldb/Symbol/Symbol.h"
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
#include "lldb/Symbol/Symtab.h"
|
|
#include "lldb/Symbol/TypeList.h"
|
|
#include "lldb/Utility/RegularExpression.h"
|
|
#include "lldb/Utility/Timer.h"
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
LLDB_PLUGIN_DEFINE(SymbolFileSymtab)
|
|
|
|
char SymbolFileSymtab::ID;
|
|
|
|
void SymbolFileSymtab::Initialize() {
|
|
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
|
GetPluginDescriptionStatic(), CreateInstance);
|
|
}
|
|
|
|
void SymbolFileSymtab::Terminate() {
|
|
PluginManager::UnregisterPlugin(CreateInstance);
|
|
}
|
|
|
|
llvm::StringRef SymbolFileSymtab::GetPluginDescriptionStatic() {
|
|
return "Reads debug symbols from an object file's symbol table.";
|
|
}
|
|
|
|
SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFileSP objfile_sp) {
|
|
return new SymbolFileSymtab(std::move(objfile_sp));
|
|
}
|
|
|
|
void SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope,
|
|
TypeClass type_mask,
|
|
lldb_private::TypeList &type_list) {}
|
|
|
|
SymbolFileSymtab::SymbolFileSymtab(ObjectFileSP objfile_sp)
|
|
: SymbolFileCommon(std::move(objfile_sp)), m_source_indexes(),
|
|
m_func_indexes(), m_code_indexes(), m_objc_class_name_to_index() {}
|
|
|
|
uint32_t SymbolFileSymtab::CalculateAbilities() {
|
|
uint32_t abilities = 0;
|
|
if (m_objfile_sp) {
|
|
const Symtab *symtab = m_objfile_sp->GetSymtab();
|
|
if (symtab) {
|
|
// The snippet of code below will get the indexes the module symbol table
|
|
// entries that are code, data, or function related (debug info), sort
|
|
// them by value (address) and dump the sorted symbols.
|
|
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile,
|
|
m_source_indexes)) {
|
|
abilities |= CompileUnits;
|
|
}
|
|
|
|
if (symtab->AppendSymbolIndexesWithType(
|
|
eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny,
|
|
m_func_indexes)) {
|
|
symtab->SortSymbolIndexesByValue(m_func_indexes, true);
|
|
abilities |= Functions;
|
|
}
|
|
|
|
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo,
|
|
Symtab::eVisibilityAny,
|
|
m_code_indexes)) {
|
|
symtab->SortSymbolIndexesByValue(m_code_indexes, true);
|
|
abilities |= Functions;
|
|
}
|
|
|
|
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData,
|
|
m_data_indexes)) {
|
|
symtab->SortSymbolIndexesByValue(m_data_indexes, true);
|
|
abilities |= GlobalVariables;
|
|
}
|
|
|
|
lldb_private::Symtab::IndexCollection objc_class_indexes;
|
|
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeObjCClass,
|
|
objc_class_indexes)) {
|
|
symtab->AppendSymbolNamesToMap(objc_class_indexes, true, true,
|
|
m_objc_class_name_to_index);
|
|
m_objc_class_name_to_index.Sort();
|
|
}
|
|
}
|
|
}
|
|
return abilities;
|
|
}
|
|
|
|
uint32_t SymbolFileSymtab::CalculateNumCompileUnits() {
|
|
// If we don't have any source file symbols we will just have one compile
|
|
// unit for the entire object file
|
|
if (m_source_indexes.empty())
|
|
return 0;
|
|
|
|
// If we have any source file symbols we will logically organize the object
|
|
// symbols using these.
|
|
return m_source_indexes.size();
|
|
}
|
|
|
|
CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) {
|
|
CompUnitSP cu_sp;
|
|
|
|
// If we don't have any source file symbols we will just have one compile
|
|
// unit for the entire object file
|
|
if (idx < m_source_indexes.size()) {
|
|
const Symbol *cu_symbol =
|
|
m_objfile_sp->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
|
|
if (cu_symbol)
|
|
cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr,
|
|
cu_symbol->GetName().AsCString(), 0,
|
|
eLanguageTypeUnknown, eLazyBoolNo);
|
|
}
|
|
return cu_sp;
|
|
}
|
|
|
|
lldb::LanguageType SymbolFileSymtab::ParseLanguage(CompileUnit &comp_unit) {
|
|
return eLanguageTypeUnknown;
|
|
}
|
|
|
|
size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) {
|
|
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
|
|
size_t num_added = 0;
|
|
// We must at least have a valid compile unit
|
|
const Symtab *symtab = m_objfile_sp->GetSymtab();
|
|
const Symbol *curr_symbol = nullptr;
|
|
const Symbol *next_symbol = nullptr;
|
|
// const char *prefix = m_objfile_sp->SymbolPrefix();
|
|
// if (prefix == NULL)
|
|
// prefix == "";
|
|
//
|
|
// const uint32_t prefix_len = strlen(prefix);
|
|
|
|
// If we don't have any source file symbols we will just have one compile
|
|
// unit for the entire object file
|
|
if (m_source_indexes.empty()) {
|
|
// The only time we will have a user ID of zero is when we don't have and
|
|
// source file symbols and we declare one compile unit for the entire
|
|
// object file
|
|
if (!m_func_indexes.empty()) {
|
|
}
|
|
|
|
if (!m_code_indexes.empty()) {
|
|
// StreamFile s(stdout);
|
|
// symtab->Dump(&s, m_code_indexes);
|
|
|
|
uint32_t idx = 0; // Index into the indexes
|
|
const uint32_t num_indexes = m_code_indexes.size();
|
|
for (idx = 0; idx < num_indexes; ++idx) {
|
|
uint32_t symbol_idx = m_code_indexes[idx];
|
|
curr_symbol = symtab->SymbolAtIndex(symbol_idx);
|
|
if (curr_symbol) {
|
|
// Union of all ranges in the function DIE (if the function is
|
|
// discontiguous)
|
|
AddressRange func_range(curr_symbol->GetAddress(), 0);
|
|
if (func_range.GetBaseAddress().IsSectionOffset()) {
|
|
uint32_t symbol_size = curr_symbol->GetByteSize();
|
|
if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
|
|
func_range.SetByteSize(symbol_size);
|
|
else if (idx + 1 < num_indexes) {
|
|
next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
|
|
if (next_symbol) {
|
|
func_range.SetByteSize(
|
|
next_symbol->GetAddressRef().GetOffset() -
|
|
curr_symbol->GetAddressRef().GetOffset());
|
|
}
|
|
}
|
|
|
|
FunctionSP func_sp(new Function(
|
|
&comp_unit,
|
|
symbol_idx, // UserID is the DIE offset
|
|
LLDB_INVALID_UID, // We don't have any type info
|
|
// for this function
|
|
curr_symbol->GetMangled(), // Linker/mangled name
|
|
nullptr, // no return type for a code symbol...
|
|
curr_symbol->GetAddress(), AddressRanges{func_range}));
|
|
|
|
if (func_sp.get() != nullptr) {
|
|
comp_unit.AddFunction(func_sp);
|
|
++num_added;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// We assume we
|
|
}
|
|
return num_added;
|
|
}
|
|
|
|
size_t SymbolFileSymtab::ParseTypes(CompileUnit &comp_unit) { return 0; }
|
|
|
|
bool SymbolFileSymtab::ParseLineTable(CompileUnit &comp_unit) { return false; }
|
|
|
|
bool SymbolFileSymtab::ParseDebugMacros(CompileUnit &comp_unit) {
|
|
return false;
|
|
}
|
|
|
|
bool SymbolFileSymtab::ParseSupportFiles(CompileUnit &comp_unit,
|
|
SupportFileList &support_files) {
|
|
return false;
|
|
}
|
|
|
|
bool SymbolFileSymtab::ParseImportedModules(
|
|
const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
|
|
return false;
|
|
}
|
|
|
|
size_t SymbolFileSymtab::ParseBlocksRecursive(Function &func) { return 0; }
|
|
|
|
size_t SymbolFileSymtab::ParseVariablesForContext(const SymbolContext &sc) {
|
|
return 0;
|
|
}
|
|
|
|
Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::optional<SymbolFile::ArrayInfo>
|
|
SymbolFileSymtab::GetDynamicArrayInfoForUID(
|
|
lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
|
|
return std::nullopt;
|
|
}
|
|
|
|
bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr,
|
|
SymbolContextItem resolve_scope,
|
|
SymbolContext &sc) {
|
|
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
|
|
if (m_objfile_sp->GetSymtab() == nullptr)
|
|
return 0;
|
|
|
|
uint32_t resolved_flags = 0;
|
|
if (resolve_scope & eSymbolContextSymbol) {
|
|
sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(
|
|
so_addr.GetFileAddress());
|
|
if (sc.symbol)
|
|
resolved_flags |= eSymbolContextSymbol;
|
|
}
|
|
return resolved_flags;
|
|
}
|