cli: move `--params` option's format parsing to its own file
[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"
f7b785ac 18#include "plugins/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
MJ
25#include "common/assert.h"
26#include "compat/uuid.h"
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"
1e649dff 36
1e649dff
PP
37#define TSDL_MAGIC 0x75d11d57
38
61d6f9b1 39extern
f73367f8
PP
40int yydebug;
41
1e649dff
PP
42struct ctf_metadata_decoder {
43 struct ctf_visitor_generate_ir *visitor;
1e649dff
PP
44 uint8_t uuid[16];
45 bool is_uuid_set;
46 int bo;
a2a54545 47 struct ctf_metadata_decoder_config config;
1e649dff
PP
48};
49
50struct packet_header {
51 uint32_t magic;
52 uint8_t uuid[16];
53 uint32_t checksum;
54 uint32_t content_size;
55 uint32_t packet_size;
56 uint8_t compression_scheme;
57 uint8_t encryption_scheme;
58 uint8_t checksum_scheme;
59 uint8_t major;
60 uint8_t minor;
61} __attribute__((__packed__));
62
63BT_HIDDEN
0746848c 64bool ctf_metadata_decoder_is_packetized(FILE *fp, int *byte_order,
f7b785ac 65 bt_logging_level log_level, bt_self_component *self_comp)
1e649dff
PP
66{
67 uint32_t magic;
68 size_t len;
69 int ret = 0;
70
71 len = fread(&magic, sizeof(magic), 1, fp);
72 if (len != 1) {
f7b785ac 73 BT_COMP_LOG_CUR_LVL(BT_LOG_INFO, log_level, self_comp,
0746848c 74 "Cannot read first metadata packet header: assuming the stream is not packetized.");
1e649dff
PP
75 goto end;
76 }
77
78 if (byte_order) {
79 if (magic == TSDL_MAGIC) {
80 ret = 1;
81 *byte_order = BYTE_ORDER;
82 } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
83 ret = 1;
84 *byte_order = BYTE_ORDER == BIG_ENDIAN ?
85 LITTLE_ENDIAN : BIG_ENDIAN;
86 }
87 }
88
89end:
90 rewind(fp);
91
92 return ret;
93}
94
1e649dff 95BT_HIDDEN
55314f2a 96struct ctf_metadata_decoder *ctf_metadata_decoder_create(
862ca4ed 97 const struct ctf_metadata_decoder_config *config)
1e649dff
PP
98{
99 struct ctf_metadata_decoder *mdec =
100 g_new0(struct ctf_metadata_decoder, 1);
a2a54545 101
f7b785ac
PP
102 BT_ASSERT(config);
103 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG, config->log_level, config->self_comp,
104 "Creating CTF metadata decoder: "
a2a54545 105 "clock-class-offset-s=%" PRId64 ", "
862ca4ed
PP
106 "clock-class-offset-ns=%" PRId64,
107 config->clock_class_offset_s, config->clock_class_offset_ns);
d6e20753 108
1e649dff 109 if (!mdec) {
f7b785ac
PP
110 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, config->log_level,
111 config->self_comp,
112 "Failed to allocate one CTF metadata decoder.");
1e649dff
PP
113 goto end;
114 }
115
a2a54545 116 mdec->config = *config;
f7b785ac 117 mdec->visitor = ctf_visitor_generate_ir_create(config);
1e649dff 118 if (!mdec->visitor) {
f7b785ac 119 BT_COMP_LOGE("Failed to create a CTF IR metadata AST visitor: "
d6e20753 120 "mdec-addr=%p", mdec);
1e649dff
PP
121 ctf_metadata_decoder_destroy(mdec);
122 mdec = NULL;
123 goto end;
124 }
125
f7b785ac 126 BT_COMP_LOGD("Creating CTF metadata decoder: "
a2a54545 127 "clock-class-offset-s=%" PRId64 ", "
862ca4ed 128 "clock-class-offset-ns=%" PRId64 ", addr=%p",
a2a54545 129 config->clock_class_offset_s, config->clock_class_offset_ns,
862ca4ed 130 mdec);
d6e20753 131
1e649dff
PP
132end:
133 return mdec;
134}
135
136BT_HIDDEN
137void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec)
138{
139 if (!mdec) {
140 return;
141 }
142
f7b785ac 143 BT_COMP_LOGD("Destroying CTF metadata decoder: addr=%p", mdec);
1e649dff
PP
144 ctf_visitor_generate_ir_destroy(mdec->visitor);
145 g_free(mdec);
146}
147
148BT_HIDDEN
149enum ctf_metadata_decoder_status ctf_metadata_decoder_decode(
150 struct ctf_metadata_decoder *mdec, FILE *fp)
151{
152 enum ctf_metadata_decoder_status status =
153 CTF_METADATA_DECODER_STATUS_OK;
154 int ret;
155 struct ctf_scanner *scanner = NULL;
156 char *buf = NULL;
157 bool close_fp = false;
f7b785ac 158 struct meta_log_config log_cfg;
1e649dff 159
f6ccaed9 160 BT_ASSERT(mdec);
f7b785ac
PP
161 log_cfg.log_level = mdec->config.log_level;
162 log_cfg.self_comp = mdec->config.self_comp;
1e649dff 163
0746848c 164 if (ctf_metadata_decoder_is_packetized(fp, &mdec->bo,
f7b785ac
PP
165 mdec->config.log_level, mdec->config.self_comp)) {
166 BT_COMP_LOGI("Metadata stream is packetized: mdec-addr=%p", mdec);
3c8252a5
PP
167 ret = ctf_metadata_decoder_packetized_file_stream_to_buf(fp,
168 &buf, mdec->bo, &mdec->is_uuid_set,
169 mdec->uuid, mdec->config.log_level,
f7b785ac 170 mdec->config.self_comp);
1e649dff 171 if (ret) {
f7b785ac 172 BT_COMP_LOGE("Cannot decode packetized metadata packets to metadata text: "
d6e20753 173 "mdec-addr=%p, ret=%d", mdec, ret);
1e649dff
PP
174 status = CTF_METADATA_DECODER_STATUS_ERROR;
175 goto end;
176 }
177
7cdc2bab
MD
178 if (strlen(buf) == 0) {
179 /* An empty metadata packet is OK. */
180 goto end;
181 }
182
1e649dff
PP
183 /* Convert the real file pointer to a memory file pointer */
184 fp = bt_fmemopen(buf, strlen(buf), "rb");
185 close_fp = true;
186 if (!fp) {
f7b785ac 187 BT_COMP_LOGE("Cannot memory-open metadata buffer: %s: "
d6e20753 188 "mdec-addr=%p", strerror(errno), mdec);
1e649dff
PP
189 status = CTF_METADATA_DECODER_STATUS_ERROR;
190 goto end;
191 }
192 } else {
193 unsigned int major, minor;
194 ssize_t nr_items;
195 const long init_pos = ftell(fp);
196
f7b785ac 197 BT_COMP_LOGI("Metadata stream is plain text: mdec-addr=%p", mdec);
1e649dff 198
1e95e5e8 199 if (init_pos < 0) {
f7b785ac 200 BT_COMP_LOGE_ERRNO("Failed to get current file position", ".");
1e95e5e8
MD
201 status = CTF_METADATA_DECODER_STATUS_ERROR;
202 goto end;
203 }
204
1e649dff
PP
205 /* Check text-only metadata header and version */
206 nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor);
207 if (nr_items < 2) {
f7b785ac 208 BT_COMP_LOGW("Missing \"/* CTF major.minor\" signature in plain text metadata file stream: "
d6e20753 209 "mdec-addr=%p", mdec);
1e649dff
PP
210 }
211
f7b785ac 212 BT_COMP_LOGI("Found metadata stream version in signature: version=%u.%u", major, minor);
1e649dff 213
3c8252a5
PP
214 if (!ctf_metadata_decoder_is_packet_version_valid(major,
215 minor)) {
f7b785ac 216 BT_COMP_LOGE("Invalid metadata version found in plain text signature: "
d6e20753
PP
217 "version=%u.%u, mdec-addr=%p", major, minor,
218 mdec);
1e649dff
PP
219 status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION;
220 goto end;
221 }
222
223 if (fseek(fp, init_pos, SEEK_SET)) {
f7b785ac 224 BT_COMP_LOGE("Cannot seek metadata file stream to initial position: %s: "
d6e20753 225 "mdec-addr=%p", strerror(errno), mdec);
1e649dff
PP
226 status = CTF_METADATA_DECODER_STATUS_ERROR;
227 goto end;
228 }
229 }
230
ef267d12 231 if (BT_LOG_ON_TRACE) {
f73367f8
PP
232 yydebug = 1;
233 }
234
1e649dff
PP
235 /* Allocate a scanner and append the metadata text content */
236 scanner = ctf_scanner_alloc();
237 if (!scanner) {
f7b785ac 238 BT_COMP_LOGE("Cannot allocate a metadata lexical scanner: "
d6e20753 239 "mdec-addr=%p", mdec);
1e649dff
PP
240 status = CTF_METADATA_DECODER_STATUS_ERROR;
241 goto end;
242 }
243
f6ccaed9 244 BT_ASSERT(fp);
1e649dff
PP
245 ret = ctf_scanner_append_ast(scanner, fp);
246 if (ret) {
f7b785ac 247 BT_COMP_LOGE("Cannot create the metadata AST out of the metadata text: "
d6e20753 248 "mdec-addr=%p", mdec);
1e649dff
PP
249 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
250 goto end;
251 }
252
f7b785ac 253 ret = ctf_visitor_semantic_check(0, &scanner->ast->root, &log_cfg);
1e649dff 254 if (ret) {
f7b785ac 255 BT_COMP_LOGE("Validation of the metadata semantics failed: "
d6e20753 256 "mdec-addr=%p", mdec);
1e649dff
PP
257 status = CTF_METADATA_DECODER_STATUS_ERROR;
258 goto end;
259 }
260
261 ret = ctf_visitor_generate_ir_visit_node(mdec->visitor,
262 &scanner->ast->root);
263 switch (ret) {
264 case 0:
265 /* Success */
266 break;
267 case -EINCOMPLETE:
f7b785ac 268 BT_COMP_LOGD("While visiting metadata AST: incomplete data: "
d6e20753 269 "mdec-addr=%p", mdec);
1e649dff
PP
270 status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
271 goto end;
272 default:
f7b785ac 273 BT_COMP_LOGE("Failed to visit AST node to create CTF IR objects: "
d6e20753 274 "mdec-addr=%p, ret=%d", mdec, ret);
1e649dff
PP
275 status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR;
276 goto end;
277 }
278
279end:
280 if (scanner) {
281 ctf_scanner_free(scanner);
282 }
283
f73367f8
PP
284 yydebug = 0;
285
1e649dff
PP
286 if (fp && close_fp) {
287 if (fclose(fp)) {
f7b785ac 288 BT_COMP_LOGE("Cannot close metadata file stream: "
d6e20753 289 "mdec-addr=%p", mdec);
1e649dff
PP
290 }
291 }
292
293 if (buf) {
294 free(buf);
295 }
296
297 return status;
298}
299
300BT_HIDDEN
b19ff26f 301bt_trace_class *ctf_metadata_decoder_get_ir_trace_class(
44c440bc
PP
302 struct ctf_metadata_decoder *mdec)
303{
862ca4ed 304 return ctf_visitor_generate_ir_get_ir_trace_class(mdec->visitor);
44c440bc
PP
305}
306
307BT_HIDDEN
308struct ctf_trace_class *ctf_metadata_decoder_borrow_ctf_trace_class(
1e649dff
PP
309 struct ctf_metadata_decoder *mdec)
310{
44c440bc 311 return ctf_visitor_generate_ir_borrow_ctf_trace_class(mdec->visitor);
1e649dff 312}
This page took 0.056383 seconds and 4 git commands to generate.