dmnt2: add memory-map read, improve module shared-lib names

This commit is contained in:
Michael Scire 2021-10-31 18:32:23 -07:00 committed by SciresM
parent 3dce23773a
commit 277bd101c5
5 changed files with 100 additions and 5 deletions

View file

@ -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");

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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() { /* ... */ }
@ -37,6 +38,7 @@ namespace ams::dmnt {
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;
}
}; };
} }