Skip to content

Commit

Permalink
Ability to request stackwalk per EventPipe session (#84077)
Browse files Browse the repository at this point in the history
* Ability to request stackwalk per EventPipe session

* Fix build

* Fix build 2

* Revert all the changes to start over

* Propagate disable_stacktrace parameter up to ep_enable

* Refactor ds-eventpipe-protocol to use the same object for CollectTracing command

* Parse disable_stacktrace in ds-eventpipe-protocol

* Fix a bug in ep.c enable declaration

* Introduce ep_enable_3

* Try fix failing tests

* Fix incorrect validation

* Use ep_enable_3 in IPC

* Allocate EventPipeSessionOptions on stack

* Pass EventPipeOptions by address

* Rename IPC parameter to enable_stackwalk

* Rename IPC parameter to stackwalk_requested

* Include ds-types.h in ds-sources.c to fix the build issue

* Fix jump bypasses variable initialization

* Fix incorrect struct initialization

* Fix incorrect struct initialization 2

* Fix incorrect struct initialization 3

* Apply code format suggestions

Co-authored-by: Johan Lorensson <lateralusx.github@gmail.com>

* Add ds_ipc_message_try_parse_bool

* Remove EventPipeSessionOptions from ep-types-forward

* init function for ep options

* Use coherent if style in validation

* Fix missing inline keyword

* Remove inline specifier

* Re-introduce EP_ASSERT in enable

* add ep_session_options_fini

* Fix fini called without init

---------

Co-authored-by: Johan Lorensson <lateralusx.github@gmail.com>
  • Loading branch information
ezsilmar and lateralusX authored Oct 13, 2023
1 parent 946c524 commit e8c8ab8
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 228 deletions.
215 changes: 106 additions & 109 deletions src/native/eventpipe/ds-eventpipe-protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested (
uint32_t *buffer_len,
bool *rundown_requested);

static
bool
eventpipe_collect_tracing_command_try_parse_stackwalk_requested (
uint8_t **buffer,
uint32_t *buffer_len,
bool *stackwalk_requested);

static
bool
eventpipe_collect_tracing_command_try_parse_config (
Expand All @@ -66,21 +73,21 @@ eventpipe_collect_tracing2_command_try_parse_payload (
uint16_t buffer_len);

static
bool
eventpipe_protocol_helper_stop_tracing (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream);
uint8_t *
eventpipe_collect_tracing3_command_try_parse_payload (
uint8_t *buffer,
uint16_t buffer_len);

static
bool
eventpipe_protocol_helper_collect_tracing (
eventpipe_protocol_helper_stop_tracing (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream);

static
bool
eventpipe_protocol_helper_collect_tracing_2 (
DiagnosticsIpcMessage *message,
eventpipe_protocol_helper_collect_tracing (
EventPipeCollectTracingCommandPayload *payload,
DiagnosticsIpcStream *stream);

static
Expand Down Expand Up @@ -140,7 +147,22 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested (
EP_ASSERT (buffer_len != NULL);
EP_ASSERT (rundown_requested != NULL);

return ds_ipc_message_try_parse_value (buffer, buffer_len, (uint8_t *)rundown_requested, 1);
return ds_ipc_message_try_parse_bool (buffer, buffer_len, rundown_requested);
}

static
inline
bool
eventpipe_collect_tracing_command_try_parse_stackwalk_requested (
uint8_t **buffer,
uint32_t *buffer_len,
bool *stackwalk_requested)
{
EP_ASSERT (buffer != NULL);
EP_ASSERT (buffer_len != NULL);
EP_ASSERT (stackwalk_requested != NULL);

return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested);
}

static
Expand Down Expand Up @@ -231,6 +253,30 @@ eventpipe_collect_tracing_command_try_parse_config (
ep_exit_error_handler ();
}

EventPipeCollectTracingCommandPayload *
ds_eventpipe_collect_tracing_command_payload_alloc (void)
{
return ep_rt_object_alloc (EventPipeCollectTracingCommandPayload);
}

void
ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload)
{
ep_return_void_if_nok (payload != NULL);
ep_rt_byte_array_free (payload->incoming_buffer);

DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) {
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config));
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config));
} DN_VECTOR_FOREACH_END;

ep_rt_object_free (payload);
}

/*
* EventPipeCollectTracingCommandPayload
*/

static
uint8_t *
eventpipe_collect_tracing_command_try_parse_payload (
Expand All @@ -251,6 +297,8 @@ eventpipe_collect_tracing_command_try_parse_payload (
!eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) ||
!eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs))
ep_raise_error ();
instance->rundown_requested = true;
instance->stackwalk_requested = true;

ep_on_exit:
return (uint8_t *)instance;
Expand All @@ -261,30 +309,6 @@ eventpipe_collect_tracing_command_try_parse_payload (
ep_exit_error_handler ();
}

EventPipeCollectTracingCommandPayload *
ds_eventpipe_collect_tracing_command_payload_alloc (void)
{
return ep_rt_object_alloc (EventPipeCollectTracingCommandPayload);
}

void
ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload)
{
ep_return_void_if_nok (payload != NULL);
ep_rt_byte_array_free (payload->incoming_buffer);

DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) {
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config));
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config));
} DN_VECTOR_FOREACH_END;

ep_rt_object_free (payload);
}

/*
* EventPipeCollectTracing2CommandPayload
*/

static
uint8_t *
eventpipe_collect_tracing2_command_try_parse_payload (
Expand All @@ -296,7 +320,7 @@ eventpipe_collect_tracing2_command_try_parse_payload (
uint8_t * buffer_cursor = buffer;
uint32_t buffer_cursor_len = buffer_len;

EventPipeCollectTracing2CommandPayload *instance = ds_eventpipe_collect_tracing2_command_payload_alloc ();
EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc ();
ep_raise_error_if_nok (instance != NULL);

instance->incoming_buffer = buffer;
Expand All @@ -306,34 +330,47 @@ eventpipe_collect_tracing2_command_try_parse_payload (
!eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) ||
!eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs))
ep_raise_error ();
instance->stackwalk_requested = true;

ep_on_exit:
return (uint8_t *)instance;

ep_on_error:
ds_eventpipe_collect_tracing2_command_payload_free (instance);
ds_eventpipe_collect_tracing_command_payload_free (instance);
instance = NULL;
ep_exit_error_handler ();
}

EventPipeCollectTracing2CommandPayload *
ds_eventpipe_collect_tracing2_command_payload_alloc (void)
static
uint8_t *
eventpipe_collect_tracing3_command_try_parse_payload (
uint8_t *buffer,
uint16_t buffer_len)
{
return ep_rt_object_alloc (EventPipeCollectTracing2CommandPayload);
}
EP_ASSERT (buffer != NULL);

void
ds_eventpipe_collect_tracing2_command_payload_free (EventPipeCollectTracing2CommandPayload *payload)
{
ep_return_void_if_nok (payload != NULL);
ep_rt_byte_array_free (payload->incoming_buffer);
uint8_t * buffer_cursor = buffer;
uint32_t buffer_cursor_len = buffer_len;

DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) {
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config));
ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config));
} DN_VECTOR_FOREACH_END;
EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc ();
ep_raise_error_if_nok (instance != NULL);

ep_rt_object_free (payload);
instance->incoming_buffer = buffer;

if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) ||
!eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) ||
!eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) ||
!eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) ||
!eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs))
ep_raise_error ();

ep_on_exit:
return (uint8_t *)instance;

ep_on_error:
ds_eventpipe_collect_tracing_command_payload_free (instance);
instance = NULL;
ep_exit_error_handler ();
}

/*
Expand Down Expand Up @@ -415,82 +452,34 @@ eventpipe_protocol_helper_stop_tracing (
static
bool
eventpipe_protocol_helper_collect_tracing (
DiagnosticsIpcMessage *message,
EventPipeCollectTracingCommandPayload *payload,
DiagnosticsIpcStream *stream)
{
ep_return_false_if_nok (message != NULL && stream != NULL);

bool result = false;
EventPipeCollectTracingCommandPayload *payload;
payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing_command_try_parse_payload);
ep_return_false_if_nok (stream != NULL);

if (!payload) {
ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING);
ep_raise_error ();
return false;
}

EventPipeSessionID session_id;
session_id = ep_enable (
EventPipeSessionOptions options;
ep_session_options_init(
&options,
NULL,
payload->circular_buffer_size_in_mb,
dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration),
dn_vector_size (payload->provider_configs),
EP_SESSION_TYPE_IPCSTREAM,
payload->serialization_format,
true,
payload->rundown_requested,
payload->stackwalk_requested,
ds_ipc_stream_get_stream_ref (stream),
NULL,
NULL);

if (session_id == 0) {
ds_ipc_message_send_error (stream, DS_IPC_E_FAIL);
ep_raise_error ();
} else {
eventpipe_protocol_helper_send_start_tracing_success (stream, session_id);
ep_start_streaming (session_id);
}

result = true;

ep_on_exit:
ds_eventpipe_collect_tracing_command_payload_free (payload);
return result;

ep_on_error:
EP_ASSERT (!result);
ds_ipc_stream_free (stream);
ep_exit_error_handler ();
}

static
bool
eventpipe_protocol_helper_collect_tracing_2 (
DiagnosticsIpcMessage *message,
DiagnosticsIpcStream *stream)
{
ep_return_false_if_nok (message != NULL && stream != NULL);

EventPipeSessionID session_id = 0;
bool result = false;
EventPipeCollectTracing2CommandPayload *payload;
payload = (EventPipeCollectTracing2CommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing2_command_try_parse_payload);

if (!payload) {
ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING);
ep_raise_error ();
}

EventPipeSessionID session_id;
session_id = ep_enable (
NULL,
payload->circular_buffer_size_in_mb,
dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration),
dn_vector_size (payload->provider_configs),
EP_SESSION_TYPE_IPCSTREAM,
payload->serialization_format,
payload->rundown_requested,
ds_ipc_stream_get_stream_ref (stream),
NULL,
NULL);
session_id = ep_enable_3(&options);

if (session_id == 0) {
ds_ipc_message_send_error (stream, DS_IPC_E_FAIL);
Expand All @@ -503,7 +492,8 @@ eventpipe_protocol_helper_collect_tracing_2 (
result = true;

ep_on_exit:
ds_eventpipe_collect_tracing2_command_payload_free (payload);
ep_session_options_fini(&options);
ds_eventpipe_collect_tracing_command_payload_free (payload);
return result;

ep_on_error:
Expand Down Expand Up @@ -539,13 +529,20 @@ ds_eventpipe_protocol_helper_handle_ipc_message (
ep_return_false_if_nok (message != NULL && stream != NULL);

bool result = false;
EventPipeCollectTracingCommandPayload* payload = NULL;

switch ((EventPipeCommandId)ds_ipc_header_get_commandid (ds_ipc_message_get_header_cref (message))) {
case EP_COMMANDID_COLLECT_TRACING:
result = eventpipe_protocol_helper_collect_tracing (message, stream);
payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing_command_try_parse_payload);
result = eventpipe_protocol_helper_collect_tracing (payload, stream);
break;
case EP_COMMANDID_COLLECT_TRACING_2:
result = eventpipe_protocol_helper_collect_tracing_2 (message, stream);
payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing2_command_try_parse_payload);
result = eventpipe_protocol_helper_collect_tracing (payload, stream);
break;
case EP_COMMANDID_COLLECT_TRACING_3:
payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing3_command_try_parse_payload);
result = eventpipe_protocol_helper_collect_tracing (payload, stream);
break;
case EP_COMMANDID_STOP_TRACING:
result = eventpipe_protocol_helper_stop_tracing (message, stream);
Expand Down
42 changes: 4 additions & 38 deletions src/native/eventpipe/ds-eventpipe-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/

// Command = 0x0202
// Command = 0x0203
// Command = 0x0204
#if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER)
struct _EventPipeCollectTracingCommandPayload {
#else
Expand All @@ -36,6 +38,8 @@ struct _EventPipeCollectTracingCommandPayload_Internal {
dn_vector_t *provider_configs;
uint32_t circular_buffer_size_in_mb;
EventPipeSerializationFormat serialization_format;
bool rundown_requested;
bool stackwalk_requested;
};

#if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER)
Expand All @@ -50,44 +54,6 @@ ds_eventpipe_collect_tracing_command_payload_alloc (void);
void
ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload);

/*
* EventPipeCollectTracing2CommandPayload
*/

// Command = 0x0202
#if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER)
struct _EventPipeCollectTracing2CommandPayload {
#else
struct _EventPipeCollectTracing2CommandPayload_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
// message = uint circularBufferMB, uint format, array<provider_config> providers
// uint = 4 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)
// provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data

uint8_t *incoming_buffer;
dn_vector_t *provider_configs;
uint32_t circular_buffer_size_in_mb;
EventPipeSerializationFormat serialization_format;
bool rundown_requested;
};

#if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER)
struct _EventPipeCollectTracing2CommandPayload {
uint8_t _internal [sizeof (struct _EventPipeCollectTracing2CommandPayload_Internal)];
};
#endif

EventPipeCollectTracing2CommandPayload *
ds_eventpipe_collect_tracing2_command_payload_alloc (void);

void
ds_eventpipe_collect_tracing2_command_payload_free (EventPipeCollectTracing2CommandPayload *payload);

/*
* EventPipeStopTracingCommandPayload
*/
Expand Down
Loading

0 comments on commit e8c8ab8

Please sign in to comment.