mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 09:36:35 +00:00
dmnt2: fix module name detection, add auto-break on hb nro launch
This commit is contained in:
parent
7e110ee8f7
commit
d30af4763a
3 changed files with 50 additions and 13 deletions
|
@ -27,7 +27,7 @@ namespace ams::creport {
|
||||||
|
|
||||||
struct ModulePath {
|
struct ModulePath {
|
||||||
u32 zero;
|
u32 zero;
|
||||||
u32 path_length;
|
s32 path_length;
|
||||||
char path[ModulePathLengthMax];
|
char path[ModulePathLengthMax];
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ModulePath) == 0x208, "ModulePath definition!");
|
static_assert(sizeof(ModulePath) == 0x208, "ModulePath definition!");
|
||||||
|
@ -210,7 +210,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also validate that we're looking at a valid name. */
|
/* Also validate that we're looking at a valid name. */
|
||||||
if (rodata_start.module_path.zero != 0 || rodata_start.module_path.path_length != strnlen(rodata_start.module_path.path, sizeof(rodata_start.module_path.path))) {
|
if (rodata_start.module_path.zero != 0 || rodata_start.module_path.path_length <= 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ namespace ams::creport {
|
||||||
/* Start after last slash in path. */
|
/* Start after last slash in path. */
|
||||||
const char *path = rodata_start.module_path.path;
|
const char *path = rodata_start.module_path.path;
|
||||||
int ofs;
|
int ofs;
|
||||||
for (ofs = rodata_start.module_path.path_length; ofs >= 0; ofs--) {
|
for (ofs = std::min<size_t>(rodata_start.module_path.path_length, sizeof(rodata_start.module_path.path)); ofs >= 0; ofs--) {
|
||||||
if (path[ofs] == '/' || path[ofs] == '\\') {
|
if (path[ofs] == '/' || path[ofs] == '\\') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -227,8 +227,8 @@ namespace ams::creport {
|
||||||
ofs++;
|
ofs++;
|
||||||
|
|
||||||
/* Copy name to output. */
|
/* Copy name to output. */
|
||||||
const size_t name_size = std::min(ModuleNameLengthMax, sizeof(rodata_start.module_path.path) - ofs);
|
const size_t name_size = std::min(ModuleNameLengthMax, std::min<size_t>(rodata_start.module_path.path_length, sizeof(rodata_start.module_path.path)) - ofs);
|
||||||
std::strncpy(out_name, path + ofs, name_size);
|
std::memcpy(out_name, path + ofs, name_size);
|
||||||
out_name[ModuleNameLengthMax - 1] = '\x00';
|
out_name[ModuleNameLengthMax - 1] = '\x00';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,9 +196,11 @@ namespace ams::dmnt {
|
||||||
char path[ModuleDefinition::PathLengthMax];
|
char path[ModuleDefinition::PathLengthMax];
|
||||||
} module_path;
|
} module_path;
|
||||||
if (R_SUCCEEDED(this->ReadMemory(std::addressof(module_path), memory_info.base_address + memory_info.size, sizeof(module_path)))) {
|
if (R_SUCCEEDED(this->ReadMemory(std::addressof(module_path), memory_info.base_address + memory_info.size, sizeof(module_path)))) {
|
||||||
if (module_path.zero == 0 && module_path.path_length == util::Strnlen(module_path.path, sizeof(module_path.path))) {
|
if (module_path.zero == 0 && module_path.path_length > 0) {
|
||||||
std::memcpy(module_name, module_path.path, ModuleDefinition::PathLengthMax);
|
std::memcpy(module_name, module_path.path, std::min<size_t>(ModuleDefinition::PathLengthMax, module_path.path_length));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
module_path.path_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Truncate module name. */
|
/* Truncate module name. */
|
||||||
|
@ -208,7 +210,7 @@ namespace ams::dmnt {
|
||||||
module.SetNameStart(0);
|
module.SetNameStart(0);
|
||||||
|
|
||||||
/* Ignore leading directories. */
|
/* Ignore leading directories. */
|
||||||
for (size_t i = 0; i < static_cast<size_t>(module_path.path_length); ++i) {
|
for (size_t i = 0; i < std::min<size_t>(ModuleDefinition::PathLengthMax, module_path.path_length) && module_name[i] != 0; ++i) {
|
||||||
if (module_name[i] == '/' || module_name[i] == '\\') {
|
if (module_name[i] == '/' || module_name[i] == '\\') {
|
||||||
module.SetNameStart(i + 1);
|
module.SetNameStart(i + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -947,6 +947,9 @@ namespace ams::dmnt {
|
||||||
void GdbServerImpl::ProcessDebugEvents() {
|
void GdbServerImpl::ProcessDebugEvents() {
|
||||||
AMS_DMNT2_GDB_LOG_DEBUG("Processing debug events for %016lx\n", m_process_id.value);
|
AMS_DMNT2_GDB_LOG_DEBUG("Processing debug events for %016lx\n", m_process_id.value);
|
||||||
|
|
||||||
|
u64 new_hb_nro_addr = 0;
|
||||||
|
u32 new_hb_nro_insn = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Wait for an event to come in. */
|
/* Wait for an event to come in. */
|
||||||
const Result wait_result = [&] ALWAYS_INLINE_LAMBDA {
|
const Result wait_result = [&] ALWAYS_INLINE_LAMBDA {
|
||||||
|
@ -1028,6 +1031,25 @@ namespace ams::dmnt {
|
||||||
/* Re-collect the process's modules. */
|
/* Re-collect the process's modules. */
|
||||||
m_debug_process.CollectModules();
|
m_debug_process.CollectModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_debug_process.GetOverrideStatus().IsHbl() && reason == svc::BreakReason_PostLoadDll) {
|
||||||
|
if (R_SUCCEEDED(m_debug_process.ReadMemory(std::addressof(new_hb_nro_insn), info.address, sizeof(new_hb_nro_insn)))) {
|
||||||
|
const u32 break_insn = SdkBreakPoint;
|
||||||
|
if (R_SUCCEEDED(m_debug_process.WriteMemory(std::addressof(break_insn), info.address, sizeof(break_insn)))) {
|
||||||
|
AMS_DMNT2_GDB_LOG_DEBUG("Set automatic break on new homebrew NRO (%lx, %lx)\n", info.address, info.size);
|
||||||
|
|
||||||
|
new_hb_nro_addr = info.address;
|
||||||
|
} else {
|
||||||
|
AMS_DMNT2_GDB_LOG_DEBUG("Failed to set automatic break on new homebrew NRO (%lx, %lx)\n", info.address, info.size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AMS_DMNT2_GDB_LOG_DEBUG("Failed to read first insn on new homebrew NRO (%lx, %lx)\n", info.address, info.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This was just a notification, so we should continue. */
|
||||||
|
m_debug_process.Continue();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we should automatically continue. */
|
/* Check if we should automatically continue. */
|
||||||
|
@ -1074,6 +1096,8 @@ namespace ams::dmnt {
|
||||||
const u32 insn = d.info.exception.specific.undefined_instruction.insn;
|
const u32 insn = d.info.exception.specific.undefined_instruction.insn;
|
||||||
u32 new_insn = 0;
|
u32 new_insn = 0;
|
||||||
|
|
||||||
|
bool is_new_hb_nro = false;
|
||||||
|
|
||||||
svc::ThreadContext ctx;
|
svc::ThreadContext ctx;
|
||||||
if (R_SUCCEEDED(m_debug_process.GetThreadContext(std::addressof(ctx), thread_id, svc::ThreadContextFlag_Control))) {
|
if (R_SUCCEEDED(m_debug_process.GetThreadContext(std::addressof(ctx), thread_id, svc::ThreadContextFlag_Control))) {
|
||||||
bool insn_changed = false;
|
bool insn_changed = false;
|
||||||
|
@ -1115,6 +1139,19 @@ namespace ams::dmnt {
|
||||||
{
|
{
|
||||||
signal = GdbSignal_BreakpointTrap;
|
signal = GdbSignal_BreakpointTrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_debug_process.GetOverrideStatus().IsHbl() && address == new_hb_nro_addr && insn == SdkBreakPoint) {
|
||||||
|
if (R_SUCCEEDED(m_debug_process.WriteMemory(std::addressof(new_hb_nro_insn), new_hb_nro_addr, sizeof(new_hb_nro_insn)))) {
|
||||||
|
AMS_DMNT2_GDB_LOG_DEBUG("Did automatic break on new homebrew NRO (%lx)\n", address);
|
||||||
|
|
||||||
|
new_hb_nro_addr = 0;
|
||||||
|
new_hb_nro_insn = 0;
|
||||||
|
|
||||||
|
is_new_hb_nro = true;
|
||||||
|
} else {
|
||||||
|
AMS_DMNT2_GDB_LOG_ERROR("Failed to restore instruction for new homebrew NRO (%lx)!\n", address);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insn_changed) {
|
if (insn_changed) {
|
||||||
|
@ -1128,7 +1165,7 @@ namespace ams::dmnt {
|
||||||
AMS_DMNT2_GDB_LOG_DEBUG("Non-SDK BreakPoint %lx, address=%p, insn=%08x\n", thread_id, reinterpret_cast<void *>(address), insn);
|
AMS_DMNT2_GDB_LOG_DEBUG("Non-SDK BreakPoint %lx, address=%p, insn=%08x\n", thread_id, reinterpret_cast<void *>(address), insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signal == GdbSignal_BreakpointTrap) {
|
if (signal == GdbSignal_BreakpointTrap && !is_new_hb_nro) {
|
||||||
SetReply(send_buffer, "T%02Xthread:p%lx.%lx;swbreak:;", static_cast<u32>(signal), m_process_id.value, thread_id);
|
SetReply(send_buffer, "T%02Xthread:p%lx.%lx;swbreak:;", static_cast<u32>(signal), m_process_id.value, thread_id);
|
||||||
reply = true;
|
reply = true;
|
||||||
}
|
}
|
||||||
|
@ -2049,8 +2086,6 @@ namespace ams::dmnt {
|
||||||
|
|
||||||
/* Note that we're attaching. */
|
/* Note that we're attaching. */
|
||||||
SetReply(m_buffer, "Attach to 0x%lx.\n", m_wait_process_id.value);
|
SetReply(m_buffer, "Attach to 0x%lx.\n", m_wait_process_id.value);
|
||||||
} else if (ParsePrefix(command, "wait homebrew") || ParsePrefix(command, "wait hb")) {
|
|
||||||
SetReply(m_buffer, "[TODO] wait for next homebrew\n");
|
|
||||||
} else if (ParsePrefix(command, "wait ")) {
|
} else if (ParsePrefix(command, "wait ")) {
|
||||||
/* Allow optional "0x" prefix. */
|
/* Allow optional "0x" prefix. */
|
||||||
ParsePrefix(command, "0x");
|
ParsePrefix(command, "0x");
|
||||||
|
@ -2074,8 +2109,8 @@ namespace ams::dmnt {
|
||||||
AppendReply(m_reply_packet, ";qXfer:osdata:read+");
|
AppendReply(m_reply_packet, ";qXfer:osdata:read+");
|
||||||
AppendReply(m_reply_packet, ";qXfer:features:read+");
|
AppendReply(m_reply_packet, ";qXfer:features:read+");
|
||||||
AppendReply(m_reply_packet, ";qXfer:libraries:read+");
|
AppendReply(m_reply_packet, ";qXfer:libraries:read+");
|
||||||
AppendReply(m_reply_packet, ";qXfer:libraries-svr4:read+");
|
// TODO: AppendReply(m_reply_packet, ";qXfer:libraries-svr4:read+");
|
||||||
AppendReply(m_reply_packet, ";augmented-libraries-svr4-read+");
|
// TODO: AppendReply(m_reply_packet, ";augmented-libraries-svr4-read+");
|
||||||
AppendReply(m_reply_packet, ";qXfer:threads:read+");
|
AppendReply(m_reply_packet, ";qXfer:threads:read+");
|
||||||
AppendReply(m_reply_packet, ";qXfer:exec-file:read+");
|
AppendReply(m_reply_packet, ";qXfer:exec-file:read+");
|
||||||
AppendReply(m_reply_packet, ";swbreak+");
|
AppendReply(m_reply_packet, ";swbreak+");
|
||||||
|
|
Loading…
Reference in a new issue