fix: add missing symbol store and PDB debug info sources

These files were referenced in CMakeLists.txt and main.cpp but
never committed, breaking the CI build.
This commit is contained in:
IChooseYou
2026-03-14 08:13:58 -06:00
committed by IChooseYou
parent 5b2cf1ae1f
commit 5d2d324946
7 changed files with 664 additions and 6 deletions

95
src/symbolstore.h Normal file
View File

@@ -0,0 +1,95 @@
#pragma once
#include <QString>
#include <QStringList>
#include <QHash>
#include <QVector>
#include <QPair>
#include <algorithm>
namespace rcx {
class Provider; // forward declaration
struct PdbSymbolSet {
QString pdbPath;
QString moduleName; // canonical lowercase name (e.g. "ntoskrnl")
QHash<QString, uint32_t> nameToRva;
QVector<QPair<uint32_t, QString>> rvaToName; // sorted by RVA for binary search
void sortRvaIndex() {
std::sort(rvaToName.begin(), rvaToName.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
}
};
class SymbolStore {
public:
static SymbolStore& instance() {
static SymbolStore s;
return s;
}
// Add a pre-extracted symbol set for a module.
// moduleName is the canonical name (e.g. "ntoskrnl").
// Returns the number of unique symbols stored.
int addModule(const QString& moduleName, const QString& pdbPath,
const QVector<QPair<QString, uint32_t>>& symbols);
// Unload symbols for a module.
void unloadModule(const QString& moduleName);
// Resolve a token from the expression parser.
// Handles "module!symbol" (qualified) and bare "symbol" (unqualified).
// Uses provider->symbolToAddress() to get the module's runtime base address.
uint64_t resolve(const QString& token, const Provider* provider, bool* ok) const;
// Reverse lookup: given an absolute address and a provider, find the nearest symbol.
// Returns "module!symbol" or "module!symbol+0xN", or empty if no match.
QString getSymbolForAddress(uint64_t addr, const Provider* provider) const;
// Check if any symbols are loaded.
bool hasSymbols() const { return !m_modules.isEmpty(); }
// List loaded module names.
QStringList loadedModules() const { return m_modules.keys(); }
// Number of loaded modules.
int moduleCount() const { return m_modules.size(); }
// Access module data by name (returns nullptr if not found).
const PdbSymbolSet* moduleData(const QString& moduleName) const {
QString canonical = resolveAlias(moduleName);
auto it = m_modules.find(canonical);
return it != m_modules.end() ? &*it : nullptr;
}
// Add a module alias (e.g. "nt" → "ntoskrnl").
void addAlias(const QString& alias, const QString& canonicalModule);
// Resolve alias to canonical module name (public for callers that need it)
QString resolveAlias(const QString& name) const {
QString lower = name.toLower();
if (lower.endsWith(QStringLiteral(".exe")) || lower.endsWith(QStringLiteral(".dll")) ||
lower.endsWith(QStringLiteral(".sys")))
lower = lower.left(lower.lastIndexOf('.'));
auto it = m_aliases.find(lower);
return it != m_aliases.end() ? *it : lower;
}
private:
SymbolStore() {
// Common Windows kernel aliases
m_aliases[QStringLiteral("nt")] = QStringLiteral("ntoskrnl");
m_aliases[QStringLiteral("ntkrnlmp")] = QStringLiteral("ntoskrnl");
m_aliases[QStringLiteral("ntkrnlpa")] = QStringLiteral("ntoskrnl");
m_aliases[QStringLiteral("ntkrpamp")] = QStringLiteral("ntoskrnl");
}
// Get the module base address, trying various name forms
uint64_t getModuleBase(const Provider* provider, const QString& canonical) const;
QHash<QString, PdbSymbolSet> m_modules; // canonical lowercase name → symbol set
QHash<QString, QString> m_aliases; // alias → canonical name
};
} // namespace rcx