Skip to content

Commit

Permalink
[wasm][debugger] Improve debugger performance based on JMC (#86982)
Browse files Browse the repository at this point in the history
* Improve debugger performance.

* Loading assembly bytes if JMC is disabled after the debugger session is started.

* Fix CI.

* Load symbols on demand if JMC is enabled, we don't need to spend a lot of time loading information from 149 assemblies if we will probably not need all of them.

* Impriving the performance sending only metadata and not the full assembly.

* Fixing compilation error on tvos

* Apply suggestions from code review

Co-authored-by: Ankit Jain <radical@gmail.com>

* Apply suggestions from code review

Co-authored-by: Ankit Jain <radical@gmail.com>

* fix changes from code review

* addressing @radical comments

* addressing @radical and @lewing comments

---------

Co-authored-by: Ankit Jain <radical@gmail.com>
  • Loading branch information
thaystg and radical authored Jul 14, 2023
1 parent 2ad94b4 commit ae99bb2
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 151 deletions.
208 changes: 136 additions & 72 deletions src/mono/mono/component/debugger-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include <mono/metadata/custom-attrs-internals.h>
#include <mono/metadata/components.h>
#include <mono/mini/debugger-agent-external.h>
#include <mono/metadata/bundled-resources-internals.h>

#ifdef HAVE_UCONTEXT_H
#include <ucontext.h>
Expand Down Expand Up @@ -6945,6 +6946,88 @@ valid_memory_address (gpointer addr, gint size)
return ret;
}

static MonoAssembly*
find_assembly_by_name (char* assembly_name)
{
//we get 'foo.dll' but mono_assembly_load expects 'foo' so we strip the last dot
char *lookup_name = g_strdup (assembly_name);
for (int i = ((int)strlen (lookup_name) - 1); i >= 0; --i) {
if (lookup_name [i] == '.') {
lookup_name [i] = 0;
break;
}
}

//resolve the assembly
MonoImageOpenStatus status;
MonoAssemblyName* aname = mono_assembly_name_new (lookup_name);
g_free (lookup_name);
if (!aname) {
PRINT_DEBUG_MSG (1, "Could not resolve assembly %s\n", assembly_name);
return NULL;
}

MonoAssemblyByNameRequest byname_req;
mono_assembly_request_prepare_byname (&byname_req, mono_alc_get_default ());
MonoAssembly *assembly = mono_assembly_request_byname (aname, &byname_req, &status);
if (!assembly) {
GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
for (guint i = 0; i < assemblies->len; ++i) {
MonoAssembly *assemblyOnALC = (MonoAssembly*)g_ptr_array_index (assemblies, i);
if (!strcmp(assemblyOnALC->aname.name, aname->name)) {
assembly = assemblyOnALC;
break;
}
}
g_ptr_array_free (assemblies, TRUE);
if (!assembly) {
PRINT_DEBUG_MSG (1, "Could not resolve assembly %s\n", assembly_name);
goto exit;
}
}
exit:
mono_assembly_name_free_internal (aname);
return assembly;
}

