Skip to content

Commit

Permalink
Add some more symbol accessor functions
Browse files Browse the repository at this point in the history
  • Loading branch information
chaoticgd committed Feb 17, 2024
1 parent 4279230 commit af6f16a
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 62 deletions.
107 changes: 83 additions & 24 deletions src/ccc/symbol_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ typename SymbolList<SymbolType>::NameToHandleMapIterators SymbolList<SymbolType>
return {iterators.first, iterators.second};
}

template <typename SymbolType>
SymbolHandle<SymbolType> SymbolList<SymbolType>::first_handle_after_address(Address address) const
{
auto iterator = m_address_to_handle.upper_bound(address.value);
if(iterator != m_address_to_handle.end()) {
return iterator->second;
} else {
return SymbolHandle<SymbolType>();
}
}

template <typename SymbolType>
SymbolHandle<SymbolType> SymbolList<SymbolType>::first_handle_from_name(const std::string& name) const
{
Expand Down Expand Up @@ -725,51 +736,78 @@ s32 SymbolDatabase::symbol_count() const
return sum;
}

const Symbol* SymbolDatabase::first_symbol_from_starting_address(Address address) const
const Symbol* SymbolDatabase::first_symbol_starting_at_address(
Address address, u32 descriptors, SymbolDescriptor* descriptor_out) const
{
#define CCC_X(SymbolType, symbol_list) \
if constexpr(SymbolType::FLAGS & WITH_ADDRESS_MAP) { \
const SymbolHandle<SymbolType> handle = symbol_list.first_handle_from_starting_address(address); \
const SymbolType* symbol = symbol_list.symbol_from_handle(handle); \
if(symbol) { \
return symbol; \
if(descriptors & SymbolType::DESCRIPTOR) { \
const SymbolHandle<SymbolType> handle = symbol_list.first_handle_from_starting_address(address); \
const SymbolType* symbol = symbol_list.symbol_from_handle(handle); \
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);
if(!handle.valid()) {
Result<SymbolSource*> source = symbol_sources.create_symbol(name, SymbolSourceHandle(), nullptr);
CCC_RETURN_IF_ERROR(source);
handle = (*source)->handle();
}
return handle;
}

void SymbolDatabase::clear()
const Symbol* SymbolDatabase::first_symbol_after_address(
Address address, u32 descriptors, SymbolDescriptor* descriptor_out) const
{
#define CCC_X(SymbolType, symbol_list) symbol_list.clear();
const Symbol* result = nullptr;
#define CCC_X(SymbolType, symbol_list) \
if constexpr(SymbolType::FLAGS & WITH_ADDRESS_MAP) { \
if(descriptors & SymbolType::DESCRIPTOR) { \
const SymbolHandle<SymbolType> handle = symbol_list.first_handle_after_address(address); \
const SymbolType* symbol = symbol_list.symbol_from_handle(handle); \
if(symbol && (!result || symbol->address() < result->address())) { \
if(descriptor_out) { \
*descriptor_out = SymbolType::DESCRIPTOR; \
} \
result = symbol; \
} \
} \
}
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
return result;
}

void SymbolDatabase::destroy_symbols_from_sources(SymbolSourceRange source_range)
const Symbol* SymbolDatabase::first_symbol_overlapping_address(
Address address, u32 descriptors, SymbolDescriptor* descriptor_out) const
{
#define CCC_X(SymbolType, symbol_list) symbol_list.destroy_symbols_from_sources(source_range);
#define CCC_X(SymbolType, symbol_list) \
if constexpr(SymbolType::FLAGS & WITH_ADDRESS_MAP) { \
if(descriptors & SymbolType::DESCRIPTOR) { \
const SymbolType* symbol = symbol_list.symbol_overlapping_address(address); \
if(symbol) { \
if(descriptor_out) { \
*descriptor_out = SymbolType::DESCRIPTOR; \
} \
return symbol; \
} \
} \
}
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
return nullptr;
}

void SymbolDatabase::destroy_symbols_from_modules(ModuleRange module_range)
Result<SymbolSourceHandle> SymbolDatabase::get_symbol_source(const std::string& name)
{
#define CCC_X(SymbolType, symbol_list) symbol_list.destroy_symbols_from_modules(module_range);
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
SymbolSourceHandle handle = symbol_sources.first_handle_from_name(name);
if(!handle.valid()) {
Result<SymbolSource*> source = symbol_sources.create_symbol(name, SymbolSourceHandle(), nullptr);
CCC_RETURN_IF_ERROR(source);
handle = (*source)->handle();
}
return handle;
}

Result<DataType*> SymbolDatabase::create_data_type_if_unique(
Expand Down Expand Up @@ -855,6 +893,20 @@ Result<DataType*> SymbolDatabase::create_data_type_if_unique(
return nullptr;
}

void SymbolDatabase::destroy_symbols_from_sources(SymbolSourceRange source_range)
{
#define CCC_X(SymbolType, symbol_list) symbol_list.destroy_symbols_from_sources(source_range);
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
}

void SymbolDatabase::destroy_symbols_from_modules(ModuleRange module_range)
{
#define CCC_X(SymbolType, symbol_list) symbol_list.destroy_symbols_from_modules(module_range);
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
}

bool SymbolDatabase::destroy_function(FunctionHandle handle)
{
Function* function = functions.symbol_from_handle(handle);
Expand All @@ -874,6 +926,13 @@ bool SymbolDatabase::destroy_function(FunctionHandle handle)
return functions.destroy_symbol(handle);
}

void SymbolDatabase::clear()
{
#define CCC_X(SymbolType, symbol_list) symbol_list.clear();
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
#undef CCC_X
}

// *****************************************************************************

MultiSymbolHandle::MultiSymbolHandle() {}
Expand Down
89 changes: 51 additions & 38 deletions src/ccc/symbol_database.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,21 @@ namespace ccc {
CCC_X(SymbolSource, symbol_sources)

// An enum for all the symbol types.
enum class SymbolDescriptor {
DATA_TYPE,
FUNCTION,
GLOBAL_VARIABLE,
LABEL,
LOCAL_VARIABLE,
MODULE,
PARAMETER_VARIABLE,
SECTION,
SOURCE_FILE,
SYMBOL_SOURCE
enum SymbolDescriptor {
DATA_TYPE = 1 << 0,
FUNCTION = 1 << 1,
GLOBAL_VARIABLE = 1 << 2,
LABEL = 1 << 3,
LOCAL_VARIABLE = 1 << 4,
MODULE = 1 << 5,
PARAMETER_VARIABLE = 1 << 6,
SECTION = 1 << 7,
SOURCE_FILE = 1 << 8,
SYMBOL_SOURCE = 1 << 9
};

enum {
ALL_SYMBOL_TYPES = 0xffff
};

// Forward declare all the different types of symbol objects.
Expand Down Expand Up @@ -152,9 +156,11 @@ class SymbolList {
using AddressToHandleMapIterators = Iterators<typename AddressToHandleMap::const_iterator>;
using NameToHandleMapIterators = Iterators<typename NameToHandleMap::const_iterator>;

// Lookup symbol by their address.
AddressToHandleMapIterators handles_from_starting_address(Address address) const;
AddressToHandleMapIterators handles_from_address_range(AddressRange range) const;
SymbolHandle<SymbolType> first_handle_from_starting_address(Address address) const;
SymbolHandle<SymbolType> first_handle_after_address(Address address) const;
NameToHandleMapIterators handles_from_name(const std::string& name) const;
SymbolHandle<SymbolType> first_handle_from_name(const std::string& name) const;

Expand All @@ -163,8 +169,10 @@ class SymbolList {
SymbolType* symbol_overlapping_address(Address address);
const SymbolType* symbol_overlapping_address(Address address) const;

// Convert handles to underlying array indices, for the JSON code.
// Convert handles to underlying array indices.
s32 index_from_handle(SymbolHandle<SymbolType> handle) const;

// Index into the underlying array.
SymbolType& symbol_from_index(s32 index);
const SymbolType& symbol_from_index(s32 index) const;

Expand Down Expand Up @@ -358,7 +366,7 @@ class DataType : public Symbol {
friend SourceFile;
friend SymbolList<DataType>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::DATA_TYPE;
static constexpr const SymbolDescriptor DESCRIPTOR = DATA_TYPE;
static constexpr const char* NAME = "Data Type";
static constexpr const u32 FLAGS = WITH_NAME_MAP;

Expand All @@ -378,7 +386,7 @@ class Function : public Symbol {

friend void write_json();
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::FUNCTION;
static constexpr const SymbolDescriptor DESCRIPTOR = FUNCTION;
static constexpr const char* NAME = "Function";
static constexpr const u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP | NAME_NEEDS_DEMANGLING;

Expand Down Expand Up @@ -434,7 +442,7 @@ class GlobalVariable : public Symbol {
friend SourceFile;
friend SymbolList<GlobalVariable>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::GLOBAL_VARIABLE;
static constexpr const SymbolDescriptor DESCRIPTOR = GLOBAL_VARIABLE;
static constexpr const char* NAME = "Global Variable";
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP | NAME_NEEDS_DEMANGLING;

Expand All @@ -457,7 +465,7 @@ class GlobalVariable : public Symbol {
class Label : public Symbol {
friend SymbolList<Label>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::LABEL;
static constexpr const SymbolDescriptor DESCRIPTOR = LABEL;
static constexpr const char* NAME = "Label";
static constexpr u32 FLAGS = WITH_ADDRESS_MAP;

Expand All @@ -470,7 +478,7 @@ class LocalVariable : public Symbol {
friend Function;
friend SymbolList<LocalVariable>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::LOCAL_VARIABLE;
static constexpr const SymbolDescriptor DESCRIPTOR = LOCAL_VARIABLE;
static constexpr const char* NAME = "Local Variable";
static constexpr u32 FLAGS = WITH_ADDRESS_MAP;

Expand All @@ -491,7 +499,7 @@ class LocalVariable : public Symbol {
// the symbol will be added to the address of the new symbol.
class Module : public Symbol {
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::MODULE;
static constexpr const SymbolDescriptor DESCRIPTOR = MODULE;
static constexpr const char* NAME = "Module";
static constexpr u32 FLAGS = WITH_NAME_MAP;

Expand All @@ -508,7 +516,7 @@ class ParameterVariable : public Symbol {
friend Function;
friend SymbolList<ParameterVariable>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::PARAMETER_VARIABLE;
static constexpr const SymbolDescriptor DESCRIPTOR = PARAMETER_VARIABLE;
static constexpr const char* NAME = "Parameter Variable";
static constexpr u32 FLAGS = NO_SYMBOL_FLAGS;

Expand All @@ -525,7 +533,7 @@ class ParameterVariable : public Symbol {
class Section : public Symbol {
friend SymbolList<Section>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::SECTION;
static constexpr const SymbolDescriptor DESCRIPTOR = SECTION;
static constexpr const char* NAME = "Section";
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP;

Expand All @@ -537,7 +545,7 @@ class Section : public Symbol {
class SourceFile : public Symbol {
friend SymbolList<SourceFile>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::SOURCE_FILE;
static constexpr const SymbolDescriptor DESCRIPTOR = SOURCE_FILE;
static constexpr const char* NAME = "Source File";
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP;

Expand Down Expand Up @@ -572,7 +580,7 @@ class SourceFile : public Symbol {
class SymbolSource : public Symbol {
friend SymbolList<SymbolSource>;
public:
static constexpr const SymbolDescriptor DESCRIPTOR = SymbolDescriptor::SYMBOL_SOURCE;
static constexpr const SymbolDescriptor DESCRIPTOR = SYMBOL_SOURCE;
static constexpr const char* NAME = "Symbol Source";
static constexpr u32 FLAGS = WITH_NAME_MAP;

Expand Down Expand Up @@ -607,17 +615,28 @@ class SymbolDatabase {
// Sum up the symbol counts for each symbol list.
s32 symbol_count() const;

// Find a symbol of any type that exists at the specified address. Symbols
// of the types specified higher up in the CCC_FOR_EACH_SYMBOL_TYPE_DO_X
// macro are checked for first.
const Symbol* first_symbol_from_starting_address(Address address) const;
// Find a symbol of any of the specified types given an address. Symbols of
// the types specified higher up in the CCC_FOR_EACH_SYMBOL_TYPE_DO_X macro
// are checked for first.
const Symbol* first_symbol_starting_at_address(
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
const Symbol* first_symbol_after_address(
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
const Symbol* first_symbol_overlapping_address(
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;

// Finds a symbol source object with the given name or creates one if it
// doesn't already exist.
Result<SymbolSourceHandle> get_symbol_source(const std::string& name);

// Destroy all the symbols in the symbol database.
void clear();
// Deduplicate matching data types with the same name. May replace the
// existing data type with the new one if the new one is better.
Result<DataType*> create_data_type_if_unique(
std::unique_ptr<ast::Node> node,
StabsTypeNumber number,
const char* name,
SourceFile& source_file,
const SymbolGroup& group);

// Destroy all the symbols that have symbol source handles within a given
// range. For example, you can use this to free a symbol table without
Expand All @@ -629,19 +648,13 @@ class SymbolDatabase {
// symbol tables for a given module.
void destroy_symbols_from_modules(ModuleRange module_range);

// Deduplicate matching data types with the same name. May replace the
// existing data type with the new one if the new one is better.
Result<DataType*> create_data_type_if_unique(
std::unique_ptr<ast::Node> node,
StabsTypeNumber number,
const char* name,
SourceFile& source_file,
const SymbolGroup& group);

// Destroy a function handle as well as all parameter variables and local
// variables associated with it.
bool destroy_function(FunctionHandle handle);

// Destroy all the symbols in the symbol database.
void clear();

template <typename Callback>
void for_each_symbol(Callback callback) {
// Use indices here to avoid iterator invalidation.
Expand Down Expand Up @@ -673,7 +686,7 @@ class MultiSymbolHandle {
friend auto operator<=>(const MultiSymbolHandle& lhs, const MultiSymbolHandle& rhs) = default;

protected:
SymbolDescriptor m_descriptor = SymbolDescriptor::DATA_TYPE;
SymbolDescriptor m_descriptor = DATA_TYPE;
u32 m_symbol_handle = (u32) -1;
};

Expand Down

0 comments on commit af6f16a

Please sign in to comment.