flt.lttng-utils.debug-info: adapt debug-info component to API changes
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Tue, 19 Feb 2019 18:55:40 +0000 (13:55 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 3 May 2019 22:19:38 +0000 (18:19 -0400)
General idea
------------
Given that:
* debug-info filter component needs to add new fields to the
  events common context,
* Metadata and data objects are immutable after being added to
  the trace class or trace respectively.

The debug-info component needs output a new augmented trace containing
the new fields along side all the received input data. It thus needs to
act both as a sink AND a source of graph messages in the sense that it
consumes and creates graph messages.

For every message received, the corresponding output objects(e.g.
stream) are created in an output trace. Those objects are stored in
hashmaps corresponding to their types for later use. These hashmaps map
input object to their corresponding output objects.

For example, when handling a packet beginning message, we need to create
a new output packet. To do that, the corresponding output stream is
needed, amongst other things. This output stream was created earlier
when a stream beginning message was received and can be recovered from
the stream hashmap.

For each type of message received from the upstream iterator, we must
create a copy of that message and its corresponding trace IR objects,
and send it downstream. This is true for all but one message type,
inactivity messages can be forwarded directly as they are independent of
the data and metadata IR objects.

Implementation
--------------
This commit adds the concept of mapping between input and output objects
and implements copy functions to create (nearly) identical output
objects based on the input ones.

The entry point of the mapping of objects is the struct trace_id_maps
structure.

The metadata_map and data_map hashtables have input trace class and
input trace objects, respectively, as key and are pointing to struct
trace_ir_metadata_maps and struct trace_ir_data_maps. Each of the IR
object maps contained in these structs have the input object of their
specific types as key.

All input and mapped output objects are identical except for the stream
classes. Event-common-context of the stream classes needs to be modified
to include the debug-info fields if and only if the right fields
(instruction pointer (ip) and vpid) are present in the input stream
class.
Here are the objects kept in the mapping:
  - Trace class
  - Stream class
  - Event class
  - Clock class
  - Trace
  - Stream
  - Packet

The memory layout of each processes is kept up to date using the
lttng-ust-statedump and lib-load events. This information is then used
to resolve source locations based on ip and vpid values found in the
event-common-context of events.

Future Improvements
---------------------
Decoupling the trace-ir-mapping library from the debug-info component so
it can be used in other filter components.

Other fixes
-----------
- Don't resolve debug-info on build id mismatch
- When parsing the build id of a statedump event, confirm that it
  matches the one present on disk for that file.
- Prevent NULL pointer access of arg_debug_info_field_name
- Typo in the lttng_ust_statedump:debug_link event name.
- Typo in the crc field name of the lttng_ust_statedump:debug_link
  event.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
27 files changed:
configure.ac
plugins/Makefile.am
plugins/libctfcopytrace/Makefile.am [deleted file]
plugins/libctfcopytrace/clock-fields.c [deleted file]
plugins/libctfcopytrace/clock-fields.h [deleted file]
plugins/libctfcopytrace/ctfcopytrace.c [deleted file]
plugins/libctfcopytrace/ctfcopytrace.h [deleted file]
plugins/libctfcopytrace/logging.c [deleted file]
plugins/libctfcopytrace/logging.h [deleted file]
plugins/lttng-utils/Makefile.am
plugins/lttng-utils/bin-info.c
plugins/lttng-utils/bin-info.h
plugins/lttng-utils/copy.c [deleted file]
plugins/lttng-utils/copy.h [deleted file]
plugins/lttng-utils/debug-info.c
plugins/lttng-utils/debug-info.h
plugins/lttng-utils/plugin.c
plugins/lttng-utils/trace-ir-data-copy.c [new file with mode: 0644]
plugins/lttng-utils/trace-ir-data-copy.h [new file with mode: 0644]
plugins/lttng-utils/trace-ir-mapping.c [new file with mode: 0644]
plugins/lttng-utils/trace-ir-mapping.h [new file with mode: 0644]
plugins/lttng-utils/trace-ir-metadata-copy.c [new file with mode: 0644]
plugins/lttng-utils/trace-ir-metadata-copy.h [new file with mode: 0644]
plugins/lttng-utils/trace-ir-metadata-field-class-copy.c [new file with mode: 0644]
plugins/lttng-utils/trace-ir-metadata-field-class-copy.h [new file with mode: 0644]
plugins/lttng-utils/utils.c
plugins/lttng-utils/utils.h

index 6426e574d1c1529f318b2dc197a950e3047d426b..723386db821ed2a4361958061da32a376e18f880 100644 (file)
@@ -68,7 +68,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 ##                      ##
 
 MINGW32=no
-DEFAULT_ENABLE_DEBUG_INFO=no
+DEFAULT_ENABLE_DEBUG_INFO=yes
 LT_NO_UNDEFINED=""
 AS_CASE([$host_os],
   [solaris*|darwin*],
@@ -787,7 +787,6 @@ AC_CONFIG_FILES([
        plugins/utils/trimmer/Makefile
        plugins/utils/muxer/Makefile
        python-plugin-provider/Makefile
-       plugins/libctfcopytrace/Makefile
        plugins/lttng-utils/Makefile
        babeltrace.pc
        babeltrace-ctf.pc
index a1dd508a08726b2522441b73044128a27edaaac3..9b23e3c41c86ed738d33246052ef330f7d4929ec 100644 (file)
@@ -1,8 +1,7 @@
 SUBDIRS = utils text ctf
-# libctfcopytrace
 
 if ENABLE_DEBUG_INFO
-#SUBDIRS += lttng-utils
+SUBDIRS += lttng-utils
 endif
 
 noinst_HEADERS = plugins-common.h
diff --git a/plugins/libctfcopytrace/Makefile.am b/plugins/libctfcopytrace/Makefile.am
deleted file mode 100644 (file)
index d8f4b3e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-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
diff --git a/plugins/libctfcopytrace/clock-fields.c b/plugins/libctfcopytrace/clock-fields.c
deleted file mode 100644 (file)
index 07d129d..0000000
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * 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;
-}
-
diff --git a/plugins/libctfcopytrace/clock-fields.h b/plugins/libctfcopytrace/clock-fields.h
deleted file mode 100644 (file)
index c5781aa..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#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 */
diff --git a/plugins/libctfcopytrace/ctfcopytrace.c b/plugins/libctfcopytrace/ctfcopytrace.c
deleted file mode 100644 (file)
index a65b050..0000000
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/libctfcopytrace/ctfcopytrace.h b/plugins/libctfcopytrace/ctfcopytrace.h
deleted file mode 100644 (file)
index 7658773..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-#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 */
diff --git a/plugins/libctfcopytrace/logging.c b/plugins/libctfcopytrace/logging.c
deleted file mode 100644 (file)
index 83b1872..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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");
diff --git a/plugins/libctfcopytrace/logging.h b/plugins/libctfcopytrace/logging.h
deleted file mode 100644 (file)
index fe1513d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#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 */
index f8262926617ae3f380b85a23789fffb824b38ffb..a090390f9f9d83bb3c62e1cc92a8ea0de09734bc 100644 (file)
@@ -1,5 +1,4 @@
-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 = \
@@ -11,6 +10,14 @@ 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
 
@@ -20,9 +27,7 @@ plugin_LTLIBRARIES = babeltrace-plugin-lttng-utils.la
 babeltrace_plugin_lttng_utils_la_SOURCES = \
        plugin.c \
        utils.c \
-       copy.c \
        utils.h \
-       copy.h \
        logging.h
 
 babeltrace_plugin_lttng_utils_la_LIBADD = \
@@ -37,6 +42,5 @@ if !ENABLE_BUILT_IN_PLUGINS
 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
index 33314bbc5dfa8593bc022bf79cb72ecabf2ca5cb..176b37784b9db0f94973902def34ffdf0222e53c 100644 (file)
@@ -51,6 +51,7 @@
  * character).
  */
 #define ADDR_STR_LEN 20
+#define BUILD_ID_NOTE_NAME "GNU"
 
 BT_HIDDEN
 int bin_info_init(void)
@@ -86,7 +87,7 @@ struct bin_info *bin_info_create(const char *path, uint64_t low_addr,
                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) {
@@ -104,6 +105,9 @@ struct bin_info *bin_info_create(const char *path, uint64_t low_addr,
        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;
 
@@ -135,6 +139,227 @@ void bin_info_destroy(struct bin_info *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)
@@ -143,7 +368,8 @@ int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
                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;
        }
@@ -151,6 +377,17 @@ int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
        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
@@ -161,7 +398,6 @@ int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
        return 0;
 
 error:
-
        return -1;
 }
 
@@ -364,7 +600,7 @@ end_noclose:
 
 /**
  * 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
@@ -490,54 +726,6 @@ end:
        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)
 {
@@ -930,6 +1118,14 @@ int bin_info_lookup_function_name(struct bin_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;
+       }
+
        /* 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);
@@ -977,6 +1173,14 @@ int bin_info_get_bin_loc(struct bin_info *bin, uint64_t addr, char **bin_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;
+       }
+
        if (bin->is_pic) {
                addr -= bin->low_addr;
                ret = asprintf(&_bin_loc, "+%#0" PRIx64, addr);
@@ -1303,6 +1507,14 @@ int bin_info_lookup_source_location(struct bin_info *bin, uint64_t 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)) {
index 05d0d797d0372697a45eb23f33394507df965ed0..42cb1abcb60a9e8aeba358dfff1b11528b2341ff 100644 (file)
@@ -54,6 +54,7 @@ struct bin_info {
        /* 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;
@@ -64,6 +65,8 @@ struct bin_info {
        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.
diff --git a/plugins/lttng-utils/copy.c b/plugins/lttng-utils/copy.c
deleted file mode 100644 (file)
index 918e6e1..0000000
+++ /dev/null
@@ -1,1956 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/lttng-utils/copy.h b/plugins/lttng-utils/copy.h
deleted file mode 100644 (file)
index 33c26c2..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#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 */
index 614b1b43c025327969d948a6b74e3e5b1fdd6f40..fbffff2f994a270c5dc9aa7794a71d5420580d6d 100644 (file)
@@ -5,6 +5,7 @@
  * 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 {
        /*
@@ -51,6 +109,8 @@ 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
@@ -72,7 +132,7 @@ int debug_info_init(struct debug_info *info)
        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(
@@ -92,6 +152,7 @@ void debug_info_source_destroy(struct debug_info_source *debug_info_src)
        }
 
        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);
@@ -99,8 +160,8 @@ void debug_info_source_destroy(struct debug_info_source *debug_info_src)
 }
 
 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;
@@ -122,11 +183,17 @@ struct debug_info_source *debug_info_source_create_from_bin(struct bin_info *bin
        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);
@@ -137,7 +204,6 @@ struct debug_info_source *debug_info_source_create_from_bin(struct bin_info *bin
                        debug_info_src->short_src_path = get_filename_from_path(
                                        debug_info_src->src_path);
                }
-
                source_location_destroy(src_loc);
        }
 
@@ -248,6 +314,125 @@ end:
        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)
@@ -325,7 +510,8 @@ end:
 }
 
 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;
@@ -348,6 +534,8 @@ struct debug_info *debug_info_create(struct debug_info_component *comp)
                goto error;
        }
 
+       debug_info->input_trace = trace;
+
 end:
        return debug_info;
 error:
@@ -358,6 +546,7 @@ error:
 BT_HIDDEN
 void debug_info_destroy(struct debug_info *debug_info)
 {
+       bt_trace_status status;
        if (!debug_info) {
                goto end;
        }
@@ -366,35 +555,29 @@ void debug_info_destroy(struct debug_info *debug_info)
                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);
@@ -411,16 +594,23 @@ void handle_statedump_build_id_event(FILE *err, struct debug_info *debug_info,
                 */
                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;
        }
 
        /*
@@ -430,15 +620,13 @@ void handle_statedump_build_id_event(FILE *err, struct debug_info *debug_info,
         */
        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;
@@ -447,42 +635,21 @@ void handle_statedump_debug_link_event(FILE *err, struct debug_info *debug_info,
        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);
@@ -507,7 +674,7 @@ end:
 }
 
 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;
@@ -517,46 +684,32 @@ void handle_bin_info_event(FILE *err, struct debug_info *debug_info,
        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
@@ -565,16 +718,8 @@ void handle_bin_info_event(FILE *err, struct debug_info *debug_info,
                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);
@@ -613,70 +758,60 @@ end:
 }
 
 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);