static void
send_debug_information (MonoAssembly *ass, Buffer *buf)
{
guint8 pe_guid [16];
gint32 pe_age;
gint32 pe_timestamp;
guint8 *ppdb_data = NULL;
int ppdb_size = 0, ppdb_compressed_size = 0;
char *ppdb_path;
GArray *pdb_checksum_hash_type = g_array_new (FALSE, TRUE, sizeof (char*));
GArray *pdb_checksum = g_array_new (FALSE, TRUE, sizeof (guint8*));
gboolean has_debug_info = mono_get_pe_debug_info_full (ass->image, pe_guid, &pe_age, &pe_timestamp, &ppdb_data, &ppdb_size, &ppdb_compressed_size, &ppdb_path, pdb_checksum_hash_type, pdb_checksum);
if (!has_debug_info || ppdb_size > 0)
{
buffer_add_byte (buf, 0);
g_array_free (pdb_checksum_hash_type, TRUE);
g_array_free (pdb_checksum, TRUE);
return;
}
buffer_add_byte (buf, 1);
buffer_add_int (buf, pe_age);
buffer_add_byte_array (buf, pe_guid, 16);
buffer_add_string (buf, ppdb_path);
buffer_add_int (buf, pdb_checksum_hash_type->len);
for (int i = 0 ; i < pdb_checksum_hash_type->len; ++i) {
char* checksum_hash_type = g_array_index (pdb_checksum_hash_type, char*, i);
buffer_add_string (buf, checksum_hash_type);
if (!strcmp (checksum_hash_type, "SHA256"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 32);
else if (!strcmp (checksum_hash_type, "SHA384"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 48);
else if (!strcmp (checksum_hash_type, "SHA512"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 64);
}
g_array_free (pdb_checksum_hash_type, TRUE);
g_array_free (pdb_checksum, TRUE);
}

static ErrorCode
vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
{
Expand Down Expand Up @@ -7303,45 +7386,9 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
}
case MDBGPROT_CMD_GET_ASSEMBLY_BY_NAME: {
char* assembly_name = decode_string (p, &p, end);
//we get 'foo.dll' but mono_assembly_load expects 'foo' so we strip the last dot
char *lookup_name = g_strdup (assembly_name);
for (int i = ((int)strlen (lookup_name) - 1); i >= 0; --i) {
if (lookup_name [i] == '.') {
lookup_name [i] = 0;
break;
}
}

//resolve the assembly
MonoImageOpenStatus status;
MonoAssemblyName* aname = mono_assembly_name_new (lookup_name);
if (!aname) {
PRINT_DEBUG_MSG (1, "Could not resolve assembly %s\n", assembly_name);
buffer_add_int(buf, -1);
break;
}
MonoAssemblyByNameRequest byname_req;
mono_assembly_request_prepare_byname (&byname_req, mono_alc_get_default ());
MonoAssembly *assembly = mono_assembly_request_byname (aname, &byname_req, &status);
g_free (lookup_name);
if (!assembly) {
GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
for (guint i = 0; i < assemblies->len; ++i) {
MonoAssembly *assemblyOnALC = (MonoAssembly*)g_ptr_array_index (assemblies, i);
if (!strcmp(assemblyOnALC->aname.name, aname->name)) {
assembly = assemblyOnALC;
break;
}
}
g_ptr_array_free (assemblies, TRUE);
if (!assembly) {
PRINT_DEBUG_MSG (1, "Could not resolve assembly %s\n", assembly_name);
buffer_add_int(buf, -1);
mono_assembly_name_free_internal (aname);
break;
}
}
mono_assembly_name_free_internal (aname);
MonoAssembly* assembly = find_assembly_by_name (assembly_name);
if (!assembly)
buffer_add_int (buf, -1);
buffer_add_assemblyid (buf, mono_get_root_domain (), assembly);
break;
}
Expand Down Expand Up @@ -7418,6 +7465,55 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
}
break;
}
case MDBGPROT_CMD_GET_ASSEMBLY_BYTES: { //only used by wasm
#ifdef HOST_WASM
char* assembly_name = m_dbgprot_decode_string (p, &p, end);
if (assembly_name == NULL)
{
m_dbgprot_buffer_add_int (buf, 0);
m_dbgprot_buffer_add_int (buf, 0);
m_dbgprot_buffer_add_int (buf, 0);
}
else
{
int ppdb_size = 0;
const unsigned char* assembly_bytes = NULL;
unsigned int assembly_size = 0;
const unsigned char* pdb_bytes = NULL;
unsigned int symfile_size = 0;
mono_bundled_resources_get_assembly_resource_symbol_values (assembly_name, &pdb_bytes, &symfile_size);
MonoAssembly* assembly = find_assembly_by_name (assembly_name);
assembly_size = assembly->image->image_info->cli_cli_header.ch_metadata.size;
assembly_bytes = (const unsigned char*) assembly->image->raw_metadata;
if (symfile_size == 0) //try to send embedded pdb data
{
guint8 pe_guid [16];
gint32 pe_age;
gint32 pe_timestamp;
guint8 *ppdb_data = NULL;
int ppdb_compressed_size = 0;
char *ppdb_path;
mono_get_pe_debug_info_full (assembly->image, pe_guid, &pe_age, &pe_timestamp, &ppdb_data, &ppdb_size, &ppdb_compressed_size, &ppdb_path, NULL, NULL);
if (ppdb_compressed_size > 0)
{
symfile_size = ppdb_compressed_size;
pdb_bytes = ppdb_data;
}
}
m_dbgprot_buffer_init (buf, assembly_size + symfile_size + 1024);
m_dbgprot_buffer_add_byte_array (buf, (uint8_t *) assembly_bytes, assembly_size);
m_dbgprot_buffer_add_int (buf, ppdb_size);
m_dbgprot_buffer_add_byte_array (buf, (uint8_t *) pdb_bytes, symfile_size);
if (assembly)
send_debug_information (assembly, buf);
}
#else
m_dbgprot_buffer_add_int (buf, 0);
m_dbgprot_buffer_add_int (buf, 0);
m_dbgprot_buffer_add_int (buf, 0);
#endif
break;
}
default:
return ERR_NOT_IMPLEMENTED;
}
Expand Down Expand Up @@ -8042,39 +8138,7 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
break;
}
case MDBGPROT_CMD_ASSEMBLY_GET_DEBUG_INFORMATION: {
guint8 pe_guid [16];
gint32 pe_age;
gint32 pe_timestamp;
guint8 *ppdb_data = NULL;
int ppdb_size = 0, ppdb_compressed_size = 0;
char *ppdb_path;
GArray *pdb_checksum_hash_type = g_array_new (FALSE, TRUE, sizeof (char*));
GArray *pdb_checksum = g_array_new (FALSE, TRUE, sizeof (guint8*));
gboolean has_debug_info = mono_get_pe_debug_info_full (ass->image, pe_guid, &pe_age, &pe_timestamp, &ppdb_data, &ppdb_size, &ppdb_compressed_size, &ppdb_path, pdb_checksum_hash_type, pdb_checksum);
if (!has_debug_info || ppdb_size > 0)
{
buffer_add_byte (buf, 0);
g_array_free (pdb_checksum_hash_type, TRUE);
g_array_free (pdb_checksum, TRUE);
return ERR_NONE;
}
buffer_add_byte (buf, 1);
buffer_add_int (buf, pe_age);
buffer_add_byte_array (buf, pe_guid, 16);
buffer_add_string (buf, ppdb_path);
buffer_add_int (buf, pdb_checksum_hash_type->len);
for (int i = 0 ; i < pdb_checksum_hash_type->len; ++i) {
char* checksum_hash_type = g_array_index (pdb_checksum_hash_type, char*, i);
buffer_add_string (buf, checksum_hash_type);
if (!strcmp (checksum_hash_type, "SHA256"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 32);
else if (!strcmp (checksum_hash_type, "SHA384"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 48);
else if (!strcmp (checksum_hash_type, "SHA512"))
buffer_add_byte_array (buf, g_array_index (pdb_checksum, guint8*, i), 64);
}
g_array_free (pdb_checksum_hash_type, TRUE);
g_array_free (pdb_checksum, TRUE);
send_debug_information (ass, buf);
break;
}
case MDBGPROT_CMD_ASSEMBLY_HAS_DEBUG_INFO_LOADED: {
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/component/debugger-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

#define MAJOR_VERSION 2
#define MINOR_VERSION 63
#define MINOR_VERSION 64

typedef enum {
MDBGPROT_CMD_COMPOSITE = 100
Expand Down
22 changes: 0 additions & 22 deletions src/mono/mono/component/mini-wasm-debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,28 +432,6 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command,
invoke_data.flags = INVOKE_FLAG_DISABLE_BREAKPOINTS_AND_STEPPING;
error = mono_do_invoke_method (tls, &buf, &invoke_data, data, &data);
}
else if (command_set == MDBGPROT_CMD_SET_VM && (command == MDBGPROT_CMD_GET_ASSEMBLY_BYTES))
{
char* assembly_name = m_dbgprot_decode_string (data, &data, data + size);
if (assembly_name == NULL)
{
m_dbgprot_buffer_init (&buf, 128);
m_dbgprot_buffer_add_int (&buf, 0);
m_dbgprot_buffer_add_int (&buf, 0);
}
else
{
const unsigned char* assembly_bytes = NULL;
unsigned int assembly_size = 0;
mono_bundled_resources_get_assembly_resource_values (assembly_name, &assembly_bytes, &assembly_size);
const unsigned char* pdb_bytes = NULL;
unsigned int symfile_size = 0;
mono_bundled_resources_get_assembly_resource_symbol_values (assembly_name, &pdb_bytes, &symfile_size);
m_dbgprot_buffer_init (&buf, assembly_size + symfile_size);
m_dbgprot_buffer_add_byte_array (&buf, (uint8_t *) assembly_bytes, assembly_size);
m_dbgprot_buffer_add_byte_array (&buf, (uint8_t *) pdb_bytes, symfile_size);
}
}
else
{
m_dbgprot_buffer_init (&buf, 128);
Expand Down
Loading

0 comments on commit ae99bb2

Please sign in to comment.