Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 110 additions & 1 deletion src/ccc/symbol_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,95 @@ SymbolHandle<SymbolType> SymbolList<SymbolType>::first_handle_from_mangled_name(
return iterator->second;
}

template <typename SymbolType>
std::vector<SymbolType*> SymbolList<SymbolType>::symbols_from_raw_name(const std::string& raw_name)
{
std::vector<SymbolType*> symbols;
std::set<SymbolHandle<SymbolType>> handles;

// All mangled names are raw names.
std::vector<SymbolHandle<SymbolType>> mangled_name_handles = handles_from_mangled_name(raw_name);
for (SymbolHandle<SymbolType> handle : mangled_name_handles) {
SymbolType* symbol = symbol_from_handle(handle);
CCC_ASSERT(symbol);

symbols.emplace_back(symbol);
handles.emplace(handle);
}

// Regular names are raw names if the symbol has no mangled name.
std::vector<SymbolHandle<SymbolType>> name_handles = handles_from_name(raw_name);
for (SymbolHandle<SymbolType> handle : name_handles) {
if (handles.contains(handle)) {
continue;
}

SymbolType* symbol = symbol_from_handle(handle);
CCC_ASSERT(symbol);

if constexpr (SymbolType::FLAGS & MANGLED_NAMES) {
if (!symbol->mangled_name().empty()) {
continue;
}
}

symbols.emplace_back(symbol);
}

return symbols;
}

template <typename SymbolType>
std::vector<const SymbolType*> SymbolList<SymbolType>::symbols_from_raw_name(const std::string& raw_name) const
{
std::vector<SymbolType*> symbols = const_cast<SymbolList<SymbolType>*>(this)->symbols_from_raw_name(raw_name);

// Make a copy of the vector to add the const. Bit silly.
std::vector<const SymbolType*> copy;
copy.reserve(symbols.size());
for (const SymbolType* symbol : symbols) {
copy.emplace_back(symbol);
}

return copy;
}

template <typename SymbolType>
SymbolType* SymbolList<SymbolType>::first_symbol_from_raw_name(const std::string& raw_name)
{
// All mangled names are raw names.
SymbolHandle<SymbolType> mangled_handle = first_handle_from_mangled_name(raw_name);
if (mangled_handle.valid()) {
SymbolType* symbol = symbol_from_handle(mangled_handle);
CCC_ASSERT(symbol);

return symbol;
}

// Regular names are raw names if the symbol has no mangled name.
std::vector<SymbolHandle<SymbolType>> name_handles = handles_from_name(raw_name);
for (SymbolHandle<SymbolType> handle : name_handles) {
SymbolType* symbol = symbol_from_handle(handle);
CCC_ASSERT(symbol);

if constexpr (SymbolType::FLAGS & MANGLED_NAMES) {
if (!symbol->mangled_name().empty()) {
continue;
}
}

return symbol;
}

return nullptr;
}

template <typename SymbolType>
const SymbolType* SymbolList<SymbolType>::first_symbol_from_raw_name(const std::string& raw_name) const
{
return const_cast<SymbolList<SymbolType>*>(this)->first_symbol_from_raw_name(raw_name);
}

template <typename SymbolType>
s32 SymbolList<SymbolType>::index_from_handle(SymbolHandle<SymbolType> handle) const
{
Expand Down Expand Up @@ -1004,7 +1093,7 @@ const Symbol* SymbolDatabase::symbol_overlapping_address(
return nullptr;
}

const Symbol* SymbolDatabase::symbol_with_name(
const Symbol* SymbolDatabase::symbol_from_name(
const std::string& name, u32 descriptors, SymbolDescriptor* descriptor_out) const
{
#define CCC_X(SymbolType, symbol_list) \
Expand All @@ -1025,6 +1114,26 @@ const Symbol* SymbolDatabase::symbol_with_name(
return nullptr;
}

const Symbol* SymbolDatabase::symbol_from_raw_name(
const std::string& name, u32 descriptors, SymbolDescriptor* descriptor_out) const
{
#define CCC_X(SymbolType, symbol_list) \
if constexpr (SymbolType::FLAGS & WITH_ADDRESS_MAP) { \
if (descriptors & SymbolType::DESCRIPTOR) { \
const SymbolType* symbol = symbol_list.first_symbol_from_raw_name(name); \
if (symbol) { \
if (descriptor_out) { \
*descriptor_out = SymbolType::DESCRIPTOR; \
} \
return symbol; \
} \
} \
}
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
return nullptr;
}

Result<SymbolSourceHandle> SymbolDatabase::get_symbol_source(const std::string& name)
{
SymbolSourceHandle handle = symbol_sources.first_handle_from_name(name);
Expand Down
14 changes: 13 additions & 1 deletion src/ccc/symbol_database.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ class SymbolList
std::vector<SymbolHandle<SymbolType>> handles_from_mangled_name(const std::string& mangled_name) const;
SymbolHandle<SymbolType> first_handle_from_mangled_name(const std::string& mangled_name) const;

// Lookup symbols by their raw name, mangled or not.
std::vector<SymbolType*> symbols_from_raw_name(const std::string& raw_name);
std::vector<const SymbolType*> symbols_from_raw_name(const std::string& raw_name) const;
SymbolType* first_symbol_from_raw_name(const std::string& raw_name);
const SymbolType* first_symbol_from_raw_name(const std::string& raw_name) const;

// Convert handles to underlying array indices.
s32 index_from_handle(SymbolHandle<SymbolType> handle) const;

Expand Down Expand Up @@ -667,7 +673,13 @@ class SymbolDatabase
// Find a symbol of any of the specified types given its name. Symbols of
// the types specified higher up in the CCC_FOR_EACH_SYMBOL_TYPE_DO_X macro
// are checked for first.
const Symbol* symbol_with_name(
const Symbol* symbol_from_name(
const std::string& name, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;

// Find a symbol of any of the specified types given its raw name.
// Symbols of the types specified higher up in the
// CCC_FOR_EACH_SYMBOL_TYPE_DO_X macro are checked for first.
const Symbol* symbol_from_raw_name(
const std::string& name, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;

// Finds a symbol source object with the given name or creates one if it
Expand Down
40 changes: 40 additions & 0 deletions test/ccc/symbol_database_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,46 @@ TEST(CCCSymbolDatabase, UnmangledSymbolsNotInMangledNameMap)
EXPECT_EQ(empty.size(), 0);
}

TEST(CCCSymbolDatabase, SymbolsFromRawName)
{
DemanglerFunctions demangler;
demangler.cplus_demangle = cplus_demangle;
demangler.cplus_demangle_opname = cplus_demangle_opname;

u32 flags = NO_IMPORTER_FLAGS;

SymbolDatabase database;

Result<SymbolSource*> source = database.symbol_sources.create_symbol("Source", SymbolSourceHandle());
CCC_GTEST_FAIL_IF_ERROR(source);

Result<Function*> a = database.functions.create_symbol(
"A", (*source)->handle(), nullptr, Address(), flags, demangler);
CCC_GTEST_FAIL_IF_ERROR(a);

Result<Function*> b_1 = database.functions.create_symbol(
"B__Fi", (*source)->handle(), nullptr, Address(), flags, demangler);
CCC_GTEST_FAIL_IF_ERROR(b_1);

auto functions_1 = database.functions.symbols_from_raw_name("A");
EXPECT_EQ(functions_1.size(), 1);

auto functions_2 = database.functions.symbols_from_raw_name("B__Fi");
EXPECT_EQ(functions_2.size(), 1);

auto functions_3 = database.functions.symbols_from_raw_name("B(int)");
EXPECT_EQ(functions_3.size(), 0);

const Function* function_1 = database.functions.first_symbol_from_raw_name("A");
EXPECT_TRUE(function_1);

const Function* function_2 = database.functions.first_symbol_from_raw_name("B__Fi");
EXPECT_TRUE(function_2);

const Function* function_3 = database.functions.first_symbol_from_raw_name("B(int)");
EXPECT_FALSE(function_3);
}

static Result<FunctionHandle> create_function(
SymbolDatabase& database, SymbolSourceHandle source, const char* name, Address address, u32 size)
{
Expand Down
Loading