Skip to content

Commit

Permalink
Debugger: Allow loading symbols conditionally and with a base address
Browse files Browse the repository at this point in the history
  • Loading branch information
chaoticgd committed Nov 13, 2024
1 parent f005522 commit 1b3cf3f
Show file tree
Hide file tree
Showing 13 changed files with 547 additions and 301 deletions.
6 changes: 4 additions & 2 deletions 3rdparty/ccc/src/ccc/symbol_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,18 @@ Result<std::unique_ptr<SymbolTable>> create_elf_symbol_table(

Result<ModuleHandle> import_symbol_tables(
SymbolDatabase& database,
std::string module_name,
const std::vector<std::unique_ptr<SymbolTable>>& symbol_tables,
std::string module_name,
Address base_address,
u32 importer_flags,
DemanglerFunctions demangler,
const std::atomic_bool* interrupt)
{
Result<SymbolSourceHandle> module_source = database.get_symbol_source("Symbol Table Importer");
CCC_RETURN_IF_ERROR(module_source);

Result<Module*> module_symbol = database.modules.create_symbol(std::move(module_name), *module_source, nullptr);
Result<Module*> module_symbol = database.modules.create_symbol(
std::move(module_name), base_address, *module_source, nullptr);
CCC_RETURN_IF_ERROR(module_symbol);

ModuleHandle module_handle = (*module_symbol)->handle();
Expand Down
3 changes: 2 additions & 1 deletion 3rdparty/ccc/src/ccc/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ Result<std::unique_ptr<SymbolTable>> create_elf_symbol_table(
// and to generate a module handle.
Result<ModuleHandle> import_symbol_tables(
SymbolDatabase& database,
std::string module_name,
const std::vector<std::unique_ptr<SymbolTable>>& symbol_tables,
std::string module_name,
Address base_address,
u32 importer_flags,
DemanglerFunctions demangler,
const std::atomic_bool* interrupt);
Expand Down
189 changes: 145 additions & 44 deletions pcsx2-qt/Settings/DebugAnalysisSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ DebugAnalysisSettingsWidget::DebugAnalysisSettingsWidget(SettingsWindow* dialog,
else
{
m_ui.symbolFileLabel->hide();
m_ui.symbolFileList->hide();
m_ui.symbolFileTable->hide();
m_ui.importSymbolFileButtons->hide();
}

Expand Down Expand Up @@ -165,16 +165,32 @@ void DebugAnalysisSettingsWidget::parseSettingsFromWidgets(Pcsx2Config::DebugAna
output.DemangleSymbols = m_ui.demangleSymbols->isChecked();
output.DemangleParameters = m_ui.demangleParameters->isChecked();

for (int i = 0; i < m_ui.symbolFileList->count(); i++)
for (int i = 0; i < m_symbol_file_model->rowCount(); i++)
{
DebugExtraSymbolFile& file = output.ExtraSymbolFiles.emplace_back();
file.Path = m_ui.symbolFileList->item(i)->text().toStdString();

file.Path = m_symbol_file_model->item(i, PATH_COLUMN)->text().toStdString();

bool ok;
u32 base_address = m_symbol_file_model->item(i, BASE_ADDRESS_COLUMN)->text().toUInt(&ok, 16);
if (ok)
file.BaseAddress = base_address;

file.Condition = m_symbol_file_model->item(i, CONDITION_COLUMN)->text().toStdString();
}

output.FunctionScanMode = static_cast<DebugFunctionScanMode>(m_ui.functionScanMode->currentIndex());
output.CustomFunctionScanRange = m_ui.customAddressRange->isChecked();
output.FunctionScanStartAddress = m_ui.addressRangeStart->text().toStdString();
output.FunctionScanEndAddress = m_ui.addressRangeEnd->text().toStdString();

bool ok;

u32 function_scan_start_address = m_ui.addressRangeStart->text().toUInt(&ok, 16);
if (ok)
output.FunctionScanStartAddress = function_scan_start_address;

u32 function_scan_end_address = m_ui.addressRangeEnd->text().toUInt(&ok, 16);
if (ok)
output.FunctionScanEndAddress = function_scan_end_address;

output.GenerateFunctionHashes = m_ui.grayOutOverwrittenFunctions->isChecked();
}
Expand All @@ -187,27 +203,12 @@ void DebugAnalysisSettingsWidget::setupSymbolSourceGrid()
{
// Add symbol sources for which the user has already selected whether or
// not they should be cleared.
int existing_symbol_source_count;
if (m_dialog)
existing_symbol_source_count = m_dialog->getEffectiveIntValue("Debugger/Analysis/SymbolSources", "Count", 0);
else
existing_symbol_source_count = Host::GetIntSettingValue("Debugger/Analysis/SymbolSources", "Count", 0);

int existing_symbol_source_count = getIntSettingValue("Debugger/Analysis/SymbolSources", "Count", 0);
for (int i = 0; i < existing_symbol_source_count; i++)
{
std::string section = "Debugger/Analysis/SymbolSources/" + std::to_string(i);

std::string name;
if (m_dialog)
name = m_dialog->getEffectiveStringValue(section.c_str(), "Name", "");
else
name = Host::GetStringSettingValue(section.c_str(), "Name", "");

bool value;
if (m_dialog)
value = m_dialog->getEffectiveBoolValue(section.c_str(), "ClearDuringAnalysis", false);
else
value = Host::GetBoolSettingValue(section.c_str(), "ClearDuringAnalysis", false);
std::string name = getStringSettingValue(section.c_str(), "Name", "");
bool value = getBoolSettingValue(section.c_str(), "ClearDuringAnalysis", false);

SymbolSourceTemp& source = m_symbol_sources[name];
source.previous_value = value;
Expand Down Expand Up @@ -320,45 +321,95 @@ void DebugAnalysisSettingsWidget::saveSymbolSources()

void DebugAnalysisSettingsWidget::setupSymbolFileList()
{
int extra_symbol_file_count;
if (m_dialog)
extra_symbol_file_count = m_dialog->getEffectiveIntValue("Debugger/Analysis/ExtraSymbolFiles", "Count", 0);
else
extra_symbol_file_count = Host::GetIntSettingValue("Debugger/Analysis/ExtraSymbolFiles", "Count", 0);
m_symbol_file_model = new QStandardItemModel(0, SYMBOL_FILE_COLUMN_COUNT, m_ui.symbolFileTable);

QStringList headers;
headers.emplace_back(tr("Path"));
headers.emplace_back(tr("Base Address"));
headers.emplace_back(tr("Condition"));
m_symbol_file_model->setHorizontalHeaderLabels(headers);

m_ui.symbolFileTable->setModel(m_symbol_file_model);

m_ui.symbolFileTable->horizontalHeader()->setSectionResizeMode(PATH_COLUMN, QHeaderView::Stretch);
m_ui.symbolFileTable->horizontalHeader()->setSectionResizeMode(BASE_ADDRESS_COLUMN, QHeaderView::Fixed);
m_ui.symbolFileTable->horizontalHeader()->setSectionResizeMode(CONDITION_COLUMN, QHeaderView::Fixed);

m_ui.symbolFileTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

int extra_symbol_file_count = getIntSettingValue("Debugger/Analysis/ExtraSymbolFiles", "Count", 0);
for (int i = 0; i < extra_symbol_file_count; i++)
{
std::string section = "Debugger/Analysis/ExtraSymbolFiles/" + std::to_string(i);
std::string path;
if (m_dialog)
path = m_dialog->getEffectiveStringValue(section.c_str(), "Path", "");
else
path = Host::GetStringSettingValue(section.c_str(), "Path", "");

m_ui.symbolFileList->addItem(QString::fromStdString(path));
int row = m_symbol_file_model->rowCount();
if (!m_symbol_file_model->insertRow(row))
continue;

QStandardItem* path_item = new QStandardItem();
path_item->setText(QString::fromStdString(getStringSettingValue(section.c_str(), "Path", "")));
m_symbol_file_model->setItem(row, PATH_COLUMN, path_item);

QStandardItem* base_address_item = new QStandardItem();
u32 base_address = getUIntSettingValue(section.c_str(), "BaseAddress", (u32)-1);
if (base_address != (u32)-1)
base_address_item->setText(QString::number(base_address, 16));
m_symbol_file_model->setItem(row, BASE_ADDRESS_COLUMN, base_address_item);

QStandardItem* condition_item = new QStandardItem();
condition_item->setText(QString::fromStdString(getStringSettingValue(section.c_str(), "Condition")));
m_symbol_file_model->setItem(row, CONDITION_COLUMN, condition_item);
}

connect(m_ui.addSymbolFile, &QPushButton::clicked, this, &DebugAnalysisSettingsWidget::addSymbolFile);
connect(m_ui.removeSymbolFile, &QPushButton::clicked, this, &DebugAnalysisSettingsWidget::removeSymbolFile);

connect(m_ui.symbolFileTable->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &DebugAnalysisSettingsWidget::updateEnabledStates);

connect(m_symbol_file_model, &QStandardItemModel::dataChanged,
this, &DebugAnalysisSettingsWidget::saveSymbolFiles);
connect(m_symbol_file_model, &QStandardItemModel::dataChanged,
this, &DebugAnalysisSettingsWidget::updateEnabledStates);
}

void DebugAnalysisSettingsWidget::addSymbolFile()
{
QString path = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Add Symbol File")));
if (path.isEmpty())
std::string path = Path::ToNativePath(QFileDialog::getOpenFileName(this, tr("Add Symbol File")).toStdString());
if (path.empty())
return;

std::string relative_path = Path::MakeRelative(path, EmuFolders::GameSettings);
if (!relative_path.starts_with(".."))
path = std::move(relative_path);

int row = m_symbol_file_model->rowCount();
if (!m_symbol_file_model->insertRow(row))
return;

m_ui.symbolFileList->addItem(path);
QStandardItem* path_item = new QStandardItem();
path_item->setText(QString::fromStdString(path));
m_symbol_file_model->setItem(row, PATH_COLUMN, path_item);

QStandardItem* base_address_item = new QStandardItem();
base_address_item->setText("");
m_symbol_file_model->setItem(row, BASE_ADDRESS_COLUMN, base_address_item);

QStandardItem* condition_item = new QStandardItem();
condition_item->setText("");
m_symbol_file_model->setItem(row, CONDITION_COLUMN, condition_item);

saveSymbolFiles();
updateEnabledStates();
}

void DebugAnalysisSettingsWidget::removeSymbolFile()
{
for (QListWidgetItem* item : m_ui.symbolFileList->selectedItems())
delete item;
for (QModelIndex index : m_ui.symbolFileTable->selectionModel()->selectedRows())
m_symbol_file_model->removeRow(index.row());

saveSymbolFiles();
updateEnabledStates();
}

void DebugAnalysisSettingsWidget::saveSymbolFiles()
Expand All @@ -380,17 +431,29 @@ void DebugAnalysisSettingsWidget::saveSymbolFiles()

sif->RemoveSection("Debugger/Analysis/ExtraSymbolFiles");

if (m_ui.symbolFileList->count() == 0)
if (m_symbol_file_model->rowCount() == 0)
return;

// Make new configuration entries.
sif->SetIntValue("Debugger/Analysis/ExtraSymbolFiles", "Count", m_ui.symbolFileList->count());
sif->SetIntValue("Debugger/Analysis/ExtraSymbolFiles", "Count", m_symbol_file_model->rowCount());

for (int i = 0; i < m_ui.symbolFileList->count(); i++)
for (int i = 0; i < m_symbol_file_model->rowCount(); i++)
{
std::string section = "Debugger/Analysis/ExtraSymbolFiles/" + std::to_string(i);
std::string path = m_ui.symbolFileList->item(i)->text().toStdString();
sif->SetStringValue(section.c_str(), "Path", path.c_str());

if (QStandardItem* path_item = m_symbol_file_model->item(i, PATH_COLUMN))
sif->SetStringValue(section.c_str(), "Path", path_item->text().toStdString().c_str());

if (QStandardItem* base_address_item = m_symbol_file_model->item(i, BASE_ADDRESS_COLUMN))
{
bool ok;
u32 base_address = base_address_item->text().toUInt(&ok, 16);
if (ok)
sif->SetUIntValue(section.c_str(), "BaseAddress", base_address);
}

if (QStandardItem* condition_item = m_symbol_file_model->item(i, CONDITION_COLUMN))
sif->SetStringValue(section.c_str(), "Condition", condition_item->text().toStdString().c_str());
}

QtHost::SaveGameSettings(sif, true);
Expand Down Expand Up @@ -423,5 +486,43 @@ void DebugAnalysisSettingsWidget::updateEnabledStates()
m_ui.symbolSourceScrollArea->setEnabled(!m_ui.automaticallyClearSymbols->isChecked());
m_ui.symbolSourceErrorMessage->setEnabled(!m_ui.automaticallyClearSymbols->isChecked());
m_ui.demangleParameters->setEnabled(m_ui.demangleSymbols->isChecked());
m_ui.removeSymbolFile->setEnabled(
m_ui.symbolFileTable->selectionModel() && m_ui.symbolFileTable->selectionModel()->hasSelection());
m_ui.customAddressRangeLineEdits->setEnabled(m_ui.customAddressRange->isChecked());
}

std::string DebugAnalysisSettingsWidget::getStringSettingValue(
const char* section, const char* key, const char* default_value)
{
if (m_dialog)
return m_dialog->getEffectiveStringValue(section, key, default_value);

return Host::GetStringSettingValue(section, key, default_value);
}

bool DebugAnalysisSettingsWidget::getBoolSettingValue(
const char* section, const char* key, bool default_value)
{
if (m_dialog)
return m_dialog->getEffectiveBoolValue(section, key, default_value);

return Host::GetBoolSettingValue(section, key, default_value);
}

int DebugAnalysisSettingsWidget::getIntSettingValue(
const char* section, const char* key, int default_value)
{
if (m_dialog)
return m_dialog->getEffectiveIntValue(section, key, default_value);

return Host::GetIntSettingValue(section, key, default_value);
}

uint DebugAnalysisSettingsWidget::getUIntSettingValue(
const char* section, const char* key, uint default_value)
{
if (m_dialog)
return m_dialog->getEffectiveUIntValue(section, key, default_value);

return Host::GetUIntSettingValue(section, key, default_value);
}
18 changes: 17 additions & 1 deletion pcsx2-qt/Settings/DebugAnalysisSettingsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "Config.h"

#include <QtGui/QStandardItemModel>
#include <QtWidgets/QDialog>

class SettingsWindow;
Expand All @@ -16,7 +17,7 @@ class DebugAnalysisSettingsWidget : public QWidget

public:
// Create a widget that will discard any settings changed after it is
// closed, for use in the dialog opened by the "Reanalyze" button.
// closed, for use in the dialog opened by the "Analyze" button.
DebugAnalysisSettingsWidget(QWidget* parent = nullptr);

// Create a widget that will write back any settings changed to the config
Expand All @@ -42,15 +43,30 @@ class DebugAnalysisSettingsWidget : public QWidget

void updateEnabledStates();

std::string getStringSettingValue(const char* section, const char* key, const char* default_value = "");
bool getBoolSettingValue(const char* section, const char* key, bool default_value = false);
int getIntSettingValue(const char* section, const char* key, int default_value = 0);
uint getUIntSettingValue(const char* section, const char* key, uint default_value = 0);

struct SymbolSourceTemp
{
QCheckBox* check_box = nullptr;
bool previous_value = false;
bool modified_by_user = false;
};

enum SymbolFileColumn
{
PATH_COLUMN = 0,
BASE_ADDRESS_COLUMN = 1,
CONDITION_COLUMN = 2,
SYMBOL_FILE_COLUMN_COUNT = 3
};

SettingsWindow* m_dialog = nullptr;
std::map<std::string, SymbolSourceTemp> m_symbol_sources;

QStandardItemModel* m_symbol_file_model;

Ui::DebugAnalysisSettingsWidget m_ui;
};
22 changes: 20 additions & 2 deletions pcsx2-qt/Settings/DebugAnalysisSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
</widget>
</item>
<item>
<widget class="QListWidget" name="symbolFileList">
<widget class="QTableView" name="symbolFileTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
Expand All @@ -184,9 +184,27 @@
<height>100</height>
</size>
</property>
<property name="sortingEnabled">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
Expand Down
Loading

0 comments on commit 1b3cf3f

Please sign in to comment.