Merge pull request #11500 from liamwhite/debug-stuff
core: improve debug workflow
This commit is contained in:
commit
62d473305d
|
@ -294,11 +294,11 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
|
bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name) const {
|
||||||
const auto build_id_raw = Common::HexToString(build_id_);
|
const auto build_id_raw = Common::HexToString(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);
|
||||||
|
|
||||||
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id);
|
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name);
|
||||||
|
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
||||||
if (load_dir == nullptr) {
|
if (load_dir == nullptr) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
// Checks to see if PatchNSO() will have any effect given the NSO's build ID.
|
// Checks to see if PatchNSO() will have any effect given the NSO's build ID.
|
||||||
// Used to prevent expensive copies in NSO loader.
|
// Used to prevent expensive copies in NSO loader.
|
||||||
[[nodiscard]] bool HasNSOPatch(const BuildID& build_id) const;
|
[[nodiscard]] bool HasNSOPatch(const BuildID& build_id, std::string_view name) const;
|
||||||
|
|
||||||
// Creates a CheatList object with all
|
// Creates a CheatList object with all
|
||||||
[[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
|
[[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
|
||||||
|
|
|
@ -96,6 +96,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string
|
||||||
process->m_is_suspended = false;
|
process->m_is_suspended = false;
|
||||||
process->m_schedule_count = 0;
|
process->m_schedule_count = 0;
|
||||||
process->m_is_handle_table_initialized = false;
|
process->m_is_handle_table_initialized = false;
|
||||||
|
process->m_is_hbl = false;
|
||||||
|
|
||||||
// Open a reference to the resource limit.
|
// Open a reference to the resource limit.
|
||||||
process->m_resource_limit->Open();
|
process->m_resource_limit->Open();
|
||||||
|
@ -351,12 +352,14 @@ Result KProcess::SetActivity(ProcessActivity activity) {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size) {
|
Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
|
||||||
|
bool is_hbl) {
|
||||||
m_program_id = metadata.GetTitleID();
|
m_program_id = metadata.GetTitleID();
|
||||||
m_ideal_core = metadata.GetMainThreadCore();
|
m_ideal_core = metadata.GetMainThreadCore();
|
||||||
m_is_64bit_process = metadata.Is64BitProgram();
|
m_is_64bit_process = metadata.Is64BitProgram();
|
||||||
m_system_resource_size = metadata.GetSystemResourceSize();
|
m_system_resource_size = metadata.GetSystemResourceSize();
|
||||||
m_image_size = code_size;
|
m_image_size = code_size;
|
||||||
|
m_is_hbl = is_hbl;
|
||||||
|
|
||||||
if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) {
|
if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) {
|
||||||
// For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
|
// For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
|
||||||
|
|
|
@ -338,7 +338,8 @@ public:
|
||||||
* @returns ResultSuccess if all relevant metadata was able to be
|
* @returns ResultSuccess if all relevant metadata was able to be
|
||||||
* loaded and parsed. Otherwise, an error code is returned.
|
* loaded and parsed. Otherwise, an error code is returned.
|
||||||
*/
|
*/
|
||||||
Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size);
|
Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
|
||||||
|
bool is_hbl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the main application thread for this process.
|
* Starts the main application thread for this process.
|
||||||
|
@ -368,6 +369,10 @@ public:
|
||||||
return GetProcessId();
|
return GetProcessId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsHbl() const {
|
||||||
|
return m_is_hbl;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsSignaled() const override;
|
bool IsSignaled() const override;
|
||||||
|
|
||||||
void DoWorkerTaskImpl();
|
void DoWorkerTaskImpl();
|
||||||
|
@ -525,6 +530,7 @@ private:
|
||||||
bool m_is_immortal{};
|
bool m_is_immortal{};
|
||||||
bool m_is_handle_table_initialized{};
|
bool m_is_handle_table_initialized{};
|
||||||
bool m_is_initialized{};
|
bool m_is_initialized{};
|
||||||
|
bool m_is_hbl{};
|
||||||
|
|
||||||
std::atomic<u16> m_num_running_threads{};
|
std::atomic<u16> m_num_running_threads{};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Result OutputDebugString(Core::System& system, u64 address, u64 len) {
|
||||||
|
|
||||||
std::string str(len, '\0');
|
std::string str(len, '\0');
|
||||||
GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size());
|
GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size());
|
||||||
LOG_DEBUG(Debug_Emulated, "{}", str);
|
LOG_INFO(Debug_Emulated, "{}", str);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/debugger/debugger.h"
|
#include "core/debugger/debugger.h"
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
#include "core/hle/kernel/svc_types.h"
|
#include "core/hle/kernel/svc_types.h"
|
||||||
|
@ -107,7 +108,10 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
||||||
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system.DebuggerEnabled()) {
|
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
|
||||||
|
const bool should_break = is_hbl || !notification_only;
|
||||||
|
|
||||||
|
if (system.DebuggerEnabled() && should_break) {
|
||||||
auto* thread = system.Kernel().GetCurrentEmuThread();
|
auto* thread = system.Kernel().GetCurrentEmuThread();
|
||||||
system.GetDebugger().NotifyThreadStopped(thread);
|
system.GetDebugger().NotifyThreadStopped(thread);
|
||||||
thread->RequestSuspend(Kernel::SuspendType::Debug);
|
thread->RequestSuspend(Kernel::SuspendType::Debug);
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Loader {
|
||||||
|
|
||||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
|
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
|
||||||
bool override_update_)
|
bool override_update_)
|
||||||
: AppLoader(std::move(file_)), override_update(override_update_) {
|
: AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) {
|
||||||
const auto file_dir = file->GetContainingDirectory();
|
const auto file_dir = file->GetContainingDirectory();
|
||||||
|
|
||||||
// Title ID
|
// Title ID
|
||||||
|
@ -69,9 +69,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys
|
||||||
}
|
}
|
||||||
|
|
||||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
|
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
|
||||||
FileSys::VirtualDir directory, bool override_update_)
|
FileSys::VirtualDir directory, bool override_update_, bool is_hbl_)
|
||||||
: AppLoader(directory->GetFile("main")), dir(std::move(directory)),
|
: AppLoader(directory->GetFile("main")), dir(std::move(directory)),
|
||||||
override_update(override_update_) {}
|
override_update(override_update_), is_hbl(is_hbl_) {}
|
||||||
|
|
||||||
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) {
|
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) {
|
||||||
if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) {
|
if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) {
|
||||||
|
@ -147,7 +147,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the process code layout
|
// Setup the process code layout
|
||||||
if (process.LoadFromMetadata(metadata, code_size).IsError()) {
|
if (process.LoadFromMetadata(metadata, code_size, is_hbl).IsError()) {
|
||||||
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ public:
|
||||||
|
|
||||||
// Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
|
// Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
|
||||||
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory,
|
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory,
|
||||||
bool override_update_ = false);
|
bool override_update_ = false,
|
||||||
|
bool is_hbl_ = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies whether or not the given file is a deconstructed ROM directory.
|
* Identifies whether or not the given file is a deconstructed ROM directory.
|
||||||
|
@ -62,6 +63,7 @@ private:
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 title_id{};
|
u64 title_id{};
|
||||||
bool override_update;
|
bool override_update;
|
||||||
|
bool is_hbl;
|
||||||
|
|
||||||
Modules modules;
|
Modules modules;
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,7 +90,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
|
||||||
codeset.DataSegment().size += kip->GetBSSSize();
|
codeset.DataSegment().size += kip->GetBSSSize();
|
||||||
|
|
||||||
// Setup the process code layout
|
// Setup the process code layout
|
||||||
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
|
if (process
|
||||||
|
.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false)
|
||||||
.IsError()) {
|
.IsError()) {
|
||||||
return {ResultStatus::ErrorNotInitialized, {}};
|
return {ResultStatus::ErrorNotInitialized, {}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,8 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
|
||||||
program_image.resize(static_cast<u32>(program_image.size()) + bss_size);
|
program_image.resize(static_cast<u32>(program_image.size()) + bss_size);
|
||||||
|
|
||||||
// Setup the process code layout
|
// Setup the process code layout
|
||||||
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
|
if (process
|
||||||
|
.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false)
|
||||||
.IsError()) {
|
.IsError()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,13 +127,14 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply patches if necessary
|
// Apply patches if necessary
|
||||||
if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
|
const auto name = nso_file.GetName();
|
||||||
|
if (pm && (pm->HasNSOPatch(nso_header.build_id, name) || Settings::values.dump_nso)) {
|
||||||
std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
|
std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
|
||||||
std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader));
|
std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader));
|
||||||
std::memcpy(pi_header.data() + sizeof(NSOHeader), program_image.data(),
|
std::memcpy(pi_header.data() + sizeof(NSOHeader), program_image.data(),
|
||||||
program_image.size());
|
program_image.size());
|
||||||
|
|
||||||
pi_header = pm->PatchNSO(pi_header, nso_file.GetName());
|
pi_header = pm->PatchNSO(pi_header, name);
|
||||||
|
|
||||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsp->IsExtractedType()) {
|
if (nsp->IsExtractedType()) {
|
||||||
secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
|
secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(
|
||||||
|
nsp->GetExeFS(), false, file->GetName() == "hbl.nsp");
|
||||||
} else {
|
} else {
|
||||||
const auto control_nca =
|
const auto control_nca =
|
||||||
nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
|
nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
|
||||||
|
|
Reference in New Issue