@@ -691,30 +826,53 @@ end:
        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) {
                /*
@@ -726,22 +884,1163 @@ void debug_info_handle_event(FILE *err, const bt_event *event,
                 * 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);
+}
index 4b765d16ae30c4a72851c782e8be52ac72edb76e..bfdbccc1c22c71ca01ef15655010f0c905b0d07f 100644 (file)
@@ -2,10 +2,11 @@
 #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 */
index 5156e81a2807384e3d0c072326c91e4fbda2dfb7..655e30f869cb14702bc83f107f8fb9c5c170126a 100644 (file)
  * 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();
@@ -444,14 +40,18 @@ BT_PLUGIN_AUTHOR_WITH_ID(lttng_utils, "Julien Desfossez");
 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);
diff --git a/plugins/lttng-utils/trace-ir-data-copy.c b/plugins/lttng-utils/trace-ir-data-copy.c
new file mode 100644 (file)
index 0000000..36d8db9
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * 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);
+}
diff --git a/plugins/lttng-utils/trace-ir-data-copy.h b/plugins/lttng-utils/trace-ir-data-copy.h
new file mode 100644 (file)
index 0000000..97eface
--- /dev/null
@@ -0,0 +1,44 @@
+#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 */
diff --git a/plugins/lttng-utils/trace-ir-mapping.c b/plugins/lttng-utils/trace-ir-mapping.c
new file mode 100644 (file)
index 0000000..0b3defc
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * 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;
+}
diff --git a/plugins/lttng-utils/trace-ir-mapping.h b/plugins/lttng-utils/trace-ir-mapping.h
new file mode 100644 (file)
index 0000000..3601e81
--- /dev/null
@@ -0,0 +1,274 @@
+#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 */
diff --git a/plugins/lttng-utils/trace-ir-metadata-copy.c b/plugins/lttng-utils/trace-ir-metadata-copy.c
new file mode 100644 (file)
index 0000000..5655e62
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * 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);
+}
diff --git a/plugins/lttng-utils/trace-ir-metadata-copy.h b/plugins/lttng-utils/trace-ir-metadata-copy.h
new file mode 100644 (file)
index 0000000..3901b26
--- /dev/null
@@ -0,0 +1,64 @@
+#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 */
diff --git a/plugins/lttng-utils/trace-ir-metadata-field-class-copy.c b/plugins/lttng-utils/trace-ir-metadata-field-class-copy.c
new file mode 100644 (file)
index 0000000..b56ba95
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+ * 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;
+}
diff --git a/plugins/lttng-utils/trace-ir-metadata-field-class-copy.h b/plugins/lttng-utils/trace-ir-metadata-field-class-copy.h
new file mode 100644 (file)
index 0000000..855e6cd
--- /dev/null
@@ -0,0 +1,42 @@
+#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 */
index 80dc87def6cf5c367ea8736e8901e4c61d3c995a..9d8a8c9cc0c73035f4a9ea6550581985cf596350 100644 (file)
@@ -50,3 +50,61 @@ const char *get_filename_from_path(const char *path)
 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;
+}
index d2a08c06e0506892079d98ee15b3e7008e14eaf7..5f65a470229815b932e3243c58b075887cbb39d1 100644 (file)
@@ -1,6 +1,5 @@
-#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
  *
@@ -28,6 +27,7 @@
  */
 
 #include <babeltrace/babeltrace-internal.h>
+#include "trace-ir-mapping.h"
 
 /*
  * Return the location of a path's file (the last element of the path).
@@ -36,4 +36,9 @@
 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 */
This page took 0.144921 seconds and 4 git commands to generate.