Commit | Line | Data |
---|---|---|
4f45f9bb JD |
1 | /* |
2 | * copy.c | |
3 | * | |
4 | * Babeltrace Copy Trace Structure | |
5 | * | |
6 | * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com> | |
7 | * | |
8 | * Author: Julien Desfossez <jdesfossez@efficios.com> | |
9 | * | |
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
11 | * of this software and associated documentation files (the "Software"), to deal | |
12 | * in the Software without restriction, including without limitation the rights | |
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
14 | * copies of the Software, and to permit persons to whom the Software is | |
15 | * furnished to do so, subject to the following conditions: | |
16 | * | |
17 | * The above copyright notice and this permission notice shall be included in | |
18 | * all copies or substantial portions of the Software. | |
19 | * | |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
26 | * SOFTWARE. | |
27 | */ | |
28 | ||
b4d4912f JD |
29 | #define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-FLT-COPY" |
30 | #include "logging.h" | |
31 | ||
4f45f9bb | 32 | #include <inttypes.h> |
b4d4912f | 33 | #include <assert.h> |
9d408fca | 34 | #include <babeltrace/babeltrace.h> |
4f45f9bb JD |
35 | |
36 | #include <ctfcopytrace.h> | |
37 | #include "debug-info.h" | |
38 | ||
cb0a5cf8 JD |
39 | static |
40 | struct bt_ctf_stream *insert_new_stream( | |
41 | struct debug_info_iterator *debug_it, | |
42 | struct bt_ctf_stream *stream, | |
43 | struct debug_info_trace *di_trace); | |
44 | ||
504db471 JD |
45 | static |
46 | void unref_stream(struct bt_ctf_stream *stream) | |
47 | { | |
48 | bt_put(stream); | |
49 | } | |
50 | ||
51 | static | |
52 | void unref_packet(struct bt_ctf_packet *packet) | |
53 | { | |
54 | bt_put(packet); | |
55 | } | |
56 | ||
57 | static | |
58 | void unref_stream_class(struct bt_ctf_stream_class *stream_class) | |
59 | { | |
60 | bt_put(stream_class); | |
61 | } | |
62 | ||
63 | static | |
64 | void unref_debug_info(struct debug_info *debug_info) | |
65 | { | |
66 | debug_info_destroy(debug_info); | |
67 | } | |
68 | ||
1c78e839 JD |
69 | static |
70 | void destroy_stream_state_key(gpointer key) | |
71 | { | |
72 | g_free((enum fs_writer_stream_state *) key); | |
73 | } | |
74 | ||
4f45f9bb JD |
75 | static |
76 | struct bt_ctf_field *get_payload_field(FILE *err, | |
77 | struct bt_ctf_event *event, const char *field_name) | |
78 | { | |
b4d4912f JD |
79 | struct bt_ctf_field *field = NULL, *payload = NULL; |
80 | struct bt_ctf_field_type *payload_type = NULL; | |
4f45f9bb | 81 | |
b4d4912f JD |
82 | payload = bt_ctf_event_get_payload(event, NULL); |
83 | assert(payload); | |
4f45f9bb | 84 | |
b4d4912f JD |
85 | payload_type = bt_ctf_field_get_type(payload); |
86 | assert(payload_type); | |
4f45f9bb | 87 | |
b4d4912f JD |
88 | if (bt_ctf_field_type_get_type_id(payload_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) { |
89 | BT_LOGE("Wrong type, expected struct: field-name=\"%s\"", | |
90 | field_name); | |
4f45f9bb JD |
91 | goto end; |
92 | } | |
93 | ||
b4d4912f | 94 | field = bt_ctf_field_structure_get_field(payload, field_name); |
4f45f9bb JD |
95 | |
96 | end: | |
b4d4912f JD |
97 | bt_put(payload_type); |
98 | bt_put(payload); | |
4f45f9bb JD |
99 | return field; |
100 | } | |
101 | ||
102 | static | |
103 | struct bt_ctf_field *get_stream_event_context_field(FILE *err, | |
104 | struct bt_ctf_event *event, const char *field_name) | |
105 | { | |
106 | struct bt_ctf_field *field = NULL, *sec = NULL; | |
107 | struct bt_ctf_field_type *sec_type = NULL; | |
108 | ||
109 | sec = bt_ctf_event_get_stream_event_context(event); | |
110 | if (!sec) { | |
4f45f9bb JD |
111 | goto end; |
112 | } | |
113 | ||
114 | sec_type = bt_ctf_field_get_type(sec); | |
b4d4912f | 115 | assert(sec_type); |
4f45f9bb | 116 | |
1487a16a | 117 | if (bt_ctf_field_type_get_type_id(sec_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) { |
b4d4912f JD |
118 | BT_LOGE("Wrong type, expected struct, field-name=\"%s\"", |
119 | field_name); | |
4f45f9bb JD |
120 | goto end; |
121 | } | |
122 | ||
123 | field = bt_ctf_field_structure_get_field(sec, field_name); | |
124 | ||
125 | end: | |
126 | bt_put(sec_type); | |
127 | bt_put(sec); | |
128 | return field; | |
129 | } | |
130 | ||
131 | BT_HIDDEN | |
132 | int get_stream_event_context_unsigned_int_field_value(FILE *err, | |
133 | struct bt_ctf_event *event, const char *field_name, | |
134 | uint64_t *value) | |
135 | { | |
136 | int ret; | |
137 | struct bt_ctf_field *field = NULL; | |
138 | struct bt_ctf_field_type *field_type = NULL; | |
139 | ||
140 | field = get_stream_event_context_field(err, event, field_name); | |
141 | if (!field) { | |
4f45f9bb JD |
142 | goto error; |
143 | } | |
144 | ||
145 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 146 | assert(field_type); |
4f45f9bb | 147 | |
1487a16a | 148 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
b4d4912f JD |
149 | BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", |
150 | field_name); | |
4f45f9bb JD |
151 | goto error; |
152 | } | |
153 | ||
154 | if (bt_ctf_field_type_integer_get_signed(field_type) != 0) { | |
b4d4912f JD |
155 | BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"", |
156 | field_name); | |
4f45f9bb JD |
157 | goto error; |
158 | } | |
159 | ||
160 | ret = bt_ctf_field_unsigned_integer_get_value(field, value); | |
b4d4912f JD |
161 | if (ret) { |
162 | BT_LOGE("Failed to get value: field-name=\"%s\"", | |
163 | field_name); | |
164 | goto error; | |
165 | } | |
4f45f9bb JD |
166 | goto end; |
167 | ||
168 | error: | |
169 | ret = -1; | |
170 | end: | |
171 | bt_put(field_type); | |
172 | bt_put(field); | |
173 | return ret; | |
174 | } | |
175 | ||
176 | BT_HIDDEN | |
177 | int get_stream_event_context_int_field_value(FILE *err, struct bt_ctf_event *event, | |
178 | const char *field_name, int64_t *value) | |
179 | { | |
180 | struct bt_ctf_field *field = NULL; | |
181 | struct bt_ctf_field_type *field_type = NULL; | |
182 | int ret; | |
183 | ||
184 | field = get_stream_event_context_field(err, event, field_name); | |
185 | if (!field) { | |
186 | goto error; | |
187 | } | |
188 | ||
189 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 190 | assert(field_type); |
4f45f9bb | 191 | |
1487a16a | 192 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
b4d4912f | 193 | BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name); |
4f45f9bb JD |
194 | goto error; |
195 | } | |
196 | ||
197 | if (bt_ctf_field_type_integer_get_signed(field_type) != 1) { | |
b4d4912f JD |
198 | BT_LOGE("Wrong type, expected signed integer: field-name=\"%s\"", |
199 | field_name); | |
4f45f9bb JD |
200 | goto error; |
201 | } | |
202 | ||
203 | ret = bt_ctf_field_signed_integer_get_value(field, value); | |
204 | goto end; | |
205 | ||
206 | error: | |
207 | ret = -1; | |
208 | end: | |
209 | bt_put(field_type); | |
210 | bt_put(field); | |
211 | return ret; | |
212 | } | |
213 | ||
214 | BT_HIDDEN | |
215 | int get_payload_unsigned_int_field_value(FILE *err, | |
216 | struct bt_ctf_event *event, const char *field_name, | |
217 | uint64_t *value) | |
218 | { | |
219 | struct bt_ctf_field *field = NULL; | |
220 | struct bt_ctf_field_type *field_type = NULL; | |
221 | int ret; | |
222 | ||
223 | field = get_payload_field(err, event, field_name); | |
224 | if (!field) { | |
b4d4912f | 225 | BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name); |
4f45f9bb JD |
226 | goto error; |
227 | } | |
228 | ||
229 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 230 | assert(field_type); |
4f45f9bb | 231 | |
1487a16a | 232 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
b4d4912f JD |
233 | BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", |
234 | field_name); | |
4f45f9bb JD |
235 | goto error; |
236 | } | |
237 | ||
238 | if (bt_ctf_field_type_integer_get_signed(field_type) != 0) { | |
b4d4912f JD |
239 | BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"", |
240 | field_name); | |
4f45f9bb JD |
241 | goto error; |
242 | } | |
243 | ||
244 | ret = bt_ctf_field_unsigned_integer_get_value(field, value); | |
b4d4912f JD |
245 | if (ret) { |
246 | BT_LOGE("Failed to get value: field-name=\"%s\"", | |
247 | field_name); | |
248 | goto error; | |
249 | } | |
4f45f9bb JD |
250 | goto end; |
251 | ||
252 | error: | |
253 | ret = -1; | |
254 | end: | |
255 | bt_put(field_type); | |
256 | bt_put(field); | |
257 | return ret; | |
258 | } | |
259 | ||
260 | BT_HIDDEN | |
261 | int get_payload_int_field_value(FILE *err, struct bt_ctf_event *event, | |
262 | const char *field_name, int64_t *value) | |
263 | { | |
264 | struct bt_ctf_field *field = NULL; | |
265 | struct bt_ctf_field_type *field_type = NULL; | |
266 | int ret; | |
267 | ||
268 | field = get_payload_field(err, event, field_name); | |
269 | if (!field) { | |
b4d4912f | 270 | BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name); |
4f45f9bb JD |
271 | goto error; |
272 | } | |
273 | ||
274 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 275 | assert(field_type); |
4f45f9bb | 276 | |
1487a16a | 277 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
b4d4912f | 278 | BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name); |
4f45f9bb JD |
279 | goto error; |
280 | } | |
281 | ||
282 | if (bt_ctf_field_type_integer_get_signed(field_type) != 1) { | |
b4d4912f JD |
283 | BT_LOGE("Wrong type, expected signed integer field-name=\"%s\"", |
284 | field_name); | |
4f45f9bb JD |
285 | goto error; |
286 | } | |
287 | ||
288 | ret = bt_ctf_field_signed_integer_get_value(field, value); | |
b4d4912f JD |
289 | if (ret) { |
290 | BT_LOGE("Failed to get value: field-name=\"%s\"", | |
291 | field_name); | |
292 | goto error; | |
293 | } | |
4f45f9bb JD |
294 | goto end; |
295 | ||
296 | error: | |
297 | ret = -1; | |
298 | end: | |
299 | bt_put(field_type); | |
300 | bt_put(field); | |
301 | return ret; | |
302 | } | |
303 | ||
304 | BT_HIDDEN | |
305 | int get_payload_string_field_value(FILE *err, | |
306 | struct bt_ctf_event *event, const char *field_name, | |
307 | const char **value) | |
308 | { | |
309 | struct bt_ctf_field *field = NULL; | |
310 | struct bt_ctf_field_type *field_type = NULL; | |
311 | int ret; | |
312 | ||
65db8b88 JD |
313 | /* |
314 | * The field might not exist, no error here. | |
315 | */ | |
4f45f9bb JD |
316 | field = get_payload_field(err, event, field_name); |
317 | if (!field) { | |
4f45f9bb JD |
318 | goto error; |
319 | } | |
320 | ||
321 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 322 | assert(field_type); |
4f45f9bb | 323 | |
1487a16a | 324 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_STRING) { |
b4d4912f JD |
325 | BT_LOGE("Wrong type, expected string: field-name=\"%s\"", |
326 | field_name); | |
4f45f9bb JD |
327 | goto error; |
328 | } | |
329 | ||
330 | *value = bt_ctf_field_string_get_value(field); | |
331 | if (!*value) { | |
b4d4912f JD |
332 | BT_LOGE("Failed to get value: field-name=\"%s\"", |
333 | field_name); | |
4f45f9bb JD |
334 | goto error; |
335 | } | |
336 | ||
337 | ret = 0; | |
338 | goto end; | |
339 | ||
340 | error: | |
341 | ret = -1; | |
342 | end: | |
343 | bt_put(field_type); | |
344 | bt_put(field); | |
345 | return ret; | |
346 | } | |
347 | ||
348 | BT_HIDDEN | |
349 | int get_payload_build_id_field_value(FILE *err, | |
350 | struct bt_ctf_event *event, const char *field_name, | |
351 | uint8_t **build_id, uint64_t *build_id_len) | |
352 | { | |
353 | struct bt_ctf_field *field = NULL, *seq_len = NULL; | |
354 | struct bt_ctf_field_type *field_type = NULL; | |
355 | struct bt_ctf_field *seq_field = NULL; | |
356 | uint64_t i; | |
357 | int ret; | |
358 | ||
359 | *build_id = NULL; | |
360 | ||
361 | field = get_payload_field(err, event, field_name); | |
362 | if (!field) { | |
b4d4912f | 363 | BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name); |
4f45f9bb JD |
364 | goto error; |
365 | } | |
366 | ||
367 | field_type = bt_ctf_field_get_type(field); | |
b4d4912f | 368 | assert(field_type); |
4f45f9bb | 369 | |
1487a16a | 370 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_SEQUENCE) { |
b4d4912f | 371 | BT_LOGE("Wrong type, expected sequence: field-name=\"%s\"", field_name); |
4f45f9bb JD |
372 | goto error; |
373 | } | |
374 | BT_PUT(field_type); | |
375 | ||
376 | seq_len = bt_ctf_field_sequence_get_length(field); | |
b4d4912f | 377 | assert(seq_len); |
4f45f9bb JD |
378 | |
379 | ret = bt_ctf_field_unsigned_integer_get_value(seq_len, build_id_len); | |
380 | if (ret) { | |
b4d4912f JD |
381 | BT_LOGE("Failed to get value: field-name=\"%s\"", |
382 | field_name); | |
4f45f9bb JD |
383 | goto error; |
384 | } | |
385 | BT_PUT(seq_len); | |
386 | ||
387 | *build_id = g_new0(uint8_t, *build_id_len); | |
388 | if (!*build_id) { | |
b4d4912f | 389 | BT_LOGE_STR("Failed to allocate build_id."); |
4f45f9bb JD |
390 | goto error; |
391 | } | |
392 | ||
393 | for (i = 0; i < *build_id_len; i++) { | |
394 | uint64_t tmp; | |
395 | ||
396 | seq_field = bt_ctf_field_sequence_get_field(field, i); | |
397 | if (!seq_field) { | |
b4d4912f JD |
398 | BT_LOGE("Failed to get field in sequence: sequence-name=\"%s\", index=%" PRIu64, |
399 | field_name, i); | |
4f45f9bb JD |
400 | goto error; |
401 | } | |
402 | ||
403 | ret = bt_ctf_field_unsigned_integer_get_value(seq_field, &tmp); | |
404 | if (ret) { | |
b4d4912f JD |
405 | BT_LOGE("Failed to get value: field-name=\"%s\"", |
406 | field_name); | |
4f45f9bb JD |
407 | goto error; |
408 | } | |
b4d4912f | 409 | |
4f45f9bb JD |
410 | BT_PUT(seq_field); |
411 | (*build_id)[i] = (uint8_t) tmp; | |
412 | } | |
413 | ret = 0; | |
414 | goto end; | |
415 | ||
416 | error: | |
417 | g_free(*build_id); | |
418 | ret = -1; | |
419 | end: | |
420 | bt_put(field_type); | |
421 | bt_put(field); | |
422 | return ret; | |
423 | } | |
424 | ||
425 | static | |
426 | struct debug_info *lookup_trace_debug_info(struct debug_info_iterator *debug_it, | |
504db471 JD |
427 | struct bt_ctf_trace *writer_trace, |
428 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
429 | { |
430 | return (struct debug_info *) g_hash_table_lookup( | |
504db471 | 431 | di_trace->trace_debug_map, |
4f45f9bb JD |
432 | (gpointer) writer_trace); |
433 | } | |
434 | ||
435 | static | |
436 | struct debug_info *insert_new_debug_info(struct debug_info_iterator *debug_it, | |
504db471 JD |
437 | struct bt_ctf_trace *writer_trace, |
438 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
439 | { |
440 | struct debug_info *debug_info = NULL; | |
441 | struct bt_value *field = NULL; | |
442 | const char *str_value; | |
443 | enum bt_value_status ret; | |
444 | ||
445 | field = bt_ctf_trace_get_environment_field_value_by_name(writer_trace, | |
446 | "domain"); | |
447 | /* No domain field, no debug info */ | |
448 | if (!field) { | |
449 | goto end; | |
450 | } | |
451 | ret = bt_value_string_get(field, &str_value); | |
b4d4912f JD |
452 | assert(ret == BT_VALUE_STATUS_OK); |
453 | ||
4f45f9bb JD |
454 | /* Domain not ust, no debug info */ |
455 | if (strcmp(str_value, "ust") != 0) { | |
456 | goto end; | |
457 | } | |
458 | BT_PUT(field); | |
459 | ||
460 | /* No tracer_name, no debug info */ | |
461 | field = bt_ctf_trace_get_environment_field_value_by_name(writer_trace, | |
462 | "tracer_name"); | |
463 | /* No tracer_name, no debug info */ | |
464 | if (!field) { | |
465 | goto end; | |
466 | } | |
467 | ret = bt_value_string_get(field, &str_value); | |
b4d4912f JD |
468 | assert(ret == BT_VALUE_STATUS_OK); |
469 | ||
4f45f9bb JD |
470 | /* Tracer_name not lttng-ust, no debug info */ |
471 | if (strcmp(str_value, "lttng-ust") != 0) { | |
472 | goto end; | |
473 | } | |
474 | BT_PUT(field); | |
475 | ||
9d325e17 | 476 | debug_info = debug_info_create(debug_it->debug_info_component); |
4f45f9bb | 477 | if (!debug_info) { |
b4d4912f | 478 | BT_LOGE_STR("Failed to create debug info."); |
4f45f9bb JD |
479 | goto end; |
480 | } | |
481 | ||
504db471 | 482 | g_hash_table_insert(di_trace->trace_debug_map, (gpointer) writer_trace, |
4f45f9bb JD |
483 | debug_info); |
484 | ||
485 | end: | |
486 | bt_put(field); | |
487 | return debug_info; | |
488 | } | |
489 | ||
490 | static | |
491 | struct debug_info *get_trace_debug_info(struct debug_info_iterator *debug_it, | |
504db471 JD |
492 | struct bt_ctf_trace *writer_trace, |
493 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
494 | { |
495 | struct debug_info *debug_info; | |
496 | ||
504db471 | 497 | debug_info = lookup_trace_debug_info(debug_it, writer_trace, di_trace); |
4f45f9bb JD |
498 | if (debug_info) { |
499 | goto end; | |
500 | } | |
501 | ||
504db471 | 502 | debug_info = insert_new_debug_info(debug_it, writer_trace, di_trace); |
4f45f9bb JD |
503 | |
504 | end: | |
505 | return debug_info; | |
506 | } | |
507 | ||
508 | static | |
504db471 | 509 | struct debug_info_trace *lookup_trace(struct debug_info_iterator *debug_it, |
4f45f9bb JD |
510 | struct bt_ctf_trace *trace) |
511 | { | |
504db471 | 512 | return (struct debug_info_trace *) g_hash_table_lookup( |
4f45f9bb JD |
513 | debug_it->trace_map, |
514 | (gpointer) trace); | |
515 | } | |
516 | ||
1c78e839 JD |
517 | static |
518 | enum debug_info_stream_state *insert_new_stream_state( | |
519 | struct debug_info_iterator *debug_it, | |
520 | struct debug_info_trace *di_trace, struct bt_ctf_stream *stream) | |
521 | { | |
522 | enum debug_info_stream_state *v = NULL; | |
523 | ||
524 | v = g_new0(enum debug_info_stream_state, 1); | |
525 | if (!v) { | |
b4d4912f | 526 | BT_LOGE_STR("Failed to allocate debug_info_stream_state."); |
ec273a88 | 527 | goto end; |
1c78e839 JD |
528 | } |
529 | *v = DEBUG_INFO_UNKNOWN_STREAM; | |
530 | ||
531 | g_hash_table_insert(di_trace->stream_states, stream, v); | |
532 | ||
ec273a88 | 533 | end: |
1c78e839 JD |
534 | return v; |
535 | } | |
536 | ||
537 | static | |
538 | void check_completed_trace(gpointer key, gpointer value, gpointer user_data) | |
539 | { | |
540 | enum debug_info_stream_state *state = value; | |
541 | int *trace_completed = user_data; | |
542 | ||
543 | if (*state != DEBUG_INFO_COMPLETED_STREAM) { | |
544 | *trace_completed = 0; | |
545 | } | |
546 | } | |
547 | ||
548 | static | |
549 | gboolean empty_ht(gpointer key, gpointer value, gpointer user_data) | |
550 | { | |
551 | return TRUE; | |
552 | } | |
553 | ||
554 | BT_HIDDEN | |
555 | void debug_info_close_trace(struct debug_info_iterator *debug_it, | |
556 | struct debug_info_trace *di_trace) | |
557 | { | |
ec273a88 | 558 | if (di_trace->static_listener_id >= 0) { |
1c78e839 JD |
559 | bt_ctf_trace_remove_is_static_listener(di_trace->trace, |
560 | di_trace->static_listener_id); | |
561 | } | |
562 | ||
563 | /* Empty the stream class HT. */ | |
564 | g_hash_table_foreach_remove(di_trace->stream_class_map, | |
565 | empty_ht, NULL); | |
566 | g_hash_table_destroy(di_trace->stream_class_map); | |
567 | ||
568 | /* Empty the stream HT. */ | |
569 | g_hash_table_foreach_remove(di_trace->stream_map, | |
570 | empty_ht, NULL); | |
571 | g_hash_table_destroy(di_trace->stream_map); | |
572 | ||
573 | /* Empty the stream state HT. */ | |
574 | g_hash_table_foreach_remove(di_trace->stream_states, | |
575 | empty_ht, NULL); | |
576 | g_hash_table_destroy(di_trace->stream_states); | |
577 | ||
578 | /* Empty the packet HT. */ | |
579 | g_hash_table_foreach_remove(di_trace->packet_map, | |
580 | empty_ht, NULL); | |
581 | g_hash_table_destroy(di_trace->packet_map); | |
582 | ||
583 | /* Empty the trace_debug HT. */ | |
584 | g_hash_table_foreach_remove(di_trace->trace_debug_map, | |
585 | empty_ht, NULL); | |
586 | g_hash_table_destroy(di_trace->trace_debug_map); | |
587 | } | |
588 | ||
cb0a5cf8 JD |
589 | static |
590 | int sync_event_classes(struct debug_info_iterator *debug_it, | |
591 | struct bt_ctf_stream *stream, | |
592 | struct bt_ctf_stream *writer_stream) | |
593 | { | |
594 | int int_ret; | |
595 | struct bt_ctf_stream_class *stream_class = NULL, | |
596 | *writer_stream_class = NULL; | |
597 | enum bt_component_status ret; | |
598 | ||
599 | stream_class = bt_ctf_stream_get_class(stream); | |
b4d4912f | 600 | assert(stream_class); |
cb0a5cf8 JD |
601 | |
602 | writer_stream_class = bt_ctf_stream_get_class(writer_stream); | |
b4d4912f | 603 | assert(writer_stream_class); |
cb0a5cf8 JD |
604 | |
605 | ret = ctf_copy_event_classes(debug_it->err, stream_class, | |
606 | writer_stream_class); | |
607 | if (ret != BT_COMPONENT_STATUS_OK) { | |
b4d4912f | 608 | BT_LOGE_STR("Failed to copy event classes."); |
cb0a5cf8 JD |
609 | goto error; |
610 | } | |
611 | ||
612 | int_ret = 0; | |
613 | goto end; | |
614 | ||
615 | error: | |
616 | int_ret = -1; | |
617 | end: | |
618 | bt_put(stream_class); | |
619 | bt_put(writer_stream_class); | |
620 | return int_ret; | |
621 | } | |
622 | ||
1c78e839 JD |
623 | static |
624 | void trace_is_static_listener(struct bt_ctf_trace *trace, void *data) | |
625 | { | |
626 | struct debug_info_trace *di_trace = data; | |
cb0a5cf8 JD |
627 | int trace_completed = 1, ret, nr_stream, i; |
628 | struct bt_ctf_stream *stream = NULL, *writer_stream = NULL; | |
629 | struct bt_ctf_trace *writer_trace = di_trace->writer_trace; | |
630 | ||
631 | /* | |
632 | * When the trace becomes static, make sure that we have all | |
633 | * the event classes in our stream_class copies before setting it | |
634 | * static as well. | |
635 | */ | |
636 | nr_stream = bt_ctf_trace_get_stream_count(trace); | |
637 | for (i = 0; i < nr_stream; i++) { | |
638 | stream = bt_ctf_trace_get_stream_by_index(trace, i); | |
b4d4912f JD |
639 | assert(stream); |
640 | ||
cb0a5cf8 | 641 | writer_stream = bt_ctf_trace_get_stream_by_index(writer_trace, i); |
b4d4912f JD |
642 | assert(writer_stream); |
643 | ||
cb0a5cf8 JD |
644 | ret = sync_event_classes(di_trace->debug_it, stream, writer_stream); |
645 | if (ret) { | |
b4d4912f | 646 | BT_LOGE_STR("Failed to synchronize the event classes."); |
cb0a5cf8 JD |
647 | goto error; |
648 | } | |
649 | BT_PUT(stream); | |
650 | BT_PUT(writer_stream); | |
651 | } | |
1c78e839 | 652 | |
cb0a5cf8 | 653 | bt_ctf_trace_set_is_static(di_trace->writer_trace); |
1c78e839 JD |
654 | di_trace->trace_static = 1; |
655 | ||
656 | g_hash_table_foreach(di_trace->stream_states, | |
657 | check_completed_trace, &trace_completed); | |
658 | if (trace_completed) { | |
659 | debug_info_close_trace(di_trace->debug_it, di_trace); | |
660 | g_hash_table_remove(di_trace->debug_it->trace_map, | |
661 | di_trace->trace); | |
662 | } | |
cb0a5cf8 JD |
663 | |
664 | error: | |
665 | bt_put(writer_stream); | |
666 | bt_put(stream); | |
1c78e839 JD |
667 | } |
668 | ||
4f45f9bb | 669 | static |
504db471 JD |
670 | struct debug_info_trace *insert_new_trace(struct debug_info_iterator *debug_it, |
671 | struct bt_ctf_stream *stream) { | |
4f45f9bb | 672 | struct bt_ctf_trace *writer_trace = NULL; |
504db471 JD |
673 | struct debug_info_trace *di_trace = NULL; |
674 | struct bt_ctf_trace *trace = NULL; | |
675 | struct bt_ctf_stream_class *stream_class = NULL; | |
cb0a5cf8 | 676 | struct bt_ctf_stream *writer_stream = NULL; |
1c78e839 | 677 | int ret, nr_stream, i; |
4f45f9bb JD |
678 | |
679 | writer_trace = bt_ctf_trace_create(); | |
680 | if (!writer_trace) { | |
b4d4912f | 681 | BT_LOGE_STR("Failed to create a new trace."); |
4f45f9bb JD |
682 | goto error; |
683 | } | |
504db471 JD |
684 | |
685 | stream_class = bt_ctf_stream_get_class(stream); | |
b4d4912f | 686 | assert(stream_class); |
504db471 JD |
687 | |
688 | trace = bt_ctf_stream_class_get_trace(stream_class); | |
b4d4912f | 689 | assert(trace); |
4f45f9bb JD |
690 | |
691 | ret = ctf_copy_trace(debug_it->err, trace, writer_trace); | |
692 | if (ret != BT_COMPONENT_STATUS_OK) { | |
b4d4912f | 693 | BT_LOGE_STR("Failed to copy CTF trace."); |
4f45f9bb JD |
694 | goto error; |
695 | } | |
696 | ||
504db471 JD |
697 | di_trace = g_new0(struct debug_info_trace, 1); |
698 | if (!di_trace) { | |
b4d4912f | 699 | BT_LOGE_STR("Failed to allocate debug_info_trace."); |
504db471 JD |
700 | goto error; |
701 | } | |
702 | ||
703 | di_trace->trace = trace; | |
704 | di_trace->writer_trace = writer_trace; | |
705 | di_trace->debug_info_component = debug_it->debug_info_component; | |
1c78e839 | 706 | di_trace->debug_it = debug_it; |
504db471 JD |
707 | di_trace->stream_map = g_hash_table_new_full(g_direct_hash, |
708 | g_direct_equal, NULL, (GDestroyNotify) unref_stream); | |
709 | di_trace->stream_class_map = g_hash_table_new_full(g_direct_hash, | |
710 | g_direct_equal, NULL, (GDestroyNotify) unref_stream_class); | |
711 | di_trace->packet_map = g_hash_table_new_full(g_direct_hash, | |
712 | g_direct_equal, NULL, (GDestroyNotify) unref_packet); | |
713 | di_trace->trace_debug_map = g_hash_table_new_full(g_direct_hash, | |
714 | g_direct_equal, NULL, (GDestroyNotify) unref_debug_info); | |
1c78e839 JD |
715 | di_trace->stream_states = g_hash_table_new_full(g_direct_hash, |
716 | g_direct_equal, NULL, destroy_stream_state_key); | |
cb0a5cf8 | 717 | g_hash_table_insert(debug_it->trace_map, (gpointer) trace, di_trace); |
1c78e839 JD |
718 | |
719 | /* Set all the existing streams in the unknown state. */ | |
720 | nr_stream = bt_ctf_trace_get_stream_count(trace); | |
721 | for (i = 0; i < nr_stream; i++) { | |
722 | stream = bt_ctf_trace_get_stream_by_index(trace, i); | |
b4d4912f JD |
723 | assert(stream); |
724 | ||
1c78e839 | 725 | insert_new_stream_state(debug_it, di_trace, stream); |
cb0a5cf8 JD |
726 | writer_stream = insert_new_stream(debug_it, stream, di_trace); |
727 | if (!writer_stream) { | |
b4d4912f | 728 | BT_LOGE_STR("Failed to insert new stream."); |
cb0a5cf8 JD |
729 | goto error; |
730 | } | |
731 | bt_get(writer_stream); | |
732 | ret = sync_event_classes(debug_it, stream, writer_stream); | |
733 | if (ret) { | |
b4d4912f | 734 | BT_LOGE_STR("Failed to synchronize event classes."); |
cb0a5cf8 JD |
735 | goto error; |
736 | } | |
737 | BT_PUT(writer_stream); | |
1c78e839 JD |
738 | BT_PUT(stream); |
739 | } | |
740 | ||
741 | /* Check if the trace is already static or register a listener. */ | |
742 | if (bt_ctf_trace_is_static(trace)) { | |
743 | di_trace->trace_static = 1; | |
744 | di_trace->static_listener_id = -1; | |
cb0a5cf8 | 745 | bt_ctf_trace_set_is_static(writer_trace); |
1c78e839 JD |
746 | } else { |
747 | ret = bt_ctf_trace_add_is_static_listener(trace, | |
8480c8cc | 748 | trace_is_static_listener, NULL, di_trace); |
b4d4912f | 749 | assert(ret >= 0); |
1c78e839 JD |
750 | di_trace->static_listener_id = ret; |
751 | } | |
504db471 | 752 | |
504db471 | 753 | |
4f45f9bb JD |
754 | goto end; |
755 | ||
756 | error: | |
757 | BT_PUT(writer_trace); | |
504db471 JD |
758 | g_free(di_trace); |
759 | di_trace = NULL; | |
4f45f9bb | 760 | end: |
cb0a5cf8 JD |
761 | bt_put(stream); |
762 | bt_put(writer_stream); | |
504db471 JD |
763 | bt_put(stream_class); |
764 | bt_put(trace); | |
765 | return di_trace; | |
4f45f9bb JD |
766 | } |
767 | ||
768 | static | |
769 | struct bt_ctf_packet *lookup_packet(struct debug_info_iterator *debug_it, | |
504db471 JD |
770 | struct bt_ctf_packet *packet, |
771 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
772 | { |
773 | return (struct bt_ctf_packet *) g_hash_table_lookup( | |
504db471 | 774 | di_trace->packet_map, |
4f45f9bb JD |
775 | (gpointer) packet); |
776 | } | |
777 | ||
778 | static | |
779 | struct bt_ctf_packet *insert_new_packet(struct debug_info_iterator *debug_it, | |
780 | struct bt_ctf_packet *packet, | |
504db471 JD |
781 | struct bt_ctf_stream *writer_stream, |
782 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
783 | { |
784 | struct bt_ctf_packet *writer_packet; | |
387483fc | 785 | int ret; |
4f45f9bb JD |
786 | |
787 | writer_packet = bt_ctf_packet_create(writer_stream); | |
788 | if (!writer_packet) { | |
b4d4912f | 789 | BT_LOGE_STR("Failed to create new packet."); |
387483fc JD |
790 | goto error; |
791 | } | |
792 | ||
793 | ret = ctf_packet_copy_header(debug_it->err, packet, writer_packet); | |
794 | if (ret) { | |
b4d4912f | 795 | BT_LOGE_STR("Failed to copy packet header."); |
387483fc | 796 | goto error; |
4f45f9bb | 797 | } |
4f45f9bb | 798 | |
387483fc JD |
799 | g_hash_table_insert(di_trace->packet_map, (gpointer) packet, |
800 | writer_packet); | |
801 | goto end; | |
802 | ||
803 | error: | |
804 | BT_PUT(writer_packet); | |
4f45f9bb JD |
805 | end: |
806 | return writer_packet; | |
807 | } | |
808 | ||
809 | static | |
810 | int add_debug_info_fields(FILE *err, | |
811 | struct bt_ctf_field_type *writer_event_context_type, | |
812 | struct debug_info_component *component) | |
813 | { | |
814 | struct bt_ctf_field_type *ip_field = NULL, *debug_field_type = NULL, | |
815 | *bin_field_type = NULL, *func_field_type = NULL, | |
816 | *src_field_type = NULL; | |
817 | int ret = 0; | |
818 | ||
819 | ip_field = bt_ctf_field_type_structure_get_field_type_by_name( | |
820 | writer_event_context_type, "_ip"); | |
821 | /* No ip field, so no debug info. */ | |
822 | if (!ip_field) { | |
823 | goto end; | |
824 | } | |
825 | BT_PUT(ip_field); | |
826 | ||
827 | debug_field_type = bt_ctf_field_type_structure_get_field_type_by_name( | |
828 | writer_event_context_type, | |
829 | component->arg_debug_info_field_name); | |
830 | /* Already existing debug_info field, no need to add it. */ | |
831 | if (debug_field_type) { | |
832 | goto end; | |
833 | } | |
834 | ||
835 | debug_field_type = bt_ctf_field_type_structure_create(); | |
836 | if (!debug_field_type) { | |
b4d4912f | 837 | BT_LOGE_STR("Failed to create debug_info structure."); |
4f45f9bb JD |
838 | goto error; |
839 | } | |
840 | ||
841 | bin_field_type = bt_ctf_field_type_string_create(); | |
842 | if (!bin_field_type) { | |
b4d4912f | 843 | BT_LOGE_STR("Failed to create string for field=bin."); |
4f45f9bb JD |
844 | goto error; |
845 | } | |
846 | ||
847 | func_field_type = bt_ctf_field_type_string_create(); | |
848 | if (!func_field_type) { | |
b4d4912f | 849 | BT_LOGE_STR("Failed to create string for field=func."); |
4f45f9bb JD |
850 | goto error; |
851 | } | |
852 | ||
853 | src_field_type = bt_ctf_field_type_string_create(); | |
854 | if (!src_field_type) { | |
b4d4912f | 855 | BT_LOGE_STR("Failed to create string for field=src."); |
4f45f9bb JD |
856 | goto error; |
857 | } | |
858 | ||
859 | ret = bt_ctf_field_type_structure_add_field(debug_field_type, | |
860 | bin_field_type, "bin"); | |
861 | if (ret) { | |
b4d4912f | 862 | BT_LOGE_STR("Failed to add a field to debug_info struct: field=bin."); |
4f45f9bb JD |
863 | goto error; |
864 | } | |
865 | ||
866 | ret = bt_ctf_field_type_structure_add_field(debug_field_type, | |
867 | func_field_type, "func"); | |
868 | if (ret) { | |
b4d4912f | 869 | BT_LOGE_STR("Failed to add a field to debug_info struct: field=func."); |
4f45f9bb JD |
870 | goto error; |
871 | } | |
872 | ||
873 | ret = bt_ctf_field_type_structure_add_field(debug_field_type, | |
874 | src_field_type, "src"); | |
875 | if (ret) { | |
b4d4912f | 876 | BT_LOGE_STR("Failed to add a field to debug_info struct: field=src."); |
4f45f9bb JD |
877 | goto error; |
878 | } | |
879 | ||
880 | ret = bt_ctf_field_type_structure_add_field(writer_event_context_type, | |
881 | debug_field_type, component->arg_debug_info_field_name); | |
882 | if (ret) { | |
b4d4912f | 883 | BT_LOGE_STR("Failed to add debug_info field to event_context."); |
4f45f9bb JD |
884 | goto error; |
885 | } | |
886 | ||
887 | ret = 0; | |
888 | goto end; | |
889 | ||
890 | error: | |
891 | BT_PUT(debug_field_type); | |
892 | ret = -1; | |
893 | end: | |
894 | bt_put(src_field_type); | |
895 | bt_put(func_field_type); | |
896 | bt_put(bin_field_type); | |
897 | bt_put(debug_field_type); | |
898 | return ret; | |
899 | } | |
900 | ||
901 | static | |
902 | int create_debug_info_event_context_type(FILE *err, | |
903 | struct bt_ctf_field_type *event_context_type, | |
904 | struct bt_ctf_field_type *writer_event_context_type, | |
905 | struct debug_info_component *component) | |
906 | { | |
907 | int ret, nr_fields, i; | |
908 | ||
909 | nr_fields = bt_ctf_field_type_structure_get_field_count(event_context_type); | |
910 | for (i = 0; i < nr_fields; i++) { | |
911 | struct bt_ctf_field_type *field_type = NULL; | |
912 | const char *field_name; | |
913 | ||
914 | if (bt_ctf_field_type_structure_get_field(event_context_type, | |
915 | &field_name, &field_type, i) < 0) { | |
b4d4912f JD |
916 | BT_LOGE("Failed to get a field from the event-context: field-name=\"%s\"", |
917 | field_name); | |
4f45f9bb JD |
918 | goto error; |
919 | } | |
920 | ||
921 | ret = bt_ctf_field_type_structure_add_field(writer_event_context_type, | |
922 | field_type, field_name); | |
923 | BT_PUT(field_type); | |
924 | if (ret) { | |
b4d4912f JD |
925 | BT_LOGE("Failed to add a field to the event-context: field-name=\"%s\"", |
926 | field_name); | |
4f45f9bb JD |
927 | goto error; |
928 | } | |
929 | } | |
930 | ||
931 | ret = add_debug_info_fields(err, writer_event_context_type, | |
932 | component); | |
933 | goto end; | |
934 | ||
935 | error: | |
936 | ret = -1; | |
937 | end: | |
938 | return ret; | |
939 | } | |
940 | ||
941 | static | |
942 | struct bt_ctf_stream_class *copy_stream_class_debug_info(FILE *err, | |
943 | struct bt_ctf_stream_class *stream_class, | |
944 | struct bt_ctf_trace *writer_trace, | |
945 | struct debug_info_component *component) | |
946 | { | |
947 | struct bt_ctf_field_type *type = NULL; | |
948 | struct bt_ctf_stream_class *writer_stream_class = NULL; | |
949 | struct bt_ctf_field_type *writer_event_context_type = NULL; | |
950 | int ret_int; | |
951 | const char *name = bt_ctf_stream_class_get_name(stream_class); | |
952 | ||
2d64a1eb | 953 | writer_stream_class = bt_ctf_stream_class_create_empty(name); |
4f45f9bb | 954 | if (!writer_stream_class) { |
b4d4912f | 955 | BT_LOGE_STR("Failed to create empty stream class."); |
4f45f9bb JD |
956 | goto error; |
957 | } | |
958 | ||
959 | type = bt_ctf_stream_class_get_packet_context_type(stream_class); | |
2d64a1eb JD |
960 | if (type) { |
961 | ret_int = bt_ctf_stream_class_set_packet_context_type( | |
962 | writer_stream_class, type); | |
963 | if (ret_int < 0) { | |
b4d4912f | 964 | BT_LOGE_STR("Failed to set packet_context type."); |
2d64a1eb JD |
965 | goto error; |
966 | } | |
967 | BT_PUT(type); | |
4f45f9bb | 968 | } |
4f45f9bb JD |
969 | |
970 | type = bt_ctf_stream_class_get_event_header_type(stream_class); | |
290b95cc MD |
971 | if (type) { |
972 | ret_int = bt_ctf_stream_class_set_event_header_type( | |
973 | writer_stream_class, type); | |
974 | if (ret_int < 0) { | |
b4d4912f | 975 | BT_LOGE_STR("Failed to set event_header type."); |
290b95cc MD |
976 | goto error; |
977 | } | |
978 | BT_PUT(type); | |
4f45f9bb | 979 | } |
4f45f9bb JD |
980 | |
981 | type = bt_ctf_stream_class_get_event_context_type(stream_class); | |
982 | if (type) { | |
983 | writer_event_context_type = bt_ctf_field_type_structure_create(); | |
984 | if (!writer_event_context_type) { | |
b4d4912f | 985 | BT_LOGE_STR("Failed to create writer_event_context struct type."); |
4f45f9bb JD |
986 | goto error; |
987 | } | |
988 | ret_int = create_debug_info_event_context_type(err, type, | |
989 | writer_event_context_type, component); | |
990 | if (ret_int) { | |
b4d4912f | 991 | BT_LOGE_STR("Failed to create debug_info event_context type."); |
4f45f9bb JD |
992 | goto error; |
993 | } | |
994 | BT_PUT(type); | |
995 | ||
996 | ret_int = bt_ctf_stream_class_set_event_context_type( | |
997 | writer_stream_class, writer_event_context_type); | |
998 | if (ret_int < 0) { | |
b4d4912f | 999 | BT_LOGE_STR("Failed to set event_context type."); |
4f45f9bb JD |
1000 | goto error; |
1001 | } | |
1002 | BT_PUT(writer_event_context_type); | |
1003 | } | |
1004 | ||
1005 | goto end; | |
1006 | ||
1007 | error: | |
1008 | BT_PUT(writer_stream_class); | |
1009 | end: | |
1010 | bt_put(writer_event_context_type); | |
1011 | bt_put(type); | |
1012 | return writer_stream_class; | |
1013 | } | |
1014 | ||
1015 | /* | |
1016 | * Add the original clock classes to the new trace, we do not need to copy | |
1017 | * them, and if we did, we would have to manually inspect the stream class | |
1018 | * to update the integers mapping to a clock. | |
1019 | */ | |
1020 | static | |
1021 | int add_clock_classes(FILE *err, struct bt_ctf_trace *writer_trace, | |
1022 | struct bt_ctf_stream_class *writer_stream_class, | |
1023 | struct bt_ctf_trace *trace) | |
1024 | { | |
1025 | int ret, clock_class_count, i; | |
1026 | ||
1027 | clock_class_count = bt_ctf_trace_get_clock_class_count(trace); | |
1028 | ||
1029 | for (i = 0; i < clock_class_count; i++) { | |
1030 | struct bt_ctf_clock_class *clock_class = | |
9ac68eb1 | 1031 | bt_ctf_trace_get_clock_class_by_index(trace, i); |
30480ffe | 1032 | struct bt_ctf_clock_class *existing_clock_class = NULL; |
4f45f9bb | 1033 | |
b4d4912f | 1034 | assert(clock_class); |
4f45f9bb | 1035 | |
30480ffe PP |
1036 | existing_clock_class = bt_ctf_trace_get_clock_class_by_name( |
1037 | writer_trace, bt_ctf_clock_class_get_name(clock_class)); | |
1038 | bt_put(existing_clock_class); | |
1039 | if (existing_clock_class) { | |
1040 | bt_put(clock_class); | |
1041 | continue; | |
1042 | } | |
1043 | ||
4f45f9bb JD |
1044 | ret = bt_ctf_trace_add_clock_class(writer_trace, clock_class); |
1045 | BT_PUT(clock_class); | |
1046 | if (ret != 0) { | |
b4d4912f | 1047 | BT_LOGE_STR("Failed to add clock_class."); |
4f45f9bb JD |
1048 | goto error; |
1049 | } | |
1050 | } | |
1051 | ||
1052 | ret = 0; | |
1053 | goto end; | |
1054 | ||
1055 | error: | |
1056 | ret = -1; | |
1057 | end: | |
1058 | return ret; | |
1059 | ||
1060 | } | |
1061 | ||
1062 | static | |
1063 | struct bt_ctf_stream_class *insert_new_stream_class( | |
1064 | struct debug_info_iterator *debug_it, | |
1065 | struct bt_ctf_stream_class *stream_class) | |
1066 | { | |
1067 | struct bt_ctf_stream_class *writer_stream_class = NULL; | |
1068 | struct bt_ctf_trace *trace, *writer_trace = NULL; | |
504db471 | 1069 | struct debug_info_trace *di_trace; |
4f45f9bb JD |
1070 | enum bt_component_status ret; |
1071 | int int_ret; | |
1072 | ||
1073 | trace = bt_ctf_stream_class_get_trace(stream_class); | |
b4d4912f | 1074 | assert(trace); |
4f45f9bb | 1075 | |
504db471 JD |
1076 | di_trace = lookup_trace(debug_it, trace); |
1077 | if (!di_trace) { | |
b4d4912f | 1078 | BT_LOGE_STR("Failed to find existing trace."); |
504db471 JD |
1079 | ret = BT_COMPONENT_STATUS_ERROR; |
1080 | goto error; | |
4f45f9bb | 1081 | } |
504db471 | 1082 | writer_trace = di_trace->writer_trace; |
4f45f9bb JD |
1083 | bt_get(writer_trace); |
1084 | ||
1085 | writer_stream_class = copy_stream_class_debug_info(debug_it->err, stream_class, | |
1086 | writer_trace, debug_it->debug_info_component); | |
1087 | if (!writer_stream_class) { | |
b4d4912f | 1088 | BT_LOGE_STR("Failed to copy stream class."); |
4f45f9bb JD |
1089 | goto error; |
1090 | } | |
1091 | ||
1092 | int_ret = bt_ctf_trace_add_stream_class(writer_trace, writer_stream_class); | |
1093 | if (int_ret) { | |
b4d4912f | 1094 | BT_LOGE_STR("Failed to add stream class."); |
4f45f9bb JD |
1095 | goto error; |
1096 | } | |
1097 | ||
1098 | ret = add_clock_classes(debug_it->err, writer_trace, | |
1099 | writer_stream_class, trace); | |
1100 | if (ret != BT_COMPONENT_STATUS_OK) { | |
b4d4912f | 1101 | BT_LOGE_STR("Failed to add clock classes."); |
4f45f9bb JD |
1102 | goto error; |
1103 | } | |
4f45f9bb | 1104 | |
504db471 | 1105 | g_hash_table_insert(di_trace->stream_class_map, |
4f45f9bb JD |
1106 | (gpointer) stream_class, writer_stream_class); |
1107 | ||
1108 | goto end; | |
1109 | ||
1110 | error: | |
1111 | BT_PUT(writer_stream_class); | |
1112 | end: | |
1113 | bt_put(trace); | |
1114 | bt_put(writer_trace); | |
1115 | return writer_stream_class; | |
1116 | } | |
1117 | ||
1118 | static | |
1119 | struct bt_ctf_stream *insert_new_stream( | |
1120 | struct debug_info_iterator *debug_it, | |
504db471 JD |
1121 | struct bt_ctf_stream *stream, |
1122 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
1123 | { |
1124 | struct bt_ctf_stream *writer_stream = NULL; | |
504db471 | 1125 | struct bt_ctf_stream_class *stream_class = NULL; |
4f45f9bb | 1126 | struct bt_ctf_stream_class *writer_stream_class = NULL; |
b910013b | 1127 | int64_t id; |
4f45f9bb | 1128 | |
504db471 | 1129 | stream_class = bt_ctf_stream_get_class(stream); |
b4d4912f | 1130 | assert(stream_class); |
504db471 | 1131 | |
4f45f9bb | 1132 | writer_stream_class = g_hash_table_lookup( |
504db471 | 1133 | di_trace->stream_class_map, |
4f45f9bb JD |
1134 | (gpointer) stream_class); |
1135 | ||
1136 | if (!writer_stream_class) { | |
1137 | writer_stream_class = insert_new_stream_class(debug_it, | |
1138 | stream_class); | |
1139 | if (!writer_stream_class) { | |
b4d4912f | 1140 | BT_LOGE_STR("Failed to insert new stream class."); |
4f45f9bb JD |
1141 | goto error; |
1142 | } | |
1143 | } | |
1144 | bt_get(writer_stream_class); | |
1145 | ||
b910013b PP |
1146 | id = bt_ctf_stream_get_id(stream); |
1147 | if (id < 0) { | |
1148 | writer_stream = bt_ctf_stream_create(writer_stream_class, | |
1149 | bt_ctf_stream_get_name(stream)); | |
1150 | } else { | |
1151 | writer_stream = bt_ctf_stream_create_with_id( | |
1152 | writer_stream_class, | |
1153 | bt_ctf_stream_get_name(stream), id); | |
1154 | } | |
1155 | ||
4f45f9bb | 1156 | if (!writer_stream) { |
b4d4912f | 1157 | BT_LOGE_STR("Failed to create writer_stream."); |
4f45f9bb JD |
1158 | goto error; |
1159 | } | |
1160 | ||
504db471 | 1161 | g_hash_table_insert(di_trace->stream_map, (gpointer) stream, |
4f45f9bb JD |
1162 | writer_stream); |
1163 | ||
1164 | goto end; | |
1165 | ||
1166 | error: | |
1167 | BT_PUT(writer_stream); | |
1168 | end: | |
504db471 | 1169 | bt_put(stream_class); |
4f45f9bb JD |
1170 | bt_put(writer_stream_class); |
1171 | return writer_stream; | |
1172 | } | |
1173 | ||
1174 | static | |
1175 | struct bt_ctf_stream *lookup_stream(struct debug_info_iterator *debug_it, | |
504db471 JD |
1176 | struct bt_ctf_stream *stream, |
1177 | struct debug_info_trace *di_trace) | |
4f45f9bb JD |
1178 | { |
1179 | return (struct bt_ctf_stream *) g_hash_table_lookup( | |
504db471 | 1180 | di_trace->stream_map, (gpointer) stream); |
4f45f9bb JD |
1181 | } |
1182 | ||
1183 | static | |
1184 | struct bt_ctf_event_class *get_event_class(struct debug_info_iterator *debug_it, | |
1185 | struct bt_ctf_stream_class *writer_stream_class, | |
1186 | struct bt_ctf_event_class *event_class) | |
1187 | { | |
a9f0d01b PP |
1188 | return bt_ctf_stream_class_get_event_class_by_id(writer_stream_class, |
1189 | bt_ctf_event_class_get_id(event_class)); | |
4f45f9bb JD |
1190 | } |
1191 | ||
504db471 JD |
1192 | static |
1193 | struct debug_info_trace *lookup_di_trace_from_stream( | |
1194 | struct debug_info_iterator *debug_it, | |
1195 | struct bt_ctf_stream *stream) | |
1196 | { | |
1197 | struct bt_ctf_stream_class *stream_class = NULL; | |
1198 | struct bt_ctf_trace *trace = NULL; | |
1199 | struct debug_info_trace *di_trace = NULL; | |
1200 | ||
1201 | stream_class = bt_ctf_stream_get_class(stream); | |
b4d4912f | 1202 | assert(stream_class); |
504db471 JD |
1203 | |
1204 | trace = bt_ctf_stream_class_get_trace(stream_class); | |
b4d4912f | 1205 | assert(trace); |
504db471 JD |
1206 | |
1207 | di_trace = (struct debug_info_trace *) g_hash_table_lookup( | |
1208 | debug_it->trace_map, (gpointer) trace); | |
1209 | ||
504db471 JD |
1210 | BT_PUT(stream_class); |
1211 | BT_PUT(trace); | |
1212 | return di_trace; | |
1213 | } | |
1214 | ||
4f45f9bb JD |
1215 | static |
1216 | struct bt_ctf_stream *get_writer_stream( | |
1217 | struct debug_info_iterator *debug_it, | |
1218 | struct bt_ctf_packet *packet, struct bt_ctf_stream *stream) | |
1219 | { | |
1220 | struct bt_ctf_stream_class *stream_class = NULL; | |
1221 | struct bt_ctf_stream *writer_stream = NULL; | |
504db471 | 1222 | struct debug_info_trace *di_trace = NULL; |
4f45f9bb JD |
1223 | |
1224 | stream_class = bt_ctf_stream_get_class(stream); | |
b4d4912f | 1225 | assert(stream_class); |
4f45f9bb | 1226 | |
504db471 JD |
1227 | di_trace = lookup_di_trace_from_stream(debug_it, stream); |
1228 | if (!di_trace) { | |
b4d4912f | 1229 | BT_LOGE_STR("Failed to find existing trace from stream."); |
504db471 JD |
1230 | goto error; |
1231 | } | |
1232 | ||
1233 | writer_stream = lookup_stream(debug_it, stream, di_trace); | |
4f45f9bb | 1234 | if (!writer_stream) { |
b4d4912f | 1235 | BT_LOGE_STR("Failed to find existing stream."); |
504db471 | 1236 | goto error; |
4f45f9bb JD |
1237 | } |
1238 | bt_get(writer_stream); | |
1239 | ||
1240 | goto end; | |
1241 | ||
1242 | error: | |
1243 | BT_PUT(writer_stream); | |
1244 | end: | |
1245 | bt_put(stream_class); | |
1246 | return writer_stream; | |
1247 | } | |
1248 | ||
1249 | BT_HIDDEN | |
1250 | struct bt_ctf_packet *debug_info_new_packet( | |
1251 | struct debug_info_iterator *debug_it, | |
1252 | struct bt_ctf_packet *packet) | |
1253 | { | |
1254 | struct bt_ctf_stream *stream = NULL, *writer_stream = NULL; | |
4f45f9bb | 1255 | struct bt_ctf_packet *writer_packet = NULL; |
2d64a1eb | 1256 | struct bt_ctf_field *packet_context = NULL; |
504db471 | 1257 | struct debug_info_trace *di_trace; |
4f45f9bb JD |
1258 | int int_ret; |
1259 | ||
1260 | stream = bt_ctf_packet_get_stream(packet); | |
b4d4912f | 1261 | assert(stream); |
4f45f9bb JD |
1262 | |
1263 | writer_stream = get_writer_stream(debug_it, packet, stream); | |
1264 | if (!writer_stream) { | |
b4d4912f | 1265 | BT_LOGE_STR("Failed to get writer stream."); |
4f45f9bb JD |
1266 | goto error; |
1267 | } | |
1268 | ||
504db471 JD |
1269 | di_trace = lookup_di_trace_from_stream(debug_it, stream); |
1270 | if (!di_trace) { | |
b4d4912f | 1271 | BT_LOGE_STR("Failed to find existing trace from stream."); |
504db471 JD |
1272 | goto error; |
1273 | } | |
1274 | ||
4f45f9bb JD |
1275 | /* |
1276 | * If a packet was already opened, close it and remove it from | |
1277 | * the HT. | |
1278 | */ | |
504db471 | 1279 | writer_packet = lookup_packet(debug_it, packet, di_trace); |
4f45f9bb | 1280 | if (writer_packet) { |
504db471 | 1281 | g_hash_table_remove(di_trace->packet_map, packet); |
4f45f9bb JD |
1282 | BT_PUT(writer_packet); |
1283 | } | |
1284 | ||
504db471 JD |
1285 | writer_packet = insert_new_packet(debug_it, packet, writer_stream, |
1286 | di_trace); | |
4f45f9bb | 1287 | if (!writer_packet) { |
b4d4912f | 1288 | BT_LOGE_STR("Failed to insert new packet."); |
4f45f9bb JD |
1289 | goto error; |
1290 | } | |
4f45f9bb | 1291 | |
2d64a1eb JD |
1292 | packet_context = bt_ctf_packet_get_context(packet); |
1293 | if (packet_context) { | |
9877e1aa JD |
1294 | int_ret = ctf_packet_copy_context(debug_it->err, |
1295 | packet, writer_stream, writer_packet); | |
1296 | if (int_ret < 0) { | |
b4d4912f | 1297 | BT_LOGE_STR("Failed to copy packet context."); |
2d64a1eb JD |
1298 | goto error; |
1299 | } | |
1300 | BT_PUT(packet_context); | |
4f45f9bb JD |
1301 | } |
1302 | ||
1c78e839 | 1303 | bt_get(writer_packet); |
4f45f9bb JD |
1304 | goto end; |
1305 | ||
1306 | error: | |
1307 | ||
1308 | end: | |
2d64a1eb | 1309 | bt_put(packet_context); |
4f45f9bb JD |
1310 | bt_put(writer_stream); |
1311 | bt_put(stream); | |
1312 | return writer_packet; | |
1313 | } | |
1314 | ||
1315 | BT_HIDDEN | |
1316 | struct bt_ctf_packet *debug_info_close_packet( | |
1317 | struct debug_info_iterator *debug_it, | |
1318 | struct bt_ctf_packet *packet) | |
1319 | { | |
1320 | struct bt_ctf_packet *writer_packet = NULL; | |
504db471 JD |
1321 | struct bt_ctf_stream *stream = NULL; |
1322 | struct debug_info_trace *di_trace; | |
1323 | ||
1324 | stream = bt_ctf_packet_get_stream(packet); | |
b4d4912f | 1325 | assert(stream); |
504db471 JD |
1326 | |
1327 | di_trace = lookup_di_trace_from_stream(debug_it, stream); | |
1328 | if (!di_trace) { | |
b4d4912f | 1329 | BT_LOGE_STR("Failed to find trace from stream."); |
504db471 JD |
1330 | goto end; |
1331 | } | |
4f45f9bb | 1332 | |
504db471 | 1333 | writer_packet = lookup_packet(debug_it, packet, di_trace); |
4f45f9bb | 1334 | if (!writer_packet) { |
b4d4912f | 1335 | BT_LOGE_STR("Failed to find existing packet."); |
4f45f9bb JD |
1336 | goto end; |
1337 | } | |
1c78e839 | 1338 | bt_get(writer_packet); |
504db471 | 1339 | g_hash_table_remove(di_trace->packet_map, packet); |
4f45f9bb JD |
1340 | |
1341 | end: | |
504db471 | 1342 | bt_put(stream); |
4f45f9bb JD |
1343 | return writer_packet; |
1344 | } | |
1345 | ||
504db471 JD |
1346 | BT_HIDDEN |
1347 | struct bt_ctf_stream *debug_info_stream_begin( | |
1348 | struct debug_info_iterator *debug_it, | |
1349 | struct bt_ctf_stream *stream) | |
1350 | { | |
cb0a5cf8 | 1351 | struct bt_ctf_stream *writer_stream = NULL; |
1c78e839 | 1352 | enum debug_info_stream_state *state; |
504db471 JD |
1353 | struct debug_info_trace *di_trace = NULL; |
1354 | ||
1355 | di_trace = lookup_di_trace_from_stream(debug_it, stream); | |
1356 | if (!di_trace) { | |
1357 | di_trace = insert_new_trace(debug_it, stream); | |
1358 | if (!di_trace) { | |
b4d4912f | 1359 | BT_LOGE_STR("Failed to insert new trace."); |
1c78e839 | 1360 | goto error; |
504db471 JD |
1361 | } |
1362 | } | |
1363 | ||
1c78e839 JD |
1364 | /* Set the stream as active */ |
1365 | state = g_hash_table_lookup(di_trace->stream_states, stream); | |
1366 | if (!state) { | |
1367 | if (di_trace->trace_static) { | |
b4d4912f | 1368 | BT_LOGE_STR("Failed to add a new stream, trace is static."); |
1c78e839 JD |
1369 | goto error; |
1370 | } | |
1371 | state = insert_new_stream_state(debug_it, di_trace, | |
1372 | stream); | |
ec273a88 | 1373 | if (!state) { |
b4d4912f | 1374 | BT_LOGE_STR("Failed to add new stream state."); |
ec273a88 JD |
1375 | goto error; |
1376 | } | |
1c78e839 JD |
1377 | } |
1378 | if (*state != DEBUG_INFO_UNKNOWN_STREAM) { | |
b4d4912f | 1379 | BT_LOGE("Unexpected stream state: state=%d", *state); |
1c78e839 JD |
1380 | goto error; |
1381 | } | |
1382 | *state = DEBUG_INFO_ACTIVE_STREAM; | |
1383 | ||
cb0a5cf8 JD |
1384 | writer_stream = lookup_stream(debug_it, stream, di_trace); |
1385 | if (!writer_stream) { | |
1386 | writer_stream = insert_new_stream(debug_it, stream, di_trace); | |
1387 | } | |
1c78e839 | 1388 | bt_get(writer_stream); |
504db471 | 1389 | |
1c78e839 JD |
1390 | goto end; |
1391 | ||
1392 | error: | |
1393 | BT_PUT(writer_stream); | |
504db471 JD |
1394 | end: |
1395 | return writer_stream; | |
1396 | } | |
1397 | ||
4f45f9bb JD |
1398 | BT_HIDDEN |
1399 | struct bt_ctf_stream *debug_info_stream_end(struct debug_info_iterator *debug_it, | |
1400 | struct bt_ctf_stream *stream) | |
1401 | { | |
0bb3da02 | 1402 | struct bt_ctf_stream *writer_stream = NULL; |
504db471 | 1403 | struct debug_info_trace *di_trace = NULL; |
1c78e839 | 1404 | enum debug_info_stream_state *state; |
504db471 JD |
1405 | |
1406 | di_trace = lookup_di_trace_from_stream(debug_it, stream); | |
1407 | if (!di_trace) { | |
b4d4912f | 1408 | BT_LOGE_STR("Failed to find existing trace from stream."); |
1c78e839 | 1409 | goto error; |
504db471 | 1410 | } |
4f45f9bb | 1411 | |
504db471 | 1412 | writer_stream = lookup_stream(debug_it, stream, di_trace); |
4f45f9bb | 1413 | if (!writer_stream) { |
b4d4912f | 1414 | BT_LOGE_STR("Failed to find existing stream."); |
1c78e839 | 1415 | goto error; |
4f45f9bb | 1416 | } |
1c78e839 JD |
1417 | /* |
1418 | * Take the ref on the stream and keep it until the notification | |
1419 | * is created. | |
1420 | */ | |
34101229 | 1421 | bt_get(writer_stream); |
1c78e839 JD |
1422 | |
1423 | state = g_hash_table_lookup(di_trace->stream_states, stream); | |
1424 | if (*state != DEBUG_INFO_ACTIVE_STREAM) { | |
b4d4912f | 1425 | BT_LOGE("Unexpected stream state: state=%d", *state); |
1c78e839 JD |
1426 | goto error; |
1427 | } | |
1428 | *state = DEBUG_INFO_COMPLETED_STREAM; | |
1429 | ||
504db471 | 1430 | g_hash_table_remove(di_trace->stream_map, stream); |
4f45f9bb | 1431 | |
1c78e839 JD |
1432 | if (di_trace->trace_static) { |
1433 | int trace_completed = 1; | |
1434 | ||
1435 | g_hash_table_foreach(di_trace->stream_states, | |
1436 | check_completed_trace, &trace_completed); | |
1437 | if (trace_completed) { | |
1438 | debug_info_close_trace(debug_it, di_trace); | |
1439 | g_hash_table_remove(debug_it->trace_map, | |
1440 | di_trace->trace); | |
1441 | } | |
1442 | } | |
1443 | ||
1444 | goto end; | |
1445 | ||
1446 | error: | |
1447 | BT_PUT(writer_stream); | |
1448 | ||
4f45f9bb JD |
1449 | end: |
1450 | return writer_stream; | |
1451 | } | |
1452 | ||
1453 | static | |
1454 | struct debug_info_source *lookup_debug_info(FILE *err, | |
1455 | struct bt_ctf_event *event, | |
1456 | struct debug_info *debug_info) | |
1457 | { | |
1458 | int64_t vpid; | |
1459 | uint64_t ip; | |
1460 | struct debug_info_source *dbg_info_src = NULL; | |
1461 | int ret; | |
1462 | ||
1463 | ret = get_stream_event_context_int_field_value(err, event, | |
1464 | "_vpid", &vpid); | |
1465 | if (ret) { | |
1466 | goto end; | |
1467 | } | |
1468 | ||
1469 | ret = get_stream_event_context_unsigned_int_field_value(err, event, | |
1470 | "_ip", &ip); | |
1471 | if (ret) { | |
1472 | goto end; | |
1473 | } | |
1474 | ||
1475 | /* Get debug info for this context. */ | |
1476 | dbg_info_src = debug_info_query(debug_info, vpid, ip); | |
1477 | ||
1478 | end: | |
1479 | return dbg_info_src; | |
1480 | } | |
1481 | ||
1482 | static | |
1483 | int set_debug_info_field(FILE *err, struct bt_ctf_field *debug_field, | |
1484 | struct debug_info_source *dbg_info_src, | |
1485 | struct debug_info_component *component) | |
1486 | { | |
2afcfbfb | 1487 | int i, nr_fields, ret = 0; |
4f45f9bb JD |
1488 | struct bt_ctf_field_type *debug_field_type = NULL; |
1489 | struct bt_ctf_field *field = NULL; | |
1490 | struct bt_ctf_field_type *field_type = NULL; | |
1491 | ||
1492 | debug_field_type = bt_ctf_field_get_type(debug_field); | |
b4d4912f | 1493 | assert(debug_field_type); |
4f45f9bb JD |
1494 | |
1495 | nr_fields = bt_ctf_field_type_structure_get_field_count(debug_field_type); | |
1496 | for (i = 0; i < nr_fields; i++) { | |
1497 | const char *field_name; | |
1498 | ||
1499 | if (bt_ctf_field_type_structure_get_field(debug_field_type, | |
1500 | &field_name, &field_type, i) < 0) { | |
b4d4912f JD |
1501 | BT_LOGE("Failed to get field from debug_info struct: field-name=\"%s\"", |
1502 | field_name); | |
4f45f9bb JD |
1503 | goto error; |
1504 | } | |
1505 | BT_PUT(field_type); | |
1506 | ||
1507 | field = bt_ctf_field_structure_get_field_by_index(debug_field, i); | |
1508 | if (!strcmp(field_name, "bin")) { | |
1509 | if (dbg_info_src && dbg_info_src->bin_path) { | |
1510 | GString *tmp = g_string_new(NULL); | |
1511 | ||
1512 | if (component->arg_full_path) { | |
1513 | g_string_printf(tmp, "%s%s", | |
1514 | dbg_info_src->bin_path, | |
1515 | dbg_info_src->bin_loc); | |
1516 | } else { | |
1517 | g_string_printf(tmp, "%s%s", | |
1518 | dbg_info_src->short_bin_path, | |
1519 | dbg_info_src->bin_loc); | |
1520 | } | |
1521 | ret = bt_ctf_field_string_set_value(field, tmp->str); | |
1522 | g_string_free(tmp, true); | |
1523 | } else { | |
1524 | ret = bt_ctf_field_string_set_value(field, ""); | |
1525 | } | |
1526 | } else if (!strcmp(field_name, "func")) { | |
1527 | if (dbg_info_src && dbg_info_src->func) { | |
1528 | ret = bt_ctf_field_string_set_value(field, | |
1529 | dbg_info_src->func); | |
1530 | } else { | |
1531 | ret = bt_ctf_field_string_set_value(field, ""); | |
1532 | } | |
1533 | } else if (!strcmp(field_name, "src")) { | |
1534 | if (dbg_info_src && dbg_info_src->src_path) { | |
1535 | GString *tmp = g_string_new(NULL); | |
1536 | ||
1537 | if (component->arg_full_path) { | |
1538 | g_string_printf(tmp, "%s:%" PRId64, | |
1539 | dbg_info_src->src_path, | |
1540 | dbg_info_src->line_no); | |
1541 | } else { | |
1542 | g_string_printf(tmp, "%s:%" PRId64, | |
1543 | dbg_info_src->short_src_path, | |
1544 | dbg_info_src->line_no); | |
1545 | } | |
1546 | ret = bt_ctf_field_string_set_value(field, tmp->str); | |
1547 | g_string_free(tmp, true); | |
1548 | } else { | |
1549 | ret = bt_ctf_field_string_set_value(field, ""); | |
1550 | } | |
1551 | } | |
1552 | BT_PUT(field); | |
1553 | if (ret) { | |
b4d4912f JD |
1554 | BT_LOGE("Failed to set value in debug-info struct: field-name=\"%s\"", |
1555 | field_name); | |
4f45f9bb JD |
1556 | goto error; |
1557 | } | |
1558 | } | |
1559 | ret = 0; | |
1560 | goto end; | |
1561 | ||
1562 | error: | |
1563 | ret = -1; | |
1564 | end: | |
1565 | bt_put(field_type); | |
1566 | bt_put(field); | |
1567 | bt_put(debug_field_type); | |
1568 | return ret; | |
1569 | } | |
1570 | ||
1571 | static | |
1572 | int copy_set_debug_info_stream_event_context(FILE *err, | |
1573 | struct bt_ctf_field *event_context, | |
1574 | struct bt_ctf_event *event, | |
1575 | struct bt_ctf_event *writer_event, | |
1576 | struct debug_info *debug_info, | |
1577 | struct debug_info_component *component) | |
1578 | { | |
08b6e8e8 JD |
1579 | struct bt_ctf_field_type *writer_event_context_type = NULL, |
1580 | *event_context_type = NULL; | |
4f45f9bb JD |
1581 | struct bt_ctf_field *writer_event_context = NULL; |
1582 | struct bt_ctf_field *field = NULL, *copy_field = NULL, *debug_field = NULL; | |
1583 | struct bt_ctf_field_type *field_type = NULL; | |
1584 | struct debug_info_source *dbg_info_src; | |
1585 | int ret, nr_fields, i; | |
1586 | ||
1587 | writer_event_context = bt_ctf_event_get_stream_event_context(writer_event); | |
b4d4912f | 1588 | assert(writer_event_context); |
4f45f9bb JD |
1589 | |
1590 | writer_event_context_type = bt_ctf_field_get_type(writer_event_context); | |
b4d4912f | 1591 | assert(writer_event_context_type); |
4f45f9bb | 1592 | |
08b6e8e8 | 1593 | event_context_type = bt_ctf_field_get_type(event_context); |
b4d4912f | 1594 | assert(event_context_type); |
08b6e8e8 | 1595 | |
4f45f9bb JD |
1596 | /* |
1597 | * If it is not a structure, we did not modify it to add the debug info | |
1598 | * fields, so just assign it as is. | |
1599 | */ | |
1487a16a | 1600 | if (bt_ctf_field_type_get_type_id(writer_event_context_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) { |
4f45f9bb JD |
1601 | ret = bt_ctf_event_set_event_context(writer_event, event_context); |
1602 | goto end; | |
1603 | } | |
1604 | ||
1605 | dbg_info_src = lookup_debug_info(err, event, debug_info); | |
1606 | ||
1607 | nr_fields = bt_ctf_field_type_structure_get_field_count(writer_event_context_type); | |
1608 | for (i = 0; i < nr_fields; i++) { | |
1609 | const char *field_name; | |
1610 | ||
1611 | if (bt_ctf_field_type_structure_get_field(writer_event_context_type, | |
1612 | &field_name, &field_type, i) < 0) { | |
b4d4912f JD |
1613 | BT_LOGE("Failed to get field from event-context: field-name=\"%s\"", |
1614 | field_name); | |
4f45f9bb JD |
1615 | goto error; |
1616 | } | |
1617 | ||
08b6e8e8 JD |
1618 | /* |
1619 | * Prevent illegal access in the event_context. | |
1620 | */ | |
1621 | if (i < bt_ctf_field_type_structure_get_field_count(event_context_type)) { | |
1622 | field = bt_ctf_field_structure_get_field_by_index(event_context, i); | |
1623 | } | |
4f45f9bb JD |
1624 | /* |
1625 | * The debug_info field, only exists in the writer event or | |
1626 | * if it was set by a earlier pass of the debug_info plugin. | |
4f45f9bb JD |
1627 | */ |
1628 | if (!strcmp(field_name, component->arg_debug_info_field_name) && | |
1629 | !field) { | |
1630 | debug_field = bt_ctf_field_structure_get_field_by_index( | |
1631 | writer_event_context, i); | |
b4d4912f JD |
1632 | assert(debug_field); |
1633 | ||
4f45f9bb JD |
1634 | ret = set_debug_info_field(err, debug_field, |
1635 | dbg_info_src, component); | |
1636 | if (ret) { | |
b4d4912f | 1637 | BT_LOGE_STR("Failed to set debug_info field."); |
4f45f9bb JD |
1638 | goto error; |
1639 | } | |
1640 | BT_PUT(debug_field); | |
1641 | } else { | |
1642 | copy_field = bt_ctf_field_copy(field); | |
1643 | if (!copy_field) { | |
b4d4912f JD |
1644 | BT_LOGE("Failed to copy field: field-name=\"%s\"", |
1645 | field_name); | |
4f45f9bb JD |
1646 | goto error; |
1647 | } | |
1648 | ||
2225de6b PP |
1649 | ret = bt_ctf_field_structure_set_field_by_name( |
1650 | writer_event_context, | |
4f45f9bb JD |
1651 | field_name, copy_field); |
1652 | if (ret) { | |
b4d4912f JD |
1653 | BT_LOGE("Failed to set field: field-name=\"%s\"", |
1654 | field_name); | |
4f45f9bb JD |
1655 | goto error; |
1656 | } | |
1657 | BT_PUT(copy_field); | |
1658 | } | |
1659 | BT_PUT(field_type); | |
1660 | BT_PUT(field); | |
1661 | } | |
1662 | ||
1663 | ret = 0; | |
1664 | goto end; | |
1665 | ||
1666 | error: | |
1667 | ret = -1; | |
1668 | end: | |
08b6e8e8 | 1669 | bt_put(event_context_type); |
4f45f9bb JD |
1670 | bt_put(writer_event_context_type); |
1671 | bt_put(writer_event_context); | |
1672 | bt_put(field); | |
1673 | bt_put(copy_field); | |
1674 | bt_put(debug_field); | |
1675 | bt_put(field_type); | |
1676 | return ret; | |
1677 | } | |
1678 | ||
1679 | static | |
1680 | struct bt_ctf_clock_class *stream_class_get_clock_class(FILE *err, | |
1681 | struct bt_ctf_stream_class *stream_class) | |
1682 | { | |
1683 | struct bt_ctf_trace *trace = NULL; | |
1684 | struct bt_ctf_clock_class *clock_class = NULL; | |
1685 | ||
1686 | trace = bt_ctf_stream_class_get_trace(stream_class); | |
b4d4912f | 1687 | assert(trace); |
4f45f9bb | 1688 | |
290b95cc MD |
1689 | if (!bt_ctf_trace_get_clock_class_count(trace)) { |
1690 | /* No clock. */ | |
1691 | goto end; | |
1692 | } | |
1693 | ||
4f45f9bb | 1694 | /* FIXME multi-clock? */ |
9ac68eb1 | 1695 | clock_class = bt_ctf_trace_get_clock_class_by_index(trace, 0); |
4f45f9bb JD |
1696 | |
1697 | bt_put(trace); | |
1698 | ||
1699 | end: | |
1700 | return clock_class; | |
1701 | } | |
1702 | ||
1703 | static | |
1704 | struct bt_ctf_clock_class *event_get_clock_class(FILE *err, struct bt_ctf_event *event) | |
1705 | { | |
1706 | struct bt_ctf_event_class *event_class = NULL; | |
1707 | struct bt_ctf_stream_class *stream_class = NULL; | |
1708 | struct bt_ctf_clock_class *clock_class = NULL; | |
1709 | ||
1710 | event_class = bt_ctf_event_get_class(event); | |
b4d4912f | 1711 | assert(event_class); |
4f45f9bb JD |
1712 | |
1713 | stream_class = bt_ctf_event_class_get_stream_class(event_class); | |
b4d4912f | 1714 | assert(stream_class); |
4f45f9bb JD |
1715 | |
1716 | clock_class = stream_class_get_clock_class(err, stream_class); | |
1717 | goto end; | |
1718 | ||
4f45f9bb JD |
1719 | end: |
1720 | bt_put(stream_class); | |
1721 | bt_put(event_class); | |
1722 | return clock_class; | |
1723 | } | |
1724 | ||
1725 | static | |
1726 | int set_event_clock_value(FILE *err, struct bt_ctf_event *event, | |
1727 | struct bt_ctf_event *writer_event) | |
1728 | { | |
1729 | struct bt_ctf_clock_class *clock_class = NULL; | |
1730 | struct bt_ctf_clock_value *clock_value = NULL; | |
1081db08 | 1731 | int ret = 0; |
4f45f9bb JD |
1732 | |
1733 | clock_class = event_get_clock_class(err, event); | |
1734 | if (!clock_class) { | |
290b95cc MD |
1735 | /* No clock on input trace. */ |
1736 | goto end; | |
4f45f9bb JD |
1737 | } |
1738 | ||
1739 | clock_value = bt_ctf_event_get_clock_value(event, clock_class); | |
1740 | if (!clock_value) { | |
b4d4912f JD |
1741 | ret = 0; |
1742 | goto end; | |
4f45f9bb JD |
1743 | } |
1744 | ||
1745 | /* | |
1746 | * We share the same clocks, so we can assign the clock value to the | |
1747 | * writer event. | |
1748 | */ | |
1749 | ret = bt_ctf_event_set_clock_value(writer_event, clock_value); | |
1750 | if (ret) { | |
b4d4912f | 1751 | BT_LOGE_STR("Failed to set clock value."); |
4f45f9bb JD |
1752 | goto error; |
1753 | } | |
1754 | ||
1755 | ret = 0; | |
1756 | goto end; | |
1757 | ||
1758 | error: | |
1759 | ret = -1; | |
1760 | end: | |
1761 | bt_put(clock_class); | |
1762 | bt_put(clock_value); | |
1763 | return ret; | |
1764 | } | |
1765 | ||
1766 | static | |
1767 | struct bt_ctf_event *debug_info_copy_event(FILE *err, struct bt_ctf_event *event, | |
1768 | struct bt_ctf_event_class *writer_event_class, | |
1769 | struct debug_info *debug_info, | |
1770 | struct debug_info_component *component) | |
1771 | { | |
1772 | struct bt_ctf_event *writer_event = NULL; | |
f6f999a3 | 1773 | struct bt_ctf_field *field = NULL, *copy_field = NULL; |
4f45f9bb JD |
1774 | int ret; |
1775 | ||
1776 | writer_event = bt_ctf_event_create(writer_event_class); | |
1777 | if (!writer_event) { | |
b4d4912f | 1778 | BT_LOGE_STR("Failed to create new event."); |
4f45f9bb JD |
1779 | goto error; |
1780 | } | |
1781 | ||
1782 | ret = set_event_clock_value(err, event, writer_event); | |
1783 | if (ret) { | |
b4d4912f | 1784 | BT_LOGE_STR("Failed to set clock value."); |
4f45f9bb JD |
1785 | goto error; |
1786 | } | |
1787 | ||
60ef553b | 1788 | /* Optional field, so it can fail silently. */ |
4f45f9bb | 1789 | field = bt_ctf_event_get_header(event); |
60ef553b JD |
1790 | if (field) { |
1791 | ret = ctf_copy_event_header(err, event, writer_event_class, | |
1792 | writer_event, field); | |
1793 | if (ret) { | |
b4d4912f | 1794 | BT_LOGE_STR("Failed to copy event header."); |
60ef553b JD |
1795 | goto error; |
1796 | } | |
1797 | BT_PUT(field); | |
4f45f9bb | 1798 | } |
4f45f9bb JD |
1799 | |
1800 | /* Optional field, so it can fail silently. */ | |
1801 | field = bt_ctf_event_get_stream_event_context(event); | |
1802 | if (field) { | |
1803 | ret = copy_set_debug_info_stream_event_context(err, | |
1804 | field, event, writer_event, debug_info, | |
1805 | component); | |
1806 | if (ret < 0) { | |
b4d4912f | 1807 | BT_LOGE_STR("Failed to debug_info stream event context."); |
4f45f9bb JD |
1808 | goto error; |
1809 | } | |
1810 | BT_PUT(field); | |
1811 | } | |
1812 | ||
1813 | /* Optional field, so it can fail silently. */ | |
1814 | field = bt_ctf_event_get_event_context(event); | |
60ef553b JD |
1815 | if (field) { |
1816 | copy_field = bt_ctf_field_copy(field); | |
1817 | if (!copy_field) { | |
b4d4912f | 1818 | BT_LOGE_STR("Failed to copy field."); |
60ef553b JD |
1819 | goto error; |
1820 | } | |
4f45f9bb JD |
1821 | ret = bt_ctf_event_set_event_context(writer_event, copy_field); |
1822 | if (ret < 0) { | |
b4d4912f | 1823 | BT_LOGE_STR("Failed to set event_context."); |
4f45f9bb JD |
1824 | goto error; |
1825 | } | |
1826 | BT_PUT(copy_field); | |
60ef553b | 1827 | BT_PUT(field); |
4f45f9bb | 1828 | } |
4f45f9bb | 1829 | |
9ac68eb1 | 1830 | field = bt_ctf_event_get_event_payload(event); |
b4d4912f JD |
1831 | assert(field); |
1832 | ||
4f45f9bb JD |
1833 | copy_field = bt_ctf_field_copy(field); |
1834 | if (copy_field) { | |
9ac68eb1 | 1835 | ret = bt_ctf_event_set_event_payload(writer_event, copy_field); |
4f45f9bb | 1836 | if (ret < 0) { |
b4d4912f | 1837 | BT_LOGE_STR("Failed to set event payload."); |
4f45f9bb JD |
1838 | goto error; |
1839 | } | |
1840 | BT_PUT(copy_field); | |
1841 | } | |
1842 | BT_PUT(field); | |
1843 | ||
1844 | goto end; | |
1845 | ||
1846 | error: | |
1847 | BT_PUT(writer_event); | |
1848 | end: | |
1849 | bt_put(copy_field); | |
1850 | bt_put(field); | |
1851 | return writer_event; | |
1852 | } | |
1853 | ||
1854 | BT_HIDDEN | |
1855 | struct bt_ctf_event *debug_info_output_event( | |
1856 | struct debug_info_iterator *debug_it, | |
1857 | struct bt_ctf_event *event) | |
1858 | { | |
1859 | struct bt_ctf_event_class *event_class = NULL, *writer_event_class = NULL; | |
1860 | struct bt_ctf_stream_class *stream_class = NULL, *writer_stream_class = NULL; | |
1861 | struct bt_ctf_event *writer_event = NULL; | |
f6f999a3 | 1862 | struct bt_ctf_packet *packet = NULL, *writer_packet = NULL; |
4f45f9bb | 1863 | struct bt_ctf_trace *writer_trace = NULL; |
504db471 JD |
1864 | struct bt_ctf_stream *stream = NULL; |
1865 | struct debug_info_trace *di_trace; | |
4f45f9bb | 1866 | struct debug_info *debug_info; |
4f45f9bb JD |
1867 | int int_ret; |
1868 | ||
1869 | event_class = bt_ctf_event_get_class(event); | |
b4d4912f | 1870 | assert(event_class); |
4f45f9bb JD |
1871 | |
1872 | stream_class = bt_ctf_event_class_get_stream_class(event_class); | |
b4d4912f JD |
1873 | assert(stream_class); |
1874 | ||
504db471 | 1875 | stream = bt_ctf_event_get_stream(event); |
b4d4912f JD |
1876 | assert(stream); |
1877 | ||
504db471 JD |
1878 | di_trace = lookup_di_trace_from_stream(debug_it, stream); |
1879 | if (!di_trace) { | |
b4d4912f | 1880 | BT_LOGE_STR("Failed to find existing trace from stream."); |
504db471 JD |
1881 | goto error; |
1882 | } | |
4f45f9bb JD |
1883 | |
1884 | writer_stream_class = g_hash_table_lookup( | |
504db471 | 1885 | di_trace->stream_class_map, |
4f45f9bb | 1886 | (gpointer) stream_class); |
504db471 | 1887 | if (!writer_stream_class) { |
b4d4912f | 1888 | BT_LOGE_STR("Failed to find existing stream_class."); |
4f45f9bb JD |
1889 | goto error; |
1890 | } | |
504db471 | 1891 | bt_get(writer_stream_class); |
4f45f9bb JD |
1892 | |
1893 | writer_event_class = get_event_class(debug_it, | |
1894 | writer_stream_class, event_class); | |
1895 | if (!writer_event_class) { | |
1896 | writer_event_class = ctf_copy_event_class(debug_it->err, | |
1897 | event_class); | |
1898 | if (!writer_event_class) { | |
b4d4912f | 1899 | BT_LOGE_STR("Failed to copy event_class."); |
4f45f9bb JD |
1900 | goto error; |
1901 | } | |
1902 | int_ret = bt_ctf_stream_class_add_event_class( | |
1903 | writer_stream_class, writer_event_class); | |
1904 | if (int_ret) { | |
b4d4912f | 1905 | BT_LOGE_STR("Failed to add event_class."); |
4f45f9bb JD |
1906 | goto error; |
1907 | } | |
1908 | } | |
1909 | ||
1910 | writer_trace = bt_ctf_stream_class_get_trace(writer_stream_class); | |
b4d4912f | 1911 | assert(writer_trace); |
4f45f9bb | 1912 | |
504db471 | 1913 | debug_info = get_trace_debug_info(debug_it, writer_trace, di_trace); |
4f45f9bb JD |
1914 | if (debug_info) { |
1915 | debug_info_handle_event(debug_it->err, event, debug_info); | |
1916 | } | |
1917 | ||
1918 | writer_event = debug_info_copy_event(debug_it->err, event, | |
1919 | writer_event_class, debug_info, | |
1920 | debug_it->debug_info_component); | |
1921 | if (!writer_event) { | |
b4d4912f | 1922 | BT_LOGE("Failed to copy event: event-class-name=\"%s\"", |
4f45f9bb JD |
1923 | bt_ctf_event_class_get_name(writer_event_class)); |
1924 | goto error; | |
1925 | } | |
1926 | ||
1927 | packet = bt_ctf_event_get_packet(event); | |
b4d4912f | 1928 | assert(packet); |
4f45f9bb | 1929 | |
504db471 | 1930 | writer_packet = lookup_packet(debug_it, packet, di_trace); |
4f45f9bb | 1931 | if (!writer_packet) { |
b4d4912f | 1932 | BT_LOGE_STR("Failed to find existing packet."); |
4f45f9bb JD |
1933 | goto error; |
1934 | } | |
1935 | bt_get(writer_packet); | |
1936 | ||
1937 | int_ret = bt_ctf_event_set_packet(writer_event, writer_packet); | |
1938 | if (int_ret < 0) { | |
b4d4912f | 1939 | BT_LOGE("Failed to append event to event-class-name=\"%s\"", |
4f45f9bb JD |
1940 | bt_ctf_event_class_get_name(writer_event_class)); |
1941 | goto error; | |
1942 | } | |
1943 | ||
1944 | /* Keep the reference on the writer event */ | |
1945 | goto end; | |
1946 | ||
1947 | error: | |
1948 | BT_PUT(writer_event); | |
1949 | ||
1950 | end: | |
504db471 | 1951 | bt_put(stream); |
4f45f9bb JD |
1952 | bt_put(writer_trace); |
1953 | bt_put(writer_packet); | |
1954 | bt_put(packet); | |
1955 | bt_put(writer_event_class); | |
1956 | bt_put(writer_stream_class); | |
1957 | bt_put(stream_class); | |
1958 | bt_put(event_class); | |
1959 | return writer_event; | |
1960 | } |