#include <babeltrace/ctf/events-internal.h>
#include <babeltrace/ctf/iterator.h>
#include <babeltrace/ctf-text/types.h>
+#include <babeltrace/debug-info.h>
+
#include <babeltrace/iterator.h>
+#include <babeltrace/plugin/component-factory.h>
#include <popt.h>
#include <errno.h>
#include <stdlib.h>
#define NET4_URL_PREFIX "net4://"
#define NET6_URL_PREFIX "net6://"
+static struct bt_component_factory *component_factory;
static char *opt_input_format, *opt_output_format;
/*
*/
static GPtrArray *opt_input_paths;
static char *opt_output_path;
-int opt_stream_intersection;
+static int opt_stream_intersection;
+static char *opt_plugin_path;
static struct bt_format *fmt_read;
+void bt_dummy_hook(void);
+void bt_lttng_live_hook(void);
+void bt_ctf_hook(void);
+void bt_ctf_text_hook(void);
+void bt_ctf_metadata_hook(void);
+
static
void strlower(char *str)
{
OPT_OUTPUT_FORMAT,
OPT_HELP,
OPT_LIST,
+ OPT_PLUGIN_PATH,
OPT_VERBOSE,
OPT_DEBUG,
OPT_NAMES,
OPT_CLOCK_GMT,
OPT_CLOCK_FORCE_CORRELATE,
OPT_STREAM_INTERSECTION,
+ OPT_DEBUG_INFO_DIR,
+ OPT_DEBUG_INFO_FULL_PATH,
+ OPT_DEBUG_INFO_TARGET_PREFIX,
};
/*
- * We are _not_ using POPT_ARG_STRING ability to store directly into
+ * We are _not_ using POPT_ARG_STRING's ability to store directly into
* variables, because we want to cast the return to non-const, which is
* not possible without using poptGetOptArg explicitly. This helps us
* controlling memory allocation correctly without making assumptions
{ "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL },
{ "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
{ "list", 'l', POPT_ARG_NONE, NULL, OPT_LIST, NULL, NULL },
+ { "plugin-path", 0, POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
{ "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
{ "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
{ "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
{ "clock-gmt", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL },
{ "clock-force-correlate", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
{ "stream-intersection", 0, POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL },
+#ifdef ENABLE_DEBUG_INFO
+ { "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
+ { "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
+ { "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
+#endif
{ NULL, 0, 0, NULL, 0, NULL, NULL },
};
fprintf(fp, "\n");
fprintf(fp, " -h, --help This help message\n");
fprintf(fp, " -l, --list List available formats\n");
+ fprintf(fp, " --plugin-path Supplementary plug-in path\n");
fprintf(fp, " -v, --verbose Verbose mode\n");
fprintf(fp, " (or set BABELTRACE_VERBOSE environment variable)\n");
fprintf(fp, " -d, --debug Debug mode\n");
fprintf(fp, " --clock-force-correlate Assume that clocks are inherently correlated\n");
fprintf(fp, " across traces.\n");
fprintf(fp, " --stream-intersection Only print events when all streams are active.\n");
+#ifdef ENABLE_DEBUG_INFO
+ fprintf(fp, " --debug-info-dir Directory in which to look for debugging information\n");
+ fprintf(fp, " files. (default: /usr/lib/debug/)\n");
+ fprintf(fp, " --debug-info-target-prefix Directory to use as a prefix for executable lookup\n");
+ fprintf(fp, " --debug-info-full-path Show full debug info source and binary paths (if available)\n");
+#endif
list_formats(fp);
fprintf(fp, "\n");
}
list_formats(stdout);
ret = 1;
goto end;
+ case OPT_PLUGIN_PATH:
+ opt_plugin_path = (char *) poptGetOptArg(pc);
+ if (!opt_plugin_path) {
+ ret = -EINVAL;
+ goto end;
+ } ;
+ break;
case OPT_VERBOSE:
babeltrace_verbose = 1;
break;
case OPT_STREAM_INTERSECTION:
opt_stream_intersection = 1;
break;
-
+ case OPT_DEBUG_INFO_DIR:
+ opt_debug_info_dir = (char *) poptGetOptArg(pc);
+ if (!opt_debug_info_dir) {
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
+ case OPT_DEBUG_INFO_FULL_PATH:
+ opt_debug_info_full_path = 1;
+ break;
+ case OPT_DEBUG_INFO_TARGET_PREFIX:
+ opt_debug_info_target_prefix = (char *) poptGetOptArg(pc);
+ if (!opt_debug_info_target_prefix) {
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
default:
ret = -EINVAL;
goto end;
if (ipath)
g_ptr_array_add(opt_input_paths, (gpointer) ipath);
} while (ipath);
- if (opt_input_paths->len == 0) {
- ret = -EINVAL;
- goto end;
- }
end:
if (pc) {
return ret;
}
-static
-struct bt_ctf_iter *iter_create_intersect(struct bt_context *ctx,
- struct bt_iter_pos *inter_begin_pos,
- struct bt_iter_pos *inter_end_pos)
-{
- uint64_t begin = 0, end = ULLONG_MAX;
- int ret;
-
- ret = ctf_find_packets_intersection(ctx, &begin, &end);
- if (ret == 1) {
- fprintf(stderr, "[error] No intersection found between trace files.\n");
- ret = -1;
- goto error;
- } else if (ret != 0) {
- goto error;
- }
- inter_begin_pos = bt_iter_create_time_pos(NULL, begin);
- if (!inter_begin_pos) {
- goto error;
- }
- inter_end_pos = bt_iter_create_time_pos(NULL, end);
- if (!inter_end_pos) {
- goto error;
- }
-
- return bt_ctf_iter_create(ctx, inter_begin_pos,
- inter_end_pos);
-error:
- return NULL;
-}
-
static
int convert_trace(struct bt_trace_descriptor *td_write,
struct bt_context *ctx)
{
struct bt_ctf_iter *iter;
struct ctf_text_stream_pos *sout;
- struct bt_iter_pos begin_pos;
- struct bt_iter_pos *inter_begin_pos = NULL, *inter_end_pos = NULL;
+ struct bt_iter_pos *begin_pos = NULL, *end_pos = NULL;
struct bt_ctf_event *ctf_event;
int ret;
}
if (opt_stream_intersection) {
- iter = iter_create_intersect(ctx, inter_begin_pos, inter_end_pos);
+ iter = bt_ctf_iter_create_intersect(ctx, &begin_pos, &end_pos);
} else {
- begin_pos.type = BT_SEEK_BEGIN;
- iter = bt_ctf_iter_create(ctx, &begin_pos, NULL);
+ begin_pos = bt_iter_create_time_pos(NULL, 0);
+ begin_pos->type = BT_SEEK_BEGIN;
+ iter = bt_ctf_iter_create(ctx, begin_pos, NULL);
}
if (!iter) {
ret = -1;
end:
bt_ctf_iter_destroy(iter);
error_iter:
- if (inter_begin_pos) {
- bt_iter_free_pos(inter_begin_pos);
- }
- if (inter_end_pos) {
- bt_iter_free_pos(inter_end_pos);
- }
+ bt_iter_free_pos(begin_pos);
+ bt_iter_free_pos(end_pos);
return ret;
}
+void call_plugins_hooks(void)
+{
+ bt_dummy_hook();
+ bt_lttng_live_hook();
+ bt_ctf_hook();
+ bt_ctf_text_hook();
+ bt_ctf_metadata_hook();
+}
+
int main(int argc, char **argv)
{
int ret, partial_error = 0, open_success = 0;
struct bt_context *ctx;
int i;
+ call_plugins_hooks();
+
opt_input_paths = g_ptr_array_new();
ret = parse_options(argc, argv);
printf_verbose("Verbose mode active.\n");
printf_debug("Debug mode active.\n");
+ if (!opt_plugin_path) {
+ fprintf(stderr, "No plugin path specified, aborting...\n");
+ ret = -1;
+ goto end;
+ }
+ printf_verbose("Looking-up plugins at %s",
+ opt_plugin_path ? opt_plugin_path : "Invalid");
+ component_factory = bt_component_factory_create();
+ if (!component_factory) {
+ fprintf(stderr, "Failed to create component factory.\n");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_component_factory_load(component_factory, opt_plugin_path);
+ if (ret) {
+ fprintf(stderr, "Failed to load plugins.\n");
+ goto end;
+ }
+
+ if (opt_input_paths->len == 0) {
+ ret = -1;
+ goto end;
+ }
+
if (opt_input_format)
strlower(opt_input_format);
if (opt_output_format)
free(opt_input_format);
free(opt_output_format);
free(opt_output_path);
+ free(opt_debug_info_dir);
+ free(opt_debug_info_target_prefix);
g_ptr_array_free(opt_input_paths, TRUE);
if (partial_error)
exit(EXIT_FAILURE);