Merge pull request #1618 from DarkLordZach/dump-nso

patch_manager: Add support for dumping uncompressed NSOs
This commit is contained in:
bunnei 2018-11-15 14:46:10 -08:00 committed by GitHub
commit 97605e36f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 75 additions and 8 deletions

View File

@ -8,8 +8,9 @@
namespace FileSys { namespace FileSys {
BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_) BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
: nand_root(std::move(nand_root_)), load_root(std::move(load_root_)), : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
dump_root(std::move(dump_root_)),
sysnand_cache(std::make_unique<RegisteredCache>( sysnand_cache(std::make_unique<RegisteredCache>(
GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))), GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
usrnand_cache(std::make_unique<RegisteredCache>( usrnand_cache(std::make_unique<RegisteredCache>(
@ -32,4 +33,10 @@ VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const {
return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id)); return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
} }
VirtualDir BISFactory::GetModificationDumpRoot(u64 title_id) const {
if (title_id == 0)
return nullptr;
return GetOrCreateDirectoryRelative(dump_root, fmt::format("/{:016X}", title_id));
}
} // namespace FileSys } // namespace FileSys

View File

@ -17,17 +17,19 @@ class RegisteredCache;
/// registered caches. /// registered caches.
class BISFactory { class BISFactory {
public: public:
explicit BISFactory(VirtualDir nand_root, VirtualDir load_root); explicit BISFactory(VirtualDir nand_root, VirtualDir load_root, VirtualDir dump_root);
~BISFactory(); ~BISFactory();
RegisteredCache* GetSystemNANDContents() const; RegisteredCache* GetSystemNANDContents() const;
RegisteredCache* GetUserNANDContents() const; RegisteredCache* GetUserNANDContents() const;
VirtualDir GetModificationLoadRoot(u64 title_id) const; VirtualDir GetModificationLoadRoot(u64 title_id) const;
VirtualDir GetModificationDumpRoot(u64 title_id) const;
private: private:
VirtualDir nand_root; VirtualDir nand_root;
VirtualDir load_root; VirtualDir load_root;
VirtualDir dump_root;
std::unique_ptr<RegisteredCache> sysnand_cache; std::unique_ptr<RegisteredCache> sysnand_cache;
std::unique_ptr<RegisteredCache> usrnand_cache; std::unique_ptr<RegisteredCache> usrnand_cache;

View File

@ -19,6 +19,7 @@
#include "core/file_sys/vfs_vector.h" #include "core/file_sys/vfs_vector.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/settings.h"
namespace FileSys { namespace FileSys {
@ -119,6 +120,18 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
const auto build_id_raw = Common::HexArrayToString(header.build_id); const auto build_id_raw = Common::HexArrayToString(header.build_id);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1); const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
if (Settings::values.dump_nso) {
LOG_INFO(Loader, "Dumping NSO for build_id={}, title_id={:016X}", build_id, title_id);
const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
if (dump_dir != nullptr) {
const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
const auto file = nso_dir->CreateFile(fmt::format("{}.nso", build_id));
file->Resize(nso.size());
file->WriteBytes(nso);
}
}
LOG_INFO(Loader, "Patching NSO for build_id={}", build_id); LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);

View File

@ -370,6 +370,15 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
return bis_factory->GetModificationLoadRoot(title_id); return bis_factory->GetModificationLoadRoot(title_id);
} }
FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) {
LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id);
if (bis_factory == nullptr)
return nullptr;
return bis_factory->GetModificationDumpRoot(title_id);
}
void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (overwrite) { if (overwrite) {
bis_factory = nullptr; bis_factory = nullptr;
@ -383,14 +392,22 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
FileSys::Mode::ReadWrite); FileSys::Mode::ReadWrite);
auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
FileSys::Mode::ReadWrite); FileSys::Mode::ReadWrite);
auto dump_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir),
FileSys::Mode::ReadWrite);
if (bis_factory == nullptr) if (bis_factory == nullptr) {
bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory); bis_factory =
if (save_data_factory == nullptr) std::make_unique<FileSys::BISFactory>(nand_directory, load_directory, dump_directory);
}
if (save_data_factory == nullptr) {
save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
if (sdmc_factory == nullptr) }
if (sdmc_factory == nullptr) {
sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory)); sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
} }
}
void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) { void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
romfs_factory = nullptr; romfs_factory = nullptr;

View File

@ -55,6 +55,7 @@ FileSys::RegisteredCache* GetUserNANDContents();
FileSys::RegisteredCache* GetSDMCContents(); FileSys::RegisteredCache* GetSDMCContents();
FileSys::VirtualDir GetModificationLoadRoot(u64 title_id); FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
FileSys::VirtualDir GetModificationDumpRoot(u64 title_id);
// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function // Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
// above is called. // above is called.

View File

@ -154,7 +154,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAd
program_image.resize(image_size); program_image.resize(image_size);
// Apply patches if necessary // Apply patches if necessary
if (pm && pm->HasNSOPatch(nso_header.build_id)) { if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
std::vector<u8> pi_header(program_image.size() + 0x100); std::vector<u8> pi_header(program_image.size() + 0x100);
std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());

View File

@ -159,6 +159,7 @@ struct Values {
bool use_gdbstub; bool use_gdbstub;
u16 gdbstub_port; u16 gdbstub_port;
std::string program_args; std::string program_args;
bool dump_nso;
// WebService // WebService
bool enable_telemetry; bool enable_telemetry;

View File

@ -153,6 +153,7 @@ void Config::ReadValues() {
Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString(); Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString();
Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool();
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("WebService"); qt_config->beginGroup("WebService");
@ -295,6 +296,7 @@ void Config::SaveValues() {
qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args)); qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args));
qt_config->setValue("dump_nso", Settings::values.dump_nso);
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("WebService"); qt_config->beginGroup("WebService");

View File

@ -34,6 +34,7 @@ void ConfigureDebug::setConfiguration() {
ui->toggle_console->setChecked(UISettings::values.show_console); ui->toggle_console->setChecked(UISettings::values.show_console);
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter));
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso);
} }
void ConfigureDebug::applyConfiguration() { void ConfigureDebug::applyConfiguration() {
@ -42,6 +43,7 @@ void ConfigureDebug::applyConfiguration() {
UISettings::values.show_console = ui->toggle_console->isChecked(); UISettings::values.show_console = ui->toggle_console->isChecked();
Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked();
Debugger::ToggleConsole(); Debugger::ToggleConsole();
Log::Filter filter; Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter); filter.ParseFilterString(Settings::values.log_filter);

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>300</height> <height>357</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -129,6 +129,25 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Dump</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="dump_decompressed_nso">
<property name="whatsThis">
<string>When checked, any NSO yuzu tries to load or patch will be copied decompressed to the yuzu/dump directory.</string>
</property>
<property name="text">
<string>Dump Decompressed NSOs</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">

View File

@ -148,6 +148,7 @@ void Config::ReadValues() {
Settings::values.gdbstub_port = Settings::values.gdbstub_port =
static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689));
Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", "");
Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false);
// Web Service // Web Service
Settings::values.enable_telemetry = Settings::values.enable_telemetry =

View File

@ -206,6 +206,8 @@ log_filter = *:Trace
# Port for listening to GDB connections. # Port for listening to GDB connections.
use_gdbstub=false use_gdbstub=false
gdbstub_port=24689 gdbstub_port=24689
# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
dump_nso=false
[WebService] [WebService]
# Whether or not to enable telemetry # Whether or not to enable telemetry