## ##
MINGW32=no
-DEFAULT_ENABLE_DEBUG_INFO=no
+DEFAULT_ENABLE_DEBUG_INFO=yes
LT_NO_UNDEFINED=""
AS_CASE([$host_os],
[solaris*|darwin*],
plugins/utils/trimmer/Makefile
plugins/utils/muxer/Makefile
python-plugin-provider/Makefile
- plugins/libctfcopytrace/Makefile
plugins/lttng-utils/Makefile
babeltrace.pc
babeltrace-ctf.pc
SUBDIRS = utils text ctf
-# libctfcopytrace
if ENABLE_DEBUG_INFO
-#SUBDIRS += lttng-utils
+SUBDIRS += lttng-utils
endif
noinst_HEADERS = plugins-common.h
+++ /dev/null
-SUBDIRS = .
-
-noinst_LTLIBRARIES = libctfcopytrace.la
-
-libctfcopytrace_la_SOURCES = ctfcopytrace.c clock-fields.c \
- ctfcopytrace.h clock-fields.h logging.c logging.h
-
-libctfcopytrace_la_LIBADD = \
- $(top_builddir)/lib/libbabeltrace.la
+++ /dev/null
-/*
- * clock-fields.c
- *
- * Babeltrace - Update clock fields to write uint64 values
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "PLUGIN-CTFCOPYTRACE-LIB-CLOCK-FIELDS"
-#include "logging.h"
-
-#include <babeltrace/babeltrace.h>
-#include <babeltrace/assert-internal.h>
-#include <stdio.h>
-
-#include "clock-field.h"
-
-static
-int find_update_struct_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class);
-static
-int find_update_array_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class);
-static
-int find_update_enum_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class);
-static
-int find_update_sequence_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class);
-static
-int find_update_variant_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class);
-
-static
-int copy_find_clock_int_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field);
-static
-int copy_find_clock_struct_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field);
-static
-int copy_find_clock_array_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field);
-static
-int copy_find_clock_sequence_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field);
-static
-int copy_find_clock_variant_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- bt_field_type *type, const bt_field *copy_field);
-static
-int copy_find_clock_enum_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- bt_field_type *type, const bt_field *copy_field);
-
-static
-int update_header_clock_int_field_type(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- const bt_clock_class *clock = NULL;
- int ret;
-
- clock = bt_field_type_integer_get_mapped_clock_class(type);
- if (!clock) {
- return 0;
- }
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(clock);
-
- ret = bt_field_type_integer_set_size(type, 64);
- if (ret) {
- BT_LOGE_STR("Failed to set integer size to 64.");
- goto end;
- }
-
- ret = bt_field_type_integer_set_mapped_clock_class(type,
- writer_clock_class);
- if (ret) {
- BT_LOGE_STR("Failed to map integer to clock_class.");
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int find_update_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int ret;
-
- switch (bt_field_type_get_type_id(type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- return update_header_clock_int_field_type(err, type,
- writer_clock_class);
- case BT_FIELD_TYPE_ID_STRUCT:
- return find_update_struct_clock_fields(err, type,
- writer_clock_class);
- case BT_FIELD_TYPE_ID_ARRAY:
- return find_update_array_clock_fields(err, type,
- writer_clock_class);
- case BT_FIELD_TYPE_ID_SEQUENCE:
- return find_update_sequence_clock_fields(err, type,
- writer_clock_class);
- case BT_FIELD_TYPE_ID_VARIANT:
- return find_update_variant_clock_fields(err, type,
- writer_clock_class);
- case BT_FIELD_TYPE_ID_ENUM:
- return find_update_enum_clock_fields(err, type,
- writer_clock_class);
- break;
- default:
- break;
- }
-
- ret = 0;
-
- return ret;
-}
-
-static
-int find_update_variant_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int count, i, ret;
- bt_field_type *entry_type = NULL;
-
- count = bt_field_type_variant_get_field_count(type);
- for (i = 0; i < count; i++) {
- const char *entry_name;
-
- ret = bt_field_type_variant_get_field_by_index(type,
- &entry_name, &entry_type, i);
- if (ret) {
- BT_LOGE_STR("Failed to get variant field.");
- goto error;
- }
-
- ret = find_update_clock_fields(err, entry_type,
- writer_clock_class);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(entry_type);
- return ret;
-}
-
-static
-int find_update_struct_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int count, i, ret;
- bt_field_type *entry_type = NULL;
-
- count = bt_field_type_structure_get_field_count(type);
- for (i = 0; i < count; i++) {
- const char *entry_name;
-
- ret = bt_field_type_structure_get_field_by_index(type,
- &entry_name, &entry_type, i);
- if (ret) {
- BT_LOGE_STR("Failed to get struct field.");
- goto error;
- }
-
- ret = find_update_clock_fields(err, entry_type,
- writer_clock_class);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- }
-
- ret = 0;
- goto end;
-
-error:
- bt_object_put_ref(entry_type);
-end:
- return ret;
-}
-
-static
-int find_update_sequence_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int ret;
- bt_field_type *entry_type = NULL;
-
- entry_type = bt_field_type_sequence_get_element_type(type);
- BT_ASSERT(entry_type);
-
- ret = find_update_clock_fields(err, entry_type, writer_clock_class);
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-static
-int find_update_array_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int ret = 0;
- bt_field_type *entry_type = NULL;
-
- entry_type = bt_field_type_array_get_element_type(type);
- BT_ASSERT(entry_type);
-
- ret = find_update_clock_fields(err, entry_type, writer_clock_class);
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields.");
- ret = -1;
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int find_update_enum_clock_fields(FILE *err, bt_field_type *type,
- const bt_clock_class *writer_clock_class)
-{
- int ret;
- bt_field_type *entry_type = NULL;
-
- entry_type = bt_field_type_enumeration_get_container_type(type);
- BT_ASSERT(entry_type);
-
- ret = find_update_clock_fields(err, entry_type, writer_clock_class);
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-BT_HIDDEN
-bt_field_type *override_header_type(FILE *err,
- bt_field_type *type,
- const bt_trace *writer_trace)
-{
- bt_field_type *new_type = NULL;
- const bt_clock_class *writer_clock_class = NULL;
- int ret;
-
- /* FIXME multi-clock? */
- writer_clock_class = bt_trace_get_clock_class_by_index(writer_trace, 0);
- BT_ASSERT(writer_clock_class);
-
- new_type = bt_field_type_copy(type);
- if (!new_type) {
- BT_LOGE_STR("Failed to copy field type.");
- goto error;
- }
-
- if (bt_field_type_get_type_id(new_type) != BT_FIELD_TYPE_ID_STRUCT) {
- BT_LOGE("Expected header field type to be struct: type=%d",
- bt_field_type_get_type_id(new_type));
- goto error;
- }
-
- ret = find_update_struct_clock_fields(err, new_type, writer_clock_class);
- if (ret) {
- BT_LOGE_STR("Failed to find clock fields in struct.");
- goto error;
- }
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(writer_clock_class);
-
- goto end;
-
-error:
- bt_clock_class_put_ref(writer_clock_class);
- BT_OBJECT_PUT_REF_AND_RESET(new_type);
-end:
- return new_type;
-}
-
-static
-int copy_float_field(FILE *err, const bt_field *field,
- bt_field_type *type,
- const bt_field *copy_field)
-{
- double value;
- int ret;
-
- ret = bt_field_floating_point_get_value(field, &value);
- if (ret) {
- BT_LOGE_STR("Failed to get value.");
- goto error;
- }
-
- ret = bt_field_floating_point_set_value(copy_field, value);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to set floating point value.");
- goto end;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-static
-int copy_string_field(FILE *err, const bt_field *field,
- bt_field_type *type,
- const bt_field *copy_field)
-{
- const char *value;
- int ret;
-
- value = bt_field_string_get_value(field);
- if (!value) {
- BT_LOGE_STR("Failed to get value.");
- goto error;
- }
-
- ret = bt_field_string_set_value(copy_field, value);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to set string value.");
- goto end;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-BT_HIDDEN
-int copy_override_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- const bt_field *copy_field)
-{
- bt_field_type *type = NULL;
- int ret = 0;
-
- type = bt_field_get_type(field);
- BT_ASSERT(type);
-
- switch (bt_field_type_get_type_id(type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- ret = copy_find_clock_int_field(err, event, writer_event,
- field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_STRUCT:
- ret = copy_find_clock_struct_field(err, event, writer_event,
- field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_FLOAT:
- ret = copy_float_field(err, field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_ENUM:
- ret = copy_find_clock_enum_field(err, event, writer_event,
- field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_STRING:
- ret = copy_string_field(err, field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- ret = copy_find_clock_array_field(err, event, writer_event,
- field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- ret = copy_find_clock_sequence_field(err, event, writer_event,
- field, type, copy_field);
- break;
- case BT_FIELD_TYPE_ID_VARIANT:
- ret = copy_find_clock_variant_field(err, event, writer_event,
- field, type, copy_field);
- break;
- /* No default, we want to catch missing field types. */
- case BT_FIELD_TYPE_ID_UNKNOWN:
- case BT_FIELD_TYPE_ID_NR:
- break;
- }
-
- BT_OBJECT_PUT_REF_AND_RESET(type);
-
- return ret;
-}
-
-static
-int copy_find_clock_enum_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- bt_field_type *type, const bt_field *copy_field)
-{
- int ret;
- const bt_field *container = NULL, *copy_container = NULL;
-
- container = bt_field_enumeration_get_container(field);
- BT_ASSERT(container);
-
- copy_container = bt_field_enumeration_get_container(copy_field);
- BT_ASSERT(copy_container);
-
- ret = copy_override_field(err, event, writer_event, container,
- copy_container);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to override enum field.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(copy_container);
- bt_object_put_ref(container);
- return ret;
-}
-
-static
-int copy_find_clock_variant_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- bt_field_type *type, const bt_field *copy_field)
-{
- int ret;
- const bt_field *tag = NULL;
- const bt_field *variant_field = NULL, *copy_variant_field = NULL;
-
- tag = bt_field_variant_get_tag(field);
- BT_ASSERT(tag);
-
- variant_field = bt_field_variant_get_field(field, tag);
- if (!variant_field) {
- BT_LOGE_STR("Failed to get variant field.");
- goto error;
- }
-
- copy_variant_field = bt_field_variant_get_field(copy_field, tag);
- BT_ASSERT(copy_variant_field);
-
- ret = copy_override_field(err, event, writer_event, variant_field,
- copy_variant_field);
- if (ret) {
- BT_LOGE_STR("Failed to override variant field.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(copy_variant_field);
- bt_object_put_ref(variant_field);
- bt_object_put_ref(tag);
- return ret;
-}
-
-static
-int copy_find_clock_sequence_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field)
-{
- int ret;
- uint64_t i, count;
- const bt_field *length_field = NULL;
- const bt_field *entry_field = NULL, *entry_copy = NULL;
-
- length_field = bt_field_sequence_get_length(field);
- BT_ASSERT(length_field);
-
- ret = bt_field_unsigned_integer_get_value(length_field, &count);
- if (ret) {
- BT_LOGE("Failed to get value.");
- goto error;
- }
-
- ret = bt_field_sequence_set_length(copy_field, length_field);
- if (ret) {
- BT_LOGE_STR("Failed to set sequence length.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(length_field);
-
- for (i = 0; i < count; i++) {
- entry_field = bt_field_sequence_get_field(field, i);
- if (!entry_field) {
- BT_LOGE_STR("Failed to get sequence field.");
- goto error;
- }
-
- entry_copy = bt_field_sequence_get_field(copy_field, i);
- BT_ASSERT(entry_copy);
-
- ret = copy_override_field(err, event, writer_event, entry_field,
- entry_copy);
- if (ret) {
- BT_LOGE_STR("Faield to override field in sequence.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(entry_field);
- BT_OBJECT_PUT_REF_AND_RESET(entry_copy);
- }
-
- ret = 0;
- goto end;
-
-error:
- bt_object_put_ref(length_field);
- bt_object_put_ref(entry_field);
- bt_object_put_ref(entry_copy);
- ret = -1;
-end:
- return ret;
-}
-
-static
-int copy_find_clock_array_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field)
-{
- int ret, count, i;
- const bt_field *entry_field = NULL, *entry_copy = NULL;
-
- count = bt_field_type_array_get_length(type);
- for (i = 0; i < count; i++) {
- entry_field = bt_field_array_get_field(field, i);
- if (!entry_field) {
- ret = -1;
- BT_LOGE_STR("Failed to get array field.");
- goto error;
- }
-
- entry_copy = bt_field_array_get_field(copy_field, i);
- BT_ASSERT(entry_copy);
-
- ret = copy_override_field(err, event, writer_event, entry_field,
- entry_copy);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to override field in array.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(entry_field);
- BT_OBJECT_PUT_REF_AND_RESET(entry_copy);
- }
-
- ret = 0;
- goto end;
-
-error:
- bt_object_put_ref(entry_field);
- bt_object_put_ref(entry_copy);
-
-end:
- return ret;
-}
-
-static
-int copy_find_clock_struct_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field)
-{
- int count, i, ret;
- bt_field_type *entry_type = NULL;
- const bt_field *entry_field = NULL, *entry_copy = NULL;
-
- count = bt_field_type_structure_get_field_count(type);
- for (i = 0; i < count; i++) {
- const char *entry_name;
-
- entry_field = bt_field_structure_get_field_by_index(field, i);
- if (!entry_field) {
- BT_LOGE_STR("Failed to get struct field.");
- goto error;
- }
-
- ret = bt_field_type_structure_get_field_by_index(type, &entry_name,
- &entry_type, i);
- if (ret) {
- BT_LOGE_STR("Failed to get struct field.");
- goto error;
- }
-
- entry_copy = bt_field_structure_get_field_by_index(copy_field, i);
- BT_ASSERT(entry_copy);
-
- ret = copy_override_field(err, event, writer_event, entry_field,
- entry_copy);
- if (ret) {
- BT_LOGE_STR("Failed to override field in struct.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(entry_copy);
- BT_OBJECT_PUT_REF_AND_RESET(entry_field);
- BT_OBJECT_PUT_REF_AND_RESET(entry_type);
- }
-
- ret = 0;
- goto end;
-
-error:
- bt_object_put_ref(entry_type);
- bt_object_put_ref(entry_field);
- bt_object_put_ref(entry_copy);
- ret = -1;
-end:
- return ret;
-}
-
-static
-int set_int_value(FILE *err, const bt_field *field,
- const bt_field *copy_field,
- bt_field_type *type)
-{
- uint64_t uvalue;
- int64_t value;
- int ret;
-
- if (bt_field_type_integer_is_signed(type)) {
- ret = bt_field_signed_integer_get_value(field, &value);
- if (ret) {
- BT_LOGE("Failed to get value.");
- goto error;
- }
-
- ret = bt_field_signed_integer_set_value(copy_field, value);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to set signed integer value.");
- goto end;
- }
- } else {
- ret = bt_field_unsigned_integer_get_value(field,
- &uvalue);
- if (ret) {
- BT_LOGE("Failed to get value.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(copy_field, uvalue);
- if (ret) {
- ret = -1;
- BT_LOGE_STR("Failed to set unsigned integer value.");
- goto end;
- }
- }
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-const bt_clock_class *stream_class_get_clock_class(FILE *err,
- const bt_stream_class *stream_class)
-{
- const bt_trace *trace = NULL;
- const bt_clock_class *clock_class = NULL;
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- /* FIXME multi-clock? */
- clock_class = bt_trace_get_clock_class_by_index(trace, 0);
-
- bt_trace_put_ref(trace);
-
- return clock_class;
-}
-
-const bt_clock_class *event_get_clock_class(FILE *err, const bt_event *event)
-{
- const bt_event_class *event_class = NULL;
- const bt_stream_class *stream_class = NULL;
- const bt_clock_class *clock_class = NULL;
-
- event_class = bt_event_get_class(event);
- BT_ASSERT(event_class);
-
- stream_class = bt_event_class_get_stream_class(event_class);
- BT_EVENT_CLASS_PUT_REF_AND_RESET(event_class);
- BT_ASSERT(stream_class);
-
- clock_class = stream_class_get_clock_class(err, stream_class);
- bt_stream_class_put_ref(stream_class);
-
- return clock_class;
-}
-
-static
-int copy_find_clock_int_field(FILE *err,
- const bt_event *event, const bt_event *writer_event,
- const bt_field *field, bt_field_type *type,
- const bt_field *copy_field)
-{
- const bt_clock_class *clock_class = NULL, *writer_clock_class = NULL;
- bt_clock_snapshot *clock_snapshot = NULL, *writer_clock_snapshot = NULL;
- uint64_t value;
- int ret;
-
- clock_class = bt_field_type_integer_get_mapped_clock_class(type);
- if (!clock_class) {
- return set_int_value(err, field, copy_field, type);
- }
-
- clock_snapshot = bt_event_get_clock_snapshot(event, clock_class);
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(clock_class);
- BT_ASSERT(clock_snapshot);
-
- ret = bt_clock_snapshot_get_value(clock_snapshot, &value);
- BT_OBJECT_PUT_REF_AND_RESET(clock_snapshot);
- if (ret) {
- BT_LOGE("Failed to get clock value.");
- goto error;
- }
-
- ret = bt_field_unsigned_integer_set_value(copy_field, value);
- if (ret) {
- BT_LOGE_STR("Failed to set unsigned integer value.");
- goto error;
- }
-
- writer_clock_class = event_get_clock_class(err, writer_event);
- BT_ASSERT(writer_clock_class);
-
- writer_clock_snapshot = bt_clock_snapshot_create(writer_clock_class, value);
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(writer_clock_class);
- if (!writer_clock_snapshot) {
- BT_LOGE_STR("Failed to create clock value.");
- goto error;
- }
-
- ret = bt_event_set_clock_snapshot(writer_event, writer_clock_snapshot);
- BT_OBJECT_PUT_REF_AND_RESET(writer_clock_snapshot);
- if (ret) {
- BT_LOGE_STR("Failed to set clock value.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
+++ /dev/null
-#ifndef BABELTRACE_CLOCK_FIELDS_H
-#define BABELTRACE_CLOCK_FIELDS_H
-
-/*
- * BabelTrace - Update clock fields to write uint64 values
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/babeltrace.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-BT_HIDDEN
-bt_field_type *override_header_type(FILE *err,
- bt_field_type *type,
- const bt_trace *writer_trace);
-
-BT_HIDDEN
-int copy_override_field(FILE *err, const bt_event *event,
- const bt_event *writer_event, const bt_field *field,
- const bt_field *copy_field);
-
-BT_HIDDEN
-const bt_clock_class *stream_class_get_clock_class(FILE *err,
- const bt_stream_class *stream_class);
-
-BT_HIDDEN
-const bt_clock_class *event_get_clock_class(FILE *err,
- const bt_event *event);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BABELTRACE_CLOCK_FIELDS_H */
+++ /dev/null
-/*
- * copytrace.c
- *
- * Babeltrace library to create a copy of a CTF trace
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "PLUGIN-CTFCOPYTRACE-LIB"
-#include "logging.h"
-
-#include <babeltrace/babeltrace.h>
-#include <babeltrace/assert-internal.h>
-
-#include "ctfcopytrace.h"
-#include "clock-field.h"
-
-BT_HIDDEN
-const bt_clock_class *ctf_copy_clock_class(FILE *err,
- const bt_clock_class *clock_class)
-{
- int64_t offset, offset_s;
- int int_ret;
- uint64_t u64_ret;
- const char *name, *description;
- const bt_clock_class *writer_clock_class = NULL;
-
- BT_ASSERT(err && clock_class);
-
- name = bt_clock_class_get_name(clock_class);
- BT_ASSERT(name);
-
- writer_clock_class = bt_clock_class_create(name,
- bt_clock_class_get_frequency(clock_class));
- if (!writer_clock_class) {
- BT_LOGE_STR("Failed to create clock class.");
- goto end;
- }
-
- description = bt_clock_class_get_description(clock_class);
- if (description) {
- int_ret = bt_clock_class_set_description(writer_clock_class,
- description);
- BT_ASSERT(!int_ret);
- }
-
- u64_ret = bt_clock_class_get_precision(clock_class);
- BT_ASSERT(u64_ret != -1ULL);
-
- int_ret = bt_clock_class_set_precision(writer_clock_class,
- u64_ret);
- BT_ASSERT(!int_ret);
-
- int_ret = bt_clock_class_get_offset_s(clock_class, &offset_s);
- BT_ASSERT(!int_ret);
-
- int_ret = bt_clock_class_set_offset_s(writer_clock_class, offset_s);
- BT_ASSERT(!int_ret);
-
- int_ret = bt_clock_class_get_offset_cycles(clock_class, &offset);
- BT_ASSERT(!int_ret);
-
- int_ret = bt_clock_class_set_offset_cycles(writer_clock_class, offset);
- BT_ASSERT(!int_ret);
-
- int_ret = bt_clock_class_origin_is_unix_epoch(clock_class);
- BT_ASSERT(int_ret >= 0);
-
- int_ret = bt_clock_class_set_origin_is_unix_epoch(writer_clock_class, int_ret);
- BT_ASSERT(!int_ret);
-
-end:
- return writer_clock_class;
-}
-
-BT_HIDDEN
-bt_component_status ctf_copy_clock_classes(FILE *err,
- const bt_trace *writer_trace,
- const bt_stream_class *writer_stream_class,
- const bt_trace *trace)
-{
- bt_component_status ret;
- int int_ret, clock_class_count, i;
-
- clock_class_count = bt_trace_get_clock_class_count(trace);
-
- for (i = 0; i < clock_class_count; i++) {
- const bt_clock_class *writer_clock_class;
- const bt_clock_class *clock_class =
- bt_trace_get_clock_class_by_index(trace, i);
-
- BT_ASSERT(clock_class);
-
- writer_clock_class = ctf_copy_clock_class(err, clock_class);
- bt_clock_class_put_ref(clock_class);
- if (!writer_clock_class) {
- BT_LOGE_STR("Failed to copy clock class.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- int_ret = bt_trace_add_clock_class(writer_trace, writer_clock_class);
- if (int_ret != 0) {
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(writer_clock_class);
- BT_LOGE_STR("Failed to add clock class.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- /*
- * Ownership transferred to the trace.
- */
- bt_clock_class_put_ref(writer_clock_class);
- }
-
- ret = BT_COMPONENT_STATUS_OK;
-
-end:
- return ret;
-}
-
-static
-void replace_clock_classes(const bt_trace *trace_copy,
- bt_field_type *field_type)
-{
- int ret;
-
- BT_ASSERT(trace_copy);
- BT_ASSERT(field_type);
-
- switch (bt_field_type_get_type_id(field_type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- {
- const bt_clock_class *mapped_clock_class =
- bt_field_type_integer_get_mapped_clock_class(field_type);
- const bt_clock_class *clock_class_copy = NULL;
- const char *name;
-
- if (!mapped_clock_class) {
- break;
- }
-
- name = bt_clock_class_get_name(mapped_clock_class);
- BT_ASSERT(name);
- clock_class_copy = bt_trace_get_clock_class_by_name(
- trace_copy, name);
- BT_ASSERT(clock_class_copy);
- ret = bt_field_type_integer_set_mapped_clock_class(
- field_type, clock_class_copy);
- BT_ASSERT(ret == 0);
- bt_clock_class_put_ref(mapped_clock_class);
- bt_clock_class_put_ref(clock_class_copy);
- break;
- }
- case BT_FIELD_TYPE_ID_ENUM:
- case BT_FIELD_TYPE_ID_ARRAY:
- case BT_FIELD_TYPE_ID_SEQUENCE:
- {
- bt_field_type *subtype = NULL;
-
- switch (bt_field_type_get_type_id(field_type)) {
- case BT_FIELD_TYPE_ID_ENUM:
- subtype = bt_field_type_enumeration_get_container_type(
- field_type);
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- subtype = bt_field_type_array_get_element_type(
- field_type);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- subtype = bt_field_type_sequence_get_element_type(
- field_type);
- break;
- default:
- BT_LOGF("Unexpected field type ID: id=%d",
- bt_field_type_get_type_id(field_type));
- abort();
- }
-
- BT_ASSERT(subtype);
- replace_clock_classes(trace_copy, subtype);
- bt_object_put_ref(subtype);
- break;
- }
- case BT_FIELD_TYPE_ID_STRUCT:
- {
- uint64_t i;
- int64_t count = bt_field_type_structure_get_field_count(
- field_type);
-
- for (i = 0; i < count; i++) {
- const char *name;
- bt_field_type *member_type;
-
- ret = bt_field_type_structure_get_field_by_index(
- field_type, &name, &member_type, i);
- BT_ASSERT(ret == 0);
- replace_clock_classes(trace_copy, member_type);
- bt_object_put_ref(member_type);
- }
-
- break;
- }
- case BT_FIELD_TYPE_ID_VARIANT:
- {
- uint64_t i;
- int64_t count = bt_field_type_variant_get_field_count(
- field_type);
-
- for (i = 0; i < count; i++) {
- const char *name;
- bt_field_type *member_type;
-
- ret = bt_field_type_variant_get_field_by_index(
- field_type, &name, &member_type, i);
- BT_ASSERT(ret == 0);
- replace_clock_classes(trace_copy, member_type);
- bt_object_put_ref(member_type);
- }
-
- break;
- }
- default:
- break;
- }
-}
-
-BT_HIDDEN
-const bt_event_class *ctf_copy_event_class(FILE *err,
- const bt_trace *trace_copy,
- const bt_event_class *event_class)
-{
- const bt_event_class *writer_event_class = NULL;
- bt_field_type *context = NULL, *payload_type = NULL;
- const char *name;
- int ret;
- int64_t id;
- bt_event_class_log_level log_level;
- const char *emf_uri;
-
- name = bt_event_class_get_name(event_class);
-
- writer_event_class = bt_event_class_create(name);
- BT_ASSERT(writer_event_class);
-
- id = bt_event_class_get_id(event_class);
- BT_ASSERT(id >= 0);
-
- ret = bt_event_class_set_id(writer_event_class, id);
- if (ret) {
- BT_LOGE_STR("Failed to set event_class id.");
- goto error;
- }
-
- log_level = bt_event_class_get_log_level(event_class);
- if (log_level < 0) {
- BT_LOGE_STR("Failed to get log_level.");
- goto error;
- }
-
- ret = bt_event_class_set_log_level(writer_event_class, log_level);
- if (ret) {
- BT_LOGE_STR("Failed to set log_level.");
- goto error;
- }
-
- emf_uri = bt_event_class_get_emf_uri(event_class);
- if (emf_uri) {
- ret = bt_event_class_set_emf_uri(writer_event_class,
- emf_uri);
- if (ret) {
- BT_LOGE_STR("Failed to set emf uri.");
- goto error;
- }
- }
-
- payload_type = bt_event_class_get_payload_type(event_class);
- if (payload_type) {
- bt_field_type *ft_copy =
- bt_field_type_copy(payload_type);
-
- if (!ft_copy) {
- BT_LOGE_STR("Cannot copy payload field type.");
- }
-
- replace_clock_classes(trace_copy, ft_copy);
- ret = bt_event_class_set_payload_type(writer_event_class,
- ft_copy);
- bt_object_put_ref(ft_copy);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set payload type.");
- goto error;
- }
- }
-
- context = bt_event_class_get_context_type(event_class);
- if (context) {
- bt_field_type *ft_copy =
- bt_field_type_copy(context);
-
- if (!ft_copy) {
- BT_LOGE_STR("Cannot copy context field type.");
- }
-
- ret = bt_event_class_set_context_type(
- writer_event_class, ft_copy);
- bt_object_put_ref(ft_copy);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set context type.");
- goto error;
- }
- }
-
- goto end;
-
-error:
- BT_EVENT_CLASS_PUT_REF_AND_RESET(writer_event_class);
-end:
- BT_OBJECT_PUT_REF_AND_RESET(context);
- BT_OBJECT_PUT_REF_AND_RESET(payload_type);
- return writer_event_class;
-}
-
-BT_HIDDEN
-bt_component_status ctf_copy_event_classes(FILE *err,
- const bt_stream_class *stream_class,
- const bt_stream_class *writer_stream_class)
-{
- bt_component_status ret = BT_COMPONENT_STATUS_OK;
- const bt_event_class *event_class = NULL, *writer_event_class = NULL;
- int count, i;
- const bt_trace *writer_trace =
- bt_stream_class_get_trace(writer_stream_class);
-
- BT_ASSERT(writer_trace);
- count = bt_stream_class_get_event_class_count(stream_class);
- BT_ASSERT(count >= 0);
-
- for (i = 0; i < count; i++) {
- int int_ret;
-
- event_class = bt_stream_class_get_event_class_by_index(
- stream_class, i);
- BT_ASSERT(event_class);
-
- if (i < bt_stream_class_get_event_class_count(writer_stream_class)) {
- writer_event_class = bt_stream_class_get_event_class_by_index(
- writer_stream_class, i);
- if (writer_event_class) {
- /*
- * If the writer_event_class already exists,
- * just skip it. It can be used to resync the
- * event_classes after a trace has become
- * static.
- */
- BT_EVENT_CLASS_PUT_REF_AND_RESET(writer_event_class);
- BT_EVENT_CLASS_PUT_REF_AND_RESET(event_class);
- continue;
- }
- }
-
- writer_event_class = ctf_copy_event_class(err, writer_trace,
- event_class);
- if (!writer_event_class) {
- BT_LOGE_STR("Failed to copy event_class.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto error;
- }
-
- int_ret = bt_stream_class_add_event_class(writer_stream_class,
- writer_event_class);
- if (int_ret < 0) {
- BT_LOGE_STR("Failed to add event class.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto error;
- }
- BT_EVENT_CLASS_PUT_REF_AND_RESET(writer_event_class);
- BT_EVENT_CLASS_PUT_REF_AND_RESET(event_class);
- }
-
- goto end;
-
-error:
- bt_event_class_put_ref(event_class);
- bt_event_class_put_ref(writer_event_class);
-end:
- bt_trace_put_ref(writer_trace);
- return ret;
-}
-
-BT_HIDDEN
-const bt_stream_class *ctf_copy_stream_class(FILE *err,
- const bt_stream_class *stream_class,
- const bt_trace *writer_trace,
- bool override_ts64)
-{
- bt_field_type *type = NULL;
- bt_field_type *type_copy = NULL;
- const bt_stream_class *writer_stream_class = NULL;
- int ret_int;
- const char *name = bt_stream_class_get_name(stream_class);
-
- writer_stream_class = bt_stream_class_create_empty(name);
- BT_ASSERT(writer_stream_class);
-
- type = bt_stream_class_get_packet_context_type(stream_class);
- if (type) {
- type_copy = bt_field_type_copy(type);
- if (!type_copy) {
- BT_LOGE_STR("Cannot copy packet context field type.");
- }
-
- replace_clock_classes(writer_trace, type_copy);
- ret_int = bt_stream_class_set_packet_context_type(
- writer_stream_class, type_copy);
- BT_OBJECT_PUT_REF_AND_RESET(type_copy);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set packet_context type.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
- }
-
- type = bt_stream_class_get_event_header_type(stream_class);
- if (type) {
- type_copy = bt_field_type_copy(type);
- if (!type_copy) {
- BT_LOGE_STR("Cannot copy event header field type.");
- }
-
- ret_int = bt_trace_get_clock_class_count(writer_trace);
- BT_ASSERT(ret_int >= 0);
- if (override_ts64 && ret_int > 0) {
- bt_field_type *new_event_header_type;
-
- new_event_header_type = override_header_type(err, type_copy,
- writer_trace);
- if (!new_event_header_type) {
- BT_LOGE_STR("Failed to override header type.");
- goto error;
- }
- replace_clock_classes(writer_trace, type_copy);
- ret_int = bt_stream_class_set_event_header_type(
- writer_stream_class, new_event_header_type);
- BT_OBJECT_PUT_REF_AND_RESET(type_copy);
- BT_OBJECT_PUT_REF_AND_RESET(new_event_header_type);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set event_header type.");
- goto error;
- }
- } else {
- replace_clock_classes(writer_trace, type_copy);
- ret_int = bt_stream_class_set_event_header_type(
- writer_stream_class, type_copy);
- BT_OBJECT_PUT_REF_AND_RESET(type_copy);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set event_header type.");
- goto error;
- }
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
- }
-
- type = bt_stream_class_get_event_context_type(stream_class);
- if (type) {
- type_copy = bt_field_type_copy(type);
- if (!type_copy) {
- BT_LOGE_STR("Cannot copy event context field type.");
- }
-
- replace_clock_classes(writer_trace, type_copy);
- ret_int = bt_stream_class_set_event_context_type(
- writer_stream_class, type_copy);
- BT_OBJECT_PUT_REF_AND_RESET(type_copy);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set event_contexttype.");
- goto error;
- }
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
-
- goto end;
-
-error:
- BT_STREAM_CLASS_PUT_REF_AND_RESET(writer_stream_class);
-end:
- bt_object_put_ref(type);
- bt_object_put_ref(type_copy);
- return writer_stream_class;
-}
-
-BT_HIDDEN
-int ctf_stream_copy_packet_header(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream)
-{
- const bt_field *packet_header = NULL, *writer_packet_header = NULL;
- int ret = 0;
-
- packet_header = bt_packet_get_header(packet);
- if (!packet_header) {
- goto end;
- }
-
- writer_packet_header = bt_field_copy(packet_header);
- if (!writer_packet_header) {
- BT_LOGE_STR("Failed to copy field from stream packet header.");
- goto error;
- }
-
- ret = bt_stream_set_packet_header(writer_stream,
- writer_packet_header);
- if (ret) {
- BT_LOGE_STR("Failed to set stream packet header.");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(writer_packet_header);
- bt_object_put_ref(packet_header);
- return ret;
-}
-
-BT_HIDDEN
-int ctf_packet_copy_header(FILE *err, const bt_packet *packet,
- const bt_packet *writer_packet)
-{
- const bt_field *packet_header = NULL, *writer_packet_header = NULL;
- int ret = 0;
-
- packet_header = bt_packet_get_header(packet);
- if (!packet_header) {
- goto end;
- }
-
- writer_packet_header = bt_field_copy(packet_header);
- if (!writer_packet_header) {
- BT_LOGE_STR("Failed to copy field from packet header.");
- goto error;
- }
-
- ret = bt_packet_set_header(writer_packet, writer_packet_header);
- if (ret) {
- BT_LOGE_STR("Failed to set packet header.");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(packet_header);
- bt_object_put_ref(writer_packet_header);
- return ret;
-}
-
-BT_HIDDEN
-int ctf_stream_copy_packet_context(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream)
-{
- const bt_field *packet_context = NULL, *writer_packet_context = NULL;
- int ret = 0;
-
- packet_context = bt_packet_get_context(packet);
- if (!packet_context) {
- goto end;
- }
-
- writer_packet_context = bt_field_copy(packet_context);
- if (!writer_packet_context) {
- BT_LOGE_STR("Failed to copy field from stream packet context.");
- goto error;
- }
-
- ret = bt_stream_set_packet_context(writer_stream,
- writer_packet_context);
- if (ret) {
- BT_LOGE_STR("Failed to set stream packet context.");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(packet_context);
- bt_object_put_ref(writer_packet_context);
- return ret;
-}
-
-BT_HIDDEN
-int ctf_packet_copy_context(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream,
- const bt_packet *writer_packet)
-{
- const bt_field *packet_context = NULL, *writer_packet_context = NULL;
- int ret = 0;
-
- packet_context = bt_packet_get_context(packet);
- if (!packet_context) {
- goto end;
- }
-
- writer_packet_context = bt_field_copy(packet_context);
- if (!writer_packet_context) {
- BT_LOGE_STR("Failed to copy field from packet context.");
- goto error;
- }
-
- ret = bt_packet_set_context(writer_packet, writer_packet_context);
- if (ret) {
- BT_LOGE_STR("Failed to set packet context.");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-end:
- bt_object_put_ref(writer_packet_context);
- bt_object_put_ref(packet_context);
- return ret;
-}
-
-BT_HIDDEN
-int ctf_copy_event_header(FILE *err, const bt_event *event,
- const bt_event_class *writer_event_class,
- const bt_event *writer_event,
- const bt_field *event_header)
-{
- const bt_clock_class *clock_class = NULL, *writer_clock_class = NULL;
- bt_clock_snapshot *clock_snapshot = NULL, *writer_clock_snapshot = NULL;
-
- int ret;
- const bt_field *writer_event_header = NULL;
- uint64_t value;
-
- clock_class = event_get_clock_class(err, event);
- if (!clock_class) {
- BT_LOGE_STR("Failed to get event clock_class.");
- goto error;
- }
-
- clock_snapshot = bt_event_get_clock_snapshot(event, clock_class);
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(clock_class);
- BT_ASSERT(clock_snapshot);
-
- ret = bt_clock_snapshot_get_value(clock_snapshot, &value);
- BT_OBJECT_PUT_REF_AND_RESET(clock_snapshot);
- if (ret) {
- BT_LOGE_STR("Failed to get clock value.");
- goto error;
- }
-
- writer_clock_class = event_get_clock_class(err, writer_event);
- if (!writer_clock_class) {
- BT_LOGE_STR("Failed to get event clock_class.");
- goto error;
- }
-
- writer_clock_snapshot = bt_clock_snapshot_create(writer_clock_class, value);
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(writer_clock_class);
- if (!writer_clock_snapshot) {
- BT_LOGE_STR("Failed to create clock value.");
- goto error;
- }
-
- ret = bt_event_set_clock_snapshot(writer_event, writer_clock_snapshot);
- BT_OBJECT_PUT_REF_AND_RESET(writer_clock_snapshot);
- if (ret) {
- BT_LOGE_STR("Failed to set clock value.");
- goto error;
- }
-
- writer_event_header = bt_field_copy(event_header);
- if (!writer_event_header) {
- BT_LOGE_STR("Failed to copy event_header.");
- goto end;
- }
-
- ret = bt_event_set_header(writer_event, writer_event_header);
- BT_OBJECT_PUT_REF_AND_RESET(writer_event_header);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set event_header.");
- goto error;
- }
-
- ret = 0;
-
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-static
-const bt_trace *event_class_get_trace(FILE *err,
- const bt_event_class *event_class)
-{
- const bt_trace *trace = NULL;
- const bt_stream_class *stream_class = NULL;
-
- stream_class = bt_event_class_get_stream_class(event_class);
- BT_ASSERT(stream_class);
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- bt_stream_class_put_ref(stream_class);
- return trace;
-}
-
-BT_HIDDEN
-const bt_event *ctf_copy_event(FILE *err, const bt_event *event,
- const bt_event_class *writer_event_class,
- bool override_ts64)
-{
- const bt_event *writer_event = NULL;
- const bt_field *field = NULL, *copy_field = NULL;
- const bt_trace *writer_trace = NULL;
- int ret;
-
- writer_event = bt_event_create(writer_event_class);
- if (!writer_event) {
- BT_LOGE_STR("Failed to create event.");
- goto error;
- }
-
- writer_trace = event_class_get_trace(err, writer_event_class);
- if (!writer_trace) {
- BT_LOGE_STR("Failed to get trace from event_class.");
- goto error;
- }
-
- field = bt_event_get_header(event);
- if (field) {
- /*
- * If override_ts64, we override all integer fields mapped to a
- * clock to a uint64_t field type, otherwise, we just copy it as
- * is.
- */
- ret = bt_trace_get_clock_class_count(writer_trace);
- BT_ASSERT(ret >= 0);
-
- if (override_ts64 && ret > 0) {
- copy_field = bt_event_get_header(writer_event);
- BT_ASSERT(copy_field);
-
- ret = copy_override_field(err, event, writer_event, field,
- copy_field);
- if (ret) {
- BT_LOGE_STR("Failed to copy and override field.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- } else {
- ret = ctf_copy_event_header(err, event, writer_event_class,
- writer_event, field);
- if (ret) {
- BT_LOGE_STR("Failed to copy event_header.");
- goto error;
- }
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- }
-
- /* Optional field, so it can fail silently. */
- field = bt_event_get_stream_event_context(event);
- if (field) {
- copy_field = bt_field_copy(field);
- if (!copy_field) {
- BT_LOGE_STR("Failed to copy field.");
- goto error;
- }
- ret = bt_event_set_stream_event_context(writer_event,
- copy_field);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set stream_event_context.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- }
-
- /* Optional field, so it can fail silently. */
- field = bt_event_get_event_context(event);
- if (field) {
- copy_field = bt_field_copy(field);
- if (!copy_field) {
- BT_LOGE_STR("Failed to copy field.");
- goto error;
- }
- ret = bt_event_set_event_context(writer_event, copy_field);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set event_context.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- }
-
- field = bt_event_get_event_payload(event);
- if (field) {
- copy_field = bt_field_copy(field);
- if (!copy_field) {
- BT_LOGE_STR("Failed to copy field.");
- goto error;
- }
- ret = bt_event_set_event_payload(writer_event, copy_field);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set event_payload.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- }
-
- goto end;
-
-error:
- BT_OBJECT_PUT_REF_AND_RESET(writer_event);
-end:
- bt_object_put_ref(field);
- bt_object_put_ref(copy_field);
- bt_trace_put_ref(writer_trace);
- return writer_event;
-}
-
-BT_HIDDEN
-bt_component_status ctf_copy_trace(FILE *err, const bt_trace *trace,
- const bt_trace *writer_trace)
-{
- bt_component_status ret = BT_COMPONENT_STATUS_OK;
- int field_count, i, int_ret;
- bt_field_type *header_type = NULL;
- bt_byte_order order;
- const char *trace_name;
- const unsigned char *trace_uuid;
-
- field_count = bt_trace_get_environment_field_count(trace);
- for (i = 0; i < field_count; i++) {
- int ret_int;
- const char *name;
- bt_value *value = NULL;
-
- name = bt_trace_get_environment_field_name_by_index(
- trace, i);
- BT_ASSERT(name);
-
- value = bt_trace_get_environment_field_value_by_index(
- trace, i);
- BT_ASSERT(value);
-
- ret_int = bt_trace_set_environment_field(writer_trace,
- name, value);
- BT_VALUE_PUT_REF_AND_RESET(value);
- if (ret_int < 0) {
- BT_LOGE("Failed to set environment: field-name=\"%s\"",
- name);
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- }
-
- order = bt_trace_get_native_byte_order(trace);
- BT_ASSERT(order != BT_BYTE_ORDER_UNKNOWN);
-
- /*
- * Only explicitly set the writer trace's native byte order if
- * the original trace has a specific one. Otherwise leave what
- * the CTF writer object chooses, which is the machine's native
- * byte order.
- */
- if (order != BT_BYTE_ORDER_UNSPECIFIED) {
- ret = bt_trace_set_native_byte_order(writer_trace, order);
- if (ret) {
- BT_LOGE_STR("Failed to set native byte order.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- }
-
- header_type = bt_trace_get_packet_header_type(trace);
- if (header_type) {
- int_ret = bt_trace_set_packet_header_type(writer_trace, header_type);
- BT_OBJECT_PUT_REF_AND_RESET(header_type);
- if (int_ret < 0) {
- BT_LOGE_STR("Failed to set packet header type.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- }
-
- trace_name = bt_trace_get_name(trace);
- if (trace_name) {
- int_ret = bt_trace_set_name(writer_trace, trace_name);
- if (int_ret < 0) {
- BT_LOGE_STR("Failed to set trace name.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- }
-
- trace_uuid = bt_trace_get_uuid(trace);
- if (trace_uuid) {
- int_ret = bt_trace_set_uuid(writer_trace, trace_uuid);
- if (int_ret < 0) {
- BT_LOGE_STR("Failed to set trace UUID.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- }
-
-end:
- return ret;
-}
+++ /dev/null
-#ifndef BABELTRACE_LIB_COPY_TRACE_H
-#define BABELTRACE_LIB_COPY_TRACE_H
-
-/*
- * BabelTrace - Library to create a copy of a CTF trace
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/babeltrace.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Create a copy of the clock_class passed in parameter.
- *
- * Returns NULL on error.
- */
-const bt_clock_class *ctf_copy_clock_class(FILE *err,
- const bt_clock_class *clock_class);
-
-/*
- * Copy all the clock classes from the input trace and add them to the writer
- * object.
- *
- * Returns BT_COMPONENT_STATUS_OK on success, and BT_COMPONENT_STATUS_ERROR on
- * error.
- */
-BT_HIDDEN
-bt_component_status ctf_copy_clock_classes(FILE *err,
- const bt_trace *writer_trace,
- const bt_stream_class *writer_stream_class,
- const bt_trace *trace);
-
-/*
- * Create a copy of the event class passed in parameter.
- *
- * Returns NULL on error.
- */
-BT_HIDDEN
-const bt_event_class *ctf_copy_event_class(FILE *err,
- const bt_trace *trace_copy,
- const bt_event_class *event_class);
-
-/*
- * Copy all the event classes from the input stream class and add them to the
- * writer_stream_class.
- *
- * Returns BT_COMPONENT_STATUS_OK on success, and BT_COMPONENT_STATUS_ERROR on
- * error.
- */
-BT_HIDDEN
-bt_component_status ctf_copy_event_classes(FILE *err,
- const bt_stream_class *stream_class,
- const bt_stream_class *writer_stream_class);
-
-/*
- * Create a copy of the stream class passed in parameter.
- *
- * Returns NULL or error.
- */
-BT_HIDDEN
-const bt_stream_class *ctf_copy_stream_class(FILE *err,
- const bt_stream_class *stream_class,
- const bt_trace *writer_trace,
- bool override_ts64);
-
-/*
- * Copy the value of a packet context field and add it to the
- * writer_packet_context. Only supports unsigned integers for now.
- *
- * Returns BT_COMPONENT_STATUS_OK on success, and BT_COMPONENT_STATUS_ERROR on
- * error.
- */
-BT_HIDDEN
-bt_component_status ctf_copy_packet_context_field(FILE *err,
- const bt_field *field, const char *field_name,
- const bt_field *writer_packet_context,
- bt_field_type *writer_packet_context_type);
-
-
-/*
- * Copy the packet_header from the packet passed in parameter and assign it
- * to the writer_stream.
- *
- * Returns 0 on success or -1 on error.
- */
-BT_HIDDEN
-int ctf_stream_copy_packet_header(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream);
-
-/*
- * Copy the packet_header from the packet passed in parameter and assign it
- * to the writer_packet.
- *
- * Returns 0 on success or -1 on error.
- */
-BT_HIDDEN
-int ctf_packet_copy_header(FILE *err, const bt_packet *packet,
- const bt_packet *writer_packet);
-
-/*
- * Copy all the field values of the packet context from the packet passed in
- * parameter and set it to the writer_stream.
- *
- * Returns 0 on success or -1 on error.
- */
-BT_HIDDEN
-int ctf_stream_copy_packet_context(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream);
-
-/*
- * Copy all the field values of the packet context from the packet passed in
- * parameter and set it to the writer_packet.
- *
- * Returns 0 on success or -1 on error.
- */
-BT_HIDDEN
-int ctf_packet_copy_context(FILE *err, const bt_packet *packet,
- const bt_stream *writer_stream,
- const bt_packet *writer_packet);
-
-/*
- * Create and return a copy of the event passed in parameter. The caller has to
- * append it to the writer_stream.
- *
- * Returns NULL on error.
- */
-BT_HIDDEN
-const bt_event *ctf_copy_event(FILE *err, const bt_event *event,
- const bt_event_class *writer_event_class,
- bool override_ts64);
-
-/*
- * Copies the content of the event header to writer_event_header.
- *
- * Returns 0 on success, -1 on error.
- */
-BT_HIDDEN
-int ctf_copy_event_header(FILE *err, const bt_event *event,
- const bt_event_class *writer_event_class,
- const bt_event *writer_event,
- const bt_field *event_header);
-
-/*
- * Copy the environment and the packet header from the input trace to the
- * writer_trace.
- *
- * Returns BT_COMPONENT_STATUS_OK on success, and BT_COMPONENT_STATUS_ERROR on
- * error.
- */
-BT_HIDDEN
-bt_component_status ctf_copy_trace(FILE *err, const bt_trace *trace,
- const bt_trace *writer_trace);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BABELTRACE_LIB_COPY_TRACE_H */
+++ /dev/null
-/*
- * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_OUTPUT_LEVEL bt_plugin_libctfcopytrace_log_level
-#include <babeltrace/logging-internal.h>
-
-BT_LOG_INIT_LOG_LEVEL(bt_plugin_libctfcopytrace_log_level,
- "BABELTRACE_PLUGIN_CTFCOPYTRACE_LIB_LOG_LEVEL");
+++ /dev/null
-#ifndef PLUGINS_LIBCTFCOPYTRACE_LOGGING_H
-#define PLUGINS_LIBCTFCOPYTRACE_LOGGING_H
-
-/*
- * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_OUTPUT_LEVEL bt_plugin_libctfcopytrace_log_level
-#include <babeltrace/logging-internal.h>
-
-BT_LOG_LEVEL_EXTERN_SYMBOL(bt_plugin_libctfcopytrace_log_level);
-
-#endif /* PLUGINS_LIBCTFCOPYTRACE_LOGGING_H */
-AM_CPPFLAGS += -I$(top_srcdir)/plugins \
- -I$(top_srcdir)/plugins/libctfcopytrace
+AM_CPPFLAGS += -I$(top_srcdir)/plugins
noinst_LTLIBRARIES = libdebug-info.la
libdebug_info_la_SOURCES = \
debug-info.h \
dwarf.c \
dwarf.h \
+ trace-ir-data-copy.c \
+ trace-ir-data-copy.h \
+ trace-ir-mapping.c \
+ trace-ir-mapping.h \
+ trace-ir-metadata-copy.c \
+ trace-ir-metadata-copy.h \
+ trace-ir-metadata-field-class-copy.c \
+ trace-ir-metadata-field-class-copy.h \
logging.c \
logging.h
babeltrace_plugin_lttng_utils_la_SOURCES = \
plugin.c \
utils.c \
- copy.c \
utils.h \
- copy.h \
logging.h
babeltrace_plugin_lttng_utils_la_LIBADD = \
babeltrace_plugin_lttng_utils_la_LIBADD += \
$(top_builddir)/lib/libbabeltrace.la \
$(top_builddir)/common/libbabeltrace-common.la \
- $(top_builddir)/logging/libbabeltrace-logging.la \
- $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la
+ $(top_builddir)/logging/libbabeltrace-logging.la
endif
* character).
*/
#define ADDR_STR_LEN 20
+#define BUILD_ID_NOTE_NAME "GNU"
BT_HIDDEN
int bin_info_init(void)
bin->elf_path = g_build_path("/", target_prefix,
path, NULL);
} else {
- bin->elf_path = strdup(path);
+ bin->elf_path = g_strdup(path);
}
if (!bin->elf_path) {
bin->memsz = memsz;
bin->low_addr = low_addr;
bin->high_addr = bin->low_addr + bin->memsz;
+ bin->build_id = NULL;
+ bin->build_id_len = 0;
+ bin->file_build_id_matches = false;
return bin;
g_free(bin);
}
+/**
+ * Initialize the ELF file for a given executable.
+ *
+ * @param bin bin_info instance
+ * @returns 0 on success, negative value on error.
+ */
+static
+int bin_info_set_elf_file(struct bin_info *bin)
+{
+ int elf_fd = -1;
+ Elf *elf_file = NULL;
+
+ if (!bin) {
+ goto error;
+ }
+
+ elf_fd = open(bin->elf_path, O_RDONLY);
+ if (elf_fd < 0) {
+ elf_fd = -errno;
+ BT_LOGE("Failed to open %s\n", bin->elf_path);
+ goto error;
+ }
+
+ elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
+ if (!elf_file) {
+ BT_LOGE("elf_begin failed: %s\n", elf_errmsg(-1));
+ goto error;
+ }
+
+ if (elf_kind(elf_file) != ELF_K_ELF) {
+ BT_LOGE("Error: %s is not an ELF object\n",
+ bin->elf_path);
+ goto error;
+ }
+
+ bin->elf_fd = elf_fd;
+ bin->elf_file = elf_file;
+ return 0;
+
+error:
+ if (elf_fd >= 0) {
+ close(elf_fd);
+ elf_fd = -1;
+ }
+ elf_end(elf_file);
+ return elf_fd;
+}
+
+/**
+ * From a note section data buffer, check if it is a build id note.
+ *
+ * @param buf Pointer to a note section
+ *
+ * @returns 1 on match, 0 if `buf` does not contain a
+ * valid build id note
+ */
+static
+int is_build_id_note_section(uint8_t *buf)
+{
+ int ret = 0;
+ uint32_t name_sz, desc_sz, note_type;
+
+ /* The note section header has 3 32bit integer for the following:
+ * - Section name size
+ * - Description size
+ * - Note type
+ */
+ name_sz = (uint32_t) *buf;
+ buf += sizeof(name_sz);
+
+ buf += sizeof(desc_sz);
+
+ note_type = (uint32_t) *buf;
+ buf += sizeof(note_type);
+
+ /* Check the note type. */
+ if (note_type != NT_GNU_BUILD_ID) {
+ goto invalid;
+ }
+
+ /* Check the note name. */
+ if (memcmp(buf, BUILD_ID_NOTE_NAME, name_sz) != 0) {
+ goto invalid;
+ }
+
+ ret = 1;
+
+invalid:
+ return ret;
+}
+
+/**
+ * From a build id note section data buffer, check if the build id it contains
+ * is identical to the build id passed as parameter.
+ *
+ * @param file_build_id_note Pointer to the file build id note section.
+ * @param build_id Pointer to a build id to compare to.
+ * @param build_id_len length of the build id.
+ *
+ * @returns 1 on match, 0 otherwise.
+ */
+static
+int is_build_id_note_section_matching(uint8_t *file_build_id_note,
+ uint8_t *build_id, size_t build_id_len)
+{
+ uint32_t name_sz, desc_sz, note_type;
+
+ if (build_id_len <= 0) {
+ goto end;
+ }
+
+ /* The note section header has 3 32bit integer for the following:
+ * - Section name size
+ * - Description size
+ * - Note type
+ */
+ name_sz = (uint32_t) *file_build_id_note;
+ file_build_id_note += sizeof(name_sz);
+ file_build_id_note += sizeof(desc_sz);
+ file_build_id_note += sizeof(note_type);
+
+ /*
+ * Move the pointer pass the name char array. This corresponds to the
+ * beginning of the description section. The description is the build
+ * id in the case of a build id note.
+ */
+ file_build_id_note += name_sz;
+
+ /*
+ * Compare the binary build id with the supplied build id.
+ */
+ if (memcmp(build_id, file_build_id_note, build_id_len) == 0) {
+ return 1;
+ }
+end:
+ return 0;
+}
+
+/**
+ * Checks if the build id stored in `bin` (bin->build_id) is matching the build
+ * id of the ondisk file (bin->elf_file).
+ *
+ * @param bin bin_info instance
+ * @param build_id build id to compare ot the on disk file
+ * @param build_id_len length of the build id
+ *
+ * @returns 1 on if the build id of stored in `bin` matches
+ * the build id of the ondisk file.
+ * 0 on if they are different or an error occured.
+ */
+static
+int is_build_id_matching(struct bin_info *bin)
+{
+ int ret, is_build_id, is_matching = 0;
+ Elf_Scn *curr_section = NULL, *next_section = NULL;
+ Elf_Data *note_data = NULL;
+ GElf_Shdr *curr_section_hdr = NULL;
+
+ if (!bin->build_id) {
+ goto error;
+ }
+
+ /* Set ELF file if it hasn't been accessed yet. */
+ if (!bin->elf_file) {
+ ret = bin_info_set_elf_file(bin);
+ if (ret) {
+ /* Failed to set ELF file. */
+ goto error;
+ }
+ }
+
+ curr_section_hdr = g_new0(GElf_Shdr, 1);
+ if (!curr_section_hdr) {
+ goto error;
+ }
+
+ next_section = elf_nextscn(bin->elf_file, curr_section);
+ if (!next_section) {
+ goto error;
+ }
+
+ while (next_section) {
+ curr_section = next_section;
+ next_section = elf_nextscn(bin->elf_file, curr_section);
+
+ curr_section_hdr = gelf_getshdr(curr_section, curr_section_hdr);
+
+ if (!curr_section_hdr) {
+ goto error;
+ }
+
+ if (curr_section_hdr->sh_type != SHT_NOTE) {
+ continue;
+ }
+
+ note_data = elf_getdata(curr_section, NULL);
+ if (!note_data) {
+ goto error;
+ }
+
+ /* Check if the note is of the build-id type. */
+ is_build_id = is_build_id_note_section(note_data->d_buf);
+ if (!is_build_id) {
+ continue;
+ }
+
+ /*
+ * Compare the build id of the on-disk file and
+ * the build id recorded in the trace.
+ */
+ is_matching = is_build_id_note_section_matching(note_data->d_buf,
+ bin->build_id, bin->build_id_len);
+ if (!is_matching) {
+ break;
+ }
+ }
+error:
+ g_free(curr_section_hdr);
+ return is_matching;
+}
+
BT_HIDDEN
int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
size_t build_id_len)
goto error;
}
- bin->build_id = malloc(build_id_len);
+ /* Set the build id. */
+ bin->build_id = g_new0(uint8_t, build_id_len);
if (!bin->build_id) {
goto error;
}
memcpy(bin->build_id, build_id, build_id_len);
bin->build_id_len = build_id_len;
+ /*
+ * Check if the file found on the file system has the same build id
+ * that what was recorded in the trace.
+ */
+ bin->file_build_id_matches = is_build_id_matching(bin);
+ if (!bin->file_build_id_matches) {
+ BT_LOGD_STR("Supplied Build ID does not match Build ID of the "
+ "binary or library found on the file system.");
+ goto error;
+ }
+
/*
* Reset the is_elf_only flag in case it had been set
* previously, because we might find separate debug info using
return 0;
error:
-
return -1;
}
/**
* Try to set the dwarf_info for a given bin_info instance via the
- * build ID method.
+ * debug-link method.
*
* @param bin bin_info instance for which to retrieve the
* DWARF info via debug link
return ret;
}
-/**
- * Initialize the ELF file for a given executable.
- *
- * @param bin bin_info instance
- * @returns 0 on success, negative value on error.
- */
-static
-int bin_info_set_elf_file(struct bin_info *bin)
-{
- int elf_fd = -1;
- Elf *elf_file = NULL;
-
- if (!bin) {
- goto error;
- }
-
- elf_fd = open(bin->elf_path, O_RDONLY);
- if (elf_fd < 0) {
- elf_fd = -errno;
- BT_LOGD("Failed to open ELF file: path=\"%s\"", bin->elf_path);
- goto error;
- }
-
- elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
- if (!elf_file) {
- BT_LOGD("elf_begin() failed: %s.", elf_errmsg(-1));
- goto error;
- }
-
- if (elf_kind(elf_file) != ELF_K_ELF) {
- BT_LOGD("ELF file is not an ELF object: path=\"%s\"",
- bin->elf_path);
- goto error;
- }
-
- bin->elf_fd = elf_fd;
- bin->elf_file = elf_file;
- return 0;
-
-error:
- if (elf_fd >= 0) {
- close(elf_fd);
- elf_fd = -1;
- }
- elf_end(elf_file);
- return elf_fd;
-}
-
BT_HIDDEN
void source_location_destroy(struct source_location *src_loc)
{
goto error;
}
+ /*
+ * If the bin_info has a build id but it does not match the build id
+ * that was found on the file system, return an error.
+ */
+ if (bin->build_id && !bin->file_build_id_matches) {
+ 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);
goto error;
}
+ /*
+ * If the bin_info has a build id but it does not match the build id
+ * that was found on the file system, return an error.
+ */
+ if (bin->build_id && !bin->file_build_id_matches) {
+ goto error;
+ }
+
if (bin->is_pic) {
addr -= bin->low_addr;
ret = asprintf(&_bin_loc, "+%#0" PRIx64, addr);
goto error;
}
+ /*
+ * If the bin_info has a build id but it does not match the build id
+ * that was found on the file system, return an error.
+ */
+ if (bin->build_id && !bin->file_build_id_matches) {
+ goto error;
+ }
+
/* Set DWARF info if it hasn't been accessed yet. */
if (!bin->dwarf_info && !bin->is_elf_only) {
if (bin_info_set_dwarf_info(bin)) {
/* Optional build ID info. */
uint8_t *build_id;
size_t build_id_len;
+
/* Optional debug link info. */
char *dbg_link_filename;
uint32_t dbg_link_crc;
char *debug_info_dir;
/* Denotes whether the executable is position independent code. */
bool is_pic:1;
+ /* denotes whether the build id in the trace matches to one on disk. */
+ bool file_build_id_matches:1;
/*
* Denotes whether the executable only has ELF symbols and no
* DWARF info.
+++ /dev/null
-/*
- * copy.c
- *
- * Babeltrace Copy Trace Structure
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-FLT-COPY"
-#include "logging.h"
-
-#include <inttypes.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/babeltrace.h>
-
-#include <ctfcopytrace.h>
-#include "debug-info.h"
-
-static
-const bt_stream *insert_new_stream(
- struct debug_info_iterator *debug_it,
- const bt_stream *stream,
- struct debug_info_trace *di_trace);
-
-static
-void unref_stream(const bt_stream *stream)
-{
- bt_stream_put_ref(stream);
-}
-
-static
-void unref_packet(const bt_packet *packet)
-{
- bt_packet_put_ref(packet);
-}
-
-static
-void unref_stream_class(const bt_stream_class *stream_class)
-{
- bt_stream_class_put_ref(stream_class);
-}
-
-static
-void unref_debug_info(struct debug_info *debug_info)
-{
- debug_info_destroy(debug_info);
-}
-
-static
-void destroy_stream_state_key(gpointer key)
-{
- g_free((enum fs_writer_stream_state *) key);
-}
-
-static
-const bt_field *get_payload_field(FILE *err,
- const bt_event *event, const char *field_name)
-{
- const bt_field *field = NULL, *payload = NULL;
- const bt_field_class *payload_class = NULL;
-
- payload = bt_event_get_payload(event, NULL);
- BT_ASSERT(payload);
-
- payload_class = bt_field_get_class(payload);
- BT_ASSERT(payload_class);
-
- if (bt_field_class_id(payload_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
- BT_LOGE("Wrong type, expected struct: field-name=\"%s\"",
- field_name);
- goto end;
- }
-
- field = bt_field_structure_get_field_by_name(payload, field_name);
-
-end:
- bt_field_class_put_ref(payload_class);
- bt_object_put_ref(payload);
- return field;
-}
-
-static
-const bt_field *get_stream_event_context_field(FILE *err,
- const bt_event *event, const char *field_name)
-{
- const bt_field *field = NULL, *sec = NULL;
- const bt_field_class *sec_class = NULL;
-
- sec = bt_event_get_stream_event_context(event);
- if (!sec) {
- goto end;
- }
-
- sec_class = bt_field_get_class(sec);
- BT_ASSERT(sec_class);
-
- if (bt_field_class_id(sec_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
- BT_LOGE("Wrong type, expected struct, field-name=\"%s\"",
- field_name);
- goto end;
- }
-
- field = bt_field_structure_get_field_by_name(sec, field_name);
-
-end:
- bt_field_class_put_ref(sec_class);
- bt_object_put_ref(sec);
- return field;
-}
-
-BT_HIDDEN
-int get_stream_event_context_unsigned_int_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint64_t *value)
-{
- int ret;
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
-
- field = get_stream_event_context_field(err, event, field_name);
- if (!field) {
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
- BT_LOGE("Wrong type, expected integer: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- if (bt_ctf_field_class_integer_get_signed(field_class) != 0) {
- BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_unsigned_integer_get_value(field, value);
- if (ret) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-BT_HIDDEN
-int get_stream_event_context_int_field_value(FILE *err, const bt_event *event,
- const char *field_name, int64_t *value)
-{
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
- int ret;
-
- field = get_stream_event_context_field(err, event, field_name);
- if (!field) {
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
- BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name);
- goto error;
- }
-
- if (bt_ctf_field_class_integer_get_signed(field_class) != 1) {
- BT_LOGE("Wrong type, expected signed integer: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_signed_integer_get_value(field, value);
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-BT_HIDDEN
-int get_payload_unsigned_int_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint64_t *value)
-{
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
- int ret;
-
- field = get_payload_field(err, event, field_name);
- if (!field) {
- BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
- BT_LOGE("Wrong type, expected integer: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- if (bt_ctf_field_class_integer_get_signed(field_class) != 0) {
- BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_unsigned_integer_get_value(field, value);
- if (ret) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-BT_HIDDEN
-int get_payload_int_field_value(FILE *err, const bt_event *event,
- const char *field_name, int64_t *value)
-{
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
- int ret;
-
- field = get_payload_field(err, event, field_name);
- if (!field) {
- BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
- BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name);
- goto error;
- }
-
- if (bt_ctf_field_class_integer_get_signed(field_class) != 1) {
- BT_LOGE("Wrong type, expected signed integer field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_signed_integer_get_value(field, value);
- if (ret) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-BT_HIDDEN
-int get_payload_string_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- const char **value)
-{
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
- int ret;
-
- /*
- * The field might not exist, no error here.
- */
- field = get_payload_field(err, event, field_name);
- if (!field) {
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_STRING) {
- BT_LOGE("Wrong type, expected string: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- *value = bt_field_string_get_value(field);
- if (!*value) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-BT_HIDDEN
-int get_payload_build_id_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint8_t **build_id, uint64_t *build_id_len)
-{
- const bt_field *field = NULL, *seq_len = NULL;
- const bt_field_class *field_class = NULL;
- const bt_field *seq_field = NULL;
- uint64_t i;
- int ret;
-
- *build_id = NULL;
-
- field = get_payload_field(err, event, field_name);
- if (!field) {
- BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
- goto error;
- }
-
- field_class = bt_field_get_class(field);
- BT_ASSERT(field_class);
-
- if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_SEQUENCE) {
- BT_LOGE("Wrong type, expected sequence: field-name=\"%s\"", field_name);
- goto error;
- }
- BT_FIELD_CLASS_PUT_REF_AND_RESET(field_class);
-
- seq_len = bt_field_sequence_get_length(field);
- BT_ASSERT(seq_len);
-
- ret = bt_field_unsigned_integer_get_value(seq_len, build_id_len);
- if (ret) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(seq_len);
-
- *build_id = g_new0(uint8_t, *build_id_len);
- if (!*build_id) {
- BT_LOGE_STR("Failed to allocate build_id.");
- goto error;
- }
-
- for (i = 0; i < *build_id_len; i++) {
- uint64_t tmp;
-
- seq_field = bt_field_sequence_get_field(field, i);
- if (!seq_field) {
- BT_LOGE("Failed to get field in sequence: sequence-name=\"%s\", index=%" PRIu64,
- field_name, i);
- goto error;
- }
-
- ret = bt_field_unsigned_integer_get_value(seq_field, &tmp);
- if (ret) {
- BT_LOGE("Failed to get value: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- BT_OBJECT_PUT_REF_AND_RESET(seq_field);
- (*build_id)[i] = (uint8_t) tmp;
- }
- ret = 0;
- goto end;
-
-error:
- g_free(*build_id);
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- return ret;
-}
-
-static
-struct debug_info *lookup_trace_debug_info(struct debug_info_iterator *debug_it,
- const bt_trace *writer_trace,
- struct debug_info_trace *di_trace)
-{
- return (struct debug_info *) g_hash_table_lookup(
- di_trace->trace_debug_map,
- (gpointer) writer_trace);
-}
-
-static
-struct debug_info *insert_new_debug_info(struct debug_info_iterator *debug_it,
- const bt_trace *writer_trace,
- struct debug_info_trace *di_trace)
-{
- struct debug_info *debug_info = NULL;
- bt_value *field = NULL;
- const char *str_value;
- bt_value_status ret;
-
- field = bt_trace_get_environment_field_value_by_name(writer_trace,
- "domain");
- /* No domain field, no debug info */
- if (!field) {
- goto end;
- }
- str_value = bt_value_string_get(field);
-
- /* Domain not ust, no debug info */
- if (strcmp(str_value, "ust") != 0) {
- goto end;
- }
- BT_VALUE_PUT_REF_AND_RESET(field);
-
- /* No tracer_name, no debug info */
- field = bt_trace_get_environment_field_value_by_name(writer_trace,
- "tracer_name");
- /* No tracer_name, no debug info */
- if (!field) {
- goto end;
- }
- str_value = bt_value_string_get(field);
-
- /* Tracer_name not lttng-ust, no debug info */
- if (strcmp(str_value, "lttng-ust") != 0) {
- goto end;
- }
- BT_VALUE_PUT_REF_AND_RESET(field);
-
- debug_info = debug_info_create(debug_it->debug_info_component);
- if (!debug_info) {
- BT_LOGE_STR("Failed to create debug info.");
- goto end;
- }
-
- g_hash_table_insert(di_trace->trace_debug_map, (gpointer) writer_trace,
- debug_info);
-
-end:
- bt_value_put_ref(field);
- return debug_info;
-}
-
-static
-struct debug_info *get_trace_debug_info(struct debug_info_iterator *debug_it,
- const bt_trace *writer_trace,
- struct debug_info_trace *di_trace)
-{
- struct debug_info *debug_info;
-
- debug_info = lookup_trace_debug_info(debug_it, writer_trace, di_trace);
- if (debug_info) {
- goto end;
- }
-
- debug_info = insert_new_debug_info(debug_it, writer_trace, di_trace);
-
-end:
- return debug_info;
-}
-
-static
-struct debug_info_trace *lookup_trace(struct debug_info_iterator *debug_it,
- const bt_trace *trace)
-{
- return (struct debug_info_trace *) g_hash_table_lookup(
- debug_it->trace_map,
- (gpointer) trace);
-}
-
-static
-enum debug_info_stream_state *insert_new_stream_state(
- struct debug_info_iterator *debug_it,
- struct debug_info_trace *di_trace, const bt_stream *stream)
-{
- enum debug_info_stream_state *v = NULL;
-
- v = g_new0(enum debug_info_stream_state, 1);
- if (!v) {
- BT_LOGE_STR("Failed to allocate debug_info_stream_state.");
- goto end;
- }
- *v = DEBUG_INFO_UNKNOWN_STREAM;
-
- g_hash_table_insert(di_trace->stream_states, stream, v);
-
-end:
- return v;
-}
-
-static
-void check_completed_trace(gpointer key, gpointer value, gpointer user_data)
-{
- enum debug_info_stream_state *state = value;
- int *trace_completed = user_data;
-
- if (*state != DEBUG_INFO_COMPLETED_STREAM) {
- *trace_completed = 0;
- }
-}
-
-static
-gboolean empty_ht(gpointer key, gpointer value, gpointer user_data)
-{
- return TRUE;
-}
-
-BT_HIDDEN
-void debug_info_close_trace(struct debug_info_iterator *debug_it,
- struct debug_info_trace *di_trace)
-{
- if (di_trace->static_listener_id >= 0) {
- bt_trace_remove_is_static_listener(di_trace->trace,
- di_trace->static_listener_id);
- }
-
- /* Empty the stream class HT. */
- g_hash_table_foreach_remove(di_trace->stream_class_map,
- empty_ht, NULL);
- g_hash_table_destroy(di_trace->stream_class_map);
-
- /* Empty the stream HT. */
- g_hash_table_foreach_remove(di_trace->stream_map,
- empty_ht, NULL);
- g_hash_table_destroy(di_trace->stream_map);
-
- /* Empty the stream state HT. */
- g_hash_table_foreach_remove(di_trace->stream_states,
- empty_ht, NULL);
- g_hash_table_destroy(di_trace->stream_states);
-
- /* Empty the packet HT. */
- g_hash_table_foreach_remove(di_trace->packet_map,
- empty_ht, NULL);
- g_hash_table_destroy(di_trace->packet_map);
-
- /* Empty the trace_debug HT. */
- g_hash_table_foreach_remove(di_trace->trace_debug_map,
- empty_ht, NULL);
- g_hash_table_destroy(di_trace->trace_debug_map);
-}
-
-static
-int sync_event_classes(struct debug_info_iterator *debug_it,
- const bt_stream *stream,
- const bt_stream *writer_stream)
-{
- int int_ret;
- const bt_stream_class *stream_class = NULL,
- *writer_stream_class = NULL;
- bt_component_status ret;
-
- stream_class = bt_stream_get_class(stream);
- BT_ASSERT(stream_class);
-
- writer_stream_class = bt_stream_get_class(writer_stream);
- BT_ASSERT(writer_stream_class);
-
- ret = ctf_copy_event_classes(debug_it->err, stream_class,
- writer_stream_class);
- if (ret != BT_COMPONENT_STATUS_OK) {
- BT_LOGE_STR("Failed to copy event classes.");
- goto error;
- }
-
- int_ret = 0;
- goto end;
-
-error:
- int_ret = -1;
-end:
- bt_stream_class_put_ref(stream_class);
- bt_stream_class_put_ref(writer_stream_class);
- return int_ret;
-}
-
-static
-void trace_is_static_listener(const bt_trace *trace, void *data)
-{
- struct debug_info_trace *di_trace = data;
- int trace_completed = 1, ret, nr_stream, i;
- const bt_stream *stream = NULL, *writer_stream = NULL;
- const bt_trace *writer_trace = di_trace->writer_trace;
-
- /*
- * When the trace becomes static, make sure that we have all
- * the event classes in our stream_class copies before setting it
- * static as well.
- */
- nr_stream = bt_trace_get_stream_count(trace);
- for (i = 0; i < nr_stream; i++) {
- stream = bt_trace_get_stream_by_index(trace, i);
- BT_ASSERT(stream);
-
- writer_stream = bt_trace_get_stream_by_index(writer_trace, i);
- BT_ASSERT(writer_stream);
-
- ret = sync_event_classes(di_trace->debug_it, stream, writer_stream);
- if (ret) {
- BT_LOGE_STR("Failed to synchronize the event classes.");
- goto error;
- }
- BT_STREAM_PUT_REF_AND_RESET(stream);
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
- }
-
- bt_trace_set_is_static(di_trace->writer_trace);
- di_trace->trace_static = 1;
-
- g_hash_table_foreach(di_trace->stream_states,
- check_completed_trace, &trace_completed);
- if (trace_completed) {
- debug_info_close_trace(di_trace->debug_it, di_trace);
- g_hash_table_remove(di_trace->debug_it->trace_map,
- di_trace->trace);
- }
-
-error:
- bt_stream_put_ref(writer_stream);
- bt_stream_put_ref(stream);
-}
-
-static
-struct debug_info_trace *insert_new_trace(struct debug_info_iterator *debug_it,
- const bt_stream *stream) {
- const bt_trace *writer_trace = NULL;
- struct debug_info_trace *di_trace = NULL;
- const bt_trace *trace = NULL;
- const bt_stream_class *stream_class = NULL;
- const bt_stream *writer_stream = NULL;
- int ret, nr_stream, i;
-
- writer_trace = bt_trace_create();
- if (!writer_trace) {
- BT_LOGE_STR("Failed to create a new trace.");
- goto error;
- }
-
- stream_class = bt_stream_get_class(stream);
- BT_ASSERT(stream_class);
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- ret = ctf_copy_trace(debug_it->err, trace, writer_trace);
- if (ret != BT_COMPONENT_STATUS_OK) {
- BT_LOGE_STR("Failed to copy CTF trace.");
- goto error;
- }
-
- di_trace = g_new0(struct debug_info_trace, 1);
- if (!di_trace) {
- BT_LOGE_STR("Failed to allocate debug_info_trace.");
- goto error;
- }
-
- di_trace->trace = trace;
- di_trace->writer_trace = writer_trace;
- di_trace->debug_info_component = debug_it->debug_info_component;
- di_trace->debug_it = debug_it;
- di_trace->stream_map = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) unref_stream);
- di_trace->stream_class_map = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
- di_trace->packet_map = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) unref_packet);
- di_trace->trace_debug_map = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) unref_debug_info);
- di_trace->stream_states = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, destroy_stream_state_key);
- g_hash_table_insert(debug_it->trace_map, (gpointer) trace, di_trace);
-
- /* Set all the existing streams in the unknown state. */
- nr_stream = bt_trace_get_stream_count(trace);
- for (i = 0; i < nr_stream; i++) {
- stream = bt_trace_get_stream_by_index(trace, i);
- BT_ASSERT(stream);
-
- insert_new_stream_state(debug_it, di_trace, stream);
- writer_stream = insert_new_stream(debug_it, stream, di_trace);
- if (!writer_stream) {
- BT_LOGE_STR("Failed to insert new stream.");
- goto error;
- }
- bt_stream_get_ref(writer_stream);
- ret = sync_event_classes(debug_it, stream, writer_stream);
- if (ret) {
- BT_LOGE_STR("Failed to synchronize event classes.");
- goto error;
- }
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
- BT_STREAM_PUT_REF_AND_RESET(stream);
- }
-
- /* Check if the trace is already static or register a listener. */
- if (bt_trace_is_static(trace)) {
- di_trace->trace_static = 1;
- di_trace->static_listener_id = -1;
- bt_trace_set_is_static(writer_trace);
- } else {
- ret = bt_trace_add_is_static_listener(trace,
- trace_is_static_listener, NULL, di_trace);
- BT_ASSERT(ret >= 0);
- di_trace->static_listener_id = ret;
- }
-
-
- goto end;
-
-error:
- BT_TRACE_PUT_REF_AND_RESET(writer_trace);
- g_free(di_trace);
- di_trace = NULL;
-end:
- bt_stream_put_ref(stream);
- bt_stream_put_ref(writer_stream);
- bt_stream_class_put_ref(stream_class);
- bt_trace_put_ref(trace);
- return di_trace;
-}
-
-static
-const bt_packet *lookup_packet(struct debug_info_iterator *debug_it,
- const bt_packet *packet,
- struct debug_info_trace *di_trace)
-{
- return (const bt_packet *) g_hash_table_lookup(
- di_trace->packet_map,
- (gpointer) packet);
-}
-
-static
-const bt_packet *insert_new_packet(struct debug_info_iterator *debug_it,
- const bt_packet *packet,
- const bt_stream *writer_stream,
- struct debug_info_trace *di_trace)
-{
- const bt_packet *writer_packet;
- int ret;
-
- writer_packet = bt_packet_create(writer_stream);
- if (!writer_packet) {
- BT_LOGE_STR("Failed to create new packet.");
- goto error;
- }
-
- ret = ctf_packet_copy_header(debug_it->err, packet, writer_packet);
- if (ret) {
- BT_LOGE_STR("Failed to copy packet header.");
- goto error;
- }
-
- g_hash_table_insert(di_trace->packet_map, (gpointer) packet,
- writer_packet);
- goto end;
-
-error:
- BT_PACKET_PUT_REF_AND_RESET(writer_packet);
-end:
- return writer_packet;
-}
-
-static
-int add_debug_info_fields(FILE *err,
- const bt_field_class *writer_event_context_class,
- struct debug_info_component *component)
-{
- const bt_field_class *ip_field = NULL, *debug_field_class = NULL,
- *bin_field_class = NULL, *func_field_class = NULL,
- *src_field_class = NULL;
- int ret = 0;
-
- ip_field = bt_field_class_structure_get_field_class_by_name(
- writer_event_context_class, IP_FIELD_NAME);
- /* No ip field, so no debug info. */
- if (!ip_field) {
- goto end;
- }
- BT_FIELD_CLASS_PUT_REF_AND_RESET(ip_field);
-
- debug_field_class = bt_field_class_structure_get_field_class_by_name(
- writer_event_context_class,
- component->arg_debug_info_field_name);
- /* Already existing debug_info field, no need to add it. */
- if (debug_field_class) {
- goto end;
- }
-
- debug_field_class = bt_field_class_structure_create();
- if (!debug_field_class) {
- BT_LOGE_STR("Failed to create debug_info structure.");
- goto error;
- }
-
- bin_field_class = bt_field_class_string_create();
- if (!bin_field_class) {
- BT_LOGE_STR("Failed to create string for field=bin.");
- goto error;
- }
-
- func_field_class = bt_field_class_string_create();
- if (!func_field_class) {
- BT_LOGE_STR("Failed to create string for field=func.");
- goto error;
- }
-
- src_field_class = bt_field_class_string_create();
- if (!src_field_class) {
- BT_LOGE_STR("Failed to create string for field=src.");
- goto error;
- }
-
- ret = bt_field_class_structure_add_field(debug_field_class,
- bin_field_class, "bin");
- if (ret) {
- BT_LOGE_STR("Failed to add a field to debug_info struct: field=bin.");
- goto error;
- }
-
- ret = bt_field_class_structure_add_field(debug_field_class,
- func_field_class, "func");
- if (ret) {
- BT_LOGE_STR("Failed to add a field to debug_info struct: field=func.");
- goto error;
- }
-
- ret = bt_field_class_structure_add_field(debug_field_class,
- src_field_class, "src");
- if (ret) {
- BT_LOGE_STR("Failed to add a field to debug_info struct: field=src.");
- goto error;
- }
-
- ret = bt_field_class_structure_add_field(writer_event_context_class,
- debug_field_class, component->arg_debug_info_field_name);
- if (ret) {
- BT_LOGE_STR("Failed to add debug_info field to event_context.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class);
- ret = -1;
-end:
- bt_field_class_put_ref(src_field_class);
- bt_field_class_put_ref(func_field_class);
- bt_field_class_put_ref(bin_field_class);
- bt_field_class_put_ref(debug_field_class);
- return ret;
-}
-
-static
-int create_debug_info_event_context_class(FILE *err,
- const bt_field_class *event_context_class,
- const bt_field_class *writer_event_context_class,
- struct debug_info_component *component)
-{
- int ret, nr_fields, i;
-
- nr_fields = bt_field_class_structure_get_field_count(event_context_class);
- for (i = 0; i < nr_fields; i++) {
- const bt_field_class *field_class = NULL;
- const char *field_name;
-
- if (bt_field_class_structure_get_field_by_index(event_context_class,
- &field_name, &field_class, i) < 0) {
- BT_LOGE("Failed to get a field from the event-context: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_class_structure_add_field(writer_event_context_class,
- field_class, field_name);
- BT_FIELD_CLASS_PUT_REF_AND_RESET(field_class);
- if (ret) {
- BT_LOGE("Failed to add a field to the event-context: field-name=\"%s\"",
- field_name);
- goto error;
- }
- }
-
- ret = add_debug_info_fields(err, writer_event_context_class,
- component);
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
-static
-const bt_stream_class *copy_stream_class_debug_info(FILE *err,
- const bt_stream_class *stream_class,
- const bt_trace *writer_trace,
- struct debug_info_component *component)
-{
- const bt_field_class *cls = NULL;
- const bt_stream_class *writer_stream_class = NULL;
- const bt_field_class *writer_event_context_class = NULL;
- int ret_int;
- const char *name = bt_stream_class_get_name(stream_class);
-
- writer_stream_class = bt_stream_class_create_empty(name);
- if (!writer_stream_class) {
- BT_LOGE_STR("Failed to create empty stream class.");
- goto error;
- }
-
- type = bt_stream_class_get_packet_context_class(stream_class);
- if (type) {
- ret_int = bt_stream_class_set_packet_context_class(
- writer_stream_class, type);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set packet_context type.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
- }
-
- type = bt_stream_class_get_event_header_type(stream_class);
- if (type) {
- ret_int = bt_stream_class_set_event_header_type(
- writer_stream_class, type);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set event_header type.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
- }
-
- type = bt_stream_class_get_event_context_class(stream_class);
- if (type) {
- writer_event_context_class = bt_field_class_structure_create();
- if (!writer_event_context_class) {
- BT_LOGE_STR("Failed to create writer_event_context struct type.");
- goto error;
- }
- ret_int = create_debug_info_event_context_class(err, type,
- writer_event_context_class, component);
- if (ret_int) {
- BT_LOGE_STR("Failed to create debug_info event_context type.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(type);
-
- ret_int = bt_stream_class_set_event_context_class(
- writer_stream_class, writer_event_context_class);
- if (ret_int < 0) {
- BT_LOGE_STR("Failed to set event_context type.");
- goto error;
- }
- BT_FIELD_CLASS_PUT_REF_AND_RESET(writer_event_context_class);
- }
-
- goto end;
-
-error:
- BT_STREAM_CLASS_PUT_REF_AND_RESET(writer_stream_class);
-end:
- bt_field_class_put_ref(writer_event_context_class);
- bt_object_put_ref(type);
- return writer_stream_class;
-}
-
-/*
- * Add the original clock classes to the new trace, we do not need to copy
- * them, and if we did, we would have to manually inspect the stream class
- * to update the integers mapping to a clock.
- */
-static
-int add_clock_classes(FILE *err, const bt_trace *writer_trace,
- const bt_stream_class *writer_stream_class,
- const bt_trace *trace)
-{
- int ret, clock_class_count, i;
-
- clock_class_count = bt_trace_get_clock_class_count(trace);
-
- for (i = 0; i < clock_class_count; i++) {
- const bt_clock_class *clock_class =
- bt_trace_get_clock_class_by_index(trace, i);
- const bt_clock_class *existing_clock_class = NULL;
-
- BT_ASSERT(clock_class);
-
- existing_clock_class = bt_trace_get_clock_class_by_name(
- writer_trace, bt_clock_class_get_name(clock_class));
- bt_clock_class_put_ref(existing_clock_class);
- if (existing_clock_class) {
- bt_clock_class_put_ref(clock_class);
- continue;
- }
-
- ret = bt_trace_add_clock_class(writer_trace, clock_class);
- BT_CLOCK_CLASS_PUT_REF_AND_RESET(clock_class);
- if (ret != 0) {
- BT_LOGE_STR("Failed to add clock_class.");
- goto error;
- }
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-
-}
-
-static
-const bt_stream_class *insert_new_stream_class(
- struct debug_info_iterator *debug_it,
- const bt_stream_class *stream_class)
-{
- const bt_stream_class *writer_stream_class = NULL;
- const bt_trace *trace, *writer_trace = NULL;
- struct debug_info_trace *di_trace;
- bt_component_status ret;
- int int_ret;
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- di_trace = lookup_trace(debug_it, trace);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find existing trace.");
- ret = BT_COMPONENT_STATUS_ERROR;
- goto error;
- }
- writer_trace = di_trace->writer_trace;
- bt_trace_get_ref(writer_trace);
-
- writer_stream_class = copy_stream_class_debug_info(debug_it->err, stream_class,
- writer_trace, debug_it->debug_info_component);
- if (!writer_stream_class) {
- BT_LOGE_STR("Failed to copy stream class.");
- goto error;
- }
-
- int_ret = bt_trace_add_stream_class(writer_trace, writer_stream_class);
- if (int_ret) {
- BT_LOGE_STR("Failed to add stream class.");
- goto error;
- }
-
- ret = add_clock_classes(debug_it->err, writer_trace,
- writer_stream_class, trace);
- if (ret != BT_COMPONENT_STATUS_OK) {
- BT_LOGE_STR("Failed to add clock classes.");
- goto error;
- }
-
- g_hash_table_insert(di_trace->stream_class_map,
- (gpointer) stream_class, writer_stream_class);
-
- goto end;
-
-error:
- BT_STREAM_CLASS_PUT_REF_AND_RESET(writer_stream_class);
-end:
- bt_trace_put_ref(trace);
- bt_trace_put_ref(writer_trace);
- return writer_stream_class;
-}
-
-static
-const bt_stream *insert_new_stream(
- struct debug_info_iterator *debug_it,
- const bt_stream *stream,
- struct debug_info_trace *di_trace)
-{
- const bt_stream *writer_stream = NULL;
- const bt_stream_class *stream_class = NULL;
- const bt_stream_class *writer_stream_class = NULL;
- int64_t id;
-
- stream_class = bt_stream_get_class(stream);
- BT_ASSERT(stream_class);
-
- writer_stream_class = g_hash_table_lookup(
- di_trace->stream_class_map,
- (gpointer) stream_class);
-
- if (!writer_stream_class) {
- writer_stream_class = insert_new_stream_class(debug_it,
- stream_class);
- if (!writer_stream_class) {
- BT_LOGE_STR("Failed to insert new stream class.");
- goto error;
- }
- }
- bt_stream_class_get_ref(writer_stream_class);
-
- id = bt_stream_get_id(stream);
- if (id < 0) {
- writer_stream = bt_stream_create(writer_stream_class,
- bt_stream_get_name(stream));
- } else {
- writer_stream = bt_stream_create_with_id(
- writer_stream_class,
- bt_stream_get_name(stream), id);
- }
-
- if (!writer_stream) {
- BT_LOGE_STR("Failed to create writer_stream.");
- goto error;
- }
-
- g_hash_table_insert(di_trace->stream_map, (gpointer) stream,
- writer_stream);
-
- goto end;
-
-error:
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
-end:
- bt_stream_class_put_ref(stream_class);
- bt_stream_class_put_ref(writer_stream_class);
- return writer_stream;
-}
-
-static
-const bt_stream *lookup_stream(struct debug_info_iterator *debug_it,
- const bt_stream *stream,
- struct debug_info_trace *di_trace)
-{
- return (const bt_stream *) g_hash_table_lookup(
- di_trace->stream_map, (gpointer) stream);
-}
-
-static
-const bt_event_class *get_event_class(struct debug_info_iterator *debug_it,
- const bt_stream_class *writer_stream_class,
- const bt_event_class *event_class)
-{
- return bt_stream_class_get_event_class_by_id(writer_stream_class,
- bt_event_class_get_id(event_class));
-}
-
-static
-struct debug_info_trace *lookup_di_trace_from_stream(
- struct debug_info_iterator *debug_it,
- const bt_stream *stream)
-{
- const bt_stream_class *stream_class = NULL;
- const bt_trace *trace = NULL;
- struct debug_info_trace *di_trace = NULL;
-
- stream_class = bt_stream_get_class(stream);
- BT_ASSERT(stream_class);
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- di_trace = (struct debug_info_trace *) g_hash_table_lookup(
- debug_it->trace_map, (gpointer) trace);
-
- BT_STREAM_CLASS_PUT_REF_AND_RESET(stream_class);
- BT_TRACE_PUT_REF_AND_RESET(trace);
- return di_trace;
-}
-
-static
-const bt_stream *get_writer_stream(
- struct debug_info_iterator *debug_it,
- const bt_packet *packet, const bt_stream *stream)
-{
- const bt_stream_class *stream_class = NULL;
- const bt_stream *writer_stream = NULL;
- struct debug_info_trace *di_trace = NULL;
-
- stream_class = bt_stream_get_class(stream);
- BT_ASSERT(stream_class);
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find existing trace from stream.");
- goto error;
- }
-
- writer_stream = lookup_stream(debug_it, stream, di_trace);
- if (!writer_stream) {
- BT_LOGE_STR("Failed to find existing stream.");
- goto error;
- }
- bt_stream_get_ref(writer_stream);
-
- goto end;
-
-error:
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
-end:
- bt_stream_class_put_ref(stream_class);
- return writer_stream;
-}
-
-BT_HIDDEN
-const bt_packet *debug_info_new_packet(
- struct debug_info_iterator *debug_it,
- const bt_packet *packet)
-{
- const bt_stream *stream = NULL, *writer_stream = NULL;
- const bt_packet *writer_packet = NULL;
- const bt_field *packet_context = NULL;
- struct debug_info_trace *di_trace;
- int int_ret;
-
- stream = bt_packet_get_stream(packet);
- BT_ASSERT(stream);
-
- writer_stream = get_writer_stream(debug_it, packet, stream);
- if (!writer_stream) {
- BT_LOGE_STR("Failed to get writer stream.");
- goto error;
- }
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find existing trace from stream.");
- goto error;
- }
-
- /*
- * If a packet was already opened, close it and remove it from
- * the HT.
- */
- writer_packet = lookup_packet(debug_it, packet, di_trace);
- if (writer_packet) {
- g_hash_table_remove(di_trace->packet_map, packet);
- BT_PACKET_PUT_REF_AND_RESET(writer_packet);
- }
-
- writer_packet = insert_new_packet(debug_it, packet, writer_stream,
- di_trace);
- if (!writer_packet) {
- BT_LOGE_STR("Failed to insert new packet.");
- goto error;
- }
-
- packet_context = bt_packet_get_context(packet);
- if (packet_context) {
- int_ret = ctf_packet_copy_context(debug_it->err,
- packet, writer_stream, writer_packet);
- if (int_ret < 0) {
- BT_LOGE_STR("Failed to copy packet context.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(packet_context);
- }
-
- bt_packet_get_ref(writer_packet);
- goto end;
-
-error:
-
-end:
- bt_object_put_ref(packet_context);
- bt_stream_put_ref(writer_stream);
- bt_stream_put_ref(stream);
- return writer_packet;
-}
-
-BT_HIDDEN
-const bt_packet *debug_info_close_packet(
- struct debug_info_iterator *debug_it,
- const bt_packet *packet)
-{
- const bt_packet *writer_packet = NULL;
- const bt_stream *stream = NULL;
- struct debug_info_trace *di_trace;
-
- stream = bt_packet_get_stream(packet);
- BT_ASSERT(stream);
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find trace from stream.");
- goto end;
- }
-
- writer_packet = lookup_packet(debug_it, packet, di_trace);
- if (!writer_packet) {
- BT_LOGE_STR("Failed to find existing packet.");
- goto end;
- }
- bt_packet_get_ref(writer_packet);
- g_hash_table_remove(di_trace->packet_map, packet);
-
-end:
- bt_stream_put_ref(stream);
- return writer_packet;
-}
-
-BT_HIDDEN
-const bt_stream *debug_info_stream_begin(
- struct debug_info_iterator *debug_it,
- const bt_stream *stream)
-{
- const bt_stream *writer_stream = NULL;
- enum debug_info_stream_state *state;
- struct debug_info_trace *di_trace = NULL;
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- di_trace = insert_new_trace(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to insert new trace.");
- goto error;
- }
- }
-
- /* Set the stream as active */
- state = g_hash_table_lookup(di_trace->stream_states, stream);
- if (!state) {
- if (di_trace->trace_static) {
- BT_LOGE_STR("Failed to add a new stream, trace is static.");
- goto error;
- }
- state = insert_new_stream_state(debug_it, di_trace,
- stream);
- if (!state) {
- BT_LOGE_STR("Failed to add new stream state.");
- goto error;
- }
- }
- if (*state != DEBUG_INFO_UNKNOWN_STREAM) {
- BT_LOGE("Unexpected stream state: state=%d", *state);
- goto error;
- }
- *state = DEBUG_INFO_ACTIVE_STREAM;
-
- writer_stream = lookup_stream(debug_it, stream, di_trace);
- if (!writer_stream) {
- writer_stream = insert_new_stream(debug_it, stream, di_trace);
- }
- bt_stream_get_ref(writer_stream);
-
- goto end;
-
-error:
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
-end:
- return writer_stream;
-}
-
-BT_HIDDEN
-const bt_stream *debug_info_stream_end(struct debug_info_iterator *debug_it,
- const bt_stream *stream)
-{
- const bt_stream *writer_stream = NULL;
- struct debug_info_trace *di_trace = NULL;
- enum debug_info_stream_state *state;
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find existing trace from stream.");
- goto error;
- }
-
- writer_stream = lookup_stream(debug_it, stream, di_trace);
- if (!writer_stream) {
- BT_LOGE_STR("Failed to find existing stream.");
- goto error;
- }
- /*
- * Take the ref on the stream and keep it until the message
- * is created.
- */
- bt_stream_get_ref(writer_stream);
-
- state = g_hash_table_lookup(di_trace->stream_states, stream);
- if (*state != DEBUG_INFO_ACTIVE_STREAM) {
- BT_LOGE("Unexpected stream state: state=%d", *state);
- goto error;
- }
- *state = DEBUG_INFO_COMPLETED_STREAM;
-
- g_hash_table_remove(di_trace->stream_map, stream);
-
- if (di_trace->trace_static) {
- int trace_completed = 1;
-
- g_hash_table_foreach(di_trace->stream_states,
- check_completed_trace, &trace_completed);
- if (trace_completed) {
- debug_info_close_trace(debug_it, di_trace);
- g_hash_table_remove(debug_it->trace_map,
- di_trace->trace);
- }
- }
-
- goto end;
-
-error:
- BT_STREAM_PUT_REF_AND_RESET(writer_stream);
-
-end:
- return writer_stream;
-}
-
-static
-struct debug_info_source *lookup_debug_info(FILE *err,
- const bt_event *event,
- struct debug_info *debug_info)
-{
- int64_t vpid;
- uint64_t ip;
- struct debug_info_source *dbg_info_src = NULL;
- int ret;
-
- ret = get_stream_event_context_int_field_value(err, event,
- VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
-
- ret = get_stream_event_context_unsigned_int_field_value(err, event,
- IP_FIELD_NAME, &ip);
- if (ret) {
- goto end;
- }
-
- /* Get debug info for this context. */
- dbg_info_src = debug_info_query(debug_info, vpid, ip);
-
-end:
- return dbg_info_src;
-}
-
-static
-int set_debug_info_field(FILE *err, const bt_field *debug_field,
- struct debug_info_source *dbg_info_src,
- struct debug_info_component *component)
-{
- int i, nr_fields, ret = 0;
- const bt_field_class *debug_field_class = NULL;
- const bt_field *field = NULL;
- const bt_field_class *field_class = NULL;
-
- debug_field_class = bt_field_get_class(debug_field);
- BT_ASSERT(debug_field_class);
-
- nr_fields = bt_field_class_structure_get_field_count(debug_field_class);
- for (i = 0; i < nr_fields; i++) {
- const char *field_name;
-
- if (bt_field_class_structure_get_field_by_index(debug_field_class,
- &field_name, &field_class, i) < 0) {
- BT_LOGE("Failed to get field from debug_info struct: field-name=\"%s\"",
- field_name);
- goto error;
- }
- BT_FIELD_CLASS_PUT_REF_AND_RESET(field_class);
-
- field = bt_field_structure_get_field_by_index(debug_field, i);
- if (!strcmp(field_name, "bin")) {
- if (dbg_info_src && dbg_info_src->bin_path) {
- GString *tmp = g_string_new(NULL);
-
- if (component->arg_full_path) {
- g_string_printf(tmp, "%s%s",
- dbg_info_src->bin_path,
- dbg_info_src->bin_loc);
- } else {
- g_string_printf(tmp, "%s%s",
- dbg_info_src->short_bin_path,
- dbg_info_src->bin_loc);
- }
- ret = bt_field_string_set_value(field, tmp->str);
- g_string_free(tmp, true);
- } else {
- ret = bt_field_string_set_value(field, "");
- }
- } else if (!strcmp(field_name, "func")) {
- if (dbg_info_src && dbg_info_src->func) {
- ret = bt_field_string_set_value(field,
- dbg_info_src->func);
- } else {
- ret = bt_field_string_set_value(field, "");
- }
- } else if (!strcmp(field_name, "src")) {
- if (dbg_info_src && dbg_info_src->src_path) {
- GString *tmp = g_string_new(NULL);
-
- if (component->arg_full_path) {
- g_string_printf(tmp, "%s:%" PRId64,
- dbg_info_src->src_path,
- dbg_info_src->line_no);
- } else {
- g_string_printf(tmp, "%s:%" PRId64,
- dbg_info_src->short_src_path,
- dbg_info_src->line_no);
- }
- ret = bt_field_string_set_value(field, tmp->str);
- g_string_free(tmp, true);
- } else {
- ret = bt_field_string_set_value(field, "");
- }
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- if (ret) {
- BT_LOGE("Failed to set value in debug-info struct: field-name=\"%s\"",
- field_name);
- goto error;
- }
- }
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(field_class);
- bt_object_put_ref(field);
- bt_field_class_put_ref(debug_field_class);
- return ret;
-}
-
-static
-int copy_set_debug_info_stream_event_context(FILE *err,
- const bt_field *event_context,
- const bt_event *event,
- const bt_event *writer_event,
- struct debug_info *debug_info,
- struct debug_info_component *component)
-{
- const bt_field_class *writer_event_context_class = NULL,
- *event_context_class = NULL;
- const bt_field *writer_event_context = NULL;
- const bt_field *field = NULL, *copy_field = NULL, *debug_field = NULL;
- const bt_field_class *field_class = NULL;
- struct debug_info_source *dbg_info_src;
- int ret, nr_fields, i;
-
- writer_event_context = bt_event_get_stream_event_context(writer_event);
- BT_ASSERT(writer_event_context);
-
- writer_event_context_class = bt_field_get_class(writer_event_context);
- BT_ASSERT(writer_event_context_class);
-
- event_context_class = bt_field_get_class(event_context);
- BT_ASSERT(event_context_class);
-
- /*
- * If it is not a structure, we did not modify it to add the debug info
- * fields, so just assign it as is.
- */
- if (bt_field_class_id(writer_event_context_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
- ret = bt_event_set_event_context(writer_event, event_context);
- goto end;
- }
-
- dbg_info_src = lookup_debug_info(err, event, debug_info);
-
- nr_fields = bt_field_class_structure_get_field_count(writer_event_context_class);
- for (i = 0; i < nr_fields; i++) {
- const char *field_name;
-
- if (bt_field_class_structure_get_field_by_index(writer_event_context_class,
- &field_name, &field_class, i) < 0) {
- BT_LOGE("Failed to get field from event-context: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- /*
- * Prevent illegal access in the event_context.
- */
- if (i < bt_field_class_structure_get_field_count(event_context_class)) {
- field = bt_field_structure_get_field_by_index(event_context, i);
- }
- /*
- * The debug_info field, only exists in the writer event or
- * if it was set by a earlier pass of the debug_info plugin.
- */
- if (!strcmp(field_name, component->arg_debug_info_field_name) &&
- !field) {
- debug_field = bt_field_structure_get_field_by_index(
- writer_event_context, i);
- BT_ASSERT(debug_field);
-
- ret = set_debug_info_field(err, debug_field,
- dbg_info_src, component);
- if (ret) {
- BT_LOGE_STR("Failed to set debug_info field.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(debug_field);
- } else {
- copy_field = bt_field_copy(field);
- if (!copy_field) {
- BT_LOGE("Failed to copy field: field-name=\"%s\"",
- field_name);
- goto error;
- }
-
- ret = bt_field_structure_set_field_by_name(
- writer_event_context,
- field_name, copy_field);
- if (ret) {
- BT_LOGE("Failed to set field: field-name=\"%s\"",
- field_name);
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- }
- BT_FIELD_CLASS_PUT_REF_AND_RESET(field_class);
- BT_OBJECT_PUT_REF_AND_RESET(field);
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_field_class_put_ref(event_context_class);
- bt_field_class_put_ref(writer_event_context_class);
- bt_object_put_ref(writer_event_context);
- bt_object_put_ref(field);
- bt_object_put_ref(copy_field);
- bt_object_put_ref(debug_field);
- bt_field_class_put_ref(field_class);
- return ret;
-}
-
-static
-const bt_clock_class *stream_class_get_clock_class(FILE *err,
- const bt_stream_class *stream_class)
-{
- const bt_trace *trace = NULL;
- const bt_clock_class *clock_class = NULL;
-
- trace = bt_stream_class_get_trace(stream_class);
- BT_ASSERT(trace);
-
- if (!bt_trace_get_clock_class_count(trace)) {
- /* No clock. */
- goto end;
- }
-
- /* FIXME multi-clock? */
- clock_class = bt_trace_get_clock_class_by_index(trace, 0);
-
- bt_trace_put_ref(trace);
-
-end:
- return clock_class;
-}
-
-static
-const bt_clock_class *event_get_clock_class(FILE *err, const bt_event *event)
-{
- const bt_event_class *event_class = NULL;
- const bt_stream_class *stream_class = NULL;
- const bt_clock_class *clock_class = NULL;
-
- event_class = bt_event_get_class(event);
- BT_ASSERT(event_class);
-
- stream_class = bt_event_class_get_stream_class(event_class);
- BT_ASSERT(stream_class);
-
- clock_class = stream_class_get_clock_class(err, stream_class);
- goto end;
-
-end:
- bt_stream_class_put_ref(stream_class);
- bt_event_class_put_ref(event_class);
- return clock_class;
-}
-
-static
-int set_event_clock_snapshot(FILE *err, const bt_event *event,
- const bt_event *writer_event)
-{
- const bt_clock_class *clock_class = NULL;
- bt_clock_snapshot *clock_snapshot = NULL;
- int ret = 0;
-
- clock_class = event_get_clock_class(err, event);
- if (!clock_class) {
- /* No clock on input trace. */
- goto end;
- }
-
- clock_snapshot = bt_event_get_clock_snapshot(event, clock_class);
- if (!clock_snapshot) {
- ret = 0;
- goto end;
- }
-
- /*
- * We share the same clocks, so we can assign the clock value to the
- * writer event.
- */
- ret = bt_event_set_clock_snapshot(writer_event, clock_snapshot);
- if (ret) {
- BT_LOGE_STR("Failed to set clock value.");
- goto error;
- }
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- bt_clock_class_put_ref(clock_class);
- bt_object_put_ref(clock_snapshot);
- return ret;
-}
-
-static
-const bt_event *debug_info_copy_event(FILE *err, const bt_event *event,
- const bt_event_class *writer_event_class,
- struct debug_info *debug_info,
- struct debug_info_component *component)
-{
- const bt_event *writer_event = NULL;
- const bt_field *field = NULL, *copy_field = NULL;
- int ret;
-
- writer_event = bt_event_create(writer_event_class);
- if (!writer_event) {
- BT_LOGE_STR("Failed to create new event.");
- goto error;
- }
-
- ret = set_event_clock_snapshot(err, event, writer_event);
- if (ret) {
- BT_LOGE_STR("Failed to set clock value.");
- goto error;
- }
-
- /* Optional field, so it can fail silently. */
- field = bt_event_get_header(event);
- if (field) {
- ret = ctf_copy_event_header(err, event, writer_event_class,
- writer_event, field);
- if (ret) {
- BT_LOGE_STR("Failed to copy event header.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- }
-
- /* Optional field, so it can fail silently. */
- field = bt_event_get_stream_event_context(event);
- if (field) {
- ret = copy_set_debug_info_stream_event_context(err,
- field, event, writer_event, debug_info,
- component);
- if (ret < 0) {
- BT_LOGE_STR("Failed to debug_info stream event context.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
- }
-
- /* Optional field, so it can fail silently. */
- field = bt_event_get_event_context(event);
- if (field) {
- copy_field = bt_field_copy(field);
- if (!copy_field) {
- BT_LOGE_STR("Failed to copy field.");
- goto error;
- }
- ret = bt_event_set_event_context(writer_event, copy_field);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set event_context.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- BT_OBJECT_PUT_REF_AND_RESET(field);
- }
-
- field = bt_event_get_event_payload(event);
- BT_ASSERT(field);
-
- copy_field = bt_field_copy(field);
- if (copy_field) {
- ret = bt_event_set_event_payload(writer_event, copy_field);
- if (ret < 0) {
- BT_LOGE_STR("Failed to set event payload.");
- goto error;
- }
- BT_OBJECT_PUT_REF_AND_RESET(copy_field);
- }
- BT_OBJECT_PUT_REF_AND_RESET(field);
-
- goto end;
-
-error:
- BT_OBJECT_PUT_REF_AND_RESET(writer_event);
-end:
- bt_object_put_ref(copy_field);
- bt_object_put_ref(field);
- return writer_event;
-}
-
-BT_HIDDEN
-const bt_event *debug_info_output_event(
- struct debug_info_iterator *debug_it,
- const bt_event *event)
-{
- const bt_event_class *event_class = NULL, *writer_event_class = NULL;
- const bt_stream_class *stream_class = NULL, *writer_stream_class = NULL;
- const bt_event *writer_event = NULL;
- const bt_packet *packet = NULL, *writer_packet = NULL;
- const bt_trace *writer_trace = NULL;
- const bt_stream *stream = NULL;
- struct debug_info_trace *di_trace;
- struct debug_info *debug_info;
- int int_ret;
-
- event_class = bt_event_get_class(event);
- BT_ASSERT(event_class);
-
- stream_class = bt_event_class_get_stream_class(event_class);
- BT_ASSERT(stream_class);
-
- stream = bt_event_get_stream(event);
- BT_ASSERT(stream);
-
- di_trace = lookup_di_trace_from_stream(debug_it, stream);
- if (!di_trace) {
- BT_LOGE_STR("Failed to find existing trace from stream.");
- goto error;
- }
-
- writer_stream_class = g_hash_table_lookup(
- di_trace->stream_class_map,
- (gpointer) stream_class);
- if (!writer_stream_class) {
- BT_LOGE_STR("Failed to find existing stream_class.");
- goto error;
- }
- bt_stream_class_get_ref(writer_stream_class);
- writer_trace = bt_stream_class_get_trace(writer_stream_class);
- BT_ASSERT(writer_trace);
- writer_event_class = get_event_class(debug_it,
- writer_stream_class, event_class);
- if (!writer_event_class) {
- writer_event_class = ctf_copy_event_class(debug_it->err,
- writer_trace, event_class);
- if (!writer_event_class) {
- BT_LOGE_STR("Failed to copy event_class.");
- goto error;
- }
- int_ret = bt_stream_class_add_event_class(
- writer_stream_class, writer_event_class);
- if (int_ret) {
- BT_LOGE_STR("Failed to add event_class.");
- goto error;
- }
- }
-
- debug_info = get_trace_debug_info(debug_it, writer_trace, di_trace);
- if (debug_info) {
- debug_info_handle_event(debug_it->err, event, debug_info);
- }
-
- writer_event = debug_info_copy_event(debug_it->err, event,
- writer_event_class, debug_info,
- debug_it->debug_info_component);
- if (!writer_event) {
- BT_LOGE("Failed to copy event: event-class-name=\"%s\"",
- bt_event_class_get_name(writer_event_class));
- goto error;
- }
-
- packet = bt_event_get_packet(event);
- BT_ASSERT(packet);
-
- writer_packet = lookup_packet(debug_it, packet, di_trace);
- if (!writer_packet) {
- BT_LOGE_STR("Failed to find existing packet.");
- goto error;
- }
- bt_packet_get_ref(writer_packet);
-
- int_ret = bt_event_set_packet(writer_event, writer_packet);
- if (int_ret < 0) {
- BT_LOGE("Failed to append event to event-class-name=\"%s\"",
- bt_event_class_get_name(writer_event_class));
- goto error;
- }
-
- /* Keep the reference on the writer event */
- goto end;
-
-error:
- BT_OBJECT_PUT_REF_AND_RESET(writer_event);
-
-end:
- bt_stream_put_ref(stream);
- bt_trace_put_ref(writer_trace);
- bt_packet_put_ref(writer_packet);
- bt_packet_put_ref(packet);
- bt_event_class_put_ref(writer_event_class);
- bt_stream_class_put_ref(writer_stream_class);
- bt_stream_class_put_ref(stream_class);
- bt_event_class_put_ref(event_class);
- return writer_event;
-}
+++ /dev/null
-#ifndef BABELTRACE_PLUGIN_TRIMMER_COPY_H
-#define BABELTRACE_PLUGIN_TRIMMER_COPY_H
-
-/*
- * BabelTrace - Copy Trace Structure
- *
- * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * Author: Julien Desfossez <jdesfossez@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/babeltrace.h>
-
-BT_HIDDEN
-const bt_event *debug_info_output_event(struct debug_info_iterator *debug_it,
- const bt_event *event);
-BT_HIDDEN
-const bt_packet *debug_info_new_packet(struct debug_info_iterator *debug_it,
- const bt_packet *packet);
-BT_HIDDEN
-const bt_packet *debug_info_close_packet(struct debug_info_iterator *debug_it,
- const bt_packet *packet);
-BT_HIDDEN
-const bt_stream *debug_info_stream_begin(
- struct debug_info_iterator *debug_it,
- const bt_stream *stream);
-BT_HIDDEN
-const bt_stream *debug_info_stream_end(struct debug_info_iterator *debug_it,
- const bt_stream *stream);
-
-BT_HIDDEN
-int get_stream_event_context_unsigned_int_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint64_t *value);
-BT_HIDDEN
-int get_stream_event_context_int_field_value(FILE *err, const bt_event *event,
- const char *field_name, int64_t *value);
-BT_HIDDEN
-int get_payload_unsigned_int_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint64_t *value);
-BT_HIDDEN
-int get_payload_int_field_value(FILE *err, const bt_event *event,
- const char *field_name, int64_t *value);
-BT_HIDDEN
-int get_payload_string_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- const char **value);
-BT_HIDDEN
-int get_payload_build_id_field_value(FILE *err,
- const bt_event *event, const char *field_name,
- uint8_t **build_id, uint64_t *build_id_len);
-
-#endif /* BABELTRACE_PLUGIN_TRIMMER_COPY_H */
* Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
* Copyright (c) 2015 Antoine Busque <abusque@efficios.com>
* Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
#define BT_LOG_TAG "PLUGIN-CTF-LTTNG-UTILS-DEBUG-INFO-FLT"
#include "logging.h"
-#include <babeltrace/assert-internal.h>
#include <glib.h>
-#include "debug-info.h"
+#include <plugins-common.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/common-internal.h>
+
#include "bin-info.h"
+#include "debug-info.h"
+#include "trace-ir-data-copy.h"
+#include "trace-ir-mapping.h"
+#include "trace-ir-metadata-copy.h"
#include "utils.h"
-#include "copy.h"
+
+#define DEFAULT_DEBUG_INFO_FIELD_NAME "debug_info"
+#define LTTNG_UST_STATEDUMP_PREFIX "lttng_ust"
+#define VPID_FIELD_NAME "vpid"
+#define IP_FIELD_NAME "ip"
+#define BADDR_FIELD_NAME "baddr"
+#define CRC32_FIELD_NAME "crc"
+#define BUILD_ID_FIELD_NAME "build_id"
+#define FILENAME_FIELD_NAME "filename"
+#define IS_PIC_FIELD_NAME "is_pic"
+#define MEMSZ_FIELD_NAME "memsz"
+#define PATH_FIELD_NAME "path"
+
+struct debug_info_component {
+ char *arg_debug_info_field_name;
+ const char *arg_debug_dir;
+ bool arg_full_path;
+ const char *arg_target_prefix;
+};
+
+struct debug_info_msg_iter {
+ struct debug_info_component *debug_info_component;
+ bt_self_message_iterator *input_iterator;
+ bt_self_component *self_comp;
+ bt_self_component_port_input_message_iterator *msg_iter;
+
+ struct trace_ir_maps *ir_maps;
+ /* in_trace -> debug_info_mapping. */
+ GHashTable *debug_info_map;
+};
+
+struct debug_info_source {
+ /* Strings are owned by debug_info_source. */
+ char *func;
+ /*
+ * Store the line number as a string so that the allocation and
+ * conversion to string is only done once.
+ */
+ char *line_no;
+ char *src_path;
+ /* short_src_path points inside src_path, no need to free. */
+ const char *short_src_path;
+ char *bin_path;
+ /* short_bin_path points inside bin_path, no need to free. */
+ const char *short_bin_path;
+ /*
+ * Location within the binary. Either absolute (@0x1234) or
+ * relative (+0x4321).
+ */
+ char *bin_loc;
+};
struct proc_debug_info_sources {
/*
struct debug_info {
struct debug_info_component *comp;
+ const bt_trace *input_trace;
+ uint64_t destruction_listener_id;
/*
* Hash table of VPIDs (pointer to int64_t) to
info->q_statedump_bin_info = g_quark_from_string(
"lttng_ust_statedump:bin_info");
info->q_statedump_debug_link = g_quark_from_string(
- "lttng_ust_statedump:debug_link)");
+ "lttng_ust_statedump:debug_link");
info->q_statedump_build_id = g_quark_from_string(
"lttng_ust_statedump:build_id");
info->q_statedump_start = g_quark_from_string(
}
free(debug_info_src->func);
+ free(debug_info_src->line_no);
free(debug_info_src->src_path);
free(debug_info_src->bin_path);
free(debug_info_src->bin_loc);
}
static
-struct debug_info_source *debug_info_source_create_from_bin(struct bin_info *bin,
- uint64_t ip)
+struct debug_info_source *debug_info_source_create_from_bin(
+ struct bin_info *bin, uint64_t ip)
{
int ret;
struct debug_info_source *debug_info_src = NULL;
if (!bin->is_elf_only || !debug_info_src->func) {
/* Lookup source location */
ret = bin_info_lookup_source_location(bin, ip, &src_loc);
- BT_LOGD("Failed to lookup source location: ret=%d", ret);
+ if (ret) {
+ BT_LOGD("Failed to lookup source location: ret=%d", ret);
+ }
}
if (src_loc) {
- debug_info_src->line_no = src_loc->line_no;
+ ret = asprintf(&debug_info_src->line_no, "%"PRId64, src_loc->line_no);
+ if (ret == -1) {
+ BT_LOGD("Error occured when setting line_no field.");
+ goto error;
+ }
if (src_loc->filename) {
debug_info_src->src_path = strdup(src_loc->filename);
debug_info_src->short_src_path = get_filename_from_path(
debug_info_src->src_path);
}
-
source_location_destroy(src_loc);
}
return proc_dbg_info_src;
}
+static inline
+const bt_field *event_borrow_payload_field(const bt_event *event,
+ const char *field_name)
+{
+ const bt_field *event_payload, *field;
+
+ event_payload = bt_event_borrow_payload_field_const(event);
+ BT_ASSERT(event_payload);
+
+ field = bt_field_structure_borrow_member_field_by_name_const(
+ event_payload, field_name);
+ return field;
+}
+
+static inline
+const bt_field *event_borrow_common_context_field(const bt_event *event,
+ const char *field_name)
+{
+ const bt_field *event_common_ctx, *field = NULL;
+
+ event_common_ctx = bt_event_borrow_common_context_field_const(event);
+ if (!event_common_ctx) {
+ goto end;
+ }
+
+ field = bt_field_structure_borrow_member_field_by_name_const(
+ event_common_ctx, field_name);
+
+end:
+ return field;
+}
+
+static inline
+void event_get_common_context_signed_integer_field_value(
+ const bt_event *event, const char *field_name, int64_t *value)
+{
+ *value = bt_field_signed_integer_get_value(
+ event_borrow_common_context_field(event, field_name));
+}
+
+static inline
+int event_get_payload_build_id_length(const bt_event *event,
+ const char *field_name, uint64_t *build_id_len)
+{
+ const bt_field *build_id_field;
+ const bt_field_class *build_id_field_class;
+
+ build_id_field = event_borrow_payload_field(event, field_name);
+ build_id_field_class = bt_field_borrow_class_const(build_id_field);
+
+ BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
+ BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
+ BT_ASSERT(bt_field_class_get_type(
+ bt_field_class_array_borrow_element_field_class_const(
+ build_id_field_class)) ==
+ BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
+
+ *build_id_len = bt_field_array_get_length(build_id_field);
+
+ return 0;
+}
+
+static inline
+int event_get_payload_build_id_value(const bt_event *event,
+ const char *field_name, uint8_t *build_id)
+{
+ const bt_field *curr_field, *build_id_field;
+ const bt_field_class *build_id_field_class;
+ uint64_t i, build_id_len;
+ int ret;
+
+ ret = 0;
+
+ build_id_field = event_borrow_payload_field(event, field_name);
+ build_id_field_class = bt_field_borrow_class_const(build_id_field);
+
+ BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
+ BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
+ BT_ASSERT(bt_field_class_get_type(
+ bt_field_class_array_borrow_element_field_class_const(
+ build_id_field_class)) ==
+ BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
+
+ build_id_len = bt_field_array_get_length(build_id_field);
+
+ for (i = 0; i < build_id_len; i++) {
+ curr_field =
+ bt_field_array_borrow_element_field_by_index_const(
+ build_id_field, i);
+
+ build_id[i] = bt_field_unsigned_integer_get_value(curr_field);
+ }
+
+ return ret;
+}
+
+static
+void event_get_payload_unsigned_integer_field_value(const bt_event *event,
+ const char *field_name, uint64_t *value)
+{
+ *value = bt_field_unsigned_integer_get_value(
+ event_borrow_payload_field(event, field_name));
+}
+
+static
+void event_get_payload_string_field_value(const bt_event *event,
+ const char *field_name, const char **value)
+{
+ *value = bt_field_string_get_value(
+ event_borrow_payload_field(event, field_name));
+}
+
+static inline
+bool event_has_payload_field(const bt_event *event,
+ const char *field_name)
+{
+ return event_borrow_payload_field(event, field_name) != NULL;
+}
+
static
struct debug_info_source *proc_debug_info_sources_get_entry(
struct proc_debug_info_sources *proc_dbg_info_src, uint64_t ip)
}
BT_HIDDEN
-struct debug_info *debug_info_create(struct debug_info_component *comp)
+struct debug_info *debug_info_create(struct debug_info_component *comp,
+ const bt_trace *trace)
{
int ret;
struct debug_info *debug_info;
goto error;
}
+ debug_info->input_trace = trace;
+
end:
return debug_info;
error:
BT_HIDDEN
void debug_info_destroy(struct debug_info *debug_info)
{
+ bt_trace_status status;
if (!debug_info) {
goto end;
}
g_hash_table_destroy(debug_info->vpid_to_proc_dbg_info_src);
}
+ status = bt_trace_remove_destruction_listener(debug_info->input_trace,
+ debug_info->destruction_listener_id);
+
g_free(debug_info);
end:
return;
}
static
-void handle_statedump_build_id_event(FILE *err, struct debug_info *debug_info,
+void handle_event_statedump_build_id(struct debug_info *debug_info,
const bt_event *event)
{
struct proc_debug_info_sources *proc_dbg_info_src;
- struct bin_info *bin = NULL;
- int ret;
+ uint64_t build_id_len, baddr;
+ uint8_t *build_id = NULL;
+ struct bin_info *bin;
int64_t vpid;
- uint64_t baddr;
- uint64_t build_id_len;
-
- ret = get_stream_event_context_int_field_value(err,
- event, VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
+ int ret = 0;
- ret = get_payload_unsigned_int_field_value(err,
- event, BADDR_FIELD_NAME, &baddr);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- VPID_FIELD_NAME " field.");
- goto end;
- }
+ event_get_common_context_signed_integer_field_value(event,
+ VPID_FIELD_NAME, &vpid);
+ event_get_payload_unsigned_integer_field_value(event,
+ BADDR_FIELD_NAME, &baddr);
proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
debug_info->vpid_to_proc_dbg_info_src, vpid);
*/
goto end;
}
+ ret = event_get_payload_build_id_length(event, BUILD_ID_FIELD_NAME,
+ &build_id_len);
+
+ build_id = g_new0(uint8_t, build_id_len);
+ if (!build_id) {
+ goto end;
+ }
- ret = get_payload_build_id_field_value(err, event, BUILD_ID_FIELD_NAME,
- &bin->build_id, &build_id_len);
+ ret = event_get_payload_build_id_value(event, BUILD_ID_FIELD_NAME,
+ build_id);
if (ret) {
- BT_LOGE_STR("Failed to get " BUILD_ID_FIELD_NAME
- " field value.");
goto end;
}
- if (build_id_len > SIZE_MAX) {
- bin->build_id_len = (size_t) build_id_len;
+
+ ret = bin_info_set_build_id(bin, build_id, build_id_len);
+ if (ret) {
+ goto end;
}
/*
*/
bin->is_elf_only = false;
- // TODO
- // bin_info_set_build_id(bin, build_id, build_id_len);
-
end:
+ g_free(build_id);
return;
}
static
-void handle_statedump_debug_link_event(FILE *err, struct debug_info *debug_info,
+void handle_event_statedump_debug_link(struct debug_info *debug_info,
const bt_event *event)
{
struct proc_debug_info_sources *proc_dbg_info_src;
uint64_t baddr;
const char *filename = NULL;
uint32_t crc32;
- uint64_t tmp;
- int ret;
+ uint64_t crc_field_value;
- ret = get_stream_event_context_int_field_value(err, event,
+ event_get_common_context_signed_integer_field_value(event,
VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
- ret = get_payload_unsigned_int_field_value(err,
- event, BADDR_FIELD_NAME, &baddr);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- BADDR_FIELD_NAME " field.");
- ret = -1;
- goto end;
- }
+ event_get_payload_unsigned_integer_field_value(event,
+ BADDR_FIELD_NAME, &baddr);
- ret = get_payload_unsigned_int_field_value(err, event, CRC32_FIELD_NAME,
- &tmp);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- CRC32_FIELD_NAME " field.");
- ret = -1;
- goto end;
- }
- crc32 = (uint32_t) tmp;
+ event_get_payload_unsigned_integer_field_value(event,
+ CRC32_FIELD_NAME, &crc_field_value);
- ret = get_payload_string_field_value(err,
- event, FILENAME_FIELD_NAME, &filename);
- if (ret) {
- BT_LOGE_STR("Failed to get string value for "
- FILENAME_FIELD_NAME " field.");
- ret = -1;
- goto end;
- }
+ crc32 = (uint32_t) crc_field_value;
+
+ event_get_payload_string_field_value(event,
+ FILENAME_FIELD_NAME, &filename);
proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
debug_info->vpid_to_proc_dbg_info_src, vpid);
}
static
-void handle_bin_info_event(FILE *err, struct debug_info *debug_info,
+void handle_bin_info_event(struct debug_info *debug_info,
const bt_event *event, bool has_pic_field)
{
struct proc_debug_info_sources *proc_dbg_info_src;
const char *path;
gpointer key = NULL;
bool is_pic;
- int ret;
- ret = get_payload_unsigned_int_field_value(err,
- event, BADDR_FIELD_NAME, &baddr);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- BADDR_FIELD_NAME " field.");
+ event_get_payload_unsigned_integer_field_value(event,
+ MEMSZ_FIELD_NAME, &memsz);
+ if (memsz == 0) {
+ /* Ignore VDSO. */
goto end;
}
- ret = get_payload_unsigned_int_field_value(err,
- event, MEMSZ_FIELD_NAME, &memsz);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- MEMSZ_FIELD_NAME " field.");
- goto end;
- }
+ event_get_payload_unsigned_integer_field_value(event,
+ BADDR_FIELD_NAME, &baddr);
/*
* This field is not produced by the dlopen event emitted before
* lttng-ust 2.9.
*/
- ret = get_payload_string_field_value(err,
- event, PATH_FIELD_NAME, &path);
- if (ret || !path) {
+ if (!event_has_payload_field(event, PATH_FIELD_NAME)) {
goto end;
}
+ event_get_payload_string_field_value(event, PATH_FIELD_NAME, &path);
if (has_pic_field) {
- uint64_t tmp;
+ uint64_t is_pic_field_value;
- ret = get_payload_unsigned_int_field_value(err,
- event, IS_PIC_FIELD_NAME, &tmp);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- IS_PIC_FIELD_NAME " field.");
- ret = -1;
- goto end;
- }
- is_pic = (tmp == 1);
+ event_get_payload_unsigned_integer_field_value(event,
+ IS_PIC_FIELD_NAME, &is_pic_field_value);
+ is_pic = is_pic_field_value == 1;
} else {
/*
* dlopen has no is_pic field, because the shared
is_pic = true;
}
- ret = get_stream_event_context_int_field_value(err, event,
+ event_get_common_context_signed_integer_field_value(event,
VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
-
- if (memsz == 0) {
- /* Ignore VDSO. */
- goto end;
- }
proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
debug_info->vpid_to_proc_dbg_info_src, vpid);
}
static inline
-void handle_statedump_bin_info_event(FILE *err, struct debug_info *debug_info,
+void handle_event_statedump_bin_info(struct debug_info *debug_info,
const bt_event *event)
{
- handle_bin_info_event(err, debug_info, event, true);
+ handle_bin_info_event(debug_info, event, true);
}
static inline
-void handle_lib_load_event(FILE *err, struct debug_info *debug_info,
+void handle_event_lib_load(struct debug_info *debug_info,
const bt_event *event)
{
- handle_bin_info_event(err, debug_info, event, false);
+ handle_bin_info_event(debug_info, event, false);
}
-static inline
-void handle_lib_unload_event(FILE *err, struct debug_info *debug_info,
+static
+void handle_event_lib_unload(struct debug_info *debug_info,
const bt_event *event)
{
+ gboolean ret;
struct proc_debug_info_sources *proc_dbg_info_src;
uint64_t baddr;
int64_t vpid;
- gpointer key_ptr = NULL;
- int ret;
- ret = get_payload_unsigned_int_field_value(err,
- event, BADDR_FIELD_NAME, &baddr);
- if (ret) {
- BT_LOGE_STR("Failed to get unsigned int value for "
- BADDR_FIELD_NAME " field.");
- ret = -1;
- goto end;
- }
+ event_get_payload_unsigned_integer_field_value(event, BADDR_FIELD_NAME,
+ &baddr);
- ret = get_stream_event_context_int_field_value(err, event,
- VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
+ event_get_common_context_signed_integer_field_value(event,
+ VPID_FIELD_NAME, &vpid);
proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
debug_info->vpid_to_proc_dbg_info_src, vpid);
if (!proc_dbg_info_src) {
+ /*
+ * It's an unload event for a library for which no load event
+ * was previously received.
+ */
goto end;
}
- key_ptr = (gpointer) &baddr;
- (void) g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
- key_ptr);
+ ret = g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
+ (gpointer) &baddr);
+ BT_ASSERT(ret);
end:
return;
}
static
-void handle_statedump_start(FILE *err, struct debug_info *debug_info,
+void handle_event_statedump_start(struct debug_info *debug_info,
const bt_event *event)
{
struct proc_debug_info_sources *proc_dbg_info_src;
int64_t vpid;
- int ret;
- ret = get_stream_event_context_int_field_value(err, event,
- VPID_FIELD_NAME, &vpid);
- if (ret) {
- goto end;
- }
+ event_get_common_context_signed_integer_field_value(
+ event, VPID_FIELD_NAME, &vpid);
proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
debug_info->vpid_to_proc_dbg_info_src, vpid);
return;
}
-BT_HIDDEN
-void debug_info_handle_event(FILE *err, const bt_event *event,
- struct debug_info *debug_info)
+void trace_debug_info_remove_func(const bt_trace *in_trace, void *data)
+{
+ struct debug_info_msg_iter *debug_it = data;
+ if (debug_it->debug_info_map) {
+ gboolean ret;
+ ret = g_hash_table_remove(debug_it->debug_info_map,
+ (gpointer) in_trace);
+ BT_ASSERT(ret);
+ }
+}
+
+static
+void handle_event_statedump(struct debug_info_msg_iter *debug_it,
+ const bt_event *event)
{
const bt_event_class *event_class;
const char *event_name;
GQuark q_event_name;
+ const bt_trace *trace;
+ struct debug_info *debug_info;
+
+ BT_ASSERT(debug_it);
+ BT_ASSERT(event);
+
+ event_class = bt_event_borrow_class_const(event);
- if (!debug_info || !event) {
- goto end;
- }
- event_class = bt_event_get_class(event);
- if (!event_class) {
- goto end;
- }
event_name = bt_event_class_get_name(event_class);
- if (!event_name) {
- goto end_put_class;
+
+ trace = bt_stream_borrow_trace_const(
+ bt_event_borrow_stream_const(event));
+
+ debug_info = g_hash_table_lookup(debug_it->debug_info_map, trace);
+ if (!debug_info) {
+ debug_info = debug_info_create(debug_it->debug_info_component,
+ trace);
+ g_hash_table_insert(debug_it->debug_info_map, (gpointer) trace,
+ debug_info);
+ bt_trace_add_destruction_listener(trace,
+ trace_debug_info_remove_func, debug_it,
+ &debug_info->destruction_listener_id);
}
+
q_event_name = g_quark_try_string(event_name);
if (q_event_name == debug_info->q_statedump_bin_info) {
/* State dump */
- handle_statedump_bin_info_event(err, debug_info, event);
+ handle_event_statedump_bin_info(debug_info, event);
} else if (q_event_name == debug_info->q_dl_open ||
q_event_name == debug_info->q_lib_load) {
/*
* of the dlopen family are called (e.g. dlmopen) and when
* library are transitively loaded.
*/
- handle_lib_load_event(err, debug_info, event);
+ handle_event_lib_load(debug_info, event);
} else if (q_event_name == debug_info->q_statedump_start) {
/* Start state dump */
- handle_statedump_start(err, debug_info, event);
+ handle_event_statedump_start(debug_info, event);
} else if (q_event_name == debug_info->q_statedump_debug_link) {
/* Debug link info */
- handle_statedump_debug_link_event(err, debug_info, event);
+ handle_event_statedump_debug_link(debug_info, event);
} else if (q_event_name == debug_info->q_statedump_build_id) {
/* Build ID info */
- handle_statedump_build_id_event(err, debug_info, event);
+ handle_event_statedump_build_id(debug_info, event);
} else if (q_event_name == debug_info-> q_lib_unload) {
- handle_lib_unload_event(err, debug_info, event);
+ handle_event_lib_unload(debug_info, event);
+ }
+
+ return;
+}
+
+static
+void destroy_debug_info_comp(struct debug_info_component *debug_info)
+{
+ free(debug_info->arg_debug_info_field_name);
+ g_free(debug_info);
+}
+
+static
+void fill_debug_info_bin_field(struct debug_info_source *dbg_info_src,
+ bool full_path, bt_field *curr_field)
+{
+ bt_field_status status;
+
+ BT_ASSERT(bt_field_get_class_type(curr_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+
+ if (dbg_info_src) {
+ if (full_path) {
+ status = bt_field_string_set_value(curr_field,
+ dbg_info_src->bin_path);
+ } else {
+ status = bt_field_string_set_value(curr_field,
+ dbg_info_src->short_bin_path);
+ }
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set path component of \"bin\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+
+ status = bt_field_string_append(curr_field, ":");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set colon component of \"bin\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+
+ status = bt_field_string_append(curr_field, dbg_info_src->bin_loc);
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set bin location component of \"bin\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+ } else {
+ status = bt_field_string_set_value(curr_field, "");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"bin\" curr_field field's value: "
+ "str-fc-addr=%p", curr_field);
+ }
+ }
+}
+
+static
+void fill_debug_info_func_field(struct debug_info_source *dbg_info_src,
+ bt_field *curr_field)
+{
+ bt_field_status status;
+
+ BT_ASSERT(bt_field_get_class_type(curr_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+ if (dbg_info_src && dbg_info_src->func) {
+ status = bt_field_string_set_value(curr_field,
+ dbg_info_src->func);
+ } else {
+ status = bt_field_string_set_value(curr_field, "");
+ }
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"func\" curr_field field's value: "
+ "str-fc-addr=%p", curr_field);
+ }
+}
+
+static
+void fill_debug_info_src_field(struct debug_info_source *dbg_info_src,
+ bool full_path, bt_field *curr_field)
+{
+ bt_field_status status;
+
+ BT_ASSERT(bt_field_get_class_type(curr_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+
+ if (dbg_info_src && dbg_info_src->src_path) {
+ if (full_path) {
+ status = bt_field_string_set_value(curr_field,
+ dbg_info_src->src_path);
+ } else {
+ status = bt_field_string_set_value(curr_field,
+ dbg_info_src->short_src_path);
+ }
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set path component of \"src\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+
+ status = bt_field_string_append(curr_field, ":");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set colon component of \"src\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+
+ status = bt_field_string_append(curr_field, dbg_info_src->line_no);
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set line number component of \"src\" "
+ "curr_field field's value: str-fc-addr=%p",
+ curr_field);
+ }
+ } else {
+ status = bt_field_string_set_value(curr_field, "");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"src\" curr_field field's value: "
+ "str-fc-addr=%p", curr_field);
+ }
+ }
+}
+
+void fill_debug_info_field_empty(bt_field *debug_info_field)
+{
+ bt_field_status status;
+ bt_field *bin_field, *func_field, *src_field;
+
+ BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
+ BT_FIELD_CLASS_TYPE_STRUCTURE);
+
+ bin_field = bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "bin");
+ func_field = bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "func");
+ src_field = bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "src");
+
+ BT_ASSERT(bt_field_get_class_type(bin_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+ BT_ASSERT(bt_field_get_class_type(func_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+ BT_ASSERT(bt_field_get_class_type(src_field) ==
+ BT_FIELD_CLASS_TYPE_STRING);
+
+ status = bt_field_string_set_value(bin_field, "");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"bin\" bin_field field's value: "
+ "str-fc-addr=%p", bin_field);
+ }
+
+ status = bt_field_string_set_value(func_field, "");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"func\" func_field field's value: "
+ "str-fc-addr=%p", func_field);
+ }
+
+ status = bt_field_string_set_value(src_field, "");
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set \"src\" src_field field's value: "
+ "str-fc-addr=%p", src_field);
+ }
+}
+static
+void fill_debug_info_field(struct debug_info *debug_info, int64_t vpid,
+ uint64_t ip, bt_field *debug_info_field)
+{
+ struct debug_info_source *dbg_info_src;
+ const bt_field_class *debug_info_fc;
+
+ BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
+ BT_FIELD_CLASS_TYPE_STRUCTURE);
+
+ debug_info_fc = bt_field_borrow_class_const(debug_info_field);
+
+ BT_ASSERT(bt_field_class_structure_get_member_count(debug_info_fc) == 3);
+
+ dbg_info_src = debug_info_query(debug_info, vpid, ip);
+
+ fill_debug_info_bin_field(dbg_info_src, debug_info->comp->arg_full_path,
+ bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "bin"));
+ fill_debug_info_func_field(dbg_info_src,
+ bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "func"));
+ fill_debug_info_src_field(dbg_info_src, debug_info->comp->arg_full_path,
+ bt_field_structure_borrow_member_field_by_name(
+ debug_info_field, "src"));
+}
+
+static
+void fill_debug_info_event_if_needed(struct debug_info_msg_iter *debug_it,
+ const bt_event *in_event, bt_event *out_event)
+{
+ bt_field *out_common_ctx_field, *out_debug_info_field;
+ const bt_field *vpid_field, *ip_field, *in_common_ctx_field;
+ const bt_field_class *in_common_ctx_fc;
+ struct debug_info *debug_info;
+ uint64_t vpid;
+ int64_t ip;
+ char *debug_info_field_name =
+ debug_it->debug_info_component->arg_debug_info_field_name;
+
+ in_common_ctx_field = bt_event_borrow_common_context_field_const(
+ in_event);
+ if (!in_common_ctx_field) {
+ /*
+ * There is no event common context so no need to add debug
+ * info field.
+ */
+ goto end;
+ }
+
+ in_common_ctx_fc = bt_field_borrow_class_const(in_common_ctx_field);
+ if (!is_event_common_ctx_dbg_info_compatible(in_common_ctx_fc,
+ debug_it->ir_maps->debug_info_field_class_name)) {
+ /*
+ * The input event common context does not have the necessary
+ * fields to resolve debug information.
+ */
+ goto end;
+ }
+
+ /* Borrow the debug-info field. */
+ out_common_ctx_field = bt_event_borrow_common_context_field(out_event);
+ if (!out_common_ctx_field) {
+ goto end;
}
-end_put_class:
- bt_event_class_put_ref(event_class);
+ out_debug_info_field = bt_field_structure_borrow_member_field_by_name(
+ out_common_ctx_field, debug_info_field_name);
+
+ vpid_field = bt_field_structure_borrow_member_field_by_name_const(
+ out_common_ctx_field, VPID_FIELD_NAME);
+ ip_field = bt_field_structure_borrow_member_field_by_name_const(
+ out_common_ctx_field, IP_FIELD_NAME);
+
+ vpid = bt_field_signed_integer_get_value(vpid_field);
+ ip = bt_field_unsigned_integer_get_value(ip_field);
+
+ /*
+ * Borrow the debug_info structure needed for the source
+ * resolving.
+ */
+ debug_info = g_hash_table_lookup(debug_it->debug_info_map,
+ bt_stream_borrow_trace_const(
+ bt_event_borrow_stream_const(in_event)));
+
+ if (debug_info) {
+ /*
+ * Perform the debug-info resolving and set the event fields
+ * accordingly.
+ */
+ fill_debug_info_field(debug_info, vpid, ip, out_debug_info_field);
+ } else {
+ BT_LOGD("No debug information for this trace. Setting debug "
+ "info fields to empty strings.");
+ fill_debug_info_field_empty(out_debug_info_field);
+ }
end:
return;
}
+
+static
+void update_event_statedump_if_needed(struct debug_info_msg_iter *debug_it,
+ const bt_event *in_event)
+{
+ const bt_field *event_common_ctx;
+ const bt_field_class *event_common_ctx_fc;
+ const bt_event_class *in_event_class = bt_event_borrow_class_const(in_event);
+
+ /*
+ * If the event is an lttng_ust_statedump event AND has the right event
+ * common context fields update the debug-info view for this process.
+ */
+ event_common_ctx = bt_event_borrow_common_context_field_const(in_event);
+ if (!event_common_ctx) {
+ goto end;
+ }
+
+ event_common_ctx_fc = bt_field_borrow_class_const(event_common_ctx);
+ if (is_event_common_ctx_dbg_info_compatible(event_common_ctx_fc,
+ debug_it->ir_maps->debug_info_field_class_name)) {
+ /* Checkout if it might be a one of lttng ust statedump events. */
+ const char *in_event_name = bt_event_class_get_name(in_event_class);
+ if (strncmp(in_event_name, LTTNG_UST_STATEDUMP_PREFIX,
+ strlen(LTTNG_UST_STATEDUMP_PREFIX)) == 0) {
+ /* Handle statedump events. */
+ handle_event_statedump(debug_it, in_event);
+ }
+ }
+end:
+ return;
+}
+
+static
+bt_message *handle_event_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *cs;
+ const bt_clock_class *default_cc;
+ const bt_packet *in_packet;
+ bt_clock_snapshot_state cs_state;
+ bt_event_class *out_event_class;
+ bt_packet *out_packet;
+ bt_event *out_event;
+
+ bt_message *out_message = NULL;
+
+ /* Borrow the input event and its event class. */
+ const bt_event *in_event =
+ bt_message_event_borrow_event_const(in_message);
+ const bt_event_class *in_event_class =
+ bt_event_borrow_class_const(in_event);
+
+ update_event_statedump_if_needed(debug_it, in_event);
+
+ out_event_class = trace_ir_mapping_borrow_mapped_event_class(
+ debug_it->ir_maps, in_event_class);
+ if (!out_event_class) {
+ out_event_class = trace_ir_mapping_create_new_mapped_event_class(
+ debug_it->ir_maps, in_event_class);
+ }
+ BT_ASSERT(out_event_class);
+
+ /* Borrow the input and output packets. */
+ in_packet = bt_event_borrow_packet_const(in_event);
+ out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps,
+ in_packet);
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_event_class_borrow_stream_class_const(in_event_class));
+ if (default_cc) {
+ /* Borrow event clock snapshot. */
+ cs_state =
+ bt_message_event_borrow_default_clock_snapshot_const(
+ in_message, &cs);
+
+ /* Create an output event message. */
+ BT_ASSERT (cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
+ out_message = bt_message_event_create_with_default_clock_snapshot(
+ debug_it->input_iterator,
+ out_event_class, out_packet,
+ bt_clock_snapshot_get_value(cs));
+ } else {
+ out_message = bt_message_event_create(debug_it->input_iterator,
+ out_event_class, out_packet);
+ }
+
+ if (!out_message) {
+ BT_LOGE("Error creating output event message.");
+ goto error;
+ }
+
+ out_event = bt_message_event_borrow_event(out_message);
+
+ /* Copy the original fields to the output event. */
+ copy_event_content(in_event, out_event);
+
+ /*
+ * Try to set the debug-info fields based on debug information that is
+ * gathered so far.
+ */
+ fill_debug_info_event_if_needed(debug_it, in_event, out_event);
+
+error:
+ return out_message;
+}
+
+static
+bt_message *handle_stream_begin_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_stream *in_stream;
+ bt_message *out_message;
+ bt_stream *out_stream;
+
+ in_stream = bt_message_stream_beginning_borrow_stream_const(in_message);
+ BT_ASSERT(in_stream);
+
+ /* Create a duplicated output stream. */
+ out_stream = trace_ir_mapping_create_new_mapped_stream(
+ debug_it->ir_maps, in_stream);
+ if (!out_stream) {
+ out_message = NULL;
+ goto error;
+ }
+
+ /* Create an output stream beginning message. */
+ out_message = bt_message_stream_beginning_create(
+ debug_it->input_iterator, out_stream);
+ if (!out_message) {
+ BT_LOGE("Error creating output stream beginning message: "
+ "out-s-addr=%p", out_stream);
+ }
+error:
+ return out_message;
+}
+
+static
+bt_message *handle_stream_end_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_stream *in_stream;
+ bt_message *out_message = NULL;
+ bt_stream *out_stream;
+
+ in_stream = bt_message_stream_end_borrow_stream_const(in_message);
+ BT_ASSERT(in_stream);
+
+ out_stream = trace_ir_mapping_borrow_mapped_stream(
+ debug_it->ir_maps, in_stream);
+ BT_ASSERT(out_stream);
+
+ /* Create an output stream end message. */
+ out_message = bt_message_stream_end_create(debug_it->input_iterator,
+ out_stream);
+ if (!out_message) {
+ BT_LOGE("Error creating output stream end message: out-s-addr=%p",
+ out_stream);
+ }
+
+ /* Remove stream from trace mapping hashtable. */
+ trace_ir_mapping_remove_mapped_stream(debug_it->ir_maps, in_stream);
+
+ return out_message;
+}
+
+static
+bt_message *handle_packet_begin_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_class *default_cc;
+ bt_clock_snapshot_state cs_state;
+ const bt_clock_snapshot *cs;
+ bt_message *out_message = NULL;
+ bt_packet *out_packet;
+
+ const bt_packet *in_packet =
+ bt_message_packet_beginning_borrow_packet_const(in_message);
+ BT_ASSERT(in_packet);
+
+ /* This packet should not be already mapped. */
+ BT_ASSERT(!trace_ir_mapping_borrow_mapped_packet(
+ debug_it->ir_maps, in_packet));
+
+ out_packet = trace_ir_mapping_create_new_mapped_packet(debug_it->ir_maps,
+ in_packet);
+
+ BT_ASSERT(out_packet);
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(
+ bt_packet_borrow_stream_const(in_packet)));
+ if (default_cc) {
+ /* Borrow clock snapshot. */
+ cs_state =
+ bt_message_packet_beginning_borrow_default_clock_snapshot_const(
+ in_message, &cs);
+
+ /* Create an output packet beginning message. */
+ BT_ASSERT(cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
+ out_message = bt_message_packet_beginning_create_with_default_clock_snapshot(
+ debug_it->input_iterator, out_packet,
+ bt_clock_snapshot_get_value(cs));
+ } else {
+ out_message = bt_message_packet_beginning_create(
+ debug_it->input_iterator, out_packet);
+ }
+ if (!out_message) {
+ BT_LOGE("Error creating output packet beginning message: "
+ "out-p-addr=%p", out_packet);
+ }
+
+ return out_message;
+}
+
+static
+bt_message *handle_packet_end_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *cs;
+ const bt_packet *in_packet;
+ const bt_clock_class *default_cc;
+ bt_clock_snapshot_state cs_state;
+ bt_message *out_message = NULL;
+ bt_packet *out_packet;
+
+ in_packet = bt_message_packet_end_borrow_packet_const(in_message);
+ BT_ASSERT(in_packet);
+
+ out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps, in_packet);
+ BT_ASSERT(out_packet);
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(
+ bt_packet_borrow_stream_const(in_packet)));
+ if (default_cc) {
+ /* Borrow clock snapshot. */
+ cs_state =
+ bt_message_packet_end_borrow_default_clock_snapshot_const(
+ in_message, &cs);
+
+ /* Create an outpute packet end message. */
+ BT_ASSERT(cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
+ out_message = bt_message_packet_end_create_with_default_clock_snapshot(
+ debug_it->input_iterator, out_packet,
+ bt_clock_snapshot_get_value(cs));
+ } else {
+ out_message = bt_message_packet_end_create(
+ debug_it->input_iterator, out_packet);
+ }
+
+ if (!out_message) {
+ BT_LOGE("Error creating output packet end message: "
+ "out-p-addr=%p", out_packet);
+ }
+
+ /* Remove packet from data mapping hashtable. */
+ trace_ir_mapping_remove_mapped_packet(debug_it->ir_maps, in_packet);
+
+ return out_message;
+}
+
+static
+bt_message *handle_msg_iterator_inactivity(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ /*
+ * This message type can be forwarded directly because it does
+ * not refer to any objects in the trace class.
+ */
+ bt_message_get_ref(in_message);
+ return (bt_message*) in_message;
+}
+
+static
+bt_message *handle_stream_act_begin_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *cs;
+ const bt_clock_class *default_cc;
+ bt_message *out_message = NULL;
+ bt_stream *out_stream;
+ uint64_t cs_value;
+ bt_message_stream_activity_clock_snapshot_state cs_state;
+
+ const bt_stream *in_stream =
+ bt_message_stream_activity_beginning_borrow_stream_const(
+ in_message);
+ BT_ASSERT(in_stream);
+
+ out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps,
+ in_stream);
+ BT_ASSERT(out_stream);
+
+ out_message = bt_message_stream_activity_beginning_create(
+ debug_it->input_iterator, out_stream);
+ if (!out_message) {
+ BT_LOGE("Error creating output stream activity beginning "
+ "message: out-s-addr=%p", out_stream);
+ goto error;
+ }
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(in_stream));
+ if (default_cc) {
+ /* Borrow clock snapshot. */
+ cs_state =
+ bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
+ in_message, &cs);
+
+ if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN) {
+ cs_value = bt_clock_snapshot_get_value(cs);
+ bt_message_stream_activity_beginning_set_default_clock_snapshot(
+ out_message, cs_value);
+ } else {
+ bt_message_stream_activity_beginning_set_default_clock_snapshot_state(
+ out_message, cs_state);
+ }
+ }
+
+error:
+ return out_message;
+}
+
+static
+bt_message *handle_stream_act_end_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *cs;
+ const bt_clock_class *default_cc;
+ const bt_stream *in_stream;
+ bt_message *out_message;
+ bt_stream *out_stream;
+ uint64_t cs_value;
+ bt_message_stream_activity_clock_snapshot_state cs_state;
+
+ in_stream = bt_message_stream_activity_end_borrow_stream_const(
+ in_message);
+ BT_ASSERT(in_stream);
+
+ out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps, in_stream);
+ BT_ASSERT(out_stream);
+
+ out_message = bt_message_stream_activity_end_create(
+ debug_it->input_iterator, out_stream);
+ if (!out_message) {
+ BT_LOGE("Error creating output stream activity end message: "
+ "out-s-addr=%p", out_stream);
+ goto error;
+ }
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(in_stream));
+
+ if (default_cc) {
+ cs_state =
+ bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
+ in_message, &cs);
+
+ if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN ) {
+ cs_value = bt_clock_snapshot_get_value(cs);
+ bt_message_stream_activity_end_set_default_clock_snapshot(
+ out_message, cs_value);
+ } else {
+ bt_message_stream_activity_end_set_default_clock_snapshot_state(
+ out_message, cs_state);
+ }
+ }
+
+error:
+ return out_message;
+}
+
+static
+bt_message *handle_discarded_events_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *begin_cs, *end_cs;
+ const bt_stream *in_stream;
+ const bt_clock_class *default_cc;
+ uint64_t discarded_events, begin_cs_value, end_cs_value;
+ bt_clock_snapshot_state begin_cs_state, end_cs_state;
+ bt_property_availability prop_avail;
+ bt_message *out_message = NULL;
+ bt_stream *out_stream;
+
+ in_stream = bt_message_discarded_events_borrow_stream_const(
+ in_message);
+ BT_ASSERT(in_stream);
+
+ out_stream = trace_ir_mapping_borrow_mapped_stream(
+ debug_it->ir_maps, in_stream);
+ BT_ASSERT(out_stream);
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(in_stream));
+ if (default_cc) {
+ begin_cs_state =
+ bt_message_discarded_events_borrow_default_beginning_clock_snapshot_const(
+ in_message, &begin_cs);
+ end_cs_state =
+ bt_message_discarded_events_borrow_default_end_clock_snapshot_const(
+ in_message, &end_cs);
+ /*
+ * Both clock snapshots should be known as we check that the
+ * all input stream classes have an always known clock. Unknown
+ * clock is not yet supported.
+ */
+ BT_ASSERT(begin_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN &&
+ end_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
+
+ begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
+ end_cs_value = bt_clock_snapshot_get_value(end_cs);
+
+ out_message =
+ bt_message_discarded_events_create_with_default_clock_snapshots(
+ debug_it->input_iterator, out_stream,
+ begin_cs_value, end_cs_value);
+ } else {
+ out_message = bt_message_discarded_events_create(
+ debug_it->input_iterator, out_stream);
+ }
+ if (!out_message) {
+ BT_LOGE("Error creating output discarded events message: "
+ "out-s-addr=%p", out_stream);
+ goto error;
+ }
+
+ prop_avail = bt_message_discarded_events_get_count(in_message,
+ &discarded_events);
+
+ if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
+ bt_message_discarded_events_set_count(out_message,
+ discarded_events);
+ }
+
+error:
+ return out_message;
+}
+
+static
+bt_message *handle_discarded_packets_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ const bt_clock_snapshot *begin_cs, *end_cs;
+ const bt_clock_class *default_cc;
+ const bt_stream *in_stream;
+ uint64_t discarded_packets, begin_cs_value, end_cs_value;
+ bt_clock_snapshot_state begin_cs_state, end_cs_state;
+ bt_property_availability prop_avail;
+ bt_message *out_message = NULL;
+ bt_stream *out_stream;
+
+ in_stream = bt_message_discarded_packets_borrow_stream_const(
+ in_message);
+ BT_ASSERT(in_stream);
+
+ out_stream = trace_ir_mapping_borrow_mapped_stream(
+ debug_it->ir_maps, in_stream);
+ BT_ASSERT(out_stream);
+
+ default_cc = bt_stream_class_borrow_default_clock_class_const(
+ bt_stream_borrow_class_const(in_stream));
+ if (default_cc) {
+ begin_cs_state =
+ bt_message_discarded_packets_borrow_default_beginning_clock_snapshot_const(
+ in_message, &begin_cs);
+
+ end_cs_state =
+ bt_message_discarded_packets_borrow_default_end_clock_snapshot_const(
+ in_message, &end_cs);
+
+ /*
+ * Both clock snapshots should be known as we check that the
+ * all input stream classes have an always known clock. Unknown
+ * clock is not yet supported.
+ */
+ BT_ASSERT(begin_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN &&
+ end_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
+
+ begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
+ end_cs_value = bt_clock_snapshot_get_value(end_cs);
+
+ out_message = bt_message_discarded_packets_create_with_default_clock_snapshots(
+ debug_it->input_iterator, out_stream,
+ begin_cs_value, end_cs_value);
+ } else {
+ out_message = bt_message_discarded_packets_create(
+ debug_it->input_iterator, out_stream);
+ }
+ if (!out_message) {
+ BT_LOGE("Error creating output discarded packet message: "
+ "out-s-addr=%p", out_stream);
+ goto error;
+ }
+
+ prop_avail = bt_message_discarded_packets_get_count(in_message,
+ &discarded_packets);
+ if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
+ bt_message_discarded_packets_set_count(out_message,
+ discarded_packets);
+ }
+
+error:
+ return out_message;
+}
+
+static
+const bt_message *handle_message(struct debug_info_msg_iter *debug_it,
+ const bt_message *in_message)
+{
+ bt_message *out_message = NULL;
+
+ switch (bt_message_get_type(in_message)) {
+ case BT_MESSAGE_TYPE_EVENT:
+ out_message = handle_event_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_PACKET_BEGINNING:
+ out_message = handle_packet_begin_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_PACKET_END:
+ out_message = handle_packet_end_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_STREAM_BEGINNING:
+ out_message = handle_stream_begin_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_STREAM_END:
+ out_message = handle_stream_end_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY:
+ out_message = handle_msg_iterator_inactivity(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING:
+ out_message = handle_stream_act_begin_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END:
+ out_message = handle_stream_act_end_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
+ out_message = handle_discarded_events_message(debug_it,
+ in_message);
+ break;
+ case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
+ out_message = handle_discarded_packets_message(debug_it,
+ in_message);
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ return out_message;
+}
+
+static
+int init_from_params(struct debug_info_component *debug_info_component,
+ const bt_value *params)
+{
+ const bt_value *value = NULL;
+ int ret = 0;
+
+ BT_ASSERT(params);
+
+ value = bt_value_map_borrow_entry_value_const(params,
+ "debug-info-field-name");
+ if (value) {
+ const char *debug_info_field_name;
+
+ debug_info_field_name = bt_value_string_get(value);
+ debug_info_component->arg_debug_info_field_name =
+ strdup(debug_info_field_name);
+ } else {
+ debug_info_component->arg_debug_info_field_name =
+ malloc(strlen(DEFAULT_DEBUG_INFO_FIELD_NAME) + 1);
+ if (!debug_info_component->arg_debug_info_field_name) {
+ ret = BT_SELF_COMPONENT_STATUS_NOMEM;
+ BT_LOGE_STR("Missing field name.");
+ goto end;
+ }
+ sprintf(debug_info_component->arg_debug_info_field_name,
+ DEFAULT_DEBUG_INFO_FIELD_NAME);
+ }
+ if (ret) {
+ goto end;
+ }
+
+ value = bt_value_map_borrow_entry_value_const(params, "debug-info-dir");
+ if (value) {
+ debug_info_component->arg_debug_dir = bt_value_string_get(value);
+ }
+
+ value = bt_value_map_borrow_entry_value_const(params, "target-prefix");
+ if (value) {
+ debug_info_component->arg_target_prefix =
+ bt_value_string_get(value);
+ }
+
+ value = bt_value_map_borrow_entry_value_const(params, "full-path");
+ if (value) {
+ debug_info_component->arg_full_path = bt_value_bool_get(value);
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+bt_self_component_status debug_info_comp_init(
+ bt_self_component_filter *self_comp,
+ const bt_value *params, UNUSED_VAR void *init_method_data)
+{
+ int ret;
+ struct debug_info_component *debug_info_comp;
+ bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
+
+ BT_LOGD("Initializing debug_info component: "
+ "comp-addr=%p, params-addr=%p", self_comp, params);
+
+ debug_info_comp = g_new0(struct debug_info_component, 1);
+ if (!debug_info_comp) {
+ BT_LOGE_STR("Failed to allocate one debug_info component.");
+ goto error;
+ }
+
+ bt_self_component_set_data(
+ bt_self_component_filter_as_self_component(self_comp),
+ debug_info_comp);
+
+ status = bt_self_component_filter_add_input_port(self_comp, "in",
+ NULL, NULL);
+ if (status != BT_SELF_COMPONENT_STATUS_OK) {
+ goto error;
+ }
+
+ status = bt_self_component_filter_add_output_port(self_comp, "out",
+ NULL, NULL);
+ if (status != BT_SELF_COMPONENT_STATUS_OK) {
+ goto error;
+ }
+
+ ret = init_from_params(debug_info_comp, params);
+ if (ret) {
+ BT_LOGE("Cannot configure debug_info component: "
+ "debug_info-comp-addr=%p, params-addr=%p",
+ debug_info_comp, params);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ destroy_debug_info_comp(debug_info_comp);
+ bt_self_component_set_data(
+ bt_self_component_filter_as_self_component(self_comp),
+ NULL);
+
+ if (status == BT_SELF_COMPONENT_STATUS_OK) {
+ status = BT_SELF_COMPONENT_STATUS_ERROR;
+ }
+end:
+ return status;
+}
+
+BT_HIDDEN
+void debug_info_comp_finalize(bt_self_component_filter *self_comp)
+{
+ struct debug_info_component *debug_info =
+ bt_self_component_get_data(
+ bt_self_component_filter_as_self_component(
+ self_comp));
+ BT_LOGD("Finalizing debug_info self_component: comp-addr=%p",
+ self_comp);
+
+ destroy_debug_info_comp(debug_info);
+}
+
+BT_HIDDEN
+bt_self_message_iterator_status debug_info_msg_iter_next(
+ bt_self_message_iterator *self_msg_iter,
+ const bt_message_array_const msgs, uint64_t capacity,
+ uint64_t *count)
+{
+ bt_self_component_port_input_message_iterator *upstream_iterator = NULL;
+ bt_message_iterator_status upstream_iterator_ret_status;
+ struct debug_info_msg_iter *debug_info_msg_iter;
+ struct debug_info_component *debug_info = NULL;
+ bt_self_message_iterator_status status;
+ bt_self_component *self_comp = NULL;
+ bt_message_array_const input_msgs;
+ const bt_message *out_message;
+ uint64_t curr_msg_idx, i;
+
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
+
+ self_comp = bt_self_message_iterator_borrow_component(self_msg_iter);
+ BT_ASSERT(self_comp);
+
+ debug_info = bt_self_component_get_data(self_comp);
+ BT_ASSERT(debug_info);
+
+ debug_info_msg_iter = bt_self_message_iterator_get_data(self_msg_iter);
+ BT_ASSERT(debug_info_msg_iter);
+
+ upstream_iterator = debug_info_msg_iter->msg_iter;
+ BT_ASSERT(upstream_iterator);
+
+ upstream_iterator_ret_status =
+ bt_self_component_port_input_message_iterator_next(
+ upstream_iterator, &input_msgs, count);
+ if (upstream_iterator_ret_status != BT_MESSAGE_ITERATOR_STATUS_OK) {
+ /*
+ * No messages were returned. Not necessarily an error. Convert
+ * the upstream message iterator status to a self status.
+ */
+ status = bt_common_message_iterator_status_to_self(
+ upstream_iterator_ret_status);
+ goto end;
+ }
+
+ /*
+ * There should never be more received messages than the capacity we
+ * provided.
+ */
+ BT_ASSERT(*count <= capacity);
+
+ for (curr_msg_idx = 0; curr_msg_idx < *count; curr_msg_idx++) {
+ out_message = handle_message(debug_info_msg_iter,
+ input_msgs[curr_msg_idx]);
+ if (!out_message) {
+ goto handle_msg_error;
+ }
+
+ msgs[curr_msg_idx] = out_message;
+ /*
+ * Drop our reference of the input message as we are done with
+ * it and created a output copy.
+ */
+ bt_message_put_ref(input_msgs[curr_msg_idx]);
+ }
+
+ goto end;
+
+handle_msg_error:
+ /*
+ * Drop references of all the output messages created before the
+ * failure.
+ */
+ for (i = 0; i < curr_msg_idx; i++) {
+ bt_message_put_ref(msgs[i]);
+ }
+
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+end:
+ return status;
+}
+
+BT_HIDDEN
+bt_self_message_iterator_status debug_info_msg_iter_init(
+ bt_self_message_iterator *self_msg_iter,
+ bt_self_component_filter *self_comp,
+ bt_self_component_port_output *self_port)
+{
+ bt_self_message_iterator_status status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
+ struct bt_self_component_port_input *input_port;
+ bt_self_component_port_input_message_iterator *upstream_iterator;
+ struct debug_info_msg_iter *debug_info_msg_iter;
+
+ /* Borrow the upstream input port. */
+ input_port = bt_self_component_filter_borrow_input_port_by_name(
+ self_comp, "in");
+ if (!input_port) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+
+ /* Create an iterator on the upstream component. */
+ upstream_iterator = bt_self_component_port_input_message_iterator_create(
+ input_port);
+ if (!upstream_iterator) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+ goto end;
+ }
+
+ debug_info_msg_iter = g_new0(struct debug_info_msg_iter, 1);
+ if (!debug_info_msg_iter) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+ goto end;
+ }
+
+ debug_info_msg_iter->debug_info_map = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) debug_info_destroy);
+ if (!debug_info_msg_iter->debug_info_map) {
+ g_free(debug_info_msg_iter);
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+ goto end;
+ }
+
+ debug_info_msg_iter->self_comp =
+ bt_self_component_filter_as_self_component(self_comp);
+
+ BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_MOVE_REF(
+ debug_info_msg_iter->msg_iter, upstream_iterator);
+
+ debug_info_msg_iter->debug_info_component = bt_self_component_get_data(
+ bt_self_component_filter_as_self_component(
+ self_comp));
+
+ debug_info_msg_iter->ir_maps = trace_ir_maps_create(
+ bt_self_component_filter_as_self_component(self_comp),
+ debug_info_msg_iter->debug_info_component->arg_debug_info_field_name);
+ if (!debug_info_msg_iter->ir_maps) {
+ g_hash_table_destroy(debug_info_msg_iter->debug_info_map);
+ g_free(debug_info_msg_iter);
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+ goto end;
+ }
+
+ bt_self_message_iterator_set_data(self_msg_iter, debug_info_msg_iter);
+
+ debug_info_msg_iter->input_iterator = self_msg_iter;
+
+end:
+ return status;
+}
+
+BT_HIDDEN
+bt_bool debug_info_msg_iter_can_seek_beginning(
+ bt_self_message_iterator *self_msg_iter)
+{
+ struct debug_info_msg_iter *debug_info_msg_iter =
+ bt_self_message_iterator_get_data(self_msg_iter);
+ BT_ASSERT(debug_info_msg_iter);
+
+ return bt_self_component_port_input_message_iterator_can_seek_beginning(
+ debug_info_msg_iter->msg_iter);
+}
+
+BT_HIDDEN
+bt_self_message_iterator_status debug_info_msg_iter_seek_beginning(
+ bt_self_message_iterator *self_msg_iter)
+{
+ struct debug_info_msg_iter *debug_info_msg_iter =
+ bt_self_message_iterator_get_data(self_msg_iter);
+ bt_message_iterator_status status = BT_MESSAGE_ITERATOR_STATUS_OK;
+
+ BT_ASSERT(debug_info_msg_iter);
+
+ /* Ask the upstream component to seek to the beginning. */
+ status = bt_self_component_port_input_message_iterator_seek_beginning(
+ debug_info_msg_iter->msg_iter);
+ if (status != BT_MESSAGE_ITERATOR_STATUS_OK) {
+ goto end;
+ }
+
+ /* Clear this iterator data. */
+ trace_ir_maps_clear(debug_info_msg_iter->ir_maps);
+ g_hash_table_remove_all(debug_info_msg_iter->debug_info_map);
+end:
+ return bt_common_message_iterator_status_to_self(status);
+}
+
+BT_HIDDEN
+void debug_info_msg_iter_finalize(bt_self_message_iterator *it)
+{
+ struct debug_info_msg_iter *debug_info_msg_iter;
+
+ debug_info_msg_iter = bt_self_message_iterator_get_data(it);
+ BT_ASSERT(debug_info_msg_iter);
+
+ bt_self_component_port_input_message_iterator_put_ref(
+ debug_info_msg_iter->msg_iter);
+
+ trace_ir_maps_destroy(debug_info_msg_iter->ir_maps);
+ g_hash_table_destroy(debug_info_msg_iter->debug_info_map);
+
+ g_free(debug_info_msg_iter);
+}
#define BABELTRACE_PLUGIN_DEBUG_INFO_H
/*
- * Babeltrace - Debug information Plug-in
+ * Babeltrace - Debug information Plugin
*
- * Copyright (c) 2015 EfficiOS Inc.
+ * Copyright (c) 2015-2019 EfficiOS Inc.
* Copyright (c) 2015 Antoine Busque <abusque@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers francis.deslauriers@efficios.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* SOFTWARE.
*/
-#include <stdbool.h>
#include <stdint.h>
-#include <stddef.h>
-#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
#define VPID_FIELD_NAME "vpid"
#define IP_FIELD_NAME "ip"
-#define BADDR_FIELD_NAME "baddr"
-#define CRC32_FIELD_NAME "crc32"
-#define BUILD_ID_FIELD_NAME "build_id"
-#define FILENAME_FIELD_NAME "filename"
-#define IS_PIC_FIELD_NAME "is_pic"
-#define MEMSZ_FIELD_NAME "memsz"
-#define PATH_FIELD_NAME "path"
-
-enum debug_info_stream_state {
- /*
- * We know the stream exists but we have never received a
- * stream_begin message for it.
- */
- DEBUG_INFO_UNKNOWN_STREAM,
- /* We know this stream is active (between stream_begin and _end). */
- DEBUG_INFO_ACTIVE_STREAM,
- /* We have received a stream_end for this stream. */
- DEBUG_INFO_COMPLETED_STREAM,
-};
-
-struct debug_info_component {
- FILE *err;
- char *arg_debug_info_field_name;
- const char *arg_debug_dir;
- bool arg_full_path;
- const char *arg_target_prefix;
-};
-struct debug_info_iterator {
- struct debug_info_component *debug_info_component;
- /* Map between bt_trace and struct bt_writer. */
- GHashTable *trace_map;
- /* Input iterators associated with this output iterator. */
- GPtrArray *input_iterator_group;
- const bt_message *current_message;
- bt_message_iterator *input_iterator;
- FILE *err;
-};
-
-struct debug_info_trace {
- const bt_trace *trace;
- const bt_trace *writer_trace;
- struct debug_info_component *debug_info_component;
- struct debug_info_iterator *debug_it;
- int static_listener_id;
- int trace_static;
- /* Map between reader and writer stream. */
- GHashTable *stream_map;
- /* Map between reader and writer stream class. */
- GHashTable *stream_class_map;
- /* Map between reader and writer stream class. */
- GHashTable *packet_map;
- /* Map between a trace_class and its corresponding debug_info. */
- GHashTable *trace_debug_map;
- /* Map between a stream and enum debug_info_stream_state. */
- GHashTable *stream_states;
-};
+BT_HIDDEN
+bt_self_component_status debug_info_comp_init(
+ bt_self_component_filter *self_comp,
+ const bt_value *params, void *init_method_data);
-struct debug_info_source {
- /* Strings are owned by debug_info_source. */
- char *func;
- uint64_t line_no;
- char *src_path;
- /* short_src_path points inside src_path, no need to free. */
- const char *short_src_path;
- char *bin_path;
- /* short_bin_path points inside bin_path, no need to free. */
- const char *short_bin_path;
- /*
- * Location within the binary. Either absolute (@0x1234) or
- * relative (+0x4321).
- */
- char *bin_loc;
-};
+BT_HIDDEN
+void debug_info_comp_finalize(bt_self_component_filter *self_comp);
BT_HIDDEN
-struct debug_info *debug_info_create(struct debug_info_component *comp);
+bt_self_message_iterator_status debug_info_msg_iter_init(
+ bt_self_message_iterator *self_msg_iter,
+ bt_self_component_filter *self_comp,
+ bt_self_component_port_output *self_port);
BT_HIDDEN
-void debug_info_destroy(struct debug_info *debug_info);
+bt_self_message_iterator_status debug_info_msg_iter_next(
+ bt_self_message_iterator *self_msg_iter,
+ const bt_message_array_const msgs, uint64_t capacity,
+ uint64_t *count);
BT_HIDDEN
-struct debug_info_source *debug_info_query(struct debug_info *debug_info,
- int64_t vpid, uint64_t ip);
+bt_bool debug_info_msg_iter_can_seek_beginning(
+ bt_self_message_iterator *message_iterator);
BT_HIDDEN
-void debug_info_handle_event(FILE *err, const bt_event *event,
- struct debug_info *debug_info);
+bt_self_message_iterator_status debug_info_msg_iter_seek_beginning(
+ bt_self_message_iterator *message_iterator);
BT_HIDDEN
-void debug_info_close_trace(struct debug_info_iterator *debug_it,
- struct debug_info_trace *di_trace);
+void debug_info_msg_iter_finalize(bt_self_message_iterator *it);
#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_H */
* SOFTWARE.
*/
-#define BT_LOG_TAG "PLUGIN-CTF-LTTNG-UTILS-DEBUG-INFO-FLT"
-#include "logging.h"
-
#include <babeltrace/babeltrace.h>
-#include <plugins-common.h>
-#include <babeltrace/assert-internal.h>
#include "debug-info.h"
-#include "copy.h"
-
-static
-gboolean empty_trace_map(gpointer key, gpointer value, gpointer user_data)
-{
- struct debug_info_trace *di_trace = value;
-
- di_trace->trace_static = 1;
- debug_info_close_trace(di_trace->debug_it, di_trace);
-
- return TRUE;
-}
-
-static
-void destroy_debug_info_data(struct debug_info_component *debug_info)
-{
- free(debug_info->arg_debug_info_field_name);
- g_free(debug_info);
-}
-
-static
-void destroy_debug_info_component(bt_self_component *component)
-{
- void *data = bt_self_component_get_user_data(component);
- destroy_debug_info_data(data);
-}
-
-static
-struct debug_info_component *create_debug_info_component_data(void)
-{
- struct debug_info_component *debug_info;
-
- debug_info = g_new0(struct debug_info_component, 1);
- if (!debug_info) {
- goto end;
- }
- debug_info->err = stderr;
-
-end:
- return debug_info;
-}
-
-static
-void unref_trace(struct debug_info_trace *di_trace)
-{
- bt_trace_put_ref(di_trace->writer_trace);
- g_free(di_trace);
-}
-
-static
-void debug_info_iterator_destroy(bt_self_message_iterator *it)
-{
- struct debug_info_iterator *it_data;
-
- it_data = bt_self_message_iterator_get_user_data(it);
- BT_ASSERT(it_data);
-
- if (it_data->input_iterator_group) {
- g_ptr_array_free(it_data->input_iterator_group, TRUE);
- }
-
- g_hash_table_foreach_remove(it_data->trace_map,
- empty_trace_map, it_data);
- g_hash_table_destroy(it_data->trace_map);
-
- bt_message_put_ref(it_data->current_message);
- bt_object_put_ref(it_data->input_iterator);
-
- g_free(it_data);
-}
-
-static
-const bt_message *handle_message(FILE *err,
- struct debug_info_iterator *debug_it,
- const bt_message *message)
-{
- const bt_message *new_message = NULL;
-
- switch (bt_message_get_type(message)) {
- case BT_MESSAGE_TYPE_PACKET_BEGINNING:
- {
- const bt_packet *packet =
- bt_message_packet_beginning_get_packet(message);
- const bt_packet *writer_packet;
-
- if (!packet) {
- goto end;
- }
-
- writer_packet = debug_info_new_packet(debug_it, packet);
- BT_ASSERT(writer_packet);
- new_message = bt_message_packet_beginning_create(
- writer_packet);
- BT_ASSERT(new_message);
- bt_packet_put_ref(packet);
- bt_packet_put_ref(writer_packet);
- break;
- }
- case BT_MESSAGE_TYPE_PACKET_END:
- {
- const bt_packet *packet =
- bt_message_packet_end_get_packet(message);
- const bt_packet *writer_packet;
-
- if (!packet) {
- goto end;
- }
-
- writer_packet = debug_info_close_packet(debug_it, packet);
- BT_ASSERT(writer_packet);
- new_message = bt_message_packet_end_create(
- writer_packet);
- BT_ASSERT(new_message);
- bt_packet_put_ref(packet);
- bt_packet_put_ref(writer_packet);
- break;
- }
- case BT_MESSAGE_TYPE_EVENT:
- {
- const bt_event *event = bt_message_event_get_event(
- message);
- const bt_event *writer_event;
- bt_clock_class_priority_map *cc_prio_map =
- bt_message_event_get_clock_class_priority_map(
- message);
-
- if (!event) {
- goto end;
- }
- writer_event = debug_info_output_event(debug_it, event);
- BT_ASSERT(writer_event);
- new_message = bt_message_event_create(writer_event,
- cc_prio_map);
- bt_object_put_ref(cc_prio_map);
- BT_ASSERT(new_message);
- bt_object_put_ref(event);
- bt_object_put_ref(writer_event);
- break;
- }
- case BT_MESSAGE_TYPE_STREAM_BEGINNING:
- {
- const bt_stream *stream =
- bt_message_stream_beginning_get_stream(message);
- const bt_stream *writer_stream;
-
- if (!stream) {
- goto end;
- }
-
- writer_stream = debug_info_stream_begin(debug_it, stream);
- BT_ASSERT(writer_stream);
- new_message = bt_message_stream_beginning_create(
- writer_stream);
- BT_ASSERT(new_message);
- bt_stream_put_ref(stream);
- bt_stream_put_ref(writer_stream);
- break;
- }
- case BT_MESSAGE_TYPE_STREAM_END:
- {
- const bt_stream *stream =
- bt_message_stream_end_get_stream(message);
- const bt_stream *writer_stream;
-
- if (!stream) {
- goto end;
- }
-
- writer_stream = debug_info_stream_end(debug_it, stream);
- BT_ASSERT(writer_stream);
- new_message = bt_message_stream_end_create(
- writer_stream);
- BT_ASSERT(new_message);
- bt_stream_put_ref(stream);
- bt_stream_put_ref(writer_stream);
- break;
- }
- default:
- new_message = bt_message_get_ref(message);
- break;
- }
-
-end:
- return new_message;
-}
-
-static
-bt_message_iterator_next_method_return debug_info_iterator_next(
- bt_self_message_iterator *iterator)
-{
- struct debug_info_iterator *debug_it = NULL;
- bt_self_component *component = NULL;
- struct debug_info_component *debug_info = NULL;
- bt_message_iterator *source_it = NULL;
- const bt_message *message;
- bt_message_iterator_next_method_return ret = {
- .status = BT_MESSAGE_ITERATOR_STATUS_OK,
- .message = NULL,
- };
-
- debug_it = bt_self_message_iterator_get_user_data(iterator);
- BT_ASSERT(debug_it);
-
- component = bt_self_message_iterator_get_private_component(iterator);
- BT_ASSERT(component);
- debug_info = bt_self_component_get_user_data(component);
- BT_ASSERT(debug_info);
-
- source_it = debug_it->input_iterator;
-
- ret.status = bt_message_iterator_next(source_it);
- if (ret.status != BT_MESSAGE_ITERATOR_STATUS_OK) {
- goto end;
- }
-
- message = bt_message_iterator_get_message(
- source_it);
- if (!message) {
- ret.status = BT_MESSAGE_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- ret.message = handle_message(debug_info->err, debug_it,
- message);
- BT_ASSERT(ret.message);
- bt_message_put_ref(message);
-
-end:
- bt_object_put_ref(component);
- return ret;
-}
-
-static
-bt_message_iterator_status debug_info_iterator_init(
- bt_self_message_iterator *iterator,
- struct bt_private_port *port)
-{
- bt_message_iterator_status ret =
- BT_MESSAGE_ITERATOR_STATUS_OK;
- bt_message_iterator_status it_ret;
- bt_connection_status conn_status;
- struct bt_private_connection *connection = NULL;
- bt_self_component *component =
- bt_self_message_iterator_get_private_component(iterator);
- struct debug_info_iterator *it_data = g_new0(struct debug_info_iterator, 1);
- struct bt_private_port *input_port;
-
- if (!it_data) {
- ret = BT_MESSAGE_ITERATOR_STATUS_NOMEM;
- goto end;
- }
-
- input_port = bt_self_component_filter_get_input_port_by_name(
- component, "in");
- if (!input_port) {
- ret = BT_MESSAGE_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- connection = bt_private_port_get_connection(input_port);
- bt_object_put_ref(input_port);
- if (!connection) {
- ret = BT_MESSAGE_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- conn_status = bt_private_connection_create_message_iterator(
- connection, &it_data->input_iterator);
- if (conn_status != BT_CONNECTION_STATUS_OK) {
- ret = BT_MESSAGE_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- it_data->debug_info_component = (struct debug_info_component *)
- bt_self_component_get_user_data(component);
- it_data->err = it_data->debug_info_component->err;
- it_data->trace_map = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) unref_trace);
-
- it_ret = bt_self_message_iterator_set_user_data(iterator, it_data);
- if (it_ret) {
- goto end;
- }
-
-end:
- bt_object_put_ref(connection);
- bt_object_put_ref(component);
- return ret;
-}
-
-static
-bt_component_status init_from_params(
- struct debug_info_component *debug_info_component,
- bt_value *params)
-{
- bt_value *value = NULL;
- bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- BT_ASSERT(params);
-
- value = bt_value_map_get(params, "debug-info-field-name");
- if (value) {
- bt_value_status value_ret;
- const char *tmp;
-
- tmp = bt_value_string_get(value);
- strcpy(debug_info_component->arg_debug_info_field_name, tmp);
- bt_value_put_ref(value);
- } else {
- debug_info_component->arg_debug_info_field_name =
- malloc(strlen("debug_info") + 1);
- if (!debug_info_component->arg_debug_info_field_name) {
- ret = BT_COMPONENT_STATUS_NOMEM;
- BT_LOGE_STR("Missing field name.");
- goto end;
- }
- sprintf(debug_info_component->arg_debug_info_field_name,
- "debug_info");
- }
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- value = bt_value_map_get(params, "debug-info-dir");
- if (value) {
- bt_value_status value_ret;
-
- debug_info_component->arg_debug_dir = bt_value_string_get(value);
- }
- bt_value_put_ref(value);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- value = bt_value_map_get(params, "target-prefix");
- if (value) {
- bt_value_status value_ret;
-
- debug_info_component->arg_target_prefix = bt_value_string_get(value);
- }
- bt_value_put_ref(value);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- value = bt_value_map_get(params, "full-path");
- if (value) {
- bt_value_status value_ret;
- bt_bool bool_val;
-
- bool_val = bt_value_bool_get(value);
-
- debug_info_component->arg_full_path = bool_val;
- }
- bt_value_put_ref(value);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
-end:
- return ret;
-}
-
-bt_component_status debug_info_component_init(
- bt_self_component *component, bt_value *params,
- UNUSED_VAR void *init_method_data)
-{
- bt_component_status ret;
- struct debug_info_component *debug_info = create_debug_info_component_data();
-
- if (!debug_info) {
- ret = BT_COMPONENT_STATUS_NOMEM;
- goto end;
- }
-
- ret = bt_self_component_set_user_data(component, debug_info);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto error;
- }
-
- ret = bt_self_component_filter_add_input_port(
- component, "in", NULL, NULL);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- ret = bt_self_component_filter_add_output_port(
- component, "out", NULL, NULL);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
-
- ret = init_from_params(debug_info, params);
-end:
- return ret;
-error:
- destroy_debug_info_data(debug_info);
- return ret;
-}
#ifndef BT_BUILT_IN_PLUGINS
BT_PLUGIN_MODULE();
BT_PLUGIN_LICENSE_WITH_ID(lttng_utils, "MIT");
BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(lttng_utils, debug_info, "debug-info",
- debug_info_iterator_next);
+ debug_info_msg_iter_next);
BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION_WITH_ID(lttng_utils, debug_info,
"Augment compatible events with debugging information.");
BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD_WITH_ID(lttng_utils,
- debug_info, debug_info_component_init);
+ debug_info, debug_info_comp_init);
BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID(lttng_utils,
- debug_info, destroy_debug_info_component);
+ debug_info, debug_info_comp_finalize);
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_INIT_METHOD_WITH_ID(
- lttng_utils, debug_info, debug_info_iterator_init);
+ lttng_utils, debug_info, debug_info_msg_iter_init);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_SEEK_BEGINNING_METHOD_WITH_ID(
+ lttng_utils, debug_info, debug_info_msg_iter_seek_beginning);
+BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CAN_SEEK_BEGINNING_METHOD_WITH_ID(
+ lttng_utils, debug_info, debug_info_msg_iter_can_seek_beginning);
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_FINALIZE_METHOD_WITH_ID(
- lttng_utils, debug_info, debug_info_iterator_destroy);
+ lttng_utils, debug_info, debug_info_msg_iter_finalize);
--- /dev/null
+/*
+ * Babeltrace - Trace IR data object copy
+ *
+ * Copyright (c) 2015-2019 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-DATA-COPY"
+#include "logging.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <babeltrace/assert-internal.h>
+
+#include "trace-ir-data-copy.h"
+
+BT_HIDDEN
+void copy_trace_content(const bt_trace *in_trace, bt_trace *out_trace)
+{
+ bt_trace_status status;
+ const char *trace_name;
+
+ BT_LOGD("Copying content of trace: in-t-addr=%p, out-t-addr=%p",
+ in_trace, out_trace);
+
+ trace_name = bt_trace_get_name(in_trace);
+ /* Copy the trace name. */
+ if (trace_name) {
+ status = bt_trace_set_name(out_trace, trace_name);
+ if (status != BT_TRACE_STATUS_OK) {
+ BT_LOGE("Cannot set trace's name: trace-addr=%p, name=\"%s\"",
+ out_trace, trace_name);
+ goto end;
+ }
+ }
+
+ BT_LOGD("Copied content of trace: in-t-addr=%p, out-t-addr=%p",
+ in_trace, out_trace);
+end:
+ return;
+}
+
+BT_HIDDEN
+void copy_stream_content(const bt_stream *in_stream, bt_stream *out_stream)
+{
+ const bt_trace *in_trace;
+ const bt_stream_class *in_stream_class;
+ const char *stream_name;
+ bt_stream_status status;
+
+ BT_LOGD("Copying content of stream: in-s-addr=%p, out-s-addr=%p",
+ in_stream, out_stream);
+
+ in_stream_class = bt_stream_borrow_class_const(in_stream);
+ in_trace = bt_stream_borrow_trace_const(in_stream);
+
+ stream_name = bt_stream_get_name(in_stream);
+ if (stream_name) {
+ status = bt_stream_set_name(out_stream, stream_name);
+ if (status != BT_STREAM_STATUS_OK) {
+ BT_LOGE("Cannot set stream's name: stream-addr=%p, "
+ "name=%s", out_stream, stream_name);
+ goto end;
+ }
+ }
+
+ BT_LOGD("Copied content of stream: in-s-addr=%p, out-s-addr=%p",
+ in_stream, out_stream);
+end:
+ return;
+}
+
+BT_HIDDEN
+void copy_packet_content(const bt_packet *in_packet, bt_packet *out_packet)
+{
+ const bt_field *in_context_field;
+ bt_field *out_context_field;
+
+ BT_LOGD("Copying content of packet: in-p-addr=%p, out-p-addr=%p",
+ in_packet, out_packet);
+
+ /* Copy context field. */
+ in_context_field = bt_packet_borrow_context_field_const(in_packet);
+ if (in_context_field) {
+ out_context_field = bt_packet_borrow_context_field(out_packet);
+ BT_ASSERT(out_context_field);
+ copy_field_content(in_context_field, out_context_field);
+ }
+
+ BT_LOGD("Copied content of packet: in-p-addr=%p, out-p-addr=%p",
+ in_packet, out_packet);
+ return;
+}
+
+BT_HIDDEN
+void copy_event_content(const bt_event *in_event, bt_event *out_event)
+{
+ const bt_field *in_common_ctx_field, *in_specific_ctx_field,
+ *in_payload_field;
+ bt_field *out_common_ctx_field, *out_specific_ctx_field,
+ *out_payload_field;
+
+ BT_LOGD("Copying content of event: in-e-addr=%p, out-e-addr=%p",
+ in_event, out_event);
+ in_common_ctx_field =
+ bt_event_borrow_common_context_field_const(in_event);
+ if (in_common_ctx_field) {
+ out_common_ctx_field =
+ bt_event_borrow_common_context_field(out_event);
+ BT_ASSERT(out_common_ctx_field);
+ copy_field_content(in_common_ctx_field,
+ out_common_ctx_field);
+ }
+
+ in_specific_ctx_field =
+ bt_event_borrow_specific_context_field_const(in_event);
+ if (in_specific_ctx_field) {
+ out_specific_ctx_field =
+ bt_event_borrow_specific_context_field(out_event);
+ BT_ASSERT(out_specific_ctx_field);
+ copy_field_content(in_specific_ctx_field,
+ out_specific_ctx_field);
+ }
+
+ in_payload_field = bt_event_borrow_payload_field_const(in_event);
+ if (in_payload_field) {
+ out_payload_field = bt_event_borrow_payload_field(out_event);
+ BT_ASSERT(out_payload_field);
+ copy_field_content(in_payload_field,
+ out_payload_field);
+ }
+
+ BT_LOGD("Copied content of event: in-e-addr=%p, out-e-addr=%p",
+ in_event, out_event);
+}
+
+BT_HIDDEN
+void copy_field_content(const bt_field *in_field, bt_field *out_field)
+{
+ bt_field_class_type in_fc_type, out_fc_type;
+
+ in_fc_type = bt_field_get_class_type(in_field);
+ out_fc_type = bt_field_get_class_type(out_field);
+ BT_ASSERT(in_fc_type == out_fc_type);
+
+ BT_LOGD("Copying content of field: in-f-addr=%p, out-f-addr=%p",
+ in_field, out_field);
+ switch (in_fc_type) {
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
+ bt_field_unsigned_integer_set_value(out_field,
+ bt_field_unsigned_integer_get_value(in_field));
+ break;
+ case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
+ case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
+ bt_field_signed_integer_set_value(out_field,
+ bt_field_signed_integer_get_value(in_field));
+ break;
+ case BT_FIELD_CLASS_TYPE_REAL:
+ bt_field_real_set_value(out_field,
+ bt_field_real_get_value(in_field));
+ break;
+ case BT_FIELD_CLASS_TYPE_STRING:
+ {
+ const char *str = bt_field_string_get_value(in_field);
+ bt_field_status status = bt_field_string_set_value(out_field, str);
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set string field's value: "
+ "str-field-addr=%p, str=%s" PRId64,
+ out_field, str);
+ }
+ break;
+ }
+ case BT_FIELD_CLASS_TYPE_STRUCTURE:
+ {
+ uint64_t i, nb_member_struct;
+ const bt_field *in_member_field;
+ bt_field *out_member_field;
+ const bt_field_class *in_field_class, *in_member_field_class;
+ const char *in_member_name;
+
+ in_field_class = bt_field_borrow_class_const(in_field);
+ nb_member_struct = bt_field_class_structure_get_member_count(
+ in_field_class);
+
+ /*
+ * Iterate over the fields by names in the input field to avoid
+ * problem if the struct fields are not in the same order after
+ * the debug-info was added.
+ */
+ for (i = 0; i < nb_member_struct; i++) {
+ bt_field_class_structure_borrow_member_by_index_const(
+ in_field_class, i, &in_member_name,
+ &in_member_field_class);
+
+ in_member_field =
+ bt_field_structure_borrow_member_field_by_name_const(
+ in_field, in_member_name);
+ out_member_field =
+ bt_field_structure_borrow_member_field_by_name(
+ out_field, in_member_name);
+
+ copy_field_content(in_member_field,
+ out_member_field);
+ }
+ break;
+ }
+ case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
+ /* fall through */
+ case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
+ {
+ const bt_field *in_element_field;
+ bt_field *out_element_field;
+ uint64_t i, array_len;
+ bt_field_status status;
+
+ array_len = bt_field_array_get_length(in_field);
+
+ if (in_fc_type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY) {
+ status = bt_field_dynamic_array_set_length(out_field,
+ array_len);
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot set dynamic array field's "
+ "length field: field-addr=%p, "
+ "length=%" PRIu64, out_field, array_len);
+ }
+ }
+
+ for (i = 0; i < array_len; i++) {
+ in_element_field =
+ bt_field_array_borrow_element_field_by_index_const(
+ in_field, i);
+ out_element_field =
+ bt_field_array_borrow_element_field_by_index(
+ out_field, i);
+ copy_field_content(in_element_field, out_element_field);
+ }
+ break;
+ }
+ case BT_FIELD_CLASS_TYPE_VARIANT:
+ {
+ bt_field_status status;
+ uint64_t in_selected_option_idx;
+ const bt_field *in_option_field;
+ bt_field *out_option_field;
+
+ in_selected_option_idx =
+ bt_field_variant_get_selected_option_field_index(
+ in_field);
+ status = bt_field_variant_select_option_field(out_field,
+ in_selected_option_idx);
+ if (status != BT_FIELD_STATUS_OK) {
+ BT_LOGE("Cannot select variant field's option field: "
+ "var-field-addr=%p, opt-index=%" PRId64,
+ out_field, in_selected_option_idx);
+ }
+
+ in_option_field = bt_field_variant_borrow_selected_option_field_const(in_field);
+ out_option_field = bt_field_variant_borrow_selected_option_field(out_field);
+
+ copy_field_content(in_option_field, out_option_field);
+
+ break;
+ }
+ default:
+ abort();
+ }
+ BT_LOGD("Copied content of field: in-f-addr=%p, out-f-addr=%p",
+ in_field, out_field);
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_DATA_COPY_H
+#define BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_DATA_COPY_H
+
+/*
+ * Babeltrace - Trace IR data object copy
+ *
+ * Copyright (c) 2019 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/babeltrace.h>
+
+#include "trace-ir-mapping.h"
+
+BT_HIDDEN
+void copy_trace_content(const bt_trace *in_trace, bt_trace *out_trace);
+BT_HIDDEN
+void copy_stream_content(const bt_stream *in_stream, bt_stream *out_stream);
+BT_HIDDEN
+void copy_packet_content(const bt_packet *in_packet, bt_packet *out_packet);
+BT_HIDDEN
+void copy_event_content(const bt_event *in_event, bt_event *out_event);
+BT_HIDDEN
+void copy_field_content(const bt_field *in_field, bt_field *out_field);
+
+#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_DATA_COPY_H */
--- /dev/null
+/*
+ * Babeltrace - Mapping of IR metadata and data object between input and output
+ * trace
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-MAPPING"
+#include "logging.h"
+
+#include <stdbool.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace.h>
+/* For bt_property_availability */
+#include <babeltrace/property.h>
+
+#include "debug-info.h"
+#include "trace-ir-data-copy.h"
+#include "trace-ir-mapping.h"
+#include "trace-ir-metadata-copy.h"
+
+static
+bt_trace_class *create_new_mapped_trace_class(struct trace_ir_maps *ir_maps,
+ const bt_trace_class *in_trace_class)
+{
+ int ret;
+ bt_trace_class *out_trace_class;
+
+ BT_LOGD("Creating new mapped trace class: in-tc-addr=%p", in_trace_class);
+
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_trace_class);
+
+ /* Create the ouput trace class. */
+ out_trace_class = bt_trace_class_create(ir_maps->self_comp);
+ if (!out_trace_class) {
+ BT_LOGE_STR("Error create output trace class");
+ goto end;
+ }
+
+ /* If not, create a new one and add it to the mapping. */
+ ret = copy_trace_class_content(in_trace_class, out_trace_class);
+ if (ret) {
+ BT_LOGE_STR("Error copy content to output trace class");
+ out_trace_class = NULL;
+ goto end;
+ }
+
+ BT_LOGD("Created new mapped trace class: in-tc-addr=%p, out-tc-addr=%p",
+ in_trace_class, out_trace_class);
+
+end:
+ return out_trace_class;
+}
+
+static
+bt_trace *create_new_mapped_trace(struct trace_ir_maps *ir_maps,
+ const bt_trace *in_trace)
+{
+ bt_trace *out_trace;
+ const bt_trace_class *in_trace_class;
+ struct trace_ir_metadata_maps *metadata_maps;
+
+ BT_LOGD("Creating new mapped trace: in-t-addr=%p", in_trace);
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_trace);
+
+ in_trace_class = bt_trace_borrow_class_const(in_trace);
+ metadata_maps = borrow_metadata_maps_from_input_trace_class(ir_maps,
+ in_trace_class);
+
+ if (!metadata_maps->output_trace_class) {
+ metadata_maps->output_trace_class =
+ create_new_mapped_trace_class(ir_maps, in_trace_class);
+ if (!metadata_maps->output_trace_class) {
+ out_trace = NULL;
+ goto end;
+ }
+ }
+
+ out_trace = bt_trace_create(metadata_maps->output_trace_class);
+ if (!out_trace) {
+ BT_LOGE_STR("Error create output trace");
+ goto end;
+ }
+
+ /* If not, create a new one and add it to the mapping. */
+ copy_trace_content(in_trace, out_trace);
+
+ BT_LOGD("Created new mapped trace: in-t-addr=%p, out-t-addr=%p",
+ in_trace, out_trace);
+end:
+ return out_trace;
+}
+
+static
+bt_stream_class *borrow_mapped_stream_class(struct trace_ir_metadata_maps *md_maps,
+ const bt_stream_class *in_stream_class)
+{
+ BT_ASSERT(md_maps);
+ BT_ASSERT(in_stream_class);
+
+ return g_hash_table_lookup(md_maps->stream_class_map,
+ (gpointer) in_stream_class);
+}
+
+static
+bt_stream_class *create_new_mapped_stream_class(struct trace_ir_maps *ir_maps,
+ const bt_stream_class *in_stream_class)
+{
+ int ret;
+ bt_stream_class *out_stream_class;
+ struct trace_ir_metadata_maps *md_maps;
+
+ BT_LOGD("Creating new mapped stream class: in-sc-addr=%p",
+ in_stream_class);
+
+ md_maps = borrow_metadata_maps_from_input_stream_class(ir_maps,
+ in_stream_class);
+
+ BT_ASSERT(md_maps);
+ BT_ASSERT(in_stream_class);
+ BT_ASSERT(!borrow_mapped_stream_class(md_maps, in_stream_class));
+
+ /* Create an out_stream_class. */
+ out_stream_class = bt_stream_class_create_with_id(
+ md_maps->output_trace_class,
+ bt_stream_class_get_id(in_stream_class));
+ if (!out_stream_class) {
+ BT_LOGE_STR("Error create output stream class");
+ goto end;
+ }
+
+ /* If not, create a new one and add it to the mapping. */
+ ret = copy_stream_class_content(ir_maps, in_stream_class,
+ out_stream_class);
+ if (ret) {
+ BT_LOGE_STR("Error copy content to output stream class");
+ out_stream_class = NULL;
+ goto end;
+ }
+
+ g_hash_table_insert(md_maps->stream_class_map,
+ (gpointer) in_stream_class, out_stream_class);
+
+ BT_LOGD("Created new mapped stream class: in-sc-addr=%p, out-sc-addr=%p",
+ in_stream_class, out_stream_class);
+
+end:
+ return out_stream_class;
+}
+
+static
+bt_stream *borrow_mapped_stream(struct trace_ir_data_maps *d_maps,
+ const bt_stream *in_stream)
+{
+ BT_ASSERT(d_maps);
+ BT_ASSERT(in_stream);
+
+ return g_hash_table_lookup(d_maps->stream_map, (gpointer) in_stream);
+}
+
+BT_HIDDEN
+bt_stream *trace_ir_mapping_create_new_mapped_stream(
+ struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream)
+{
+ struct trace_ir_data_maps *d_maps;
+ struct trace_ir_metadata_maps *md_maps;
+ const bt_stream_class *in_stream_class;
+ const bt_trace *in_trace;
+ bt_stream_class *out_stream_class;
+ bt_stream *out_stream = NULL;
+
+ BT_LOGD("Creating new mapped stream: in-s-addr=%p", in_stream);
+
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_stream);
+
+ in_trace = bt_stream_borrow_trace_const(in_stream);
+
+ d_maps = borrow_data_maps_from_input_trace(ir_maps, in_trace);
+ if (!d_maps->output_trace) {
+ d_maps->output_trace = create_new_mapped_trace(ir_maps, in_trace);
+ if (!d_maps->output_trace) {
+ goto end;
+ }
+ }
+
+ BT_ASSERT(d_maps->output_trace);
+ BT_ASSERT(!borrow_mapped_stream(d_maps, in_stream));
+
+ in_stream_class = bt_stream_borrow_class_const(in_stream);
+ if (bt_stream_class_default_clock_is_always_known(in_stream_class)
+ == BT_FALSE) {
+ BT_LOGE("Stream class default clock class is not always "
+ "known: in-sc-addr=%p", in_stream_class);
+ goto end;
+ }
+
+ md_maps = borrow_metadata_maps_from_input_stream_class(ir_maps, in_stream_class);
+ out_stream_class = borrow_mapped_stream_class(md_maps, in_stream_class);
+ if (!out_stream_class) {
+ out_stream_class = create_new_mapped_stream_class(ir_maps,
+ in_stream_class);
+ if (!out_stream_class) {
+ goto end;
+ }
+ }
+ BT_ASSERT(out_stream_class);
+
+ out_stream = bt_stream_create_with_id(out_stream_class,
+ d_maps->output_trace, bt_stream_get_id(in_stream));
+ if (!out_stream) {
+ BT_LOGE_STR("Error creating output stream");
+ goto end;
+ }
+ /*
+ * Release our ref since the trace object will be managing the life
+ * time of the stream objects.
+ */
+
+ copy_stream_content(in_stream, out_stream);
+
+ g_hash_table_insert(d_maps->stream_map, (gpointer) in_stream,
+ out_stream);
+
+ BT_LOGD("Created new mapped stream: in-s-addr=%p, out-s-addr=%p",
+ in_stream, out_stream);
+
+end:
+ return out_stream;
+}
+
+BT_HIDDEN
+bt_stream *trace_ir_mapping_borrow_mapped_stream(struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream)
+{
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_stream);
+ struct trace_ir_data_maps *d_maps;
+
+ d_maps = borrow_data_maps_from_input_stream(ir_maps, in_stream);
+ /* Return the mapped stream. */
+ return borrow_mapped_stream(d_maps, in_stream);
+}
+
+static inline
+bt_event_class *borrow_mapped_event_class(struct trace_ir_metadata_maps *md_maps,
+ const bt_event_class *in_event_class)
+{
+ return g_hash_table_lookup(md_maps->event_class_map,
+ (gpointer) in_event_class);
+}
+
+BT_HIDDEN
+bt_event_class *trace_ir_mapping_create_new_mapped_event_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class)
+{
+ bt_event_class *out_event_class;
+ const bt_trace_class *in_trace_class;
+ const bt_stream_class *in_stream_class;
+ bt_stream_class *out_stream_class;
+ struct trace_ir_metadata_maps *md_maps;
+ int ret;
+
+ BT_LOGD("Creating new mapped event class: in-ec-addr=%p",
+ in_event_class);
+
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_event_class);
+
+ in_trace_class = bt_stream_class_borrow_trace_class_const(
+ bt_event_class_borrow_stream_class_const(
+ in_event_class));
+
+ md_maps = borrow_metadata_maps_from_input_trace_class(ir_maps, in_trace_class);
+
+ BT_ASSERT(!borrow_mapped_event_class(md_maps, in_event_class));
+
+ in_stream_class =
+ bt_event_class_borrow_stream_class_const(in_event_class);
+ BT_ASSERT(in_stream_class);
+
+ /* Get the right output stream class to add the new event class to. */
+ out_stream_class = borrow_mapped_stream_class(md_maps, in_stream_class);
+ BT_ASSERT(out_stream_class);
+
+ /* Create an output event class. */
+ out_event_class = bt_event_class_create_with_id(out_stream_class,
+ bt_event_class_get_id(in_event_class));
+ if (!out_event_class) {
+ BT_LOGE_STR("Error creating output event class");
+ goto end;
+ }
+
+ /* If not, create a new one and add it to the mapping. */
+ ret = copy_event_class_content(ir_maps, in_event_class,
+ out_event_class);
+ if (ret) {
+ BT_LOGE_STR("Error copy content to output event class");
+ out_event_class = NULL;
+ goto end;
+ }
+
+ g_hash_table_insert(md_maps->event_class_map,
+ (gpointer) in_event_class, out_event_class);
+
+ BT_LOGD("Created new mapped event class: in-ec-addr=%p, out-ec-addr=%p",
+ in_event_class, out_event_class);
+
+end:
+ return out_event_class;
+}
+
+BT_HIDDEN
+bt_event_class *trace_ir_mapping_borrow_mapped_event_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class)
+{
+ struct trace_ir_metadata_maps *md_maps;
+
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_event_class);
+
+ md_maps = borrow_metadata_maps_from_input_event_class(ir_maps, in_event_class);
+
+ /* Return the mapped event_class. */
+ return borrow_mapped_event_class(md_maps, in_event_class);
+}
+
+static inline
+bt_packet *borrow_mapped_packet(struct trace_ir_data_maps *d_maps,
+ const bt_packet *in_packet)
+{
+ BT_ASSERT(d_maps);
+ BT_ASSERT(in_packet);
+
+ return g_hash_table_lookup(d_maps->packet_map,
+ (gpointer) in_packet);
+}
+
+BT_HIDDEN
+bt_packet *trace_ir_mapping_create_new_mapped_packet(
+ struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet)
+{
+ struct trace_ir_data_maps *d_maps;
+ const bt_trace *in_trace;
+ const bt_stream *in_stream;
+ bt_packet *out_packet;
+ bt_stream *out_stream;
+
+ BT_LOGD("Creating new mapped packet: in-p-addr=%p", in_packet);
+
+ in_stream = bt_packet_borrow_stream_const(in_packet);
+ in_trace = bt_stream_borrow_trace_const(in_stream);
+ d_maps = borrow_data_maps_from_input_trace(ir_maps, in_trace);
+
+ /* There should never be a mapped packet. */
+ BT_ASSERT(!borrow_mapped_packet(d_maps, in_packet));
+
+ BT_ASSERT(in_stream);
+
+ /* Get output stream corresponding to this input stream. */
+ out_stream = borrow_mapped_stream(d_maps, in_stream);
+ BT_ASSERT(out_stream);
+
+ /* Create the output packet. */
+ out_packet = bt_packet_create(out_stream);
+ if (!out_packet) {
+ BT_LOGE_STR("Error create output packet");
+ goto end;
+ }
+
+ /*
+ * Release our ref since the stream object will be managing the life
+ * time of the packet objects.
+ */
+ copy_packet_content(in_packet, out_packet);
+
+ g_hash_table_insert(d_maps->packet_map,
+ (gpointer) in_packet, out_packet);
+
+ BT_LOGD("Created new mapped packet: in-p-addr=%p, out-p-addr=%p",
+ in_packet, out_packet);
+
+end:
+ return out_packet;
+}
+
+BT_HIDDEN
+bt_packet *trace_ir_mapping_borrow_mapped_packet(struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet)
+{
+ struct trace_ir_data_maps *d_maps;
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_packet);
+
+ d_maps = borrow_data_maps_from_input_packet(ir_maps, in_packet);
+
+ return borrow_mapped_packet(d_maps, in_packet);
+}
+
+BT_HIDDEN
+void trace_ir_mapping_remove_mapped_packet(struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet)
+{
+ gboolean ret;
+
+ struct trace_ir_data_maps *d_maps;
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_packet);
+
+ d_maps = borrow_data_maps_from_input_packet(ir_maps, in_packet);
+
+ ret = g_hash_table_remove(d_maps->packet_map, in_packet);
+
+ BT_ASSERT(ret);
+}
+
+BT_HIDDEN
+void trace_ir_mapping_remove_mapped_stream(struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream)
+{
+ gboolean ret;
+ struct trace_ir_data_maps *d_maps;
+
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_stream);
+
+ d_maps = borrow_data_maps_from_input_stream(ir_maps, in_stream);
+
+ ret = g_hash_table_remove(d_maps->stream_map, in_stream);
+
+ BT_ASSERT(ret);
+}
+
+static
+void trace_ir_metadata_maps_remove_func(const bt_trace_class *in_trace_class,
+ void *data)
+{
+ struct trace_ir_maps *maps = (struct trace_ir_maps *) data;
+ if (maps->metadata_maps) {
+ gboolean ret;
+ ret = g_hash_table_remove(maps->metadata_maps,
+ (gpointer) in_trace_class);
+ BT_ASSERT(ret);
+ }
+}
+
+static
+void trace_ir_data_maps_remove_func(const bt_trace *in_trace, void *data)
+{
+ struct trace_ir_maps *maps = (struct trace_ir_maps *) data;
+ if (maps->data_maps) {
+ gboolean ret;
+ ret = g_hash_table_remove(maps->data_maps, (gpointer) in_trace);
+ BT_ASSERT(ret);
+ }
+}
+
+struct trace_ir_data_maps *trace_ir_data_maps_create(struct trace_ir_maps *ir_maps,
+ const bt_trace *in_trace)
+{
+ struct trace_ir_data_maps *d_maps =
+ g_new0(struct trace_ir_data_maps, 1);
+ if (!d_maps) {
+ BT_LOGE_STR("Error allocating trace_ir_maps");
+ goto error;
+ }
+
+ d_maps->input_trace = in_trace;
+
+ /* Create the hashtables used to map data objects. */
+ d_maps->stream_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL,(GDestroyNotify) bt_stream_put_ref);
+ d_maps->packet_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL,(GDestroyNotify) bt_packet_put_ref);
+
+ bt_trace_add_destruction_listener(in_trace, trace_ir_data_maps_remove_func,
+ ir_maps, &d_maps->destruction_listener_id);
+error:
+ return d_maps;
+}
+
+struct trace_ir_metadata_maps *trace_ir_metadata_maps_create(
+ struct trace_ir_maps *ir_maps,
+ const bt_trace_class *in_trace_class)
+{
+ struct trace_ir_metadata_maps *md_maps =
+ g_new0(struct trace_ir_metadata_maps, 1);
+ if (!md_maps) {
+ BT_LOGE_STR("Error allocating trace_ir_maps");
+ goto error;
+ }
+
+ md_maps->input_trace_class = in_trace_class;
+ /*
+ * Create the field class resolving context. This is needed to keep
+ * track of the field class already copied in order to do the field
+ * path resolution correctly.
+ */
+ md_maps->fc_resolving_ctx =
+ g_new0(struct field_class_resolving_context, 1);
+ if (!md_maps->fc_resolving_ctx) {
+ BT_LOGE_STR("Error allocating field_class_resolving_context");
+ goto error;
+ }
+
+ /* Create the hashtables used to map metadata objects. */
+ md_maps->stream_class_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) bt_stream_class_put_ref);
+ md_maps->event_class_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) bt_event_class_put_ref);
+ md_maps->field_class_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) bt_field_class_put_ref);
+ md_maps->clock_class_map = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) bt_clock_class_put_ref);
+
+ bt_trace_class_add_destruction_listener(in_trace_class,
+ trace_ir_metadata_maps_remove_func,
+ ir_maps, &md_maps->destruction_listener_id);
+error:
+ return md_maps;
+}
+
+BT_HIDDEN
+void trace_ir_data_maps_destroy(struct trace_ir_data_maps *maps)
+{
+ bt_trace_status status;
+ if (!maps) {
+ return;
+ }
+
+ if (maps->packet_map) {
+ g_hash_table_destroy(maps->packet_map);
+ }
+
+ if (maps->stream_map) {
+ g_hash_table_destroy(maps->stream_map);
+ }
+
+ if (maps->output_trace) {
+ bt_trace_put_ref(maps->output_trace);
+ }
+
+ status = bt_trace_remove_destruction_listener(maps->input_trace,
+ maps->destruction_listener_id);
+
+ g_free(maps);
+}
+
+BT_HIDDEN
+void trace_ir_metadata_maps_destroy(struct trace_ir_metadata_maps *maps)
+{
+ bt_trace_class_status status;
+ if (!maps) {
+ return;
+ }
+
+ if (maps->stream_class_map) {
+ g_hash_table_destroy(maps->stream_class_map);
+ }
+
+ if (maps->event_class_map) {
+ g_hash_table_destroy(maps->event_class_map);
+ }
+
+ if (maps->field_class_map) {
+ g_hash_table_destroy(maps->field_class_map);
+ }
+
+ if (maps->clock_class_map) {
+ g_hash_table_destroy(maps->clock_class_map);
+ }
+
+ if (maps->fc_resolving_ctx) {
+ g_free(maps->fc_resolving_ctx);
+ }
+
+ if (maps->output_trace_class) {
+ bt_trace_class_put_ref(maps->output_trace_class);
+ }
+
+ status = bt_trace_class_remove_destruction_listener(maps->input_trace_class,
+ maps->destruction_listener_id);
+
+ g_free(maps);
+}
+
+void trace_ir_maps_clear(struct trace_ir_maps *maps)
+{
+ if (maps->data_maps) {
+ g_hash_table_remove_all(maps->data_maps);
+ }
+
+ if (maps->metadata_maps) {
+ g_hash_table_remove_all(maps->metadata_maps);
+ }
+}
+
+BT_HIDDEN
+void trace_ir_maps_destroy(struct trace_ir_maps *maps)
+{
+ if (!maps) {
+ return;
+ }
+
+ if (maps->debug_info_field_class_name) {
+ g_free(maps->debug_info_field_class_name);
+ }
+
+ if (maps->data_maps) {
+ g_hash_table_destroy(maps->data_maps);
+ maps->data_maps = NULL;
+ }
+
+ if (maps->metadata_maps) {
+ g_hash_table_destroy(maps->metadata_maps);
+ maps->metadata_maps = NULL;
+ }
+
+ g_free(maps);
+}
+
+BT_HIDDEN
+struct trace_ir_maps *trace_ir_maps_create(bt_self_component *self_comp,
+ const char *debug_info_field_name)
+{
+ struct trace_ir_maps *trace_ir_maps =
+ g_new0(struct trace_ir_maps, 1);
+ if (!trace_ir_maps) {
+ BT_LOGE_STR("Error allocating trace_ir_maps");
+ goto error;
+ }
+
+ /* Copy debug info field name received from the user. */
+ trace_ir_maps->debug_info_field_class_name =
+ g_strdup(debug_info_field_name);
+ if (!trace_ir_maps->debug_info_field_class_name) {
+ BT_LOGE_STR("Cannot copy debug info field name");
+ goto error;
+ }
+
+ trace_ir_maps->self_comp = self_comp;
+
+ trace_ir_maps->data_maps = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, (GDestroyNotify) NULL,
+ (GDestroyNotify) trace_ir_data_maps_destroy);
+
+ trace_ir_maps->metadata_maps = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, (GDestroyNotify) NULL,
+ (GDestroyNotify) trace_ir_metadata_maps_destroy);
+
+ goto end;
+error:
+ trace_ir_maps_destroy(trace_ir_maps);
+ trace_ir_maps = NULL;
+end:
+ return trace_ir_maps;
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_IR_MAPPING_H
+#define BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_IR_MAPPING_H
+/*
+ * Copyright 2019 Francis Deslauriers francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <glib.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace.h>
+
+#include "debug-info.h"
+
+/* Used to resolve field paths for dynamic arrays and variant field classes. */
+struct field_class_resolving_context {
+ /* Weak reference. Owned by input stream class. */
+ const bt_field_class *packet_context;
+ /* Weak reference. Owned by input stream class. */
+ const bt_field_class *event_common_context;
+ /* Weak reference. Owned by input event class. */
+ const bt_field_class *event_specific_context;
+ /* Weak reference. Owned by input event class. */
+ const bt_field_class *event_payload;
+};
+
+struct trace_ir_metadata_maps {
+ const bt_trace_class *input_trace_class;
+ bt_trace_class *output_trace_class;
+
+ /*
+ * Map between input stream class and its corresponding output stream
+ * class.
+ * input stream class: weak reference. Owned by an upstream
+ * component.
+ * output stream class: owned by this structure.
+ */
+ GHashTable *stream_class_map;
+
+ /*
+ * Map between input event class and its corresponding output event
+ * class.
+ * input event class: weak reference. Owned by an upstream component.
+ * output event class: owned by this structure.
+ */
+ GHashTable *event_class_map;
+
+ /*
+ * Map between input field class and its corresponding output field
+ * class.
+ * input field class: weak reference. Owned by an upstream component.
+ * output field class: owned by this structure.
+ */
+ GHashTable *field_class_map;
+
+ /*
+ * Map between input clock class and its corresponding output clock
+ * class.
+ * input clock class: weak reference. Owned by an upstream component.
+ * output clock class: owned by this structure.
+ */
+ GHashTable *clock_class_map;
+
+ struct field_class_resolving_context *fc_resolving_ctx;
+
+ uint64_t destruction_listener_id;
+};
+
+struct trace_ir_data_maps {
+ const bt_trace *input_trace;
+ bt_trace *output_trace;
+
+ /*
+ * Map between input stream its corresponding output stream.
+ * input stream: weak reference. Owned by an upstream component.
+ * output stream: owned by this structure.
+ */
+ GHashTable *stream_map;
+
+ /*
+ * Map between input packet its corresponding output packet.
+ * input packet: weak reference. Owned by an upstream packet component.
+ * output packet: owned by this structure.
+ */
+ GHashTable *packet_map;
+
+ uint64_t destruction_listener_id;
+};
+
+struct trace_ir_maps {
+ /*
+ * input trace -> trace_ir_data_maps.
+ * input trace: weak reference. Owned by an upstream component.
+ * trace_ir_data_maps: Owned by this structure.
+ */
+ GHashTable *data_maps;
+
+ /*
+ * input trace class -> trace_ir_metadata_maps.
+ * input trace class: weak reference. Owned by an upstream component.
+ * trace_ir_metadata_maps: Owned by this structure.
+ */
+ GHashTable *metadata_maps;
+
+ char *debug_info_field_class_name;
+
+ bt_self_component *self_comp;
+};
+
+BT_HIDDEN
+struct trace_ir_maps *trace_ir_maps_create(bt_self_component *self_comp,
+ const char *debug_info_field_name);
+
+BT_HIDDEN
+void trace_ir_maps_clear(struct trace_ir_maps *maps);
+
+BT_HIDDEN
+void trace_ir_maps_destroy(struct trace_ir_maps *maps);
+
+BT_HIDDEN
+struct trace_ir_data_maps *trace_ir_data_maps_create(
+ struct trace_ir_maps *ir_maps,
+ const bt_trace *in_trace);
+
+BT_HIDDEN
+void trace_ir_data_maps_destroy(struct trace_ir_data_maps *d_maps);
+
+BT_HIDDEN
+struct trace_ir_metadata_maps *trace_ir_metadata_maps_create(
+ struct trace_ir_maps *ir_maps,
+ const bt_trace_class *in_trace_class);
+
+BT_HIDDEN
+void trace_ir_metadata_maps_destroy(struct trace_ir_metadata_maps *md_maps);
+
+BT_HIDDEN
+bt_stream *trace_ir_mapping_create_new_mapped_stream(
+ struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream);
+
+BT_HIDDEN
+bt_stream *trace_ir_mapping_borrow_mapped_stream(
+ struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream);
+
+BT_HIDDEN
+void trace_ir_mapping_remove_mapped_stream(
+ struct trace_ir_maps *ir_maps,
+ const bt_stream *in_stream);
+
+BT_HIDDEN
+bt_event_class *trace_ir_mapping_create_new_mapped_event_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class);
+
+BT_HIDDEN
+bt_event_class *trace_ir_mapping_borrow_mapped_event_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class);
+
+BT_HIDDEN
+bt_packet *trace_ir_mapping_create_new_mapped_packet(
+ struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet);
+
+BT_HIDDEN
+bt_packet *trace_ir_mapping_borrow_mapped_packet(
+ struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet);
+
+BT_HIDDEN
+void trace_ir_mapping_remove_mapped_packet(
+ struct trace_ir_maps *ir_maps,
+ const bt_packet *in_packet);
+
+static inline
+struct trace_ir_data_maps *borrow_data_maps_from_input_trace(
+ struct trace_ir_maps *ir_maps, const bt_trace *in_trace)
+{
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_trace);
+
+ struct trace_ir_data_maps *d_maps =
+ g_hash_table_lookup(ir_maps->data_maps, (gpointer) in_trace);
+ if (!d_maps) {
+ d_maps = trace_ir_data_maps_create(ir_maps, in_trace);
+ g_hash_table_insert(ir_maps->data_maps, (gpointer) in_trace, d_maps);
+ }
+
+ return d_maps;
+}
+
+static inline
+struct trace_ir_data_maps *borrow_data_maps_from_input_stream(
+ struct trace_ir_maps *ir_maps, const bt_stream *in_stream)
+{
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_stream);
+
+ return borrow_data_maps_from_input_trace(ir_maps,
+ bt_stream_borrow_trace_const(in_stream));
+}
+
+static inline
+struct trace_ir_data_maps *borrow_data_maps_from_input_packet(
+ struct trace_ir_maps *ir_maps, const bt_packet *in_packet)
+{
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_packet);
+
+ return borrow_data_maps_from_input_stream(ir_maps,
+ bt_packet_borrow_stream_const(in_packet));
+}
+
+static inline
+struct trace_ir_metadata_maps *borrow_metadata_maps_from_input_trace_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_trace_class *in_trace_class)
+{
+ BT_ASSERT(ir_maps);
+ BT_ASSERT(in_trace_class);
+
+ struct trace_ir_metadata_maps *md_maps =
+ g_hash_table_lookup(ir_maps->metadata_maps,
+ (gpointer) in_trace_class);
+ if (!md_maps) {
+ md_maps = trace_ir_metadata_maps_create(ir_maps, in_trace_class);
+ g_hash_table_insert(ir_maps->metadata_maps,
+ (gpointer) in_trace_class, md_maps);
+ }
+
+ return md_maps;
+}
+
+static inline
+struct trace_ir_metadata_maps *borrow_metadata_maps_from_input_stream_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_stream_class *in_stream_class) {
+
+ BT_ASSERT(in_stream_class);
+
+ return borrow_metadata_maps_from_input_trace_class(ir_maps,
+ bt_stream_class_borrow_trace_class_const(in_stream_class));
+}
+
+static inline
+struct trace_ir_metadata_maps *borrow_metadata_maps_from_input_event_class(
+ struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class) {
+
+ BT_ASSERT(in_event_class);
+
+ return borrow_metadata_maps_from_input_stream_class(ir_maps,
+ bt_event_class_borrow_stream_class_const(in_event_class));
+}
+
+#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_IR_MAPPING_H */
--- /dev/null
+/*
+ * Babeltrace - Trace IR metadata object copy
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-METADATA-COPY"
+#include "logging.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <babeltrace/assert-internal.h>
+
+#include "trace-ir-metadata-copy.h"
+#include "trace-ir-metadata-field-class-copy.h"
+#include "utils.h"
+
+BT_HIDDEN
+int copy_trace_class_content(const bt_trace_class *in_trace_class,
+ bt_trace_class *out_trace_class)
+{
+ int ret = 0;
+ uint64_t i, env_field_count;
+ const char *in_trace_class_name;
+ bt_uuid in_uuid;
+
+ BT_LOGD("Copying content of trace class: in-tc-addr=%p, out-tc-addr=%p",
+ in_trace_class, out_trace_class);
+
+ /* Use the same stream class ids as in the origin trace class. */
+ bt_trace_class_set_assigns_automatic_stream_class_id(out_trace_class,
+ BT_FALSE);
+
+ in_trace_class_name = bt_trace_class_get_name(in_trace_class);
+ if (in_trace_class_name) {
+ bt_trace_class_set_name(out_trace_class, in_trace_class_name);
+ }
+
+ in_uuid = bt_trace_class_get_uuid(in_trace_class);
+ if (in_uuid) {
+ bt_trace_class_set_uuid(out_trace_class, in_uuid);
+ }
+
+ /*
+ * Go over all the entries in the environment section of the trace class
+ * and copy the content to the new trace class.
+ */
+ env_field_count = bt_trace_class_get_environment_entry_count(in_trace_class);
+ for (i = 0; i < env_field_count; i++) {
+ const char *value_name;
+ const bt_value *value = NULL;
+ bt_trace_class_status trace_class_status;
+
+ bt_trace_class_borrow_environment_entry_by_index_const(
+ in_trace_class, i, &value_name, &value);
+
+ BT_LOGD("Copying trace class environnement entry: "
+ "index=%" PRId64 ", value-addr=%p, value-name=%s",
+ i, value, value_name);
+
+ BT_ASSERT(value_name);
+ BT_ASSERT(value);
+
+ if (bt_value_is_integer(value)) {
+ trace_class_status =
+ bt_trace_class_set_environment_entry_integer(
+ out_trace_class, value_name,
+ bt_value_integer_get(value));
+ } else if (bt_value_is_string(value)) {
+ trace_class_status =
+ bt_trace_class_set_environment_entry_string(
+ out_trace_class, value_name,
+ bt_value_string_get(value));
+ } else {
+ abort();
+ }
+
+ if (trace_class_status != BT_TRACE_CLASS_STATUS_OK) {
+ ret = -1;
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied content of trace class: in-tc-addr=%p, out-tc-addr=%p",
+ in_trace_class, out_trace_class);
+error:
+ return ret;
+}
+
+static
+int copy_clock_class_content(const bt_clock_class *in_clock_class,
+ bt_clock_class *out_clock_class)
+{
+ bt_clock_class_status status;
+ const char *clock_class_name, *clock_class_description;
+ int64_t seconds;
+ uint64_t cycles;
+ bt_uuid in_uuid;
+ int ret = 0;
+
+ BT_LOGD("Copying content of clock class: in-cc-addr=%p, out-cc-addr=%p",
+ in_clock_class, out_clock_class);
+
+ clock_class_name = bt_clock_class_get_name(in_clock_class);
+
+ if (clock_class_name) {
+ status = bt_clock_class_set_name(out_clock_class, clock_class_name);
+ if (status != BT_CLOCK_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting clock class' name cc-addr=%p, name=%p",
+ out_clock_class, clock_class_name);
+ out_clock_class = NULL;
+ ret = -1;
+ goto error;
+ }
+ }
+
+ clock_class_description = bt_clock_class_get_description(in_clock_class);
+
+ if (clock_class_description) {
+ status = bt_clock_class_set_description(out_clock_class,
+ clock_class_description);
+ if (status != BT_CLOCK_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting clock class' description cc-addr=%p, "
+ "name=%p", out_clock_class, clock_class_description);
+ out_clock_class = NULL;
+ ret = -1;
+ goto error;
+ }
+ }
+
+ in_uuid = bt_clock_class_get_uuid(in_clock_class);
+ if (in_uuid) {
+ bt_clock_class_set_uuid(out_clock_class, in_uuid);
+ }
+
+ bt_clock_class_set_frequency(out_clock_class,
+ bt_clock_class_get_frequency(in_clock_class));
+ bt_clock_class_set_precision(out_clock_class,
+ bt_clock_class_get_precision(in_clock_class));
+ bt_clock_class_get_offset(in_clock_class, &seconds, &cycles);
+ bt_clock_class_set_offset(out_clock_class, seconds, cycles);
+ bt_clock_class_set_origin_is_unix_epoch(out_clock_class,
+ bt_clock_class_origin_is_unix_epoch(in_clock_class));
+
+ BT_LOGD("Copied content of clock class: in-cc-addr=%p, out-cc-addr=%p",
+ in_clock_class, out_clock_class);
+
+error:
+ return ret;
+}
+
+static
+bt_clock_class *borrow_mapped_clock_class(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_clock_class *in_clock_class)
+{
+ BT_ASSERT(md_maps);
+ BT_ASSERT(in_clock_class);
+
+ return g_hash_table_lookup(md_maps->clock_class_map,
+ (gpointer) in_clock_class);
+}
+
+static
+bt_clock_class *create_new_mapped_clock_class(
+ bt_self_component *self_comp,
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_clock_class *in_clock_class)
+{
+ bt_clock_class *out_clock_class;
+ int ret;
+
+ BT_LOGD("Creating new mapped clock class: in-cc-addr=%p",
+ in_clock_class);
+
+ BT_ASSERT(md_maps);
+ BT_ASSERT(in_clock_class);
+
+ BT_ASSERT(!borrow_mapped_clock_class(md_maps, in_clock_class));
+
+ out_clock_class = bt_clock_class_create(self_comp);
+ if (!out_clock_class) {
+ BT_LOGE_STR("Cannot create clock class");
+ goto end;
+ }
+ /* If not, create a new one and add it to the mapping. */
+ ret = copy_clock_class_content(in_clock_class, out_clock_class);
+ if (ret) {
+ BT_LOGE_STR("Cannot copy clock class");
+ goto end;
+ }
+
+ g_hash_table_insert(md_maps->clock_class_map,
+ (gpointer) in_clock_class, out_clock_class);
+
+ BT_LOGD("Created new mapped clock class: in-cc-addr=%p, out-cc-addr=%p",
+ in_clock_class, out_clock_class);
+end:
+ return out_clock_class;
+}
+
+BT_HIDDEN
+int copy_stream_class_content(struct trace_ir_maps *ir_maps,
+ const bt_stream_class *in_stream_class,
+ bt_stream_class *out_stream_class)
+{
+ struct trace_ir_metadata_maps *md_maps;
+ const bt_clock_class *in_clock_class;
+ bt_clock_class *out_clock_class;
+ const bt_field_class *in_packet_context_fc, *in_common_context_fc;
+ bt_field_class *out_packet_context_fc, *out_common_context_fc;
+ bt_stream_class_status status;
+ const char *in_name;
+ int ret = 0;
+
+ BT_LOGD("Copying content of stream class: in-sc-addr=%p, out-sc-addr=%p",
+ in_stream_class, out_stream_class);
+
+ md_maps = borrow_metadata_maps_from_input_stream_class(ir_maps, in_stream_class);
+ in_clock_class = bt_stream_class_borrow_default_clock_class_const(
+ in_stream_class);
+
+ if (in_clock_class) {
+ /* Copy the clock class. */
+ out_clock_class =
+ borrow_mapped_clock_class(md_maps, in_clock_class);
+ if (!out_clock_class) {
+ out_clock_class = create_new_mapped_clock_class(
+ ir_maps->self_comp, md_maps,
+ in_clock_class);
+ }
+ bt_stream_class_set_default_clock_class(out_stream_class,
+ out_clock_class);
+
+ }
+
+ in_name = bt_stream_class_get_name(in_stream_class);
+ if (in_name) {
+ status = bt_stream_class_set_name(out_stream_class, in_name);
+ if (status != BT_STREAM_CLASS_STATUS_OK) {
+ BT_LOGE("Error set stream class name: out-sc-addr=%p, "
+ "name=%s", out_stream_class, in_name);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ bt_stream_class_set_assigns_automatic_stream_id(out_stream_class,
+ BT_FALSE);
+ bt_stream_class_set_assigns_automatic_event_class_id(out_stream_class,
+ BT_FALSE);
+
+ /*
+ * Add the input packet context field class to the context to
+ * resolution in the further steps.
+ */
+ in_packet_context_fc =
+ bt_stream_class_borrow_packet_context_field_class_const(
+ in_stream_class);
+ md_maps->fc_resolving_ctx->packet_context =
+ in_packet_context_fc;
+
+ if (in_packet_context_fc) {
+ /* Copy packet context. */
+ out_packet_context_fc = create_field_class_copy(
+ md_maps, in_packet_context_fc);
+
+ ret = copy_field_class_content(md_maps,
+ in_packet_context_fc, out_packet_context_fc);
+ if (ret) {
+ ret = -1;
+ goto error;
+ }
+
+ status = bt_stream_class_set_packet_context_field_class(
+ out_stream_class, out_packet_context_fc);
+ if (status != BT_STREAM_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting stream class' packet context "
+ "field class: sc-addr=%p, packet-fc-addr=%p",
+ out_stream_class, out_packet_context_fc);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ /*
+ * Add the input common context field class to the context to
+ * resolution in the further steps.
+ */
+ in_common_context_fc =
+ bt_stream_class_borrow_event_common_context_field_class_const(
+ in_stream_class);
+ md_maps->fc_resolving_ctx->event_common_context =
+ in_common_context_fc;
+
+ if (in_common_context_fc) {
+ /* Copy common context. */
+ /* TODO: I find it a bit awkward to have this special function
+ * here to add the debug-info field class. I would like to
+ * abstract that.*/
+ out_common_context_fc = create_field_class_copy(
+ md_maps, in_common_context_fc);
+
+ ret = copy_event_common_context_field_class_content(
+ md_maps, ir_maps->debug_info_field_class_name,
+ in_common_context_fc, out_common_context_fc);
+ if (ret) {
+ goto error;
+ }
+
+ status = bt_stream_class_set_event_common_context_field_class(
+ out_stream_class, out_common_context_fc);
+ if (status != BT_STREAM_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting stream class' packet context "
+ "field class: sc-addr=%p, packet-fc-addr=%p",
+ out_stream_class, out_common_context_fc);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ /* Set packet snapshot boolean fields. */
+ BT_LOGD("Copied content of stream class: in-sc-addr=%p, out-sc-addr=%p",
+ in_stream_class, out_stream_class);
+error:
+ return ret;
+}
+
+BT_HIDDEN
+int copy_event_class_content(struct trace_ir_maps *ir_maps,
+ const bt_event_class *in_event_class,
+ bt_event_class *out_event_class)
+{
+ struct trace_ir_metadata_maps *md_maps;
+ const char *in_event_class_name, *in_emf_uri;
+ bt_property_availability prop_avail;
+ bt_event_class_log_level log_level;
+ bt_event_class_status status;
+ bt_field_class *out_specific_context_fc, *out_payload_fc;
+ const bt_field_class *in_event_specific_context, *in_event_payload;
+ int ret = 0;
+
+ BT_LOGD("Copying content of event class: in-ec-addr=%p, out-ec-addr=%p",
+ in_event_class, out_event_class);
+
+ /* Copy event class name. */
+ in_event_class_name = bt_event_class_get_name(in_event_class);
+ if (in_event_class_name) {
+ status = bt_event_class_set_name(out_event_class, in_event_class_name);
+ if (status != BT_EVENT_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting event class' name: ec-addr=%p, "
+ "name=%s", out_event_class, in_event_class_name);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ /* Copy event class loglevel. */
+ prop_avail = bt_event_class_get_log_level(in_event_class, &log_level);
+ if (prop_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) {
+ bt_event_class_set_log_level(out_event_class,
+ log_level);
+ }
+
+ /* Copy event class emf uri. */
+ in_emf_uri = bt_event_class_get_emf_uri(in_event_class);
+ if (in_emf_uri) {
+ status = bt_event_class_set_emf_uri(out_event_class, in_emf_uri);
+ if (status != BT_EVENT_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting event class' emf uri: ec-addr=%p, "
+ "emf uri=%s", out_event_class, in_emf_uri);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ md_maps = borrow_metadata_maps_from_input_event_class(ir_maps, in_event_class);
+ /*
+ * Add the input event class' specific ctx to te
+ * context.
+ */
+ in_event_specific_context =
+ bt_event_class_borrow_specific_context_field_class_const(
+ in_event_class);
+
+ md_maps->fc_resolving_ctx->event_specific_context =
+ in_event_specific_context;
+
+ if (in_event_specific_context) {
+ /* Copy the specific context of this event class. */
+ out_specific_context_fc = create_field_class_copy(md_maps,
+ in_event_specific_context);
+
+ copy_field_class_content(md_maps,
+ in_event_specific_context, out_specific_context_fc);
+ if (ret) {
+ goto error;
+ }
+ /*
+ * Add the output specific context to the output event
+ * class.
+ */
+ status = bt_event_class_set_specific_context_field_class(
+ out_event_class, out_specific_context_fc);
+ if (status != BT_EVENT_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting event class' specific context "
+ "field class: ec-addr=%p, ctx-fc-addr=%p",
+ out_event_class, out_specific_context_fc);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ /*
+ * Add the input event class' payload field class to
+ * the context.
+ */
+ in_event_payload = bt_event_class_borrow_payload_field_class_const(
+ in_event_class);
+
+ md_maps->fc_resolving_ctx->event_payload = in_event_payload;
+
+ if (in_event_payload) {
+ /* Copy the payload of this event class. */
+ out_payload_fc = create_field_class_copy(md_maps,
+ in_event_payload);
+ copy_field_class_content(md_maps,
+ in_event_payload, out_payload_fc);
+ if (ret) {
+ goto error;
+ }
+
+ /* Add the output payload to the output event class. */
+ status = bt_event_class_set_payload_field_class(
+ out_event_class, out_payload_fc);
+ if (status != BT_EVENT_CLASS_STATUS_OK) {
+ BT_LOGE("Error setting event class' payload "
+ "field class: ec-addr=%p, payload-fc-addr=%p",
+ out_event_class, out_payload_fc);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied content of event class: in-ec-addr=%p, out-ec-addr=%p",
+ in_event_class, out_event_class);
+error:
+ return ret;
+}
+
+BT_HIDDEN
+int copy_event_common_context_field_class_content(
+ struct trace_ir_metadata_maps *md_maps,
+ const char *debug_info_fc_name,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ bt_field_class_status status;
+ bt_field_class *debug_field_class = NULL, *bin_field_class = NULL,
+ *func_field_class = NULL, *src_field_class = NULL;
+ int ret = 0;
+
+ BT_LOGD("Copying content of event common context field class: "
+ "in-fc-addr=%p, out-fc-addr=%p", in_field_class, out_field_class);
+
+ /* Copy the content of the input common context. */
+ ret = copy_field_class_content(md_maps, in_field_class, out_field_class);
+ if (ret) {
+ goto error;
+ }
+
+ /*
+ * If this event common context has the necessary fields to compute the
+ * debug information append the debug-info field class to the event
+ * common context.
+ */
+ if (is_event_common_ctx_dbg_info_compatible(in_field_class, debug_info_fc_name)) {
+ /*
+ * The struct field and 3 sub-fields are not stored in the
+ * field class map because they don't have input equivalent.
+ * We need to put our reference each of these field classes
+ * once they are added to their respective containing field
+ * classes.
+ */
+ debug_field_class = bt_field_class_structure_create(
+ md_maps->output_trace_class);
+ if (!debug_field_class) {
+ BT_LOGE_STR("Failed to create debug_info structure.");
+ ret = -1;
+ goto error;
+ }
+
+ bin_field_class = bt_field_class_string_create(
+ md_maps->output_trace_class);
+ if (!bin_field_class) {
+ BT_LOGE_STR("Failed to create string for field=bin.");
+ ret = -1;
+ goto error;
+ }
+
+ func_field_class = bt_field_class_string_create(
+ md_maps->output_trace_class);
+ if (!func_field_class) {
+ BT_LOGE_STR("Failed to create string for field=func.");
+ ret = -1;
+ goto error;
+ }
+
+ src_field_class = bt_field_class_string_create(
+ md_maps->output_trace_class);
+ if (!src_field_class) {
+ BT_LOGE_STR("Failed to create string for field=src.");
+ ret = -1;
+ goto error;
+ }
+
+ status = bt_field_class_structure_append_member(
+ debug_field_class, "bin", bin_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add a field to debug_info "
+ "struct: field=bin.");
+ ret = -1;
+ goto error;
+ }
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(bin_field_class);
+
+ status = bt_field_class_structure_append_member(
+ debug_field_class, "func", func_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add a field to debug_info "
+ "struct: field=func.");
+ ret = -1;
+ goto error;
+ }
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(func_field_class);
+
+ status = bt_field_class_structure_append_member(
+ debug_field_class, "src", src_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add a field to debug_info "
+ "struct: field=src.");
+ ret = -1;
+ goto error;
+ }
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(src_field_class);
+
+ /*Add the filled debug-info field class to the common context. */
+ status = bt_field_class_structure_append_member(out_field_class,
+ debug_info_fc_name,
+ debug_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add debug_info field to "
+ "event common context.");
+ ret = -1;
+ goto error;
+ }
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(debug_field_class);
+ }
+ BT_LOGD("Copied content of event common context field class: "
+ "in-fc-addr=%p, out-fc-addr=%p", in_field_class, out_field_class);
+ goto end;
+
+error:
+ if (debug_field_class) {
+ bt_field_class_put_ref(debug_field_class);
+ }
+ if (bin_field_class) {
+ bt_field_class_put_ref(bin_field_class);
+ }
+ if (func_field_class) {
+ bt_field_class_put_ref(func_field_class);
+ }
+ if (src_field_class) {
+ bt_field_class_put_ref(src_field_class);
+ }
+end:
+ return ret;
+}
+
+BT_HIDDEN
+bt_field_class *create_field_class_copy(struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class)
+{
+ return create_field_class_copy_internal(md_maps, in_field_class);
+}
+
+BT_HIDDEN
+int copy_field_class_content(struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ return copy_field_class_content_internal(md_maps, in_field_class,
+ out_field_class);
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_METADATA_COPY_H
+#define BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_METADATA_COPY_H
+
+/*
+ * Babeltrace - Trace IR metadata object copy
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/babeltrace.h>
+#include "trace-ir-mapping.h"
+
+BT_HIDDEN
+int copy_trace_class_content(const bt_trace_class *in_trace_class,
+ bt_trace_class *out_trace_class);
+
+BT_HIDDEN
+int copy_stream_class_content(struct trace_ir_maps *trace_ir_maps,
+ const bt_stream_class *in_stream_class,
+ bt_stream_class *out_stream_class);
+
+BT_HIDDEN
+int copy_event_class_content(struct trace_ir_maps *trace_ir_maps,
+ const bt_event_class *in_event_class,
+ bt_event_class *out_event_class);
+
+BT_HIDDEN
+int copy_field_class_content(struct trace_ir_metadata_maps *trace_ir_metadata_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class);
+
+BT_HIDDEN
+int copy_event_common_context_field_class_content(
+ struct trace_ir_metadata_maps *trace_ir_metadata_maps,
+ const char *debug_info_field_class_name,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class);
+
+BT_HIDDEN
+bt_field_class *create_field_class_copy(
+ struct trace_ir_metadata_maps *trace_ir_metadata_maps,
+ const bt_field_class *in_field_class);
+
+#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_TRACE_METADATA_COPY_H */
--- /dev/null
+/*
+ * Babeltrace - Trace IR field copy
+ *
+ * Copyright (c) 2015-2019 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-METADATA-FC-COPY"
+#include "logging.h"
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/babeltrace.h>
+
+#include "trace-ir-metadata-copy.h"
+#include "trace-ir-metadata-field-class-copy.h"
+
+/*
+ * This fonction walks througth the nested structures field class to resolve a
+ * field path object. A field path is made of indexes inside possibly nested
+ * structures ultimately leading to a field class.
+ */
+static
+const bt_field_class *walk_field_path(const bt_field_path *fp,
+ const bt_field_class *fc)
+{
+ uint64_t i, fp_index_count;
+ const bt_field_class *curr_fc;
+
+ BT_ASSERT(bt_field_class_get_type(fc) == BT_FIELD_CLASS_TYPE_STRUCTURE);
+ BT_LOGD("Walking field path on field class: fp-addr=%p, fc-addr=%p",
+ fp, fc);
+
+ fp_index_count = bt_field_path_get_index_count(fp);
+ curr_fc = fc;
+ for (i = 0; i < fp_index_count; i++) {
+ const char *fc_name;
+ bt_field_class_type fc_type = bt_field_class_get_type(curr_fc);
+ uint64_t curr_index = bt_field_path_get_index_by_index(fp, i);
+
+ switch (fc_type) {
+ case BT_FIELD_CLASS_TYPE_STRUCTURE:
+ bt_field_class_structure_borrow_member_by_index_const(
+ curr_fc, curr_index, &fc_name, &curr_fc);
+ break;
+ case BT_FIELD_CLASS_TYPE_VARIANT:
+ bt_field_class_variant_borrow_option_by_index_const(
+ curr_fc, curr_index, &fc_name, &curr_fc);
+ break;
+ default:
+ abort();
+ }
+ }
+
+ return curr_fc;
+}
+
+static
+const bt_field_class *resolve_field_path_to_field_class(const bt_field_path *fp,
+ struct trace_ir_metadata_maps *md_maps)
+{
+ struct field_class_resolving_context *fc_resolving_ctx;
+ const bt_field_class *fc;
+ bt_scope fp_scope;
+
+ BT_LOGD("Resolving field path: fp-addr=%p", fp);
+
+ fc_resolving_ctx = md_maps->fc_resolving_ctx;
+ fp_scope = bt_field_path_get_root_scope(fp);
+
+ switch (fp_scope) {
+ case BT_SCOPE_PACKET_CONTEXT:
+ fc = walk_field_path(fp, fc_resolving_ctx->packet_context);
+ break;
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ fc = walk_field_path(fp, fc_resolving_ctx->event_common_context);
+ break;
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ fc = walk_field_path(fp, fc_resolving_ctx->event_specific_context);
+ break;
+ case BT_SCOPE_EVENT_PAYLOAD:
+ fc = walk_field_path(fp, fc_resolving_ctx->event_payload);
+ break;
+ default:
+ abort();
+ }
+
+ return fc;
+}
+
+static inline
+void field_class_integer_set_props(const bt_field_class *input_fc,
+ bt_field_class *output_fc)
+{
+ bt_field_class_integer_set_preferred_display_base(output_fc,
+ bt_field_class_integer_get_preferred_display_base(input_fc));
+ bt_field_class_integer_set_field_value_range(output_fc,
+ bt_field_class_integer_get_field_value_range(input_fc));
+}
+
+static inline
+int field_class_unsigned_integer_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ BT_LOGD("Copying content of unsigned integer field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ field_class_integer_set_props(in_field_class, out_field_class);
+
+ BT_LOGD("Copied content of unsigned integer field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+ return 0;
+}
+
+static inline
+int field_class_signed_integer_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ BT_LOGD("Copying content of signed integer field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ field_class_integer_set_props(in_field_class, out_field_class);
+
+ BT_LOGD("Copied content of signed integer field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+ return 0;
+}
+
+BT_HIDDEN
+int field_class_unsigned_enumeration_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ uint64_t i, enum_mapping_count;
+ int ret = 0;
+
+ BT_LOGD("Copying content of unsigned enumeration field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ /* Copy properties of the inner integer. */
+ field_class_integer_set_props(in_field_class, out_field_class);
+
+ /* Copy all enumeration entries. */
+ enum_mapping_count = bt_field_class_enumeration_get_mapping_count(in_field_class);
+ for (i = 0; i < enum_mapping_count; i++) {
+ const char *label;
+ const bt_field_class_unsigned_enumeration_mapping_ranges *ranges;
+ uint64_t range_index, range_count;
+
+ /* Get the ranges and the range count. */
+ bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
+ in_field_class, i, &label, &ranges);
+ range_count =
+ bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
+ ranges);
+ /*
+ * Iterate over all the ranges to add them to copied field
+ * class.
+ */
+ for (range_index = 0; range_index < range_count; range_index++) {
+ uint64_t lower, upper;
+ bt_field_class_status status;
+ bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
+ ranges, range_index, &lower, &upper);
+
+ BT_LOGD("Copying range in enumeration field class: "
+ "label=%s, lower=%"PRId64", upper=%"PRId64,
+ label, lower, upper);
+
+ /* Add the label and its range to the copy field class. */
+ status = bt_field_class_unsigned_enumeration_map_range(
+ out_field_class, label, lower, upper);
+
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add range to unsigned "
+ "enumeration.");
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class);
+ ret = -1;
+ goto error;
+ }
+ }
+ }
+
+ BT_LOGD("Copied content of unsigned enumeration field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+error:
+ return ret;
+}
+
+static inline
+int field_class_signed_enumeration_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ uint64_t i, enum_mapping_count;
+ int ret = 0;
+
+ BT_LOGD("Copying content of signed enumeration field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ /* Copy properties of the inner integer. */
+ field_class_integer_set_props(in_field_class, out_field_class);
+
+ /* Copy all enumeration entries. */
+ enum_mapping_count =
+ bt_field_class_enumeration_get_mapping_count(in_field_class);
+ for (i = 0; i < enum_mapping_count; i++) {
+ const char *label;
+ const bt_field_class_signed_enumeration_mapping_ranges *ranges;
+ uint64_t range_index, range_count;
+
+ /* Get the ranges and the range count. */
+ bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
+ in_field_class, i, &label, &ranges);
+ range_count =
+ bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
+ ranges);
+ /*
+ * Iterate over all the ranges to add them to copied field
+ * class.
+ */
+ for (range_index = 0; range_index < range_count; range_index++) {
+ int64_t lower, upper;
+ bt_field_class_status status;
+ bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
+ ranges, range_index, &lower, &upper);
+
+ BT_LOGD("Copying range in enumeration field class: "
+ "label=%s, lower=%ld, upper=%ld",
+ label, lower, upper);
+
+ /* Add the label and its range to the copy field class. */
+ status = bt_field_class_signed_enumeration_map_range(
+ out_field_class, label, lower, upper);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Failed to add range to signed "
+ "enumeration.");
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class);
+ ret = -1;
+ goto error;
+ }
+ }
+ }
+
+ BT_LOGD("Copied content of signed enumeration field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+error:
+ return ret;
+}
+
+static inline
+int field_class_real_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ BT_LOGD("Copying content of real field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ bt_field_class_real_set_is_single_precision(out_field_class,
+ bt_field_class_real_is_single_precision(in_field_class));
+
+ BT_LOGD("Copied content real field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+
+ return 0;
+}
+
+static inline
+int field_class_structure_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ uint64_t i, struct_member_count;
+ bt_field_class_status status;
+ int ret = 0;
+
+ BT_LOGD("Copying content of structure field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+ /* Get the number of member in that struct. */
+ struct_member_count =
+ bt_field_class_structure_get_member_count(in_field_class);
+
+ /* Iterate over all the members of the struct. */
+ for (i = 0; i < struct_member_count; i++) {
+ const char *member_name;
+ const bt_field_class *member_fc;
+ bt_field_class *out_member_field_class;
+
+ bt_field_class_structure_borrow_member_by_index_const(
+ in_field_class, i, &member_name, &member_fc);
+ BT_LOGD("Copying structure field class's field: "
+ "index=%" PRId64 ", "
+ "member-fc-addr=%p, field-name=\"%s\"",
+ i, member_fc, member_name);
+
+ out_member_field_class = create_field_class_copy(md_maps,
+ member_fc);
+ if (!out_member_field_class) {
+ BT_LOGE("Cannot copy structure field class's field: "
+ "index=%" PRId64 ", "
+ "field-fc-addr=%p, field-name=\"%s\"",
+ i, member_fc, member_name);
+ ret = -1;
+ goto error;
+ }
+ ret = copy_field_class_content(md_maps, member_fc,
+ out_member_field_class);
+ if (ret) {
+ goto error;
+ }
+
+ status = bt_field_class_structure_append_member(out_field_class,
+ member_name, out_member_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE("Cannot append structure field class's field: "
+ "index=%" PRId64 ", "
+ "field-fc-addr=%p, field-name=\"%s\"",
+ i, member_fc, member_name);
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_member_field_class);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied structure field class: original-fc-addr=%p, copy-fc-addr=%p",
+ in_field_class, out_field_class);
+
+error:
+ return ret;
+}
+
+static inline
+int field_class_variant_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ bt_field_class *out_tag_field_class;
+ uint64_t i, variant_option_count;
+ const bt_field_path *tag_fp;
+ const bt_field_class *tag_fc;
+ int ret = 0;
+
+ BT_LOGD("Copying content of variant field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ tag_fp = bt_field_class_variant_borrow_selector_field_path_const(
+ in_field_class);
+ if (tag_fp) {
+ tag_fc = resolve_field_path_to_field_class(tag_fp,
+ md_maps);
+
+ out_tag_field_class = g_hash_table_lookup(
+ md_maps->field_class_map, tag_fc);
+ if (!out_tag_field_class) {
+ BT_LOGE_STR("Cannot find the tag field class.");
+ ret = -1;
+ goto error;
+ }
+ bt_field_class_variant_set_selector_field_class(out_field_class,
+ out_tag_field_class);
+ }
+
+ variant_option_count =
+ bt_field_class_variant_get_option_count(in_field_class);
+ for (i = 0; i < variant_option_count; i++) {
+ const bt_field_class *option;
+ const char *option_name;
+ bt_field_class *out_option_field_class;
+ bt_field_class_status status;
+
+ bt_field_class_variant_borrow_option_by_index_const(in_field_class,
+ i, &option_name, &option);
+
+ out_option_field_class = create_field_class_copy_internal(
+ md_maps, option);
+ if (!out_option_field_class) {
+ BT_LOGE_STR("Cannot copy field class.");
+ ret = -1;
+ goto error;
+ }
+ ret = copy_field_class_content_internal(md_maps, option,
+ out_option_field_class);
+ if (ret) {
+ BT_LOGE_STR("Error copying content of option variant "
+ "field class'");
+ goto error;
+ }
+
+ status = bt_field_class_variant_append_option(
+ out_field_class, option_name,
+ out_option_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Cannot append option to variant field class'");
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_tag_field_class);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied content of variant field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+
+error:
+ return ret;
+}
+
+static inline
+int field_class_static_array_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ BT_LOGD("Copying content of static array field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+ /*
+ * There is no content to copy. Keep this function call anyway for
+ * logging purposes.
+ */
+ BT_LOGD("Copied content of static array field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+
+ return 0;
+}
+
+static inline
+int field_class_dynamic_array_copy(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ const bt_field_class *element_fc, *len_fc;
+ const bt_field_path *len_fp;
+ bt_field_class_status status;
+ bt_field_class *out_len_field_class;
+ int ret = 0;
+
+ BT_LOGD("Copying content of dynamic array field class: "
+ "in-fc-addr=%p, out-fc-addr=%p",
+ in_field_class, out_field_class);
+
+ element_fc = bt_field_class_array_borrow_element_field_class_const(
+ in_field_class);
+ len_fp = bt_field_class_dynamic_array_borrow_length_field_path_const(
+ in_field_class);
+
+ if (len_fp) {
+ BT_LOGD("Copying dynamic array length field class using "
+ "field path: in-len-fp=%p", len_fp);
+ len_fc = resolve_field_path_to_field_class(
+ len_fp, md_maps);
+ out_len_field_class = g_hash_table_lookup(
+ md_maps->field_class_map, len_fc);
+ if (!out_len_field_class) {
+ BT_LOGE_STR("Cannot find the output matching length"
+ "field class.");
+ ret = -1;
+ goto error;
+ }
+
+ status = bt_field_class_dynamic_array_set_length_field_class(
+ out_field_class, out_len_field_class);
+ if (status != BT_FIELD_CLASS_STATUS_OK) {
+ BT_LOGE_STR("Cannot set dynamic array field class' "
+ "length field class.");
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_len_field_class);
+ ret = -1;
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied dynamic array field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+
+error:
+ return ret;
+}
+
+static inline
+int field_class_string_copy(struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ BT_LOGD("Copying content of string field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+ /*
+ * There is no content to copy. Keep this function call anyway for
+ * logging purposes.
+ */
+ BT_LOGD("Copied content of string field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+
+ return 0;
+}
+
+static
+bt_field_class *copy_field_class_array_element(struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_elem_fc)
+{
+ int ret;
+ bt_field_class *out_elem_fc =
+ create_field_class_copy_internal(md_maps, in_elem_fc);
+ if (!out_elem_fc) {
+ BT_LOGE("Error creating output elem field class "
+ "from input elem field class for static array: "
+ "in-fc-addr=%p", in_elem_fc);
+ goto error;
+ }
+
+ ret = copy_field_class_content_internal(md_maps, in_elem_fc, out_elem_fc);
+ if (ret) {
+ BT_LOGE("Error creating output elem field class "
+ "from input elem field class for static array: "
+ "in-fc-addr=%p", in_elem_fc);
+ BT_FIELD_CLASS_PUT_REF_AND_RESET(out_elem_fc);
+ goto error;
+ }
+
+error:
+ return out_elem_fc;
+}
+
+BT_HIDDEN
+bt_field_class *create_field_class_copy_internal(struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class)
+{
+ bt_field_class *out_field_class = NULL;
+
+ BT_LOGD("Creating bare field class based on field class: in-fc-addr=%p",
+ in_field_class);
+
+ switch(bt_field_class_get_type(in_field_class)) {
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
+ out_field_class = bt_field_class_unsigned_integer_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
+ out_field_class = bt_field_class_signed_integer_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
+ out_field_class = bt_field_class_unsigned_enumeration_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
+ out_field_class = bt_field_class_signed_enumeration_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_REAL:
+ out_field_class = bt_field_class_real_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STRING:
+ out_field_class = bt_field_class_string_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STRUCTURE:
+ out_field_class = bt_field_class_structure_create(
+ md_maps->output_trace_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
+ {
+ const bt_field_class *in_elem_fc =
+ bt_field_class_array_borrow_element_field_class_const(
+ in_field_class);
+ uint64_t array_len =
+ bt_field_class_static_array_get_length(in_field_class);
+
+ bt_field_class *out_elem_fc = copy_field_class_array_element(
+ md_maps, in_elem_fc);
+ if (!out_elem_fc) {
+ out_field_class = NULL;
+ goto error;
+ }
+
+ out_field_class = bt_field_class_static_array_create(
+ md_maps->output_trace_class,
+ out_elem_fc, array_len);
+ break;
+ }
+ case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
+ {
+ const bt_field_class *in_elem_fc =
+ bt_field_class_array_borrow_element_field_class_const(
+ in_field_class);
+
+ bt_field_class *out_elem_fc = copy_field_class_array_element(
+ md_maps, in_elem_fc);
+ if (!out_elem_fc) {
+ out_field_class = NULL;
+ goto error;
+ }
+
+ out_field_class = bt_field_class_dynamic_array_create(
+ md_maps->output_trace_class,
+ out_elem_fc);
+ break;
+ }
+ case BT_FIELD_CLASS_TYPE_VARIANT:
+ out_field_class = bt_field_class_variant_create(
+ md_maps->output_trace_class);
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * Add mapping from in_field_class to out_field_class. This simplifies
+ * the resolution of field paths in variant and dynamic array field
+ * classes.
+ */
+ g_hash_table_insert(md_maps->field_class_map,
+ (gpointer) in_field_class, out_field_class);
+
+error:
+ if(out_field_class){
+ BT_LOGD("Created bare field class based on field class: in-fc-addr=%p, "
+ "out-fc-addr=%p", in_field_class, out_field_class);
+ } else {
+ BT_LOGE("Error creating output field class from input field "
+ "class: in-fc-addr=%p", in_field_class);
+ }
+
+ return out_field_class;
+}
+
+BT_HIDDEN
+int copy_field_class_content_internal(
+ struct trace_ir_metadata_maps *md_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class)
+{
+ int ret = 0;
+ switch(bt_field_class_get_type(in_field_class)) {
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
+ ret = field_class_unsigned_integer_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
+ ret = field_class_signed_integer_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
+ ret = field_class_unsigned_enumeration_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
+ ret = field_class_signed_enumeration_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_REAL:
+ ret = field_class_real_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STRING:
+ ret = field_class_string_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STRUCTURE:
+ ret = field_class_structure_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
+ ret = field_class_static_array_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
+ ret = field_class_dynamic_array_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ case BT_FIELD_CLASS_TYPE_VARIANT:
+ ret = field_class_variant_copy(md_maps,
+ in_field_class, out_field_class);
+ break;
+ default:
+ abort();
+ }
+
+ return ret;
+}
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_DEBUG_INFO_FIELD_CLASS_COPY_H
+#define BABELTRACE_PLUGIN_DEBUG_INFO_FIELD_CLASS_COPY_H
+
+/*
+ * Babeltrace - Trace IR metadata field class copy
+ *
+ * Copyright (c) 2015-2019 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/babeltrace.h>
+#include "trace-ir-mapping.h"
+
+BT_HIDDEN
+int copy_field_class_content_internal(struct trace_ir_metadata_maps *trace_ir_metadata_maps,
+ const bt_field_class *in_field_class,
+ bt_field_class *out_field_class);
+
+BT_HIDDEN
+bt_field_class *create_field_class_copy_internal(
+ struct trace_ir_metadata_maps *trace_ir_metadata_maps,
+ const bt_field_class *in_field_class);
+
+#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_FIELD_CLASS_COPY_H */
end:
return path;
}
+
+BT_HIDDEN
+bt_bool is_event_common_ctx_dbg_info_compatible(const bt_field_class *in_field_class,
+ const char *debug_info_field_class_name)
+{
+ const bt_field_class *ip_fc, *vpid_fc, *debug_info_fc;
+ bt_bool match = BT_FALSE;
+
+ /*
+ * If the debug info field is already present in the event common
+ * context. Do not try to add it.
+ */
+ debug_info_fc =
+ bt_field_class_structure_borrow_member_field_class_by_name_const(
+ in_field_class, debug_info_field_class_name);
+ if (debug_info_fc) {
+ goto end;
+ }
+
+ /*
+ * Verify that the ip and vpid field are present and of the right field
+ * class.
+ */
+ ip_fc = bt_field_class_structure_borrow_member_field_class_by_name_const(
+ in_field_class, IP_FIELD_NAME);
+ if (!ip_fc) {
+ goto end;
+ }
+
+ if (bt_field_class_get_type(ip_fc) !=
+ BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER) {
+ match = BT_FALSE;
+ goto end;
+ }
+
+ if (bt_field_class_integer_get_field_value_range(ip_fc) != 64) {
+ goto end;
+ }
+
+ vpid_fc = bt_field_class_structure_borrow_member_field_class_by_name_const(
+ in_field_class, VPID_FIELD_NAME);
+ if (!vpid_fc) {
+ goto end;
+ }
+
+ if (bt_field_class_get_type(vpid_fc) !=
+ BT_FIELD_CLASS_TYPE_SIGNED_INTEGER) {
+ goto end;
+ }
+
+ if (bt_field_class_integer_get_field_value_range(vpid_fc) != 32) {
+ goto end;
+ }
+
+ match = BT_TRUE;
+end:
+ return match;
+}
-#ifndef _BABELTRACE_DEBUG_INFO_UTILS_H
-#define _BABELTRACE_DEBUG_INFO_UTILS_H
-
+#ifndef BABELTRACE_PLUGIN_DEBUG_INFO_UTILS_H
+#define BABELTRACE_PLUGIN_DEBUG_INFO_UTILS_H
/*
* Babeltrace - Debug Info Utilities
*
*/
#include <babeltrace/babeltrace-internal.h>
+#include "trace-ir-mapping.h"
/*
* Return the location of a path's file (the last element of the path).
BT_HIDDEN
const char *get_filename_from_path(const char *path);
-#endif /* _BABELTRACE_DEBUG_INFO_UTILS_H */
+BT_HIDDEN
+bt_bool is_event_common_ctx_dbg_info_compatible(
+ const bt_field_class *in_field_class,
+ const char *debug_info_field_class_name);
+
+#endif /* BABELTRACE_PLUGIN_DEBUG_INFO_UTILS_H */