Merge pull request #11500 from liamwhite/debug-stuff
core: improve debug workflow
This commit is contained in:
		| @@ -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
	
	Block a user