Skip to content
Merged
20 changes: 20 additions & 0 deletions src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "fstream.h"
#include "typestring.h"
#include "win32threadpool.h"
#include "clrversion.h"

#undef EP_ARRAY_SIZE
#define EP_ARRAY_SIZE(expr) (sizeof(expr) / sizeof ((expr) [0]))
Expand Down Expand Up @@ -1161,6 +1162,25 @@ ep_rt_coreclr_config_lock_get (void)
return &_ep_rt_coreclr_config_lock_handle;
}

static
inline
const ep_char8_t *
ep_rt_entrypoint_assembly_name_get_utf8 (void)
{
STATIC_CONTRACT_NOTHROW;

return reinterpret_cast<const ep_char8_t*>(GetAppDomain ()->GetRootAssembly ()->GetSimpleName ());
}

static
const ep_char8_t *
ep_rt_runtime_version_get_utf8 (void)
{
STATIC_CONTRACT_NOTHROW;

return reinterpret_cast<const ep_char8_t*>(CLR_PRODUCT_VERSION);
}

/*
* Atomics.
*/
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/eventpipe/ep-rt-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ char *_ep_rt_mono_os_cmd_line = NULL;
mono_lazy_init_t _ep_rt_mono_managed_cmd_line_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
char *_ep_rt_mono_managed_cmd_line = NULL;


// Sample profiler.
static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL;
static uint32_t _ep_rt_mono_max_sampled_thread_count = 32;
Expand Down
19 changes: 19 additions & 0 deletions src/mono/mono/eventpipe/ep-rt-mono.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
#include <mono/utils/mono-rand.h>
#include <mono/utils/mono-lazy-init.h>
#include <mono/utils/w32api.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/w32file.h>
#include <mono/metadata/w32event.h>
#include <mono/metadata/environment-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <runtime_version.h>
#include <mono/metadata/profiler.h>

#undef EP_ARRAY_SIZE
Expand Down Expand Up @@ -1824,6 +1827,22 @@ ep_rt_diagnostics_command_line_get (void)
return cmd_line;
}

static
inline
const ep_char8_t *
ep_rt_entrypoint_assembly_name_get_utf8 (void)
{
return (const ep_char8_t *)m_image_get_assembly_name (mono_assembly_get_main ()->image);
}

static
inline
const ep_char8_t *
ep_rt_runtime_version_get_utf8 (void)
{
return (const ep_char8_t *)EGLIB_TOSTRING (RuntimeProductVersion);
}

/*
* Thread.
*/
Expand Down
218 changes: 218 additions & 0 deletions src/native/eventpipe/ds-process-protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ process_protocol_helper_get_process_info (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream);

static
bool
process_protocol_helper_get_process_info_2 (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream);

static
bool
process_protocol_helper_get_process_env (
Expand Down Expand Up @@ -191,6 +197,143 @@ ds_process_info_payload_fini (DiagnosticsProcessInfoPayload *payload)
;
}

/*
* DiagnosticsProcessInfo2Payload.
*/

static
uint16_t
process_info_2_payload_get_size (DiagnosticsProcessInfo2Payload *payload)
{
// see IPC spec @ https://github.com/dotnet/diagnostics/blob/master/documentation/design-docs/ipc-protocol.md
// for definition of serialization format

// uint64_t ProcessId; -> 8 bytes
// GUID RuntimeCookie; -> 16 bytes
// LPCWSTR CommandLine; -> 4 bytes + strlen * sizeof(WCHAR)
// LPCWSTR OS; -> 4 bytes + strlen * sizeof(WCHAR)
// LPCWSTR Arch; -> 4 bytes + strlen * sizeof(WCHAR)
// LPCWSTR managed_entrypoint_assembly_name; -> 4 bytes + strlen * sizeof(WCHAR)
// LPCWSTR clr_product_version; -> 4 bytes + strlen * sizeof(WCHAR)

EP_ASSERT (payload != NULL);

size_t size = 0;
size += sizeof(payload->process_id);
size += sizeof(payload->runtime_cookie);

size += sizeof(uint32_t);
size += (payload->command_line != NULL) ?
(ep_rt_utf16_string_len (payload->command_line) + 1) * sizeof(ep_char16_t) : 0;

size += sizeof(uint32_t);
size += (payload->os != NULL) ?
(ep_rt_utf16_string_len (payload->os) + 1) * sizeof(ep_char16_t) : 0;

size += sizeof(uint32_t);
size += (payload->arch != NULL) ?
(ep_rt_utf16_string_len (payload->arch) + 1) * sizeof(ep_char16_t) : 0;

size += sizeof(uint32_t);
size += (payload->managed_entrypoint_assembly_name != NULL) ?
(ep_rt_utf16_string_len (payload->managed_entrypoint_assembly_name) + 1) * sizeof(ep_char16_t) : 0;

size += sizeof(uint32_t);
size += (payload->clr_product_version != NULL) ?
(ep_rt_utf16_string_len (payload->clr_product_version) + 1) * sizeof(ep_char16_t) : 0;

EP_ASSERT (size <= UINT16_MAX);
return (uint16_t)size;
}

