int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class, struct bt_ctf_field_type *type, const char *name) { int ret = 0; if (!event_class || !type) { BT_LOGW("Invalid parameter: event class or field type is NULL: " "event-class-addr=%p, field-type-addr=%p", event_class, type); ret = -1; goto end; } if (!bt_ctf_identifier_is_valid(name)) { BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: " "addr=%p, name=\"%s\", id=%" PRId64 ", field-name=\"%s\"", event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class), name); ret = -1; goto end; } if (event_class->common.frozen) { BT_LOGW("Invalid parameter: event class is frozen: " "addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class)); ret = -1; goto end; } if (!event_class->common.payload_field_type) { BT_LOGW("Event class has no payload field type: " "addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class)); ret = -1; goto end; } BT_ASSERT(bt_ctf_field_type_common_get_type_id( event_class->common.payload_field_type) == BT_CTF_FIELD_TYPE_ID_STRUCT); ret = bt_ctf_field_type_structure_add_field( (void *) event_class->common.payload_field_type, (void *) type, name); BT_LOGV("Added field to event class's payload field type: " "event-class-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p", event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class), name, type); end: return ret; }
BT_HIDDEN int bt_ctf_event_class_common_validate_single_clock_class( struct bt_ctf_event_class_common *event_class, struct bt_ctf_clock_class **expected_clock_class) { int ret = 0; BT_ASSERT(event_class); BT_ASSERT(expected_clock_class); ret = bt_ctf_field_type_common_validate_single_clock_class( event_class->context_field_type, expected_clock_class); if (ret) { BT_LOGW("Event class's context field type " "is not recursively mapped to the " "expected clock class: " "event-class-addr=%p, " "event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "ft-addr=%p", event_class, bt_ctf_event_class_common_get_name(event_class), event_class->id, event_class->context_field_type); goto end; } ret = bt_ctf_field_type_common_validate_single_clock_class( event_class->payload_field_type, expected_clock_class); if (ret) { BT_LOGW("Event class's payload field type " "is not recursively mapped to the " "expected clock class: " "event-class-addr=%p, " "event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "ft-addr=%p", event_class, bt_ctf_event_class_common_get_name(event_class), event_class->id, event_class->payload_field_type); goto end; } end: return ret; }
BT_HIDDEN struct bt_value *bt_attributes_get_field_value_by_name( struct bt_value *attr_obj, const char *name) { struct bt_value *value_obj = NULL; struct bt_value *attr_field_obj = NULL; if (!attr_obj || !name) { BT_LOGW("Invalid parameter: attributes object or name is NULL: " "value-addr=%p, name-addr=%p", attr_obj, name); goto end; } attr_field_obj = bt_attributes_get_field_by_name(attr_obj, name); if (!attr_field_obj) { BT_LOGD("Cannot find attributes object's field by name: " "value-addr=%p, name=\"%s\"", attr_obj, name); goto end; } value_obj = bt_value_array_get(attr_field_obj, BT_ATTR_VALUE_INDEX); if (!value_obj) { BT_LOGE("Cannot get attribute array value's element by index: " "value-addr=%p, index=%" PRIu64, attr_field_obj, (uint64_t) BT_ATTR_VALUE_INDEX); } end: BT_PUT(attr_field_obj); return value_obj; }
static inline int64_t get_compound_field_type_length(struct bt_btr *btr, struct bt_field_type *field_type) { int64_t length; switch (bt_field_type_get_type_id(field_type)) { case BT_FIELD_TYPE_ID_STRUCT: length = (int64_t) bt_field_type_structure_get_field_count( field_type); break; case BT_FIELD_TYPE_ID_VARIANT: /* Variant field types always "contain" a single type */ length = 1; break; case BT_FIELD_TYPE_ID_ARRAY: length = bt_field_type_array_get_length(field_type); break; case BT_FIELD_TYPE_ID_SEQUENCE: length = btr->user.cbs.query.get_sequence_length(field_type, btr->user.data); break; default: BT_LOGW("Cannot get field type's field count: btr-addr=%p, " "ft-addr=%p, ft-id=%s", btr, field_type, bt_field_type_id_string( bt_field_type_get_type_id(field_type))); length = BT_BTR_STATUS_ERROR; } return length; }
struct bt_clock_value *bt_event_get_clock_value( struct bt_event *event, struct bt_clock_class *clock_class) { struct bt_clock_value *clock_value = NULL; if (!event || !clock_class) { BT_LOGW("Invalid parameter: event or clock class is NULL: " "event-addr=%p, clock-class-addr=%p", event, clock_class); goto end; } clock_value = g_hash_table_lookup(event->clock_values, clock_class); if (!clock_value) { BT_LOGV("No clock value associated to the given clock class: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", clock-class-addr=%p, " "clock-class-name=\"%s\"", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), clock_class, bt_clock_class_get_name(clock_class)); goto end; } bt_get(clock_value); end: return clock_value; }
BT_HIDDEN int bt_event_serialize(struct bt_event *event, struct bt_stream_pos *pos, enum bt_byte_order native_byte_order) { int ret = 0; assert(event); assert(pos); BT_LOGV_STR("Serializing event's context field."); if (event->context_payload) { ret = bt_field_serialize(event->context_payload, pos, native_byte_order); if (ret) { BT_LOGW("Cannot serialize event's context field: " "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)); goto end; } } BT_LOGV_STR("Serializing event's payload field."); if (event->fields_payload) { ret = bt_field_serialize(event->fields_payload, pos, native_byte_order); if (ret) { BT_LOGW("Cannot serialize event's payload field: " "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)); goto end; } } end: return ret; }
BT_HIDDEN void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class, struct metadata_context *context) { unsigned char *uuid; BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, " "name=\"%s\", metadata-context-addr=%p", clock_class, bt_ctf_clock_class_get_name(clock_class), context); if (!clock_class || !context) { BT_LOGW("Invalid parameter: clock class or metadata context is NULL: " "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p", clock_class, bt_ctf_clock_class_get_name(clock_class), context); return; } uuid = clock_class->uuid; g_string_append(context->string, "clock {\n"); g_string_append_printf(context->string, "\tname = %s;\n", clock_class->name->str); if (clock_class->uuid_set) { g_string_append_printf(context->string, "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n", uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); } if (clock_class->description) { g_string_append_printf(context->string, "\tdescription = \"%s\";\n", clock_class->description->str); } g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n", clock_class->frequency); g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n", clock_class->precision); g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n", clock_class->offset_s); g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n", clock_class->offset); g_string_append_printf(context->string, "\tabsolute = %s;\n", clock_class->absolute ? "true" : "false"); g_string_append(context->string, "};\n\n"); }
BT_HIDDEN int bt_attributes_set_field_value(struct bt_value *attr_obj, const char *name, struct bt_value *value_obj) { int ret = 0; struct bt_value *attr_field_obj = NULL; if (!attr_obj || !name || !value_obj) { BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: " "attr-value-addr=%p, name-addr=%p, value-addr=%p", attr_obj, name, value_obj); ret = -1; goto end; } attr_field_obj = bt_attributes_get_field_by_name(attr_obj, name); if (attr_field_obj) { ret = bt_value_array_set(attr_field_obj, BT_ATTR_VALUE_INDEX, value_obj); goto end; } attr_field_obj = bt_value_array_create(); if (!attr_field_obj) { BT_LOGE_STR("Failed to create empty array value."); ret = -1; goto end; } ret = bt_value_array_append_string(attr_field_obj, name); ret |= bt_value_array_append(attr_field_obj, value_obj); if (ret) { BT_LOGE("Cannot append elements to array value: addr=%p", attr_field_obj); goto end; } ret = bt_value_array_append(attr_obj, attr_field_obj); if (ret) { BT_LOGE("Cannot append element to array value: " "array-value-addr=%p, element-value-addr=%p", attr_obj, attr_field_obj); } end: BT_PUT(attr_field_obj); return ret; }
static inline enum bt_btr_status validate_contiguous_bo(struct bt_btr *btr, enum bt_byte_order next_bo) { enum bt_btr_status status = BT_BTR_STATUS_OK; /* Always valid when at a byte boundary */ if (packet_at(btr) % 8 == 0) { goto end; } /* Always valid if last byte order is unknown */ if (btr->last_bo == BT_BYTE_ORDER_UNKNOWN) { goto end; } /* Always valid if next byte order is unknown */ if (next_bo == BT_BYTE_ORDER_UNKNOWN) { goto end; } /* Make sure last byte order is compatible with the next byte order */ switch (btr->last_bo) { case BT_BYTE_ORDER_BIG_ENDIAN: case BT_BYTE_ORDER_NETWORK: if (next_bo != BT_BYTE_ORDER_BIG_ENDIAN && next_bo != BT_BYTE_ORDER_NETWORK) { status = BT_BTR_STATUS_ERROR; } break; case BT_BYTE_ORDER_LITTLE_ENDIAN: if (next_bo != BT_BYTE_ORDER_LITTLE_ENDIAN) { status = BT_BTR_STATUS_ERROR; } break; default: status = BT_BTR_STATUS_ERROR; } end: if (status < 0) { BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: " "btr-addr=%p, last-bo=%s, next-bo=%s", btr, bt_byte_order_string(btr->last_bo), bt_byte_order_string(next_bo)); } return status; }
struct bt_ctf_field_type * bt_ctf_event_class_get_payload_type_field_type_by_name( struct bt_ctf_event_class *event_class, const char *name) { GQuark name_quark; struct bt_ctf_field_type *field_type = NULL; if (!event_class || !name) { BT_LOGW("Invalid parameter: event class or name is NULL: " "event-class-addr=%p, name-addr=%p", event_class, name); goto end; } if (!event_class->common.payload_field_type) { BT_LOGV("Event class has no payload field type: " "addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class)); goto end; } BT_ASSERT(bt_ctf_field_type_common_get_type_id( event_class->common.payload_field_type) == BT_CTF_FIELD_TYPE_ID_STRUCT); name_quark = g_quark_try_string(name); if (!name_quark) { BT_LOGE("Cannot get GQuark: string=\"%s\"", name); goto end; } /* * No need to increment field_type's reference count since getting it * from the structure already does. */ field_type = (void *) bt_ctf_field_type_structure_get_field_type_by_name( (void *) event_class->common.payload_field_type, name); end: return field_type; }
static int stack_push_with_len(struct bt_btr *btr, struct bt_field_type *base_type) { int ret = 0; int64_t base_len = get_compound_field_type_length(btr, base_type); if (base_len < 0) { BT_LOGW("Cannot get compound field type's field count: " "btr-addr=%p, ft-addr=%p, ft-id=%s", btr, base_type, bt_field_type_id_string( bt_field_type_get_type_id(base_type))); ret = BT_BTR_STATUS_ERROR; goto end; } ret = stack_push(btr->stack, base_type, (size_t) base_len); end: return ret; }
void bt_put(void *ptr) { struct bt_object *obj = ptr; if (unlikely(!obj)) { return; } if (unlikely(!obj->ref_count.release)) { return; } if (BT_LOG_ON_WARN && unlikely(bt_object_get_ref_count(obj) == 0)) { BT_LOGW("Decrementing a reference count set to 0: addr=%p", ptr); } BT_LOGV("Decrementing object's reference count: %lu -> %lu: " "addr=%p, cur-count=%lu, new-count=%lu", obj->ref_count.count, obj->ref_count.count - 1, ptr, obj->ref_count.count, obj->ref_count.count - 1); bt_ref_put(&obj->ref_count); }
int bt_event_set_clock_value(struct bt_event *event, struct bt_clock_value *value) { int ret = 0; struct bt_trace *trace; struct bt_stream_class *stream_class; struct bt_event_class *event_class; struct bt_clock_class *clock_class = NULL; if (!event || !value) { BT_LOGW("Invalid parameter: event or clock value is NULL: " "event-addr=%p, clock-value-addr=%p", event, value); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } clock_class = bt_clock_value_get_class(value); event_class = bt_event_borrow_event_class(event); assert(event_class); stream_class = bt_event_class_borrow_stream_class(event_class); assert(stream_class); trace = bt_stream_class_borrow_trace(stream_class); assert(trace); if (!bt_trace_has_clock_class(trace, clock_class)) { BT_LOGW("Invalid parameter: clock class is not part of event's trace: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", clock-class-addr=%p, " "clock-class-name=\"%s\"", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), clock_class, bt_clock_class_get_name(clock_class)); ret = -1; goto end; } g_hash_table_insert(event->clock_values, clock_class, bt_get(value)); BT_LOGV("Set event's clock value: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", clock-class-addr=%p, " "clock-class-name=\"%s\", clock-value-addr=%p, " "clock-value-cycles=%" PRIu64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), clock_class, bt_clock_class_get_name(clock_class), value, value->value); clock_class = NULL; end: bt_put(clock_class); return ret; }
int bt_event_set_stream_event_context(struct bt_event *event, struct bt_field *stream_event_context) { int ret = 0; struct bt_field_type *field_type = NULL; struct bt_stream_class *stream_class = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } stream_class = bt_event_class_get_stream_class(event->event_class); /* * We should not have been able to create the event without associating * the event class to a stream class. */ assert(stream_class); if (stream_event_context) { field_type = bt_field_get_type(stream_event_context); if (bt_field_type_compare(field_type, stream_class->event_context_type)) { BT_LOGW("Invalid parameter: stream event context field type is different from the expected field type: " "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)); ret = -1; goto end; } } else { if (stream_class->event_context_type) { BT_LOGW("Invalid parameter: setting no stream event context but stream event context field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "stream-event-context-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_class->event_context_type); ret = -1; goto end; } } bt_get(stream_event_context); BT_MOVE(event->stream_event_context, stream_event_context); BT_LOGV("Set event's stream event context field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "stream-event-context-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_event_context); end: BT_PUT(stream_class); bt_put(field_type); return ret; }
size_t bt_btr_start(struct bt_btr *btr, struct bt_field_type *type, const uint8_t *buf, size_t offset, size_t packet_offset, size_t sz, enum bt_btr_status *status) { assert(btr); assert(BYTES_TO_BITS(sz) >= offset); reset(btr); btr->buf.addr = buf; btr->buf.offset = offset; btr->buf.at = 0; btr->buf.packet_offset = packet_offset; btr->buf.buf_sz = sz; btr->buf.sz = BYTES_TO_BITS(sz) - offset; *status = BT_BTR_STATUS_OK; BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, " "buf-addr=%p, buf-size=%zu, offset=%zu, " "packet-offset=%zu", btr, type, buf, sz, offset, packet_offset); /* Set root type */ if (is_compound_type(type)) { /* Compound type: push on visit stack */ int stack_ret; if (btr->user.cbs.types.compound_begin) { BT_LOGV("Calling user function (compound, begin)."); *status = btr->user.cbs.types.compound_begin( type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(*status)); if (*status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: btr-addr=%p, status=%s", btr, bt_btr_status_string(*status)); goto end; } } stack_ret = stack_push_with_len(btr, type); if (stack_ret) { /* stack_push_with_len() logs errors */ *status = BT_BTR_STATUS_ERROR; goto end; } btr->state = BTR_STATE_ALIGN_COMPOUND; } else { /* Basic type: set as current basic type */ btr->cur_basic_field_type = type; bt_get(btr->cur_basic_field_type); btr->state = BTR_STATE_ALIGN_BASIC; } /* Run the machine! */ BT_LOGV_STR("Running the state machine."); while (true) { *status = handle_state(btr); if (*status != BT_BTR_STATUS_OK || btr->state == BTR_STATE_DONE) { break; } } /* Update packet offset for next time */ update_packet_offset(btr); end: return btr->buf.at; }
int bt_event_set_event_context(struct bt_event *event, struct bt_field *context) { int ret = 0; struct bt_field_type *field_type = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } if (context) { field_type = bt_field_get_type(context); if (bt_field_type_compare(field_type, event->event_class->context)) { BT_LOGW("Invalid parameter: context field type is different from the expected field type: " "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)); ret = -1; goto end; } } else { if (event->event_class->context) { BT_LOGW("Invalid parameter: setting no event context but event context field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "event-context-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), event->event_class->context); ret = -1; goto end; } } bt_put(event->context_payload); event->context_payload = bt_get(context); BT_LOGV("Set event's context field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "context-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), context); end: bt_put(field_type); return ret; }
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; }
int bt_event_set_payload(struct bt_event *event, const char *name, struct bt_field *payload) { int ret = 0; if (!event || !payload) { BT_LOGW("Invalid parameter: event or payload field is NULL: " "event-addr=%p, payload-field-addr=%p", event, payload); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } if (name) { ret = bt_field_structure_set_field_by_name( event->fields_payload, name, payload); } else { struct bt_field_type *payload_type; payload_type = bt_field_get_type(payload); if (bt_field_type_compare(payload_type, event->event_class->fields) == 0) { bt_put(event->fields_payload); bt_get(payload); event->fields_payload = payload; } else { BT_LOGW("Invalid parameter: payload field type is different from the expected field type: " "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)); ret = -1; } bt_put(payload_type); } if (ret) { BT_LOGW("Failed to set event's payload field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "payload-field-name=\"%s\", payload-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), name, payload); } else { BT_LOGV("Set event's payload field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "payload-field-name=\"%s\", payload-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), name, payload); } end: return ret; }
int bt_event_set_header(struct bt_event *event, struct bt_field *header) { int ret = 0; struct bt_field_type *field_type = NULL; struct bt_stream_class *stream_class = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } stream_class = (struct bt_stream_class *) bt_object_get_parent( event->event_class); /* * Ensure the provided header's type matches the one registered to the * stream class. */ if (header) { field_type = bt_field_get_type(header); if (bt_field_type_compare(field_type, stream_class->event_header_type)) { BT_LOGW("Invalid parameter: header field type is different from the expected field type: " "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)); ret = -1; goto end; } } else { if (stream_class->event_header_type) { BT_LOGW("Invalid parameter: setting no event header but event header field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "event-header-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_class->event_header_type); ret = -1; goto end; } } bt_put(event->event_header); event->event_header = bt_get(header); BT_LOGV("Set event's header field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "header-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), header); end: bt_put(stream_class); bt_put(field_type); return ret; }
static struct bt_plugin *bt_plugin_from_python_plugin_info(PyObject *plugin_info) { struct bt_plugin *plugin = NULL; PyObject *py_name = NULL; PyObject *py_author = NULL; PyObject *py_description = NULL; PyObject *py_license = NULL; PyObject *py_version = NULL; PyObject *py_comp_class_addrs = NULL; const char *name = NULL; const char *author = NULL; const char *description = NULL; const char *license = NULL; unsigned int major = 0, minor = 0, patch = 0; const char *version_extra = NULL; int ret; assert(plugin_info); assert(python_state == PYTHON_STATE_FULLY_INITIALIZED); py_name = PyObject_GetAttrString(plugin_info, "name"); if (!py_name) { BT_LOGW("Cannot find `name` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_author = PyObject_GetAttrString(plugin_info, "author"); if (!py_author) { BT_LOGW("Cannot find `author` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_description = PyObject_GetAttrString(plugin_info, "description"); if (!py_description) { BT_LOGW("Cannot find `desciption` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_license = PyObject_GetAttrString(plugin_info, "license"); if (!py_license) { BT_LOGW("Cannot find `license` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_version = PyObject_GetAttrString(plugin_info, "version"); if (!py_version) { BT_LOGW("Cannot find `version` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_comp_class_addrs = PyObject_GetAttrString(plugin_info, "comp_class_addrs"); if (!py_comp_class_addrs) { BT_LOGW("Cannot find `comp_class_addrs` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } if (PyUnicode_Check(py_name)) { name = PyUnicode_AsUTF8(py_name); if (!name) { BT_LOGW("Cannot decode Python plugin name string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } else { /* Plugin name is mandatory */ BT_LOGW("Plugin name is not a string: " "py-plugin-info-addr=%p", plugin_info); goto error; } if (PyUnicode_Check(py_author)) { author = PyUnicode_AsUTF8(py_author); if (!author) { BT_LOGW("Cannot decode Python plugin author string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyUnicode_Check(py_description)) { description = PyUnicode_AsUTF8(py_description); if (!description) { BT_LOGW("Cannot decode Python plugin description string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyUnicode_Check(py_license)) { license = PyUnicode_AsUTF8(py_license); if (!license) { BT_LOGW("Cannot decode Python plugin license string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyTuple_Check(py_version)) { if (PyTuple_Size(py_version) >= 3) { PyObject *py_major = PyTuple_GetItem(py_version, 0); PyObject *py_minor = PyTuple_GetItem(py_version, 1); PyObject *py_patch = PyTuple_GetItem(py_version, 2); assert(py_major); assert(py_minor); assert(py_patch); if (PyLong_Check(py_major)) { major = PyLong_AsUnsignedLong(py_major); } if (PyLong_Check(py_minor)) { minor = PyLong_AsUnsignedLong(py_minor); } if (PyLong_Check(py_patch)) { patch = PyLong_AsUnsignedLong(py_patch); } if (PyErr_Occurred()) { /* Overflow error, most probably */ BT_LOGW("Invalid Python plugin version format: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyTuple_Size(py_version) >= 4) { PyObject *py_extra = PyTuple_GetItem(py_version, 3); assert(py_extra); if (PyUnicode_Check(py_extra)) { version_extra = PyUnicode_AsUTF8(py_extra); if (!version_extra) { BT_LOGW("Cannot decode Python plugin version's extra string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } } } plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_PYTHON); if (!plugin) { BT_LOGE_STR("Cannot create empty plugin object."); goto error; } bt_plugin_set_name(plugin, name); if (description) { bt_plugin_set_description(plugin, description); } if (author) { bt_plugin_set_author(plugin, author); } if (license) { bt_plugin_set_license(plugin, license); } bt_plugin_set_version(plugin, major, minor, patch, version_extra); if (PyList_Check(py_comp_class_addrs)) { size_t i; for (i = 0; i < PyList_Size(py_comp_class_addrs); i++) { struct bt_component_class *comp_class; PyObject *py_comp_class_addr; py_comp_class_addr = PyList_GetItem(py_comp_class_addrs, i); assert(py_comp_class_addr); if (PyLong_Check(py_comp_class_addr)) { comp_class = (struct bt_component_class *) PyLong_AsUnsignedLongLong(py_comp_class_addr); } else { BT_LOGW("Component class address is not an integer in Python plugin info object: " "py-plugin-info-addr=%p, index=%zu", plugin_info, i); continue; } ret = bt_plugin_add_component_class(plugin, comp_class); if (ret < 0) { BT_LOGE("Cannot add component class to plugin: " "py-plugin-info-addr=%p, " "plugin-addr=%p, plugin-name=\"%s\", " "comp-class-addr=%p, " "comp-class-name=\"%s\", " "comp-class-type=%s", plugin_info, plugin, bt_plugin_get_name(plugin), comp_class, bt_component_class_get_name(comp_class), bt_component_class_type_string( bt_component_class_get_type(comp_class))); continue; } } } bt_plugin_freeze(plugin); goto end; error: print_python_traceback_warn(); pyerr_clear(); BT_PUT(plugin); end: Py_XDECREF(py_name); Py_XDECREF(py_author); Py_XDECREF(py_description); Py_XDECREF(py_license); Py_XDECREF(py_version); Py_XDECREF(py_comp_class_addrs); return plugin; }
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; }
static enum bt_btr_status read_basic_float_and_call_cb(struct bt_btr *btr, const uint8_t *buf, size_t at) { int ret; double dblval; int64_t field_size; enum bt_byte_order bo; enum bt_btr_status status = BT_BTR_STATUS_OK; field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type); bo = bt_field_type_get_byte_order(btr->cur_basic_field_type); btr->cur_bo = bo; switch (field_size) { case 32: { uint64_t v; union { uint32_t u; float f; } f32; ret = bt_field_type_floating_point_get_mantissa_digits( btr->cur_basic_field_type); assert(ret == 24); ret = bt_field_type_floating_point_get_exponent_digits( btr->cur_basic_field_type); assert(ret == 8); status = read_unsigned_bitfield(buf, at, field_size, bo, &v); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } f32.u = (uint32_t) v; dblval = (double) f32.f; break; } case 64: { union { uint64_t u; double d; } f64; ret = bt_field_type_floating_point_get_mantissa_digits( btr->cur_basic_field_type); assert(ret == 53); ret = bt_field_type_floating_point_get_exponent_digits( btr->cur_basic_field_type); assert(ret == 11); status = read_unsigned_bitfield(buf, at, field_size, bo, &f64.u); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } dblval = f64.d; break; } default: /* Only 32-bit and 64-bit fields are supported currently */ BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: " "btr-addr=%p", btr); status = BT_BTR_STATUS_ERROR; goto end; } BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f", btr, at, dblval); if (btr->user.cbs.types.floating_point) { BT_LOGV("Calling user function (floating point number)."); status = btr->user.cbs.types.floating_point(dblval, btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); } } end: return status; }
static int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, const char *path) { int64_t stream_instance_id = -1; int64_t begin_ns = -1; struct ctf_fs_ds_file_group *ds_file_group = NULL; bool add_group = false; int ret; size_t i; struct ctf_fs_ds_file *ds_file = NULL; struct ctf_fs_ds_index *index = NULL; struct bt_msg_iter *msg_iter = NULL; struct ctf_stream_class *sc = NULL; struct bt_msg_iter_packet_properties props; msg_iter = bt_msg_iter_create(ctf_fs_trace->metadata->tc, bt_common_get_page_size() * 8, ctf_fs_ds_file_medops, NULL); if (!msg_iter) { BT_LOGE_STR("Cannot create a CTF message iterator."); goto error; } ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, msg_iter, NULL, path); if (!ds_file) { goto error; } ret = bt_msg_iter_get_packet_properties(ds_file->msg_iter, &props); if (ret) { BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).", path); goto error; } sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc, props.stream_class_id); BT_ASSERT(sc); stream_instance_id = props.data_stream_id; if (props.snapshots.beginning_clock != UINT64_C(-1)) { BT_ASSERT(sc->default_clock_class); ret = bt_util_clock_cycles_to_ns_from_origin( props.snapshots.beginning_clock, sc->default_clock_class->frequency, sc->default_clock_class->offset_seconds, sc->default_clock_class->offset_cycles, &begin_ns); if (ret) { BT_LOGE("Cannot convert clock cycles to nanoseconds from origin (`%s`).", path); goto error; } } index = ctf_fs_ds_file_build_index(ds_file); if (!index) { BT_LOGW("Failed to index CTF stream file \'%s\'", ds_file->file->path->str); } if (begin_ns == -1) { /* * No beggining timestamp to sort the stream files * within a stream file group, so consider that this * file must be the only one within its group. */ stream_instance_id = -1; } if (stream_instance_id == -1) { /* * No stream instance ID or no beginning timestamp: * create a unique stream file group for this stream * file because, even if there's a stream instance ID, * there's no timestamp to order the file within its * group. */ ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace, sc, UINT64_C(-1)); if (!ds_file_group) { goto error; } ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group, path, begin_ns, index); /* Ownership of index is transferred. */ index = NULL; if (ret) { goto error; } add_group = true; goto end; } BT_ASSERT(stream_instance_id != -1); BT_ASSERT(begin_ns != -1); /* Find an existing stream file group with this ID */ for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) { ds_file_group = g_ptr_array_index( ctf_fs_trace->ds_file_groups, i); if (ds_file_group->sc == sc && ds_file_group->stream_id == stream_instance_id) { break; } ds_file_group = NULL; } if (!ds_file_group) { ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace, sc, stream_instance_id); if (!ds_file_group) { goto error; } add_group = true; } ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group, path, begin_ns, index); index = NULL; if (ret) { goto error; } goto end; error: ctf_fs_ds_file_group_destroy(ds_file_group); ds_file_group = NULL; ret = -1; end: if (add_group && ds_file_group) { g_ptr_array_add(ctf_fs_trace->ds_file_groups, ds_file_group); } ctf_fs_ds_file_destroy(ds_file); if (msg_iter) { bt_msg_iter_destroy(msg_iter); } ctf_fs_ds_index_destroy(index); return ret; }
static inline enum bt_btr_status read_basic_int_and_call(struct bt_btr *btr, const uint8_t *buf, size_t at, struct bt_field_type *int_type, struct bt_field_type *orig_type) { bt_bool signd; int64_t field_size; enum bt_byte_order bo; enum bt_btr_status status = BT_BTR_STATUS_OK; signd = bt_field_type_integer_is_signed(int_type); field_size = get_basic_field_type_size(btr, int_type); if (field_size < 1) { BT_LOGW("Cannot get integer field type's size: " "btr=%p, at=%zu, ft-addr=%p", btr, at, int_type); status = BT_BTR_STATUS_ERROR; goto end; } bo = bt_field_type_get_byte_order(int_type); /* * Update current byte order now because we could be reading * the integer value of an enumeration type, and thus we know * here the actual supporting integer type's byte order. */ btr->cur_bo = bo; if (signd) { int64_t v; status = read_signed_bitfield(buf, at, field_size, bo, &v); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read signed bit array for signed integer field: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } if (btr->user.cbs.types.signed_int) { BT_LOGV("Calling user function (signed integer)."); status = btr->user.cbs.types.signed_int(v, btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); } } } else { uint64_t v; status = read_unsigned_bitfield(buf, at, field_size, bo, &v); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read unsigned bit array for unsigned integer field: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } if (btr->user.cbs.types.unsigned_int) { BT_LOGV("Calling user function (unsigned integer)."); status = btr->user.cbs.types.unsigned_int(v, btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); } } } end: return status; }
static inline enum bt_btr_status read_basic_type_and_call_continue(struct bt_btr *btr, read_basic_and_call_cb_t read_basic_and_call_cb) { size_t available; int64_t field_size; int64_t needed_bits; enum bt_btr_status status = BT_BTR_STATUS_OK; if (!at_least_one_bit_left(btr)) { BT_LOGV("Reached end of data: btr-addr=%p", btr); status = BT_BTR_STATUS_EOF; goto end; } field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type); if (field_size < 1) { BT_LOGW("Cannot get basic field type's size: " "btr-addr=%p, ft-addr=%p", btr, btr->cur_basic_field_type); status = BT_BTR_STATUS_ERROR; goto end; } available = available_bits(btr); needed_bits = field_size - btr->stitch.at; BT_LOGV("Continuing basic field decoding: " "btr-addr=%p, field-size=%" PRId64 ", needed-size=%" PRId64 ", " "available-size=%zu", btr, field_size, needed_bits, available); if (needed_bits <= available) { /* We have all the bits; append to stitch, then decode */ stitch_append_from_buf(btr, needed_bits); status = read_basic_and_call_cb(btr, btr->stitch.buf, btr->stitch.offset); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read basic field: " "btr-addr=%p, ft-addr=%p, status=%s", btr, btr->cur_basic_field_type, bt_btr_status_string(status)); goto end; } if (stack_empty(btr->stack)) { /* Root is a basic type */ btr->state = BTR_STATE_DONE; } else { /* Go to next field */ stack_top(btr->stack)->index++; btr->state = BTR_STATE_NEXT_FIELD; btr->last_bo = btr->cur_bo; } goto end; } /* We are here; it means we don't have enough data to decode this */ BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer."); stitch_append_from_remaining_buf(btr); status = BT_BTR_STATUS_EOF; end: return status; }
static inline enum bt_btr_status read_basic_type_and_call_begin(struct bt_btr *btr, read_basic_and_call_cb_t read_basic_and_call_cb) { size_t available; int64_t field_size; enum bt_byte_order bo; enum bt_btr_status status = BT_BTR_STATUS_OK; if (!at_least_one_bit_left(btr)) { BT_LOGV("Reached end of data: btr-addr=%p", btr); status = BT_BTR_STATUS_EOF; goto end; } field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type); if (field_size < 1) { BT_LOGW("Cannot get basic field type's size: " "btr-addr=%p, ft-addr=%p", btr, btr->cur_basic_field_type); status = BT_BTR_STATUS_ERROR; goto end; } bo = bt_field_type_get_byte_order(btr->cur_basic_field_type); status = validate_contiguous_bo(btr, bo); if (status != BT_BTR_STATUS_OK) { /* validate_contiguous_bo() logs errors */ goto end; } available = available_bits(btr); if (field_size <= available) { /* We have all the bits; decode and set now */ assert(btr->buf.addr); status = read_basic_and_call_cb(btr, btr->buf.addr, buf_at_from_addr(btr)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("Cannot read basic field: " "btr-addr=%p, ft-addr=%p, status=%s", btr, btr->cur_basic_field_type, bt_btr_status_string(status)); goto end; } consume_bits(btr, field_size); if (stack_empty(btr->stack)) { /* Root is a basic type */ btr->state = BTR_STATE_DONE; } else { /* Go to next field */ stack_top(btr->stack)->index++; btr->state = BTR_STATE_NEXT_FIELD; btr->last_bo = btr->cur_bo; } goto end; } /* We are here; it means we don't have enough data to decode this */ BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer."); stitch_set_from_remaining_buf(btr); btr->state = BTR_STATE_READ_BASIC_CONTINUE; status = BT_BTR_STATUS_EOF; end: return status; }
static inline enum bt_btr_status read_basic_string_type_and_call( struct bt_btr *btr, bool begin) { size_t buf_at_bytes; const uint8_t *result; size_t available_bytes; const uint8_t *first_chr; enum bt_btr_status status = BT_BTR_STATUS_OK; if (!at_least_one_bit_left(btr)) { BT_LOGV("Reached end of data: btr-addr=%p", btr); status = BT_BTR_STATUS_EOF; goto end; } assert(buf_at_from_addr(btr) % 8 == 0); available_bytes = BITS_TO_BYTES_FLOOR(available_bits(btr)); buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr)); assert(btr->buf.addr); first_chr = &btr->buf.addr[buf_at_bytes]; result = memchr(first_chr, '\0', available_bytes); if (begin && btr->user.cbs.types.string_begin) { BT_LOGV("Calling user function (string, beginning)."); status = btr->user.cbs.types.string_begin( btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } } if (!result) { /* No null character yet */ if (btr->user.cbs.types.string) { BT_LOGV("Calling user function (substring)."); status = btr->user.cbs.types.string( (const char *) first_chr, available_bytes, btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } } consume_bits(btr, BYTES_TO_BITS(available_bytes)); btr->state = BTR_STATE_READ_BASIC_CONTINUE; status = BT_BTR_STATUS_EOF; } else { /* Found the null character */ size_t result_len = (size_t) (result - first_chr); if (btr->user.cbs.types.string && result_len) { BT_LOGV("Calling user function (substring)."); status = btr->user.cbs.types.string( (const char *) first_chr, result_len, btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } } if (btr->user.cbs.types.string_end) { BT_LOGV("Calling user function (string, end)."); status = btr->user.cbs.types.string_end( btr->cur_basic_field_type, btr->user.data); BT_LOGV("User function returned: status=%s", bt_btr_status_string(status)); if (status != BT_BTR_STATUS_OK) { BT_LOGW("User function failed: " "btr-addr=%p, status=%s", btr, bt_btr_status_string(status)); goto end; } } consume_bits(btr, BYTES_TO_BITS(result_len + 1)); if (stack_empty(btr->stack)) { /* Root is a basic type */ btr->state = BTR_STATE_DONE; } else { /* Go to next field */ stack_top(btr->stack)->index++; btr->state = BTR_STATE_NEXT_FIELD; btr->last_bo = btr->cur_bo; } } end: return status; }
BT_HIDDEN struct ctf_metadata_decoder *ctf_metadata_decoder_create( const struct ctf_metadata_decoder_config *config, const char *name) { struct ctf_metadata_decoder *mdec = g_new0(struct ctf_metadata_decoder, 1); struct ctf_metadata_decoder_config default_config = { .clock_class_offset_s = 0, .clock_class_offset_ns = 0, }; if (!config) { config = &default_config; } BT_LOGD("Creating CTF metadata decoder: " "clock-class-offset-s=%" PRId64 ", " "clock-class-offset-ns=%" PRId64 ", name=\"%s\"", config->clock_class_offset_s, config->clock_class_offset_ns, name); if (!mdec) { BT_LOGE_STR("Failed to allocate one CTF metadata decoder."); goto end; } mdec->config = *config; mdec->visitor = ctf_visitor_generate_ir_create(config, name); if (!mdec->visitor) { BT_LOGE("Failed to create a CTF IR metadata AST visitor: " "mdec-addr=%p", mdec); ctf_metadata_decoder_destroy(mdec); mdec = NULL; goto end; } BT_LOGD("Creating CTF metadata decoder: " "clock-class-offset-s=%" PRId64 ", " "clock-class-offset-ns=%" PRId64 ", " "name=\"%s\", addr=%p", config->clock_class_offset_s, config->clock_class_offset_ns, name, mdec); end: return mdec; } BT_HIDDEN void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec) { if (!mdec) { return; } BT_LOGD("Destroying CTF metadata decoder: addr=%p", mdec); ctf_visitor_generate_ir_destroy(mdec->visitor); g_free(mdec); } BT_HIDDEN enum ctf_metadata_decoder_status ctf_metadata_decoder_decode( struct ctf_metadata_decoder *mdec, FILE *fp) { enum ctf_metadata_decoder_status status = CTF_METADATA_DECODER_STATUS_OK; int ret; struct ctf_scanner *scanner = NULL; char *buf = NULL; bool close_fp = false; assert(mdec); if (ctf_metadata_decoder_is_packetized(fp, &mdec->bo)) { BT_LOGD("Metadata stream is packetized: mdec-addr=%p", mdec); ret = ctf_metadata_decoder_packetized_file_stream_to_buf_with_mdec( mdec, fp, &buf, mdec->bo); if (ret) { BT_LOGE("Cannot decode packetized metadata packets to metadata text: " "mdec-addr=%p, ret=%d", mdec, ret); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } if (strlen(buf) == 0) { /* An empty metadata packet is OK. */ goto end; } /* Convert the real file pointer to a memory file pointer */ fp = bt_fmemopen(buf, strlen(buf), "rb"); close_fp = true; if (!fp) { BT_LOGE("Cannot memory-open metadata buffer: %s: " "mdec-addr=%p", strerror(errno), mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } } else { unsigned int major, minor; ssize_t nr_items; const long init_pos = ftell(fp); BT_LOGD("Metadata stream is plain text: mdec-addr=%p", mdec); if (init_pos < 0) { BT_LOGE_ERRNO("Failed to get current file position", "."); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } /* Check text-only metadata header and version */ nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor); if (nr_items < 2) { BT_LOGW("Missing \"/* CTF major.minor\" signature in plain text metadata file stream: " "mdec-addr=%p", mdec); } BT_LOGD("Found metadata stream version in signature: version=%u.%u", major, minor); if (!is_version_valid(major, minor)) { BT_LOGE("Invalid metadata version found in plain text signature: " "version=%u.%u, mdec-addr=%p", major, minor, mdec); status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION; goto end; } if (fseek(fp, init_pos, SEEK_SET)) { BT_LOGE("Cannot seek metadata file stream to initial position: %s: " "mdec-addr=%p", strerror(errno), mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } } if (BT_LOG_ON_VERBOSE) { yydebug = 1; } /* Allocate a scanner and append the metadata text content */ scanner = ctf_scanner_alloc(); if (!scanner) { BT_LOGE("Cannot allocate a metadata lexical scanner: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } assert(fp); ret = ctf_scanner_append_ast(scanner, fp); if (ret) { BT_LOGE("Cannot create the metadata AST out of the metadata text: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; goto end; } ret = ctf_visitor_semantic_check(0, &scanner->ast->root); if (ret) { BT_LOGE("Validation of the metadata semantics failed: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } ret = ctf_visitor_generate_ir_visit_node(mdec->visitor, &scanner->ast->root); switch (ret) { case 0: /* Success */ break; case -EINCOMPLETE: BT_LOGD("While visiting metadata AST: incomplete data: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; goto end; default: BT_LOGE("Failed to visit AST node to create CTF IR objects: " "mdec-addr=%p, ret=%d", mdec, ret); status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR; goto end; } end: if (scanner) { ctf_scanner_free(scanner); } yydebug = 0; if (fp && close_fp) { if (fclose(fp)) { BT_LOGE("Cannot close metadata file stream: " "mdec-addr=%p", mdec); } } if (buf) { free(buf); } return status; } BT_HIDDEN struct bt_trace *ctf_metadata_decoder_get_trace( struct ctf_metadata_decoder *mdec) { return ctf_visitor_generate_ir_get_trace(mdec->visitor); }
int bt_event_set_packet(struct bt_event *event, struct bt_packet *packet) { struct bt_stream_class *event_stream_class = NULL; struct bt_stream_class *packet_stream_class = NULL; struct bt_stream *stream = NULL; int ret = 0; if (!event || !packet) { BT_LOGW("Invalid parameter: event or packet is NULL: " "event-addr=%p, packet-addr=%p", event, packet); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: 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)); ret = -1; goto end; } /* * Make sure the new packet was created by this event's * stream, if it is set. */ stream = bt_event_get_stream(event); if (stream) { if (packet->stream != stream) { BT_LOGW("Invalid parameter: packet's stream and event's stream differ: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", packet-stream-addr=%p, " "event-stream-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), packet->stream, stream); ret = -1; goto end; } } else { event_stream_class = bt_event_class_get_stream_class(event->event_class); packet_stream_class = bt_stream_get_class(packet->stream); assert(event_stream_class); assert(packet_stream_class); if (event_stream_class != packet_stream_class) { BT_LOGW("Invalid parameter: packet's stream class and event's stream class differ: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", packet-stream-class-addr=%p, " "event-stream-class-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), packet_stream_class, event_stream_class); ret = -1; goto end; } } bt_get(packet); BT_MOVE(event->packet, packet); BT_LOGV("Set event's packet: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "packet-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), packet); end: BT_PUT(stream); BT_PUT(event_stream_class); BT_PUT(packet_stream_class); return ret; }
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; }