mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-10-31 03:25:47 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) Atmosphère-NX
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms and conditions of the GNU General Public License,
 | |
|  * version 2, as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope it will be useful, but WITHOUT
 | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | |
|  * more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| #include <stratosphere.hpp>
 | |
| #include "osdbg_thread_info.os.horizon.hpp"
 | |
| #include "osdbg_thread_type.os.horizon.hpp"
 | |
| #include "osdbg_thread_local_region.os.horizon.hpp"
 | |
| #include "../../os/impl/os_thread_manager_impl.os.horizon.hpp"
 | |
| 
 | |
| namespace ams::osdbg::impl {
 | |
| 
 | |
|     namespace {
 | |
| 
 | |
|         s32 ConvertToUserPriority(s32 horizon_priority) {
 | |
|             return horizon_priority - os::impl::UserThreadPriorityOffset;
 | |
|         }
 | |
| 
 | |
|         s32 GetCurrentThreadPriorityImpl(const ThreadInfo *info) {
 | |
|             u64 dummy;
 | |
|             u32 horizon_priority;
 | |
|             if (R_FAILED(svc::GetDebugThreadParam(std::addressof(dummy), std::addressof(horizon_priority), info->_debug_handle, info->_debug_info_create_thread.thread_id, svc::DebugThreadParam_Priority))) {
 | |
|                 return info->_base_priority;
 | |
|             }
 | |
| 
 | |
|             return ConvertToUserPriority(static_cast<s32>(horizon_priority));
 | |
|         }
 | |
| 
 | |
|         void FillWithCurrentInfoImpl(ThreadInfo *info, const auto &thread_type_impl) {
 | |
|             /* Set fields. */
 | |
|             info->_base_priority    = thread_type_impl._base_priority;
 | |
|             info->_current_priority = GetCurrentThreadPriorityImpl(info);
 | |
|             info->_stack_size       = thread_type_impl._stack_size;
 | |
|             info->_stack            = thread_type_impl._stack;
 | |
|             info->_argument         = thread_type_impl._argument;
 | |
|             info->_function         = thread_type_impl._thread_function;
 | |
|             info->_name_pointer     = thread_type_impl._name_pointer;
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     Result ThreadInfoHorizonImpl::FillWithCurrentInfo(ThreadInfo *info) {
 | |
|         /* Detect lp64. */
 | |
|         const bool is_lp64 = IsLp64(info);
 | |
| 
 | |
|         /* Ensure that we have a thread type. */
 | |
|         if (info->_thread_type == nullptr) {
 | |
|             /* Ensure we exit with correct thread type. */
 | |
|             auto thread_guard = SCOPE_GUARD { info->_thread_type = nullptr; };
 | |
| 
 | |
|             /* Set the target thread type. */
 | |
|             GetTargetThreadType(info);
 | |
| 
 | |
|             /* If it's still nullptr, we failed to get the thread type. */
 | |
|             R_UNLESS(info->_thread_type != nullptr, osdbg::ResultCannotGetThreadInfo());
 | |
| 
 | |
|             /* Check that the thread type is valid. */
 | |
|             R_UNLESS(info->_thread_type_type != ThreadTypeType_Unknown, osdbg::ResultUnsupportedThreadVersion());
 | |
| 
 | |
|             /* We successfully got the thread type. */
 | |
|             thread_guard.Cancel();
 | |
|         }
 | |
| 
 | |
|         /* Read and process the thread type. */
 | |
|         ThreadTypeCommon thread_type;
 | |
| 
 | |
|         switch (info->_thread_type_type) {
 | |
|             case ThreadTypeType_Nintendo:
 | |
|                 if (is_lp64) {
 | |
|                     /* Read in the thread type. */
 | |
|                     R_TRY(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(thread_type.lp64)), info->_debug_handle, reinterpret_cast<uintptr_t>(info->_thread_type), sizeof(thread_type.lp64)));
 | |
| 
 | |
|                     /* Process different versions. */
 | |
|                     switch (thread_type.lp64._version) {
 | |
|                         case 0x0000:
 | |
|                         case 0xFFFF:
 | |
|                             FillWithCurrentInfoImpl(info, thread_type.lp64_v0);
 | |
|                             break;
 | |
|                         case 0x0001:
 | |
|                             FillWithCurrentInfoImpl(info, thread_type.lp64);
 | |
|                             break;
 | |
|                         default:
 | |
|                             R_THROW(osdbg::ResultUnsupportedThreadVersion());
 | |
|                     }
 | |
|                 } else {
 | |
|                     /* Read in the thread type. */
 | |
|                     R_TRY(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(thread_type.ilp32)), info->_debug_handle, reinterpret_cast<uintptr_t>(info->_thread_type), sizeof(thread_type.ilp32)));
 | |
| 
 | |
|                     /* Process different versions. */
 | |
|                     switch (thread_type.ilp32._version) {
 | |
|                         case 0x0000:
 | |
|                         case 0xFFFF:
 | |
|                             FillWithCurrentInfoImpl(info, thread_type.ilp32_v0);
 | |
|                             break;
 | |
|                         case 0x0001:
 | |
|                             FillWithCurrentInfoImpl(info, thread_type.ilp32);
 | |
|                             break;
 | |
|                         default:
 | |
|                             R_THROW(osdbg::ResultUnsupportedThreadVersion());
 | |
|                     }
 | |
|                 }
 | |
|                 break;
 | |
|             case ThreadTypeType_Stratosphere:
 | |
|                 {
 | |
|                     /* Read in the thread type. */
 | |
|                     R_TRY(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(thread_type.stratosphere)), info->_debug_handle, reinterpret_cast<uintptr_t>(info->_thread_type), sizeof(thread_type.stratosphere)));
 | |