static
bool
process_info_2_payload_flatten (
void *payload,
uint8_t **buffer,
uint16_t *size)
{
DiagnosticsProcessInfo2Payload *process_info = (DiagnosticsProcessInfo2Payload*)payload;

EP_ASSERT (payload != NULL);
EP_ASSERT (buffer != NULL);
EP_ASSERT (*buffer != NULL);
EP_ASSERT (size != NULL);
EP_ASSERT (process_info_2_payload_get_size (process_info) == *size);

// see IPC spec @ https://github.com/dotnet/diagnostics/blob/master/documentation/design-docs/ipc-protocol.md
// for definition of serialization format

bool success = true;

// uint64_t ProcessId;
memcpy (*buffer, &process_info->process_id, sizeof (process_info->process_id));
*buffer += sizeof (process_info->process_id);
*size -= sizeof (process_info->process_id);

// GUID RuntimeCookie;
memcpy(*buffer, &process_info->runtime_cookie, sizeof (process_info->runtime_cookie));
*buffer += sizeof (process_info->runtime_cookie);
*size -= sizeof (process_info->runtime_cookie);

// LPCWSTR CommandLine;
success &= ds_ipc_message_try_write_string_utf16_t (buffer, size, process_info->command_line);

// LPCWSTR OS;
if (success)
success &= ds_ipc_message_try_write_string_utf16_t (buffer, size, process_info->os);

// LPCWSTR Arch;
if (success)
success &= ds_ipc_message_try_write_string_utf16_t (buffer, size, process_info->arch);

// LPCWSTR managed_entrypoint_assembly_name;
if (success)
success &= ds_ipc_message_try_write_string_utf16_t (buffer, size, process_info->managed_entrypoint_assembly_name);

// LPCWSTR clr_product_version;
if (success)
success &= ds_ipc_message_try_write_string_utf16_t (buffer, size, process_info->clr_product_version);

// Assert we've used the whole buffer we were given
EP_ASSERT(*size == 0);

return success;
}

DiagnosticsProcessInfo2Payload *
ds_process_info_2_payload_init (
DiagnosticsProcessInfo2Payload *payload,
const ep_char16_t *command_line,
const ep_char16_t *os,
const ep_char16_t *arch,
uint32_t process_id,
const uint8_t *runtime_cookie,
const ep_char16_t *managed_entrypoint_assembly_name,
const ep_char16_t *clr_product_version)
{
ep_return_null_if_nok (payload != NULL);

payload->command_line = command_line;
payload->os = os;
payload->arch = arch;
payload->process_id = process_id;
payload->managed_entrypoint_assembly_name = managed_entrypoint_assembly_name;
payload->clr_product_version = clr_product_version;

if (runtime_cookie)
memcpy (&payload->runtime_cookie, runtime_cookie, EP_GUID_SIZE);

return payload;
}

void
ds_process_info_2_payload_fini (DiagnosticsProcessInfo2Payload *payload)
{
;
}


/*
* DiagnosticsEnvironmentInfoPayload.
*/
Expand Down Expand Up @@ -386,6 +529,78 @@ process_protocol_helper_get_process_info (
ep_exit_error_handler ();
}

