Fix: src.ctf.fs: initialize the other_entry variable
[babeltrace.git] / src / plugins / ctf / common / metadata / decoder.c
CommitLineData
1e649dff
PP
1/*
2 * Copyright 2016-2017 - Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 */
14
f7b785ac 15#define BT_COMP_LOG_SELF_COMP (mdec->config.self_comp)
0746848c 16#define BT_LOG_OUTPUT_LEVEL (mdec->config.log_level)
350ad6c1 17#define BT_LOG_TAG "PLUGIN/CTF/META/DECODER"
d9c39b0a 18#include "logging/comp-logging.h"
d6e20753 19
1e649dff
PP
20#include <stdio.h>
21#include <stdbool.h>
22#include <stdint.h>
23#include <stdlib.h>
d6e20753 24#include <inttypes.h>
578e048b 25#include "common/assert.h"
6162e6b7 26#include "common/uuid.h"
578e048b 27#include "compat/memstream.h"
3fadfbc0 28#include <babeltrace2/babeltrace.h>
1e649dff 29#include <glib.h>
e9383dfd 30#include <string.h>
1e649dff
PP
31
32#include "ast.h"
33#include "decoder.h"
34#include "scanner.h"
f7b785ac 35#include "logging.h"
9103e903 36#include "parser-wrap.h"
1e649dff 37
1e649dff
PP
38#define TSDL_MAGIC 0x75d11d57
39
40struct ctf_metadata_decoder {
06be9946
PP
41 struct ctf_scanner *scanner;
42 GString *text;
1e649dff 43 struct ctf_visitor_generate_ir *visitor;
6162e6b7 44 bt_uuid_t uuid;
1e649dff
PP
45 bool is_uuid_set;
46 int bo;
a2a54545 47 struct ctf_metadata_decoder_config config;
06be9946 48 struct meta_log_config log_cfg;
1e649dff
PP
49};
50
51struct packet_header {
52 uint32_t magic;
6162e6b7 53 bt_uuid_t uuid;
1e649dff
PP
54 uint32_t checksum;
55 uint32_t content_size;
56 uint32_t packet_size;
57 uint8_t compression_scheme;
58 uint8_t encryption_scheme;
59 uint8_t checksum_scheme;
60 uint8_t major;
61 uint8_t minor;
62} __attribute__((__packed__));
63
64BT_HIDDEN
06be9946
PP
65int ctf_metadata_decoder_packetized_file_stream_to_buf(FILE *fp,
66 char **buf, int byte_order, bool *is_uuid_set,
67 uint8_t *uuid, bt_logging_level log_level,
68 bt_self_component *self_comp);
69
70BT_HIDDEN
71int ctf_metadata_decoder_is_packetized(FILE *fp, bool *is_packetized,
72 int *byte_order, bt_logging_level log_level,
73 bt_self_component *self_comp)
1e649dff
PP
74{
75 uint32_t magic;
76 size_t len;
77 int ret = 0;
78
06be9946 79 *is_packetized = false;
1e649dff
PP
80 len = fread(&magic, sizeof(magic), 1, fp);
81 if (len != 1) {
f7b785ac 82 BT_COMP_LOG_CUR_LVL(BT_LOG_INFO, log_level, self_comp,
0746848c 83 "Cannot read first metadata packet header: assuming the stream is not packetized.");
06be9946 84 ret = -1;
1e649dff
PP
85 goto end;
86 }
87
88 if (byte_order) {
89 if (magic == TSDL_MAGIC) {
06be9946 90 *is_packetized = true;
1e649dff
PP
91 *byte_order = BYTE_ORDER;
92 } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
06be9946 93 *is_packetized = true;
1e649dff
PP
94 *byte_order = BYTE_ORDER == BIG_ENDIAN ?
95 LITTLE_ENDIAN : BIG_ENDIAN;
96 }
97 }
98
99end:
100 rewind(fp);
101
102 return ret;
103}
104
1e649dff 105BT_HIDDEN
55314f2a 106struct ctf_metadata_decoder *ctf_metadata_decoder_create(
862ca4ed 107 const struct ctf_metadata_decoder_config *config)
1e649dff
PP
108{
109 struct ctf_metadata_decoder *mdec =
110 g_new0(struct ctf_metadata_decoder, 1);
a2a54545 111
f7b785ac
PP
112 BT_ASSERT(config);
113 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG, config->log_level, config->self_comp,
114 "Creating CTF metadata decoder: "
a2a54545 115 "clock-class-offset-s=%" PRId64 ", "
862ca4ed
PP
116 "clock-class-offset-ns=%" PRId64,
117 config->clock_class_offset_s, config->clock_class_offset_ns);
d6e20753 118
1e649dff 119 if (!mdec) {
f7b785ac
PP
120 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, config->log_level,
121 config->self_comp,
122 "Failed to allocate one CTF metadata decoder.");
1e649dff
PP
123 goto end;
124 }
125
06be9946
PP
126 mdec->log_cfg.log_level = config->log_level;
127 mdec->log_cfg.self_comp = config->self_comp;
128 mdec->scanner = ctf_scanner_alloc();
129 if (!mdec->scanner) {
130 BT_COMP_LOGE("Cannot allocate a metadata lexical scanner: "
131 "mdec-addr=%p", mdec);
132 goto error;
133 }
134
135 mdec->text = g_string_new(NULL);
136 if (!mdec->text) {
137 BT_COMP_LOGE("Failed to allocate one GString: "
138 "mdec-addr=%p", mdec);
139 goto error;
140 }
141
142 mdec->bo = -1;
a2a54545 143 mdec->config = *config;
f7b785ac 144 mdec->visitor = ctf_visitor_generate_ir_create(config);
1e649dff 145 if (!mdec->visitor) {
f7b785ac 146 BT_COMP_LOGE("Failed to create a CTF IR metadata AST visitor: "
d6e20753 147 "mdec-addr=%p", mdec);
06be9946 148 goto error;
1e649dff
PP
149 }
150
f7b785ac 151 BT_COMP_LOGD("Creating CTF metadata decoder: "
a2a54545 152 "clock-class-offset-s=%" PRId64 ", "
862ca4ed 153 "clock-class-offset-ns=%" PRId64 ", addr=%p",
a2a54545 154 config->clock_class_offset_s, config->clock_class_offset_ns,
862ca4ed 155 mdec);
06be9946
PP
156 goto end;
157
158error:
159 ctf_metadata_decoder_destroy(mdec);
160 mdec = NULL;
d6e20753 161
1e649dff
PP
162end:
163 return mdec;
164}
165
166BT_HIDDEN
167void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec)
168{
169 if (!mdec) {
170 return;
171 }
172
06be9946
PP
173 if (mdec->scanner) {
174 ctf_scanner_free(mdec->scanner);
175 }
176
177 if (mdec->text) {
178 g_string_free(mdec->text, TRUE);
179 }
180
f7b785ac 181 BT_COMP_LOGD("Destroying CTF metadata decoder: addr=%p", mdec);
1e649dff
PP
182 ctf_visitor_generate_ir_destroy(mdec->visitor);
183 g_free(mdec);
184}
185
186BT_HIDDEN
06be9946 187enum ctf_metadata_decoder_status ctf_metadata_decoder_append_content(
1e649dff
PP
188 struct ctf_metadata_decoder *mdec, FILE *fp)
189{
190 enum ctf_metadata_decoder_status status =
191 CTF_METADATA_DECODER_STATUS_OK;
192 int ret;
1e649dff
PP
193 char *buf = NULL;
194 bool close_fp = false;
06be9946
PP
195 long start_pos = -1;
196 bool is_packetized;
1e649dff 197
f6ccaed9 198 BT_ASSERT(mdec);
06be9946
PP
199 ret = ctf_metadata_decoder_is_packetized(fp, &is_packetized, &mdec->bo,
200 mdec->config.log_level, mdec->config.self_comp);
201 if (ret) {
202 status = CTF_METADATA_DECODER_STATUS_ERROR;
203 goto end;
204 }
1e649dff 205
06be9946 206 if (is_packetized) {
f7b785ac 207 BT_COMP_LOGI("Metadata stream is packetized: mdec-addr=%p", mdec);
3c8252a5
PP
208 ret = ctf_metadata_decoder_packetized_file_stream_to_buf(fp,
209 &buf, mdec->bo, &mdec->is_uuid_set,
210 mdec->uuid, mdec->config.log_level,
f7b785ac 211 mdec->config.self_comp);
1e649dff 212 if (ret) {
f7b785ac 213 BT_COMP_LOGE("Cannot decode packetized metadata packets to metadata text: "
d6e20753 214 "mdec-addr=%p, ret=%d", mdec, ret);
1e649dff
PP
215 status = CTF_METADATA_DECODER_STATUS_ERROR;
216 goto end;
217 }
218
7cdc2bab
MD
219 if (strlen(buf) == 0) {
220 /* An empty metadata packet is OK. */
221 goto end;
222 }
223
1e649dff
PP
224 /* Convert the real file pointer to a memory file pointer */
225 fp = bt_fmemopen(buf, strlen(buf), "rb");
226 close_fp = true;
227 if (!fp) {
f7b785ac 228 BT_COMP_LOGE("Cannot memory-open metadata buffer: %s: "
d6e20753 229 "mdec-addr=%p", strerror(errno), mdec);
1e649dff
PP
230 status = CTF_METADATA_DECODER_STATUS_ERROR;
231 goto end;
232 }
233 } else {
234 unsigned int major, minor;
235 ssize_t nr_items;
236 const long init_pos = ftell(fp);
237
f7b785ac 238 BT_COMP_LOGI("Metadata stream is plain text: mdec-addr=%p", mdec);
1e649dff 239
1e95e5e8 240 if (init_pos < 0) {
f7b785ac 241 BT_COMP_LOGE_ERRNO("Failed to get current file position", ".");
1e95e5e8
MD
242 status = CTF_METADATA_DECODER_STATUS_ERROR;
243 goto end;
244 }
245
1e649dff
PP
246 /* Check text-only metadata header and version */
247 nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor);
248 if (nr_items < 2) {
f7b785ac 249 BT_COMP_LOGW("Missing \"/* CTF major.minor\" signature in plain text metadata file stream: "
d6e20753 250 "mdec-addr=%p", mdec);
1e649dff
PP
251 }
252
f7b785ac 253 BT_COMP_LOGI("Found metadata stream version in signature: version=%u.%u", major, minor);
1e649dff 254
3c8252a5
PP
255 if (!ctf_metadata_decoder_is_packet_version_valid(major,
256 minor)) {
f7b785ac 257 BT_COMP_LOGE("Invalid metadata version found in plain text signature: "
d6e20753
PP
258 "version=%u.%u, mdec-addr=%p", major, minor,
259 mdec);
1e649dff
PP
260 status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION;
261 goto end;
262 }
263
264 if (fseek(fp, init_pos, SEEK_SET)) {
f7b785ac 265 BT_COMP_LOGE("Cannot seek metadata file stream to initial position: %s: "
d6e20753 266 "mdec-addr=%p", strerror(errno), mdec);
1e649dff
PP
267 status = CTF_METADATA_DECODER_STATUS_ERROR;
268 goto end;
269 }
270 }
271
9103e903 272#if YYDEBUG
ef267d12 273 if (BT_LOG_ON_TRACE) {
f73367f8
PP
274 yydebug = 1;
275 }
9103e903 276#endif
f73367f8 277
06be9946
PP
278 /* Save the file's position: we'll seek back to append the plain text */
279 BT_ASSERT(fp);
280
281 if (mdec->config.keep_plain_text) {
282 start_pos = ftell(fp);
1e649dff
PP
283 }
284
06be9946
PP
285 /* Append the metadata text content */
286 ret = ctf_scanner_append_ast(mdec->scanner, fp);
1e649dff 287 if (ret) {
f7b785ac 288 BT_COMP_LOGE("Cannot create the metadata AST out of the metadata text: "
d6e20753 289 "mdec-addr=%p", mdec);
1e649dff
PP
290 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
291 goto end;
292 }
293
06be9946
PP
294 /* We know it's complete: append plain text */
295 if (mdec->config.keep_plain_text) {
296 BT_ASSERT(start_pos != -1);
297 ret = fseek(fp, start_pos, SEEK_SET);
298 if (ret) {
299 BT_COMP_LOGE("Failed to seek file: ret=%d, mdec-addr=%p",
300 ret, mdec);
301 status = CTF_METADATA_DECODER_STATUS_ERROR;
302 goto end;
303 }
304
305 ret = bt_common_append_file_content_to_g_string(mdec->text, fp);
306 if (ret) {
307 BT_COMP_LOGE("Failed to append to current plain text: "
308 "ret=%d, mdec-addr=%p", ret, mdec);
309 status = CTF_METADATA_DECODER_STATUS_ERROR;
310 goto end;
311 }
312 }
313
314 ret = ctf_visitor_semantic_check(0, &mdec->scanner->ast->root,
315 &mdec->log_cfg);
1e649dff 316 if (ret) {
f7b785ac 317 BT_COMP_LOGE("Validation of the metadata semantics failed: "
d6e20753 318 "mdec-addr=%p", mdec);
1e649dff
PP
319 status = CTF_METADATA_DECODER_STATUS_ERROR;
320 goto end;
321 }
322
06be9946
PP
323 if (mdec->config.create_trace_class) {
324 ret = ctf_visitor_generate_ir_visit_node(mdec->visitor,
325 &mdec->scanner->ast->root);
326 switch (ret) {
327 case 0:
328 /* Success */
329 break;
330 case -EINCOMPLETE:
331 BT_COMP_LOGD("While visiting metadata AST: incomplete data: "
332 "mdec-addr=%p", mdec);
333 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
334 goto end;
335 default:
336 BT_COMP_LOGE("Failed to visit AST node to create CTF IR objects: "
337 "mdec-addr=%p, ret=%d", mdec, ret);
338 status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR;
339 goto end;
340 }
1e649dff
PP
341 }
342
343end:
9103e903 344#if YYDEBUG
f73367f8 345 yydebug = 0;
9103e903 346#endif
f73367f8 347
1e649dff
PP
348 if (fp && close_fp) {
349 if (fclose(fp)) {
f7b785ac 350 BT_COMP_LOGE("Cannot close metadata file stream: "
d6e20753 351 "mdec-addr=%p", mdec);
1e649dff
PP
352 }
353 }
354
6b934a94 355 free(buf);
1e649dff
PP
356
357 return status;
358}
359
360BT_HIDDEN
b19ff26f 361bt_trace_class *ctf_metadata_decoder_get_ir_trace_class(
44c440bc
PP
362 struct ctf_metadata_decoder *mdec)
363{
98b15851
PP
364 BT_ASSERT_DBG(mdec);
365 BT_ASSERT_DBG(mdec->config.create_trace_class);
862ca4ed 366 return ctf_visitor_generate_ir_get_ir_trace_class(mdec->visitor);
44c440bc
PP
367}
368
369BT_HIDDEN
370struct ctf_trace_class *ctf_metadata_decoder_borrow_ctf_trace_class(
1e649dff
PP
371 struct ctf_metadata_decoder *mdec)
372{
98b15851
PP
373 BT_ASSERT_DBG(mdec);
374 BT_ASSERT_DBG(mdec->config.create_trace_class);
44c440bc 375 return ctf_visitor_generate_ir_borrow_ctf_trace_class(mdec->visitor);
1e649dff 376}
06be9946
PP
377
378BT_HIDDEN
379const char *ctf_metadata_decoder_get_text(struct ctf_metadata_decoder *mdec)
380{
98b15851
PP
381 BT_ASSERT_DBG(mdec);
382 BT_ASSERT_DBG(mdec->config.keep_plain_text);
06be9946
PP
383 return mdec->text->str;
384}
385
386BT_HIDDEN
387int ctf_metadata_decoder_get_byte_order(struct ctf_metadata_decoder *mdec)
388{
98b15851 389 BT_ASSERT_DBG(mdec);
06be9946
PP
390 return mdec->bo;
391}
392
393BT_HIDDEN
394int ctf_metadata_decoder_get_uuid(struct ctf_metadata_decoder *mdec,
395 bt_uuid_t uuid)
396{
397 int ret = 0;
398
98b15851 399 BT_ASSERT_DBG(mdec);
06be9946
PP
400
401 if (!mdec->is_uuid_set) {
402 ret = -1;
403 goto end;
404 }
405
406 bt_uuid_copy(uuid, mdec->uuid);
407
408end:
409 return ret;
410}
1a6da3f9
PP
411
412static
413enum ctf_metadata_decoder_status find_uuid_in_trace_decl(
414 struct ctf_metadata_decoder *mdec, struct ctf_node *trace_node,
415 bt_uuid_t uuid)
416{
417 enum ctf_metadata_decoder_status status =
418 CTF_METADATA_DECODER_STATUS_OK;
419 struct ctf_node *entry_node;
420 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
421 char *left = NULL;
422
423 bt_list_for_each_entry(entry_node, decl_list, siblings) {
424 if (entry_node->type == NODE_CTF_EXPRESSION) {
425 int ret;
426
427 left = ctf_ast_concatenate_unary_strings(
428 &entry_node->u.ctf_expression.left);
429 if (!left) {
430 BT_COMP_LOGE("Cannot concatenate unary strings.");
431 status = CTF_METADATA_DECODER_STATUS_ERROR;
432 goto end;
433 }
434
435 if (strcmp(left, "uuid") == 0) {
436 ret = ctf_ast_get_unary_uuid(
437 &entry_node->u.ctf_expression.right,
438 uuid, mdec->config.log_level,
439 mdec->config.self_comp);
440 if (ret) {
441 BT_COMP_LOGE("Invalid trace's `uuid` attribute.");
442 status = CTF_METADATA_DECODER_STATUS_ERROR;
443 goto end;
444 }
445
446 goto end;
447 }
448
449 g_free(left);
450 left = NULL;
451 }
452 }
453
454 status = CTF_METADATA_DECODER_STATUS_NONE;
455
456end:
457 g_free(left);
458 return status;
459}
460
461BT_HIDDEN
462enum ctf_metadata_decoder_status ctf_metadata_decoder_get_trace_class_uuid(
463 struct ctf_metadata_decoder *mdec, bt_uuid_t uuid)
464{
465 enum ctf_metadata_decoder_status status =
466 CTF_METADATA_DECODER_STATUS_INCOMPLETE;
467 struct ctf_node *root_node = &mdec->scanner->ast->root;
468 struct ctf_node *trace_node;
469
470 if (!root_node) {
471 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
472 goto end;
473 }
474
475 trace_node =
476 bt_list_entry(root_node->u.root.trace.next,
477 struct ctf_node, siblings);
478 if (!trace_node) {
479 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
480 goto end;
481 }
482
483 status = find_uuid_in_trace_decl(mdec, trace_node, uuid);
484
485end:
486 return status;
487}
This page took 0.087863 seconds and 4 git commands to generate.