summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/jni/emu_window/emu_window.cpp8
-rw-r--r--src/android/app/src/main/jni/emu_window/emu_window.h4
-rw-r--r--src/android/app/src/main/jni/native.cpp2
-rw-r--r--src/android/app/src/main/jni/native.h3
-rw-r--r--src/core/debugger/gdbstub.cpp165
-rw-r--r--src/core/hle/kernel/k_capabilities.cpp3
6 files changed, 134 insertions, 51 deletions
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp
index a7e414b81..c4f631924 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.cpp
+++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp
@@ -9,6 +9,7 @@
#include "input_common/drivers/virtual_gamepad.h"
#include "input_common/main.h"
#include "jni/emu_window/emu_window.h"
+#include "jni/native.h"
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
m_window_width = ANativeWindow_getWidth(surface);
@@ -57,6 +58,13 @@ void EmuWindow_Android::OnRemoveNfcTag() {
m_input_subsystem->GetVirtualAmiibo()->CloseAmiibo();
}
+void EmuWindow_Android::OnFrameDisplayed() {
+ if (!m_first_frame) {
+ EmulationSession::GetInstance().OnEmulationStarted();
+ m_first_frame = true;
+ }
+}
+
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem,
ANativeWindow* surface,
std::shared_ptr<Common::DynamicLibrary> driver_library)
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h
index b38087f73..a34a0e479 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.h
+++ b/src/android/app/src/main/jni/emu_window/emu_window.h
@@ -45,7 +45,7 @@ public:
float gyro_z, float accel_x, float accel_y, float accel_z);
void OnReadNfcTag(std::span<u8> data);
void OnRemoveNfcTag();
- void OnFrameDisplayed() override {}
+ void OnFrameDisplayed() override;
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
@@ -61,4 +61,6 @@ private:
float m_window_height{};
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
+
+ bool m_first_frame = false;
};
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 1484cc224..64663b084 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -372,8 +372,6 @@ void EmulationSession::RunEmulation() {
m_system.InitializeDebugger();
}
- OnEmulationStarted();
-
while (true) {
{
[[maybe_unused]] std::unique_lock lock(m_mutex);
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index 6b02c44b5..78ef96802 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -52,9 +52,10 @@ public:
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
+ static void OnEmulationStarted();
+
private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
- static void OnEmulationStarted();
static void OnEmulationStopped(Core::SystemResultStatus result);
private:
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index e9bf57895..148dd3e39 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -562,6 +562,120 @@ static std::string PaginateBuffer(std::string_view buffer, std::string_view requ
}
}
+static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
+ Kernel::KMemoryInfo mem_info;
+ Kernel::Svc::MemoryInfo svc_mem_info;
+ Kernel::Svc::PageInfo page_info;
+ VAddr cur_addr{base};
+
+ // Expect: r-x Code (.text)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
+ return cur_addr - 1;
+ }
+
+ // Expect: r-- Code (.rodata)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
+ return cur_addr - 1;
+ }
+
+ // Expect: rw- CodeData (.data)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ return cur_addr - 1;
+}
+
+static Loader::AppLoader::Modules FindModules(Core::System& system) {
+ Loader::AppLoader::Modules modules;
+
+ auto& page_table = system.ApplicationProcess()->GetPageTable();
+ auto& memory = system.ApplicationMemory();
+ VAddr cur_addr = 0;
+
+ // Look for executable sections in Code or AliasCode regions.
+ while (true) {
+ Kernel::KMemoryInfo mem_info{};
+ Kernel::Svc::PageInfo page_info{};
+ R_ASSERT(
+ page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ auto svc_mem_info = mem_info.GetSvcMemoryInfo();
+
+ if (svc_mem_info.permission == Kernel::Svc::MemoryPermission::ReadExecute &&
+ (svc_mem_info.state == Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.state == Kernel::Svc::MemoryState::AliasCode)) {
+ // Try to read the module name from its path.
+ constexpr s32 PathLengthMax = 0x200;
+ struct {
+ u32 zero;
+ s32 path_length;
+ std::array<char, PathLengthMax> path;
+ } module_path;
+
+ if (memory.ReadBlock(svc_mem_info.base_address + svc_mem_info.size, &module_path,
+ sizeof(module_path))) {
+ if (module_path.zero == 0 && module_path.path_length > 0) {
+ // Truncate module name.
+ module_path.path[PathLengthMax - 1] = '\0';
+
+ // Ignore leading directories.
+ char* path_pointer = module_path.path.data();
+
+ for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) &&
+ module_path.path[i] != '\0';
+ i++) {
+ if (module_path.path[i] == '/' || module_path.path[i] == '\\') {
+ path_pointer = module_path.path.data() + i + 1;
+ }
+ }
+
+ // Insert output.
+ modules.emplace(svc_mem_info.base_address, path_pointer);
+ }
+ }
+ }
+
+ // Check if we're done.
+ const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
+ if (next_address <= cur_addr) {
+ break;
+ }
+
+ cur_addr = next_address;
+ }
+
+ return modules;
+}
+
+static VAddr FindMainModuleEntrypoint(Core::System& system) {
+ Loader::AppLoader::Modules modules;
+ system.GetAppLoader().ReadNSOModules(modules);
+
+ // Do we have a module named main?
+ const auto main = std::find_if(modules.begin(), modules.end(),
+ [](const auto& key) { return key.second == "main"; });
+
+ if (main != modules.end()) {
+ return main->first;
+ }
+
+ // Do we have any loaded executable sections?
+ modules = FindModules(system);
+ if (!modules.empty()) {
+ return modules.begin()->first;
+ }
+
+ // As a last resort, use the start of the code region.
+ return GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart());
+}
+
void GDBStub::HandleQuery(std::string_view command) {
if (command.starts_with("TStatus")) {
// no tracepoint support
@@ -573,21 +687,10 @@ void GDBStub::HandleQuery(std::string_view command) {
const auto target_xml{arch->GetTargetXML()};
SendReply(PaginateBuffer(target_xml, command.substr(30)));
} else if (command.starts_with("Offsets")) {
- Loader::AppLoader::Modules modules;
- system.GetAppLoader().ReadNSOModules(modules);
-
- const auto main = std::find_if(modules.begin(), modules.end(),
- [](const auto& key) { return key.second == "main"; });
- if (main != modules.end()) {
- SendReply(fmt::format("TextSeg={:x}", main->first));
- } else {
- SendReply(fmt::format(
- "TextSeg={:x}",
- GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
- }
+ const auto main_offset = FindMainModuleEntrypoint(system);
+ SendReply(fmt::format("TextSeg={:x}", main_offset));
} else if (command.starts_with("Xfer:libraries:read::")) {
- Loader::AppLoader::Modules modules;
- system.GetAppLoader().ReadNSOModules(modules);
+ auto modules = FindModules(system);
std::string buffer;
buffer += R"(<?xml version="1.0"?>)";
@@ -727,37 +830,6 @@ static constexpr const char* GetMemoryPermissionString(const Kernel::Svc::Memory
}
}
-static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
- Kernel::KMemoryInfo mem_info;
- Kernel::Svc::MemoryInfo svc_mem_info;
- Kernel::Svc::PageInfo page_info;
- VAddr cur_addr{base};
-
- // Expect: r-x Code (.text)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
- svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
- return cur_addr - 1;
- }
-
- // Expect: r-- Code (.rodata)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
- svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
- return cur_addr - 1;
- }
-
- // Expect: rw- CodeData (.data)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- return cur_addr - 1;
-}
-
void GDBStub::HandleRcmd(const std::vector<u8>& command) {
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
std::string reply;
@@ -784,8 +856,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
reply = "Fastmem is not enabled.\n";
}
} else if (command_str == "get info") {
- Loader::AppLoader::Modules modules;
- system.GetAppLoader().ReadNSOModules(modules);
+ auto modules = FindModules(system);
reply = fmt::format("Process: {:#x} ({})\n"
"Program Id: {:#018x}\n",
diff --git a/src/core/hle/kernel/k_capabilities.cpp b/src/core/hle/kernel/k_capabilities.cpp
index fb890f978..274fee493 100644
--- a/src/core/hle/kernel/k_capabilities.cpp
+++ b/src/core/hle/kernel/k_capabilities.cpp
@@ -5,6 +5,7 @@
#include "core/hle/kernel/k_capabilities.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_process_page_table.h"
+#include "core/hle/kernel/k_trace.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/svc_version.h"
@@ -329,6 +330,8 @@ Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTab
// Map the range.
R_TRY(this->MapRange_(cap, size_cap, page_table));
+ } else if (GetCapabilityType(cap) == CapabilityType::MapRegion && !IsKTraceEnabled) {
+ continue;
} else {
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
}