static
bool
process_protocol_helper_get_process_info_2 (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream)
{
EP_ASSERT (message != NULL);
EP_ASSERT (stream != NULL);

bool result = false;
ep_char16_t *command_line = NULL;
ep_char16_t *os_info = NULL;
ep_char16_t *arch_info = NULL;
ep_char16_t *managed_entrypoint_assembly_name = NULL;
ep_char16_t *clr_product_version = NULL;
DiagnosticsProcessInfo2Payload payload;
DiagnosticsProcessInfo2Payload *process_info_2_payload = NULL;

command_line = ep_rt_utf8_to_utf16_string (ep_rt_diagnostics_command_line_get (), -1);
ep_raise_error_if_nok (command_line != NULL);

os_info = ep_rt_utf8_to_utf16_string (ep_event_source_get_os_info (), -1);
ep_raise_error_if_nok (os_info != NULL);

arch_info = ep_rt_utf8_to_utf16_string (ep_event_source_get_arch_info (), -1);
ep_raise_error_if_nok (arch_info != NULL);

managed_entrypoint_assembly_name = ep_rt_utf8_to_utf16_string (ep_rt_entrypoint_assembly_name_get_utf8 (), -1);
ep_raise_error_if_nok (managed_entrypoint_assembly_name != NULL);

clr_product_version = ep_rt_utf8_to_utf16_string (ep_rt_runtime_version_get_utf8 (), -1);
ep_raise_error_if_nok (clr_product_version != NULL);

process_info_2_payload = ds_process_info_2_payload_init (
&payload,
command_line,
os_info,
arch_info,
ep_rt_current_process_get_id (),
ds_ipc_advertise_cookie_v1_get (),
managed_entrypoint_assembly_name,
clr_product_version);
ep_raise_error_if_nok (process_info_2_payload != NULL);

ep_raise_error_if_nok (ds_ipc_message_initialize_buffer (
message,
ds_ipc_header_get_generic_success (),
(void *)process_info_2_payload,
process_info_2_payload_get_size (process_info_2_payload),
process_info_2_payload_flatten));

ep_raise_error_if_nok (ds_ipc_message_send (message, stream));

result = true;

ep_on_exit:
ds_process_info_2_payload_fini (process_info_2_payload);
ep_rt_utf16_string_free (arch_info);
ep_rt_utf16_string_free (os_info);
ep_rt_utf16_string_free (command_line);
ep_rt_utf16_string_free (managed_entrypoint_assembly_name);
ep_rt_utf16_string_free (clr_product_version);
ds_ipc_stream_free (stream);
return result;

ep_on_error:
EP_ASSERT (!result);
ds_ipc_message_send_error (stream, DS_IPC_E_FAIL);
DS_LOG_WARNING_0 ("Failed to send DiagnosticsIPC response");
ep_exit_error_handler ();
}

static
bool
process_protocol_helper_get_process_env (
Expand Down Expand Up @@ -566,6 +781,9 @@ ds_process_protocol_helper_handle_ipc_message (
break;
case DS_PROCESS_COMMANDID_SET_ENV_VAR:
result = process_protocol_helper_set_environment_variable (message, stream);
break;
case DS_PROCESS_COMMANDID_GET_PROCESS_INFO_2:
result = process_protocol_helper_get_process_info_2 (message, stream);
break;
default:
result = process_protocol_helper_unknown_command (message, stream);
Expand Down
51 changes: 50 additions & 1 deletion src/native/eventpipe/ds-process-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,56 @@ ds_process_info_payload_init (
void
ds_process_info_payload_fini (DiagnosticsProcessInfoPayload *payload);

/*
* DiagnosticsProcessInfo2Payload
*/

// command = 0x0400
#if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_PROCESS_PROTOCOL_GETTER_SETTER)
struct _DiagnosticsProcessInfo2Payload {
#else
struct _DiagnosticsProcessInfo2Payload_Internal {
#endif
// The protocol buffer is defined as:
// X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z
// uint = 4 little endian bytes
// long = 8 little endian bytes
// GUID = 16 little endian bytes
// wchar = 2 little endian bytes, UTF16 encoding
// array<T> = uint length, length # of Ts
// string = (array<char> where the last char must = 0) or (length = 0)

// ProcessInfo = long pid, GUID runtimeCookie, string cmdline, string OS, string arch, string managed entrypoint assembly path, string clr product version
uint64_t process_id;
const ep_char16_t *command_line;
const ep_char16_t *os;
const ep_char16_t *arch;
uint8_t runtime_cookie [EP_GUID_SIZE];
const ep_char16_t *managed_entrypoint_assembly_name;
const ep_char16_t *clr_product_version;

};

#if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_PROCESS_PROTOCOL_GETTER_SETTER)
struct _DiagnosticsProcessInfo2Payload {
uint8_t _internal [sizeof (struct _DiagnosticsProcessInfo2Payload_Internal)];
};
#endif

DiagnosticsProcessInfo2Payload *
ds_process_info_2_payload_init (
DiagnosticsProcessInfo2Payload *payload,
const ep_char16_t *command_line,
const ep_char16_t *os,
const ep_char16_t *arch,
uint32_t process_id,
const uint8_t *runtime_cookie,
const ep_char16_t *managed_entrypoint_assembly_name,
const ep_char16_t *clr_product_version);

void
ds_process_info_2_payload_fini (DiagnosticsProcessInfo2Payload *payload);

/*
* DiagnosticsEnvironmentInfoPayload
*/
Expand Down Expand Up @@ -125,4 +175,3 @@ ds_process_protocol_helper_handle_ipc_message (

#endif /* ENABLE_PERFTRACING */
#endif /* __DIAGNOSTICS_PROCESS_PROTOCOL_H__ */

Loading