| 
 | |
|                     /* Set fields. */
 | |
|                     const auto &thread_type_impl = thread_type.stratosphere;
 | |
| 
 | |
|                     /* Check that our thread version is valid. */
 | |
|                     R_UNLESS(thread_type_impl.version == 0x0000 || thread_type_impl.version == 0xFFFF, osdbg::ResultUnsupportedThreadVersion());
 | |
| 
 | |
|                     info->_base_priority    = thread_type_impl.base_priority;
 | |
|                     info->_current_priority = GetCurrentThreadPriorityImpl(info);
 | |
|                     info->_stack_size       = thread_type_impl.stack_size;
 | |
|                     info->_stack            = reinterpret_cast<uintptr_t>(thread_type_impl.stack);
 | |
|                     info->_argument         = reinterpret_cast<uintptr_t>(thread_type_impl.argument);
 | |
|                     info->_function         = reinterpret_cast<uintptr_t>(thread_type_impl.function);
 | |
|                     info->_name_pointer     = reinterpret_cast<uintptr_t>(thread_type_impl.name_pointer);
 | |
|                 }
 | |
|                 break;
 | |
|             case ThreadTypeType_Libnx:
 | |
|                 {
 | |
|                     /* Read in the thread type. */
 | |
|                     R_TRY(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(thread_type.libnx)), info->_debug_handle, reinterpret_cast<uintptr_t>(info->_thread_type), sizeof(thread_type.libnx)));
 | |
| 
 | |
|                     /* Set fields. */
 | |
|                     const auto &thread_type_impl = thread_type.libnx;
 | |
| 
 | |
|                     /* NOTE: libnx does not store/track base priority anywhere. */
 | |
|                     info->_base_priority    = -1;
 | |
|                     info->_current_priority = GetCurrentThreadPriorityImpl(info);
 | |
|                     if (info->_current_priority != info->_base_priority) {
 | |
|                         info->_base_priority = info->_current_priority;
 | |
|                     }
 | |
|                     info->_stack_size       = thread_type_impl.stack_sz;
 | |
|                     info->_stack            = reinterpret_cast<uintptr_t>(thread_type_impl.stack_mirror);
 | |
| 
 | |
|                     /* Parse thread entry args. */
 | |
|                     {
 | |
|                         LibnxThreadEntryArgs thread_entry_args;
 | |
| 
 | |
|                         if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(thread_entry_args)), info->_debug_handle, info->_stack + info->_stack_size, sizeof(LibnxThreadEntryArgs)))) {
 | |
|                             info->_argument = thread_entry_args.arg;
 | |
|                             info->_function = thread_entry_args.entry;
 | |
|                         } else {
 | |
|                             /* Failed to read the argument/function. */
 | |
|                             info->_argument = 0;
 | |
|                             info->_function = 0;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     /* Libnx threads don't have names. */
 | |
|                     info->_name_pointer     = 0;
 | |
|                 }
 | |
|                 break;
 | |
|             default:
 | |
|                 R_THROW(osdbg::ResultUnsupportedThreadVersion());
 | |
|         }
 | |
| 
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
| }
 |