mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
dmnt2: add memory-map read, improve module shared-lib names
This commit is contained in:
parent
3dce23773a
commit
277bd101c5
5 changed files with 100 additions and 5 deletions
|
@ -194,6 +194,16 @@ namespace ams::dmnt {
|
||||||
|
|
||||||
/* Truncate module name. */
|
/* Truncate module name. */
|
||||||
module_name[ModuleDefinition::PathLengthMax - 1] = 0;
|
module_name[ModuleDefinition::PathLengthMax - 1] = 0;
|
||||||
|
|
||||||
|
/* Set default module name start. */
|
||||||
|
module.SetNameStart(0);
|
||||||
|
|
||||||
|
/* Ignore leading directories. */
|
||||||
|
for (size_t i = 0; i < static_cast<size_t>(module_path.path_length); ++i) {
|
||||||
|
if (module_name[i] == '/' || module_name[i] == '\\') {
|
||||||
|
module.SetNameStart(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +238,11 @@ namespace ams::dmnt {
|
||||||
return svc::WriteDebugProcessMemory(m_debug_handle, reinterpret_cast<uintptr_t>(src), address, size);
|
return svc::WriteDebugProcessMemory(m_debug_handle, reinterpret_cast<uintptr_t>(src), address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result DebugProcess::QueryMemory(svc::MemoryInfo *out, uintptr_t address) {
|
||||||
|
svc::PageInfo dummy;
|
||||||
|
return svc::QueryDebugProcessMemory(out, std::addressof(dummy), m_debug_handle, address);
|
||||||
|
}
|
||||||
|
|
||||||
Result DebugProcess::Continue() {
|
Result DebugProcess::Continue() {
|
||||||
AMS_DMNT2_GDB_LOG_DEBUG("DebugProcess::Continue() all\n");
|
AMS_DMNT2_GDB_LOG_DEBUG("DebugProcess::Continue() all\n");
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,8 @@ namespace ams::dmnt {
|
||||||
Result ReadMemory(void *dst, uintptr_t address, size_t size);
|
Result ReadMemory(void *dst, uintptr_t address, size_t size);
|
||||||
Result WriteMemory(const void *src, uintptr_t address, size_t size);
|
Result WriteMemory(const void *src, uintptr_t address, size_t size);
|
||||||
|
|
||||||
|
Result QueryMemory(svc::MemoryInfo *out, uintptr_t address);
|
||||||
|
|
||||||
Result Continue();
|
Result Continue();
|
||||||
Result Continue(u64 thread_id);
|
Result Continue(u64 thread_id);
|
||||||
Result Step();
|
Result Step();
|
||||||
|
|
|
@ -772,6 +772,7 @@ namespace ams::dmnt {
|
||||||
AnnexBufferContents_Processes,
|
AnnexBufferContents_Processes,
|
||||||
AnnexBufferContents_Threads,
|
AnnexBufferContents_Threads,
|
||||||
AnnexBufferContents_Libraries,
|
AnnexBufferContents_Libraries,
|
||||||
|
AnnexBufferContents_MemoryMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
constinit AnnexBufferContents g_annex_buffer_contents = AnnexBufferContents_Invalid;
|
constinit AnnexBufferContents g_annex_buffer_contents = AnnexBufferContents_Invalid;
|
||||||
|
@ -1856,6 +1857,7 @@ namespace ams::dmnt {
|
||||||
AppendReply(m_reply_packet, ";augmented-libraries-svr4-read+");
|
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, ";qXfer:memory-map:read+");
|
||||||
AppendReply(m_reply_packet, ";swbreak+");
|
AppendReply(m_reply_packet, ";swbreak+");
|
||||||
AppendReply(m_reply_packet, ";hwbreak+");
|
AppendReply(m_reply_packet, ";hwbreak+");
|
||||||
AppendReply(m_reply_packet, ";vContSupported+");
|
AppendReply(m_reply_packet, ";vContSupported+");
|
||||||
|
@ -1882,6 +1884,8 @@ namespace ams::dmnt {
|
||||||
}
|
}
|
||||||
} else if (ParsePrefix(m_receive_packet, "libraries:read::")) {
|
} else if (ParsePrefix(m_receive_packet, "libraries:read::")) {
|
||||||
this->qXferLibrariesRead();
|
this->qXferLibrariesRead();
|
||||||
|
} else if (ParsePrefix(m_receive_packet, "memory-map:read::")) {
|
||||||
|
this->qXferMemoryMapRead();
|
||||||
} else if (ParsePrefix(m_receive_packet, "exec-file:read:")) {
|
} else if (ParsePrefix(m_receive_packet, "exec-file:read:")) {
|
||||||
SetReply(m_reply_packet, "l%s", m_debug_process.GetProcessName());
|
SetReply(m_reply_packet, "l%s", m_debug_process.GetProcessName());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1962,7 +1966,7 @@ namespace ams::dmnt {
|
||||||
|
|
||||||
const char *module_name = m_debug_process.GetModuleName(i);
|
const char *module_name = m_debug_process.GetModuleName(i);
|
||||||
const auto name_len = std::strlen(module_name);
|
const auto name_len = std::strlen(module_name);
|
||||||
if (name_len > 4 && std::strcmp(module_name + name_len - 4, ".elf") != 0 && std::strcmp(module_name + name_len - 4, ".nss") != 0) {
|
if (name_len < 5 || (std::strcmp(module_name + name_len - 4, ".elf") != 0 && std::strcmp(module_name + name_len - 4, ".nss") != 0)) {
|
||||||
AppendReply(g_annex_buffer, "<library name=\"%s.elf\"><segment address=\"0x%lx\" /></library>", module_name, m_debug_process.GetBaseAddress(i));
|
AppendReply(g_annex_buffer, "<library name=\"%s.elf\"><segment address=\"0x%lx\" /></library>", module_name, m_debug_process.GetBaseAddress(i));
|
||||||
} else {
|
} else {
|
||||||
AppendReply(g_annex_buffer, "<library name=\"%s\"><segment address=\"0x%lx\" /></library>", module_name, m_debug_process.GetBaseAddress(i));
|
AppendReply(g_annex_buffer, "<library name=\"%s\"><segment address=\"0x%lx\" /></library>", module_name, m_debug_process.GetBaseAddress(i));
|
||||||
|
@ -1978,6 +1982,73 @@ namespace ams::dmnt {
|
||||||
GetAnnexBufferContents(m_reply_packet, offset, length);
|
GetAnnexBufferContents(m_reply_packet, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbServerImpl::qXferMemoryMapRead() {
|
||||||
|
/* Handle the qXfer. */
|
||||||
|
u32 offset, length;
|
||||||
|
|
||||||
|
/* Parse offset/length. */
|
||||||
|
ParseOffsetLength(m_receive_packet, offset, length);
|
||||||
|
|
||||||
|
/* Acquire access to the annex buffer. */
|
||||||
|
std::scoped_lock lk(g_annex_buffer_lock);
|
||||||
|
|
||||||
|
/* If doing a fresh read, generate the module list. */
|
||||||
|
if (offset == 0 || g_annex_buffer_contents != AnnexBufferContents_MemoryMap) {
|
||||||
|
/* Set header. */
|
||||||
|
SetReply(g_annex_buffer, "<memory-map>\n");
|
||||||
|
|
||||||
|
/* Iterate over all mappings. */
|
||||||
|
uintptr_t cur_addr = 0;
|
||||||
|
svc::MemoryInfo prev_info = {};
|
||||||
|
size_t prev_size = 0;
|
||||||
|
while (true) {
|
||||||
|
/* Get current mapping. */
|
||||||
|
svc::MemoryInfo mem_info;
|
||||||
|
if (R_FAILED(m_debug_process.QueryMemory(std::addressof(mem_info), cur_addr))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the mapping is present, add it. */
|
||||||
|
if (mem_info.state != svc::MemoryState_Free && mem_info.state != svc::MemoryState_Inaccessible && mem_info.permission != svc::MemoryPermission_None) {
|
||||||
|
if (prev_size != 0 && mem_info.state == prev_info.state && mem_info.permission == prev_info.permission && mem_info.attribute == prev_info.attribute && mem_info.base_address == prev_info.base_address + prev_size) {
|
||||||
|
prev_size += mem_info.size;
|
||||||
|
} else {
|
||||||
|
if (prev_size != 0) {
|
||||||
|
AppendReply(g_annex_buffer, "<memory type=\"ram\" start=\"0x%lx\" length=\"0x%lx\" />", prev_info.base_address, prev_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_info = mem_info;
|
||||||
|
prev_size = mem_info.size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (prev_size != 0) {
|
||||||
|
AppendReply(g_annex_buffer, "<memory type=\"ram\" start=\"0x%lx\" length=\"0x%lx\" />", prev_info.base_address, prev_size);
|
||||||
|
|
||||||
|
prev_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uintptr_t next_address = mem_info.base_address + mem_info.size;
|
||||||
|
if (next_address <= cur_addr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_addr = next_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_size != 0) {
|
||||||
|
AppendReply(g_annex_buffer, "<memory type=\"ram\" start=\"0x%lx\" length=\"0x%lx\" />", prev_info.base_address, prev_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendReply(g_annex_buffer, "</memory-map>");
|
||||||
|
|
||||||
|
g_annex_buffer_contents = AnnexBufferContents_MemoryMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy out the module list. */
|
||||||
|
GetAnnexBufferContents(m_reply_packet, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
void GdbServerImpl::qXferOsdataRead() {
|
void GdbServerImpl::qXferOsdataRead() {
|
||||||
/* Handle the qXfer. */
|
/* Handle the qXfer. */
|
||||||
u32 offset, length;
|
u32 offset, length;
|
||||||
|
|
|
@ -102,6 +102,7 @@ namespace ams::dmnt {
|
||||||
void qXfer();
|
void qXfer();
|
||||||
void qXferFeaturesRead();
|
void qXferFeaturesRead();
|
||||||
void qXferLibrariesRead();
|
void qXferLibrariesRead();
|
||||||
|
void qXferMemoryMapRead();
|
||||||
void qXferOsdataRead();
|
void qXferOsdataRead();
|
||||||
bool qXferThreadsRead();
|
bool qXferThreadsRead();
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace ams::dmnt {
|
||||||
char m_name[PathLengthMax];
|
char m_name[PathLengthMax];
|
||||||
u64 m_address;
|
u64 m_address;
|
||||||
u64 m_size;
|
u64 m_size;
|
||||||
|
size_t m_name_start;
|
||||||
public:
|
public:
|
||||||
constexpr ModuleDefinition() : m_name(), m_address(), m_size() { /* ... */ }
|
constexpr ModuleDefinition() : m_name(), m_address(), m_size() { /* ... */ }
|
||||||
constexpr ~ModuleDefinition() { /* ... */ }
|
constexpr ~ModuleDefinition() { /* ... */ }
|
||||||
|
@ -34,9 +35,10 @@ namespace ams::dmnt {
|
||||||
constexpr ModuleDefinition &operator=(const ModuleDefinition &rhs) = default;
|
constexpr ModuleDefinition &operator=(const ModuleDefinition &rhs) = default;
|
||||||
|
|
||||||
constexpr void Reset() {
|
constexpr void Reset() {
|
||||||
m_name[0] = 0;
|
m_name[0] = 0;
|
||||||
m_address = 0;
|
m_address = 0;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
|
m_name_start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const ModuleDefinition &rhs) const {
|
constexpr bool operator==(const ModuleDefinition &rhs) const {
|
||||||
|
@ -48,7 +50,7 @@ namespace ams::dmnt {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr char *GetNameBuffer() { return m_name; }
|
constexpr char *GetNameBuffer() { return m_name; }
|
||||||
constexpr const char *GetName() const { return m_name; }
|
constexpr const char *GetName() const { return m_name + m_name_start; }
|
||||||
|
|
||||||
constexpr u64 GetAddress() const { return m_address; }
|
constexpr u64 GetAddress() const { return m_address; }
|
||||||
constexpr u64 GetSize() const { return m_size; }
|
constexpr u64 GetSize() const { return m_size; }
|
||||||
|
@ -57,6 +59,10 @@ namespace ams::dmnt {
|
||||||
m_address = address;
|
m_address = address;
|
||||||
m_size = size;
|
m_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr void SetNameStart(size_t offset) {
|
||||||
|
m_name_start = offset;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue