#include "ep-rt-config.h" #ifdef ENABLE_PERFTRACING #if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) #define EP_IMPL_METADATA_GENERATOR_GETTER_SETTER #include "ep-metadata-generator.h" #include "ep-rt.h" /* * Forward declares of all static functions. */ static bool metadata_generator_has_v2_param_types ( EventPipeParameterDesc *params, uint32_t params_len); static void metadata_generator_get_metadata_len ( uint32_t event_id, const ep_char16_t *event_name, size_t event_name_len, uint64_t keywords, uint32_t version, EventPipeEventLevel level, uint8_t opcode, EventPipeParameterDesc *params, uint32_t params_len, size_t *total_len, size_t *v2_len); static void metadata_generator_write_uint8_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, uint8_t value); static void metadata_generator_write_uint32_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, uint32_t value); static void metadata_generator_write_int64_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, int64_t value); static void metadata_generator_write_string_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, const ep_char16_t *value); /* * EventPipeMetadataGenerator. */ static bool metadata_generator_has_v2_param_types ( EventPipeParameterDesc *params, uint32_t params_len) { EP_ASSERT (params != NULL || params_len == 0); for (uint32_t i = 0; i < params_len; ++i) { if (params [i].type == EP_PARAMETER_TYPE_ARRAY) return true; } return false; } static void metadata_generator_get_metadata_len ( uint32_t event_id, const ep_char16_t *event_name, size_t event_name_len, uint64_t keywords, uint32_t version, EventPipeEventLevel level, uint8_t opcode, EventPipeParameterDesc *params, uint32_t params_len, size_t *total_len, size_t *v2_len) { EP_ASSERT (event_name != NULL); EP_ASSERT (params_len == 0 || params != NULL); EP_ASSERT (total_len != NULL); EP_ASSERT (v2_len != NULL); bool has_v2_types = metadata_generator_has_v2_param_types (params, params_len); *v2_len = 0; // eventID : 4 bytes // eventName : (eventName.Length + 1) * 2 bytes // keywords : 8 bytes // eventVersion : 4 bytes // level : 4 bytes // parameterCount : 4 bytes *total_len = 24 + ((event_name_len + 1) * sizeof (ep_char16_t)); if (opcode != 0) // Size of the opcode tag *total_len += 6; if (has_v2_types) { // need 4 bytes for the length of the tag // 1 byte for the tag identifier // and 4 bytes for the count of params *total_len += 9; // The metadata tag length does not include the required // length and tag fields *v2_len = 4; // Each parameter has an optional array identifier and then a 4 byte // TypeCode + the field name (parameterName.Length + 1) * 2 bytes. for(uint32_t i = 0; i < params_len; ++i) { EP_ASSERT(params [i].name != NULL); // For v2 metadata, fields start with a length (4 bytes) and then the field name size_t param_size = (4 + ((ep_rt_utf16_string_len (params [i].name) + 1) * sizeof (ep_char16_t))); if (params [i].type == EP_PARAMETER_TYPE_ARRAY) // If it's an array type we write the array descriptor (4 bytes) param_size += 4; // Then the typecode param_size += 4; *total_len += param_size; *v2_len += param_size; } } else { // Each parameter has a 4 byte TypeCode + (parameterName.Length + 1) * 2 bytes. for (uint32_t i = 0; i < params_len; ++i) { EP_ASSERT (params [i].name != NULL); *total_len += (4 + ((ep_rt_utf16_string_len (params [i].name) + 1) * sizeof (ep_char16_t))); } } } static void metadata_generator_write_uint8_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, uint8_t value) { EP_ASSERT ((*offset + sizeof (value)) <= buffer_len); memcpy (buffer + *offset, &value, sizeof (value)); *offset += sizeof (value); } static void metadata_generator_write_uint32_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, uint32_t value) { EP_ASSERT ((*offset + sizeof (value)) <= buffer_len); value = ep_rt_val_uint32_t (value); memcpy (buffer + *offset, &value, sizeof (value)); *offset += sizeof (value); } static void metadata_generator_write_int64_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, int64_t value) { EP_ASSERT ((*offset + sizeof (value)) <= buffer_len); value = ep_rt_val_int64_t (value); memcpy (buffer + *offset, &value, sizeof (value)); *offset += sizeof (value); } static void metadata_generator_write_string_to_buffer ( uint8_t *buffer, size_t buffer_len, size_t *offset, const ep_char16_t *value) { size_t const value_len = ep_rt_utf16_string_len (value); EP_ASSERT ((*offset + ((value_len + 1) * sizeof (ep_char16_t))) <= buffer_len); memcpy (buffer + *offset, value, (value_len + 1) * sizeof (ep_char16_t)); *offset += (value_len + 1) * sizeof (ep_char16_t); } uint8_t * ep_metadata_generator_generate_event_metadata ( uint32_t event_id, const ep_char16_t *event_name, uint64_t keywords, uint32_t version, EventPipeEventLevel level, uint8_t opcode, EventPipeParameterDesc *params, uint32_t params_len, size_t *metadata_len) { EP_ASSERT (event_name != NULL); EP_ASSERT (params_len == 0 || params != NULL); EP_ASSERT (metadata_len != NULL); size_t total_metadata_len = 0; size_t v2_metadata_len = 0; size_t offset = 0; uint8_t *buffer = NULL; size_t event_name_len = ep_rt_utf16_string_len (event_name); metadata_generator_get_metadata_len ( event_id, event_name, event_name_len, keywords, version, level, opcode, params, params_len, &total_metadata_len, &v2_metadata_len); bool has_v2_types = v2_metadata_len > 0; *metadata_len = total_metadata_len; // Allocate a metadata blob. buffer = ep_rt_byte_array_alloc (*metadata_len); ep_raise_error_if_nok (buffer != NULL); // Write the event ID. metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, event_id); // Write the event name. metadata_generator_write_string_to_buffer (buffer, total_metadata_len, &offset, event_name); // Write the keywords. metadata_generator_write_int64_to_buffer (buffer, total_metadata_len, &offset, keywords); // Write the version. metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, version); // Write the level. metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)level); if (has_v2_types) { // If we have V2 metadata types, we need to have 0 params for V1 metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, 0); } else { EP_ASSERT (!has_v2_types); // Write the parameter count. metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, params_len); // Write the parameter descriptions. for (uint32_t i = 0; i < params_len; ++i) { metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)params [i].type); metadata_generator_write_string_to_buffer (buffer, total_metadata_len, &offset, params [i].name); } } // Now we write optional V2 metadata, if there is any if (opcode != 0) { // Size of opcode metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, 1); // opcode tag metadata_generator_write_uint8_to_buffer (buffer, total_metadata_len, &offset, (uint8_t)EP_METADATA_TAG_OPCODE); // opcode value metadata_generator_write_uint8_to_buffer (buffer, total_metadata_len, &offset, opcode); } if (has_v2_types) { // size of V2 metadata payload metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)v2_metadata_len); // v2 param tag metadata_generator_write_uint8_to_buffer (buffer, total_metadata_len, &offset, (uint8_t)EP_METADATA_TAG_PARAMETER_PAYLOAD); // Write the parameter count. metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, params_len); // Write the parameter descriptions. for (uint32_t i = 0; i < params_len; ++i) { size_t param_name_len = ep_rt_utf16_string_len (params [i].name); size_t param_name_bytes = ((param_name_len + 1 ) * sizeof (ep_char16_t)); if (params [i].type == EP_PARAMETER_TYPE_ARRAY) { // For an array type, length is 12 (4 bytes length field, 4 bytes array descriptor, 4 bytes typecode) // + name length metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)(12 + param_name_bytes)); // Now write the event name metadata_generator_write_string_to_buffer (buffer, total_metadata_len, &offset, params [i].name); // And there is the array descriptor metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)EP_PARAMETER_TYPE_ARRAY); // Now write the underlying type metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)params [i].element_type); } else { // For a non array type, length is 8 (4 bytes length field, 4 bytes typecode) // + name length metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)(8 + param_name_bytes)); // Now write the event name metadata_generator_write_string_to_buffer (buffer, total_metadata_len, &offset, params [i].name); // And then the type metadata_generator_write_uint32_to_buffer (buffer, total_metadata_len, &offset, (uint32_t)params [i].type); } } } EP_ASSERT (*metadata_len == offset); ep_on_exit: return buffer; ep_on_error: ep_rt_byte_array_free (buffer); buffer = NULL; *metadata_len = 0; ep_exit_error_handler (); } /* * EventPipeParameterDesc. */ EventPipeParameterDesc * ep_parameter_desc_init ( EventPipeParameterDesc *parameter_desc, EventPipeParameterType type, const ep_char16_t *name) { EP_ASSERT (parameter_desc != NULL); parameter_desc->type = type; parameter_desc->element_type = EP_PARAMETER_TYPE_EMPTY; parameter_desc->name = name; return parameter_desc; } void ep_parameter_desc_fini (EventPipeParameterDesc *parameter_desc) { ; } #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ #if !defined(ENABLE_PERFTRACING) || (defined(EP_INCLUDE_SOURCE_FILES) && !defined(EP_FORCE_INCLUDE_SOURCE_FILES)) extern const char quiet_linker_empty_file_warning_eventpipe_metadata_generator; const char quiet_linker_empty_file_warning_eventpipe_metadata_generator = 0; #endif