void bt_event_destroy(struct bt_object *obj) { struct bt_event *event; event = container_of(obj, struct bt_event, base); BT_LOGD("Destroying event: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); if (!event->base.parent) { /* * Event was keeping a reference to its class since it shared no * common ancestor with it to guarantee they would both have the * same lifetime. */ bt_put(event->event_class); } g_hash_table_destroy(event->clock_values); BT_LOGD_STR("Putting event's header field."); bt_put(event->event_header); BT_LOGD_STR("Putting event's stream event context field."); bt_put(event->stream_event_context); BT_LOGD_STR("Putting event's context field."); bt_put(event->context_payload); BT_LOGD_STR("Putting event's payload field."); bt_put(event->fields_payload); BT_LOGD_STR("Putting event's packet."); bt_put(event->packet); g_free(event); }
BT_HIDDEN struct bt_value *bt_attributes_create(void) { struct bt_value *attr_obj; /* * Attributes: array value object of array value objects, each one * containing two entries: a string value object (attributes * field name), and a value object (attributes field value). * * Example (JSON representation): * * [ * ["hostname", "eeppdesk"], * ["sysname", "Linux"], * ["tracer_major", 2], * ["tracer_minor", 5] * ] */ BT_LOGD_STR("Creating attributes object."); attr_obj = bt_value_array_create(); if (!attr_obj) { BT_LOGE_STR("Failed to create array value."); } else { BT_LOGD("Created attributes object: addr=%p", attr_obj); } return attr_obj; }
BT_HIDDEN bool ctf_metadata_decoder_is_packetized(FILE *fp, int *byte_order) { uint32_t magic; size_t len; int ret = 0; len = fread(&magic, sizeof(magic), 1, fp); if (len != 1) { BT_LOGD_STR("Cannot reade first metadata packet header: assuming the stream is not packetized."); goto end; } if (byte_order) { if (magic == TSDL_MAGIC) { ret = 1; *byte_order = BYTE_ORDER; } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) { ret = 1; *byte_order = BYTE_ORDER == BIG_ENDIAN ? LITTLE_ENDIAN : BIG_ENDIAN; } } end: rewind(fp); return ret; }
struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data) { struct bt_btr *btr; BT_LOGD_STR("Creating binary type reader (BTR)."); btr = g_new0(struct bt_btr, 1); if (!btr) { BT_LOGE_STR("Failed to allocate one binary type reader."); goto end; } btr->stack = stack_new(); if (!btr->stack) { BT_LOGE_STR("Cannot create BTR's stack."); bt_btr_destroy(btr); btr = NULL; goto end; } btr->state = BTR_STATE_NEXT_FIELD; btr->user.cbs = cbs; btr->user.data = data; BT_LOGD("Created BTR: addr=%p", btr); end: return btr; }
struct bt_value *bt_value_map_create(void) { struct bt_value_map *map_obj; BT_LOGD_STR("Creating empty map value object."); map_obj = g_new0(struct bt_value_map, 1); if (!map_obj) { BT_LOGE_STR("Failed to allocate one map object."); goto end; } map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP); map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) bt_object_put_ref); if (!map_obj->ght) { BT_LOGE_STR("Failed to allocate a GHashTable."); g_free(map_obj); map_obj = NULL; goto end; } BT_LOGD("Created map value object: addr=%p", map_obj); end: return (void *) map_obj; }
struct bt_value *bt_value_array_create(void) { struct bt_value_array *array_obj; BT_LOGD_STR("Creating empty array value object."); array_obj = g_new0(struct bt_value_array, 1); if (!array_obj) { BT_LOGE_STR("Failed to allocate one array object."); goto end; } array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY); array_obj->garray = bt_g_ptr_array_new_full(0, (GDestroyNotify) bt_object_put_ref); if (!array_obj->garray) { BT_LOGE_STR("Failed to allocate a GPtrArray."); g_free(array_obj); array_obj = NULL; goto end; } BT_LOGD("Created array value object: addr=%p", array_obj); end: return (void *) array_obj; }
BT_HIDDEN void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class) { BT_ASSERT(event_class); if (event_class->frozen) { return; } BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_common_get_name(event_class), bt_ctf_event_class_common_get_id(event_class)); event_class->frozen = 1; BT_LOGD_STR("Freezing event class's context field type."); bt_ctf_field_type_common_freeze(event_class->context_field_type); BT_LOGD_STR("Freezing event class's payload field type."); bt_ctf_field_type_common_freeze(event_class->payload_field_type); }
BT_HIDDEN void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj) { struct bt_ctf_event_class_common *event_class; event_class = container_of(obj, struct bt_ctf_event_class_common, base); BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_common_get_name(event_class), bt_ctf_event_class_common_get_id(event_class)); if (event_class->name) { g_string_free(event_class->name, TRUE); } if (event_class->emf_uri) { g_string_free(event_class->emf_uri, TRUE); } BT_LOGD_STR("Putting context field type."); bt_ctf_object_put_ref(event_class->context_field_type); BT_LOGD_STR("Putting payload field type."); bt_ctf_object_put_ref(event_class->payload_field_type); }
BT_HIDDEN void bt_event_freeze(struct bt_event *event) { assert(event); if (event->frozen) { return; } BT_LOGD("Freezing event: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); bt_packet_freeze(event->packet); BT_LOGD_STR("Freezing event's header field."); bt_field_freeze(event->event_header); BT_LOGD_STR("Freezing event's stream event context field."); bt_field_freeze(event->stream_event_context); BT_LOGD_STR("Freezing event's context field."); bt_field_freeze(event->context_payload); BT_LOGD_STR("Freezing event's payload field."); bt_field_freeze(event->fields_payload); event->frozen = 1; }
BT_HIDDEN int bin_info_lookup_function_name(struct bin_info *bin, uint64_t addr, char **func_name) { int ret = 0; char *_func_name = NULL; if (!bin || !func_name) { goto error; } /* Set DWARF info if it hasn't been accessed yet. */ if (!bin->dwarf_info && !bin->is_elf_only) { ret = bin_info_set_dwarf_info(bin); if (ret) { BT_LOGD_STR("Failed to set bin dwarf info, falling back to ELF lookup."); /* Failed to set DWARF info, fallback to ELF. */ bin->is_elf_only = true; } } if (!bin_info_has_address(bin, addr)) { goto error; } /* * Addresses in ELF and DWARF are relative to base address for * PIC, so make the address argument relative too if needed. */ if (bin->is_pic) { addr -= bin->low_addr; } if (bin->is_elf_only) { ret = bin_info_lookup_elf_function_name(bin, addr, &_func_name); BT_LOGD("Failed to lookup function name (ELF): ret=%d", ret); } else { ret = bin_info_lookup_dwarf_function_name(bin, addr, &_func_name); BT_LOGD("Failed to lookup function name (DWARF): ret=%d", ret); } *func_name = _func_name; return 0; error: return -1; }
static void bt_value_destroy(struct bt_object *obj) { struct bt_value *value; value = container_of(obj, struct bt_value, base); BT_LOGD("Destroying value: addr=%p", value); if (bt_value_is_null(value)) { BT_LOGD_STR("Not destroying the null value singleton."); return; } if (destroy_funcs[value->type]) { destroy_funcs[value->type](value); } g_free(value); }
struct bt_event *bt_event_create(struct bt_event_class *event_class) { int ret; enum bt_validation_flag validation_flags = BT_VALIDATION_FLAG_STREAM | BT_VALIDATION_FLAG_EVENT; struct bt_event *event = NULL; struct bt_trace *trace = NULL; struct bt_stream_class *stream_class = NULL; struct bt_field_type *packet_header_type = NULL; struct bt_field_type *packet_context_type = NULL; struct bt_field_type *event_header_type = NULL; struct bt_field_type *stream_event_ctx_type = NULL; struct bt_field_type *event_context_type = NULL; struct bt_field_type *event_payload_type = NULL; struct bt_field *event_header = NULL; struct bt_field *stream_event_context = NULL; struct bt_field *event_context = NULL; struct bt_field *event_payload = NULL; struct bt_value *environment = NULL; struct bt_validation_output validation_output = { 0 }; int trace_valid = 0; BT_LOGD("Creating event object: event-class-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event_class, bt_event_class_get_name(event_class), bt_event_class_get_id(event_class)); if (!event_class) { BT_LOGW_STR("Invalid parameter: event class is NULL."); goto error; } stream_class = bt_event_class_get_stream_class(event_class); /* * We disallow the creation of an event if its event class has not been * associated to a stream class. */ if (!stream_class) { BT_LOGW_STR("Event class is not part of a stream class."); goto error; } /* The event class was frozen when added to its stream class */ assert(event_class->frozen); /* Validate the trace (if any), the stream class, and the event class */ trace = bt_stream_class_get_trace(stream_class); if (trace) { BT_LOGD_STR("Event's class is part of a trace."); packet_header_type = bt_trace_get_packet_header_type(trace); trace_valid = trace->valid; assert(trace_valid); environment = trace->environment; } packet_context_type = bt_stream_class_get_packet_context_type( stream_class); event_header_type = bt_stream_class_get_event_header_type( stream_class); stream_event_ctx_type = bt_stream_class_get_event_context_type( stream_class); event_context_type = bt_event_class_get_context_type(event_class); event_payload_type = bt_event_class_get_payload_type(event_class); ret = bt_validate_class_types(environment, packet_header_type, packet_context_type, event_header_type, stream_event_ctx_type, event_context_type, event_payload_type, trace_valid, stream_class->valid, event_class->valid, &validation_output, validation_flags); BT_PUT(packet_header_type); BT_PUT(packet_context_type); BT_PUT(event_header_type); BT_PUT(stream_event_ctx_type); BT_PUT(event_context_type); BT_PUT(event_payload_type); if (ret) { /* * This means something went wrong during the validation * process, not that the objects are invalid. */ BT_LOGE("Failed to validate event and parents: ret=%d", ret); goto error; } if ((validation_output.valid_flags & validation_flags) != validation_flags) { /* Invalid trace/stream class/event class */ BT_LOGW("Invalid trace, stream class, or event class: " "valid-flags=0x%x", validation_output.valid_flags); goto error; } /* * At this point we know the trace (if associated to the stream * class), the stream class, and the event class, with their * current types, are valid. We may proceed with creating * the event. */ event = g_new0(struct bt_event, 1); if (!event) { BT_LOGE_STR("Failed to allocate one event."); goto error; } bt_object_init(event, bt_event_destroy); /* * event does not share a common ancestor with the event class; it has * to guarantee its existence by holding a reference. This reference * shall be released once the event is associated to a stream since, * from that point, the event and its class will share the same * lifetime. */ event->event_class = bt_get(event_class); event->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, bt_put, bt_put); if (validation_output.event_header_type) { BT_LOGD("Creating initial event header field: ft-addr=%p", validation_output.event_header_type); event_header = bt_field_create(validation_output.event_header_type); if (!event_header) { BT_LOGE_STR("Cannot create initial event header field object."); goto error; } } if (validation_output.stream_event_ctx_type) { BT_LOGD("Creating initial stream event context field: ft-addr=%p", validation_output.stream_event_ctx_type); stream_event_context = bt_field_create( validation_output.stream_event_ctx_type); if (!stream_event_context) { BT_LOGE_STR("Cannot create initial stream event context field object."); goto error; } } if (validation_output.event_context_type) { BT_LOGD("Creating initial event context field: ft-addr=%p", validation_output.event_context_type); event_context = bt_field_create( validation_output.event_context_type); if (!event_context) { BT_LOGE_STR("Cannot create initial event context field object."); goto error; } } if (validation_output.event_payload_type) { BT_LOGD("Creating initial event payload field: ft-addr=%p", validation_output.event_payload_type); event_payload = bt_field_create( validation_output.event_payload_type); if (!event_payload) { BT_LOGE_STR("Cannot create initial event payload field object."); goto error; } } /* * At this point all the fields are created, potentially from * validated copies of field types, so that the field types and * fields can be replaced in the trace, stream class, * event class, and created event. */ bt_validation_replace_types(trace, stream_class, event_class, &validation_output, validation_flags); BT_MOVE(event->event_header, event_header); BT_MOVE(event->stream_event_context, stream_event_context); BT_MOVE(event->context_payload, event_context); BT_MOVE(event->fields_payload, event_payload); /* * Put what was not moved in bt_validation_replace_types(). */ bt_validation_output_put_types(&validation_output); /* * Freeze the stream class since the event header must not be changed * anymore. */ bt_stream_class_freeze(stream_class); /* * Mark stream class, and event class as valid since * they're all frozen now. */ stream_class->valid = 1; event_class->valid = 1; /* Put stuff we borrowed from the event class */ BT_PUT(stream_class); BT_PUT(trace); BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event_class)); return event; error: bt_validation_output_put_types(&validation_output); BT_PUT(event); BT_PUT(stream_class); BT_PUT(trace); BT_PUT(event_header); BT_PUT(stream_event_context); BT_PUT(event_context); BT_PUT(event_payload); assert(!packet_header_type); assert(!packet_context_type); assert(!event_header_type); assert(!stream_event_ctx_type); assert(!event_context_type); assert(!event_payload_type); return event; }
G_MODULE_EXPORT struct bt_plugin_set *bt_plugin_python_create_all_from_file(const char *path) { struct bt_plugin_set *plugin_set = NULL; struct bt_plugin *plugin = NULL; PyObject *py_plugin_info = NULL; gchar *basename = NULL; size_t path_len; assert(path); if (python_state == PYTHON_STATE_CANNOT_INITIALIZE) { /* * We do not even care about the rest of the function * here because we already know Python cannot be fully * initialized. */ goto error; } BT_LOGD("Creating all Python plugins from file: path=\"%s\"", path); path_len = strlen(path); /* File name ends with `.py` */ if (strncmp(path + path_len - PYTHON_PLUGIN_FILE_EXT_LEN, PYTHON_PLUGIN_FILE_EXT, PYTHON_PLUGIN_FILE_EXT_LEN) != 0) { BT_LOGD("Skipping non-Python file: path=\"%s\"", path); goto error; } /* File name starts with `bt_plugin_` */ basename = g_path_get_basename(path); if (!basename) { BT_LOGW("Cannot get path's basename: path=\"%s\"", path); goto error; } if (strncmp(basename, PYTHON_PLUGIN_FILE_PREFIX, PYTHON_PLUGIN_FILE_PREFIX_LEN) != 0) { BT_LOGD("Skipping Python file not starting with `%s`: " "path=\"%s\"", PYTHON_PLUGIN_FILE_PREFIX, path); goto error; } /* * Initialize Python now. * * This is not done in the library contructor because the * interpreter is somewhat slow to initialize. If you don't * have any potential Python plugins, you don't need to endure * this waiting time everytime you load the library. */ init_python(); if (python_state != PYTHON_STATE_FULLY_INITIALIZED) { /* * For some reason we cannot initialize Python, * import the required modules, and get the required * attributes from them. */ BT_LOGI("Failed to initialize Python interpreter."); goto error; } /* * Call bt2.py_plugin._try_load_plugin_module() with this path * to get plugin info if the plugin is loadable and complete. * This function returns None when there's an error, but just in * case we also manually clear the last Python error state. */ BT_LOGD_STR("Getting Python plugin info object from Python module."); py_plugin_info = PyObject_CallFunction(py_try_load_plugin_module_func, "(s)", path); if (!py_plugin_info || py_plugin_info == Py_None) { BT_LOGW("Cannot load Python plugin: path=\"%s\"", path); print_python_traceback_warn(); PyErr_Clear(); goto error; } /* * Get bt_plugin from plugin info object. */ plugin = bt_plugin_from_python_plugin_info(py_plugin_info); if (!plugin) { BT_LOGW("Cannot create plugin object from Python plugin info object: " "path=\"%s\", py-plugin-info-addr=%p", path, py_plugin_info); goto error; } bt_plugin_set_path(plugin, path); plugin_set = bt_plugin_set_create(); if (!plugin_set) { BT_LOGE_STR("Cannot create empty plugin set."); goto error; } bt_plugin_set_add_plugin(plugin_set, plugin); BT_LOGD("Created all Python plugins from file: path=\"%s\", " "plugin-addr=%p, plugin-name=\"%s\"", path, plugin, bt_plugin_get_name(plugin)); goto end; error: BT_PUT(plugin_set); end: bt_put(plugin); Py_XDECREF(py_plugin_info); g_free(basename); return plugin_set; }
BT_HIDDEN int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, struct metadata_context *context) { int ret = 0; struct bt_ctf_value *attr_value = NULL; BT_ASSERT(event_class); BT_ASSERT(context); BT_LOGD("Serializing event class's metadata: " "event-class-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", metadata-context-addr=%p", event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class), context); context->current_indentation_level = 1; g_string_assign(context->field_name, ""); g_string_append(context->string, "event {\n"); /* Serialize attributes */ g_string_append_printf(context->string, "\tname = \"%s\";\n", event_class->common.name->str); BT_ASSERT(event_class->common.id >= 0); g_string_append_printf(context->string, "\tid = %" PRId64 ";\n", event_class->common.id); g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n", bt_ctf_stream_class_common_get_id( bt_ctf_event_class_common_borrow_stream_class( BT_CTF_TO_COMMON(event_class)))); if (event_class->common.log_level != BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) { g_string_append_printf(context->string, "\tloglevel = %d;\n", (int) event_class->common.log_level); } if (event_class->common.emf_uri->len > 0) { g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n", event_class->common.emf_uri->str); } /* Serialize context field type */ if (event_class->common.context_field_type) { g_string_append(context->string, "\tcontext := "); BT_LOGD_STR("Serializing event class's context field type metadata."); ret = bt_ctf_field_type_serialize_recursive( (void *) event_class->common.context_field_type, context); if (ret) { BT_LOGW("Cannot serialize event class's context field type's metadata: " "ret=%d", ret); goto end; } g_string_append(context->string, ";\n"); } /* Serialize payload field type */ if (event_class->common.payload_field_type) { g_string_append(context->string, "\tfields := "); BT_LOGD_STR("Serializing event class's payload field type metadata."); ret = bt_ctf_field_type_serialize_recursive( (void *) event_class->common.payload_field_type, context); if (ret) { BT_LOGW("Cannot serialize event class's payload field type's metadata: " "ret=%d", ret); goto end; } g_string_append(context->string, ";\n"); } g_string_append(context->string, "};\n\n"); end: context->current_indentation_level = 0; BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value); return ret; }