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. */
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);
}
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() {
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 WriteMemory(const void *src, uintptr_t address, size_t size);
Result QueryMemory(svc::MemoryInfo *out, uintptr_t address);
Result Continue();
Result Continue(u64 thread_id);
Result Step();

View file

@ -772,6 +772,7 @@ namespace ams::dmnt {
AnnexBufferContents_Processes,
AnnexBufferContents_Threads,
AnnexBufferContents_Libraries,
AnnexBufferContents_MemoryMap,
};
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, ";qXfer:threads: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, ";hwbreak+");
AppendReply(m_reply_packet, ";vContSupported+");
@ -1882,6 +1884,8 @@ namespace ams::dmnt {
}
} else if (ParsePrefix(m_receive_packet, "libraries:read::")) {
this->qXferLibrariesRead();
} else if (ParsePrefix(m_receive_packet, "memory-map:read::")) {
this->qXferMemoryMapRead();
} else if (ParsePrefix(m_receive_packet, "exec-file:read:")) {
SetReply(m_reply_packet, "l%s", m_debug_process.GetProcessName());
} else {
@ -1962,7 +1966,7 @@ namespace ams::dmnt {
const char *module_name = m_debug_process.GetModuleName(i);
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));
} else {
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);
}
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() {
/* Handle the qXfer. */
u32 offset, length;

View file

@ -102,6 +102,7 @@ namespace ams::dmnt {
void qXfer();
void qXferFeaturesRead();
void qXferLibrariesRead();
void qXferMemoryMapRead();
void qXferOsdataRead();
bool qXferThreadsRead();

View file

@ -26,6 +26,7 @@ namespace ams::dmnt {
char m_name[PathLengthMax];
u64 m_address;
u64 m_size;
size_t m_name_start;
public:
constexpr ModuleDefinition() : m_name(), m_address(), m_size() { /* ... */ }
constexpr ~ModuleDefinition() { /* ... */ }
@ -34,9 +35,10 @@ namespace ams::dmnt {
constexpr ModuleDefinition &operator=(const ModuleDefinition &rhs) = default;
constexpr void Reset() {
m_name[0] = 0;
m_address = 0;
m_size = 0;
m_name[0] = 0;
m_address = 0;
m_size = 0;
m_name_start = 0;
}
constexpr bool operator==(const ModuleDefinition &rhs) const {
@ -48,7 +50,7 @@ namespace ams::dmnt {
}
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 GetSize() const { return m_size; }
@ -57,6 +59,10 @@ namespace ams::dmnt {
m_address = address;
m_size = size;
}
constexpr void SetNameStart(size_t offset) {
m_name_start = offset;
}
};
}