sink.ctf.fs: Remove unused function
[babeltrace.git] / plugins / lttng-utils / debug-info.c
CommitLineData
4f45f9bb
JD
1/*
2 * Babeltrace - Debug Information State Tracker
3 *
4 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
6 * Copyright (c) 2015 Antoine Busque <abusque@efficios.com>
7 * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
ca9f27f3 8 * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
4f45f9bb
JD
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
b4565e8b
PP
29#define BT_LOG_TAG "PLUGIN-CTF-LTTNG-UTILS-DEBUG-INFO-FLT"
30#include "logging.h"
31
4f45f9bb 32#include <glib.h>
ca9f27f3
FD
33#include <plugins-common.h>
34
35#include <babeltrace/assert-internal.h>
36#include <babeltrace/common-internal.h>
37
4f45f9bb 38#include "bin-info.h"
ca9f27f3
FD
39#include "debug-info.h"
40#include "trace-ir-data-copy.h"
41#include "trace-ir-mapping.h"
42#include "trace-ir-metadata-copy.h"
4f45f9bb 43#include "utils.h"
ca9f27f3
FD
44
45#define DEFAULT_DEBUG_INFO_FIELD_NAME "debug_info"
46#define LTTNG_UST_STATEDUMP_PREFIX "lttng_ust"
47#define VPID_FIELD_NAME "vpid"
48#define IP_FIELD_NAME "ip"
49#define BADDR_FIELD_NAME "baddr"
50#define CRC32_FIELD_NAME "crc"
51#define BUILD_ID_FIELD_NAME "build_id"
52#define FILENAME_FIELD_NAME "filename"
53#define IS_PIC_FIELD_NAME "is_pic"
54#define MEMSZ_FIELD_NAME "memsz"
55#define PATH_FIELD_NAME "path"
56
57struct debug_info_component {
58 char *arg_debug_info_field_name;
59 const char *arg_debug_dir;
60 bool arg_full_path;
61 const char *arg_target_prefix;
62};
63
64struct debug_info_msg_iter {
65 struct debug_info_component *debug_info_component;
66 bt_self_message_iterator *input_iterator;
67 bt_self_component *self_comp;
68 bt_self_component_port_input_message_iterator *msg_iter;
69
70 struct trace_ir_maps *ir_maps;
71 /* in_trace -> debug_info_mapping. */
72 GHashTable *debug_info_map;
73};
74
75struct debug_info_source {
76 /* Strings are owned by debug_info_source. */
77 char *func;
78 /*
79 * Store the line number as a string so that the allocation and
80 * conversion to string is only done once.
81 */
82 char *line_no;
83 char *src_path;
84 /* short_src_path points inside src_path, no need to free. */
85 const char *short_src_path;
86 char *bin_path;
87 /* short_bin_path points inside bin_path, no need to free. */
88 const char *short_bin_path;
89 /*
90 * Location within the binary. Either absolute (@0x1234) or
91 * relative (+0x4321).
92 */
93 char *bin_loc;
94};
4f45f9bb
JD
95
96struct proc_debug_info_sources {
97 /*
98 * Hash table: base address (pointer to uint64_t) to bin info; owned by
99 * proc_debug_info_sources.
100 */
101 GHashTable *baddr_to_bin_info;
102
103 /*
104 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
105 * owned by proc_debug_info_sources.
106 */
107 GHashTable *ip_to_debug_info_src;
108};
109
110struct debug_info {
9d325e17 111 struct debug_info_component *comp;
ca9f27f3
FD
112 const bt_trace *input_trace;
113 uint64_t destruction_listener_id;
9d325e17 114
4f45f9bb
JD
115 /*
116 * Hash table of VPIDs (pointer to int64_t) to
117 * (struct ctf_proc_debug_infos*); owned by debug_info.
118 */
119 GHashTable *vpid_to_proc_dbg_info_src;
120 GQuark q_statedump_bin_info;
121 GQuark q_statedump_debug_link;
122 GQuark q_statedump_build_id;
123 GQuark q_statedump_start;
124 GQuark q_dl_open;
125 GQuark q_lib_load;
126 GQuark q_lib_unload;
127};
128
129static
130int debug_info_init(struct debug_info *info)
131{
132 info->q_statedump_bin_info = g_quark_from_string(
133 "lttng_ust_statedump:bin_info");
134 info->q_statedump_debug_link = g_quark_from_string(
ca9f27f3 135 "lttng_ust_statedump:debug_link");
4f45f9bb
JD
136 info->q_statedump_build_id = g_quark_from_string(
137 "lttng_ust_statedump:build_id");
138 info->q_statedump_start = g_quark_from_string(
139 "lttng_ust_statedump:start");
140 info->q_dl_open = g_quark_from_string("lttng_ust_dl:dlopen");
141 info->q_lib_load = g_quark_from_string("lttng_ust_lib:load");
142 info->q_lib_unload = g_quark_from_string("lttng_ust_lib:unload");
143
144 return bin_info_init();
145}
146
147static
148void debug_info_source_destroy(struct debug_info_source *debug_info_src)
149{
150 if (!debug_info_src) {
151 return;
152 }
153
154 free(debug_info_src->func);
ca9f27f3 155 free(debug_info_src->line_no);
4f45f9bb
JD
156 free(debug_info_src->src_path);
157 free(debug_info_src->bin_path);
158 free(debug_info_src->bin_loc);
159 g_free(debug_info_src);
160}
161
162static
ca9f27f3
FD
163struct debug_info_source *debug_info_source_create_from_bin(
164 struct bin_info *bin, uint64_t ip)
4f45f9bb
JD
165{
166 int ret;
167 struct debug_info_source *debug_info_src = NULL;
168 struct source_location *src_loc = NULL;
169
170 debug_info_src = g_new0(struct debug_info_source, 1);
171
172 if (!debug_info_src) {
173 goto end;
174 }
175
176 /* Lookup function name */
177 ret = bin_info_lookup_function_name(bin, ip, &debug_info_src->func);
178 if (ret) {
179 goto error;
180 }
181
182 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
183 if (!bin->is_elf_only || !debug_info_src->func) {
184 /* Lookup source location */
185 ret = bin_info_lookup_source_location(bin, ip, &src_loc);
ca9f27f3
FD
186 if (ret) {
187 BT_LOGD("Failed to lookup source location: ret=%d", ret);
188 }
4f45f9bb
JD
189 }
190
191 if (src_loc) {
ca9f27f3
FD
192 ret = asprintf(&debug_info_src->line_no, "%"PRId64, src_loc->line_no);
193 if (ret == -1) {
194 BT_LOGD("Error occured when setting line_no field.");
195 goto error;
196 }
4f45f9bb
JD
197
198 if (src_loc->filename) {
199 debug_info_src->src_path = strdup(src_loc->filename);
200 if (!debug_info_src->src_path) {
201 goto error;
202 }
203
204 debug_info_src->short_src_path = get_filename_from_path(
205 debug_info_src->src_path);
206 }
4f45f9bb
JD
207 source_location_destroy(src_loc);
208 }
209
210 if (bin->elf_path) {
211 debug_info_src->bin_path = strdup(bin->elf_path);
212 if (!debug_info_src->bin_path) {
213 goto error;
214 }
215
216 debug_info_src->short_bin_path = get_filename_from_path(
217 debug_info_src->bin_path);
218
219 ret = bin_info_get_bin_loc(bin, ip, &(debug_info_src->bin_loc));
220 if (ret) {
221 goto error;
222 }
223 }
224
225end:
226 return debug_info_src;
227
228error:
229 debug_info_source_destroy(debug_info_src);
230 return NULL;
231}
232
233static
234void proc_debug_info_sources_destroy(
235 struct proc_debug_info_sources *proc_dbg_info_src)
236{
237 if (!proc_dbg_info_src) {
238 return;
239 }
240
241 if (proc_dbg_info_src->baddr_to_bin_info) {
242 g_hash_table_destroy(proc_dbg_info_src->baddr_to_bin_info);
243 }
244
245 if (proc_dbg_info_src->ip_to_debug_info_src) {
246 g_hash_table_destroy(proc_dbg_info_src->ip_to_debug_info_src);
247 }
248
249 g_free(proc_dbg_info_src);
250}
251
252static
253struct proc_debug_info_sources *proc_debug_info_sources_create(void)
254{
255 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
256
257 proc_dbg_info_src = g_new0(struct proc_debug_info_sources, 1);
258 if (!proc_dbg_info_src) {
259 goto end;
260 }
261
262 proc_dbg_info_src->baddr_to_bin_info = g_hash_table_new_full(
263 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
264 (GDestroyNotify) bin_info_destroy);
265 if (!proc_dbg_info_src->baddr_to_bin_info) {
266 goto error;
267 }
268
269 proc_dbg_info_src->ip_to_debug_info_src = g_hash_table_new_full(
270 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
271 (GDestroyNotify) debug_info_source_destroy);
272 if (!proc_dbg_info_src->ip_to_debug_info_src) {
273 goto error;
274 }
275
276end:
277 return proc_dbg_info_src;
278
279error:
280 proc_debug_info_sources_destroy(proc_dbg_info_src);
281 return NULL;
282}
283
284static
285struct proc_debug_info_sources *proc_debug_info_sources_ht_get_entry(
286 GHashTable *ht, int64_t vpid)
287{
288 gpointer key = g_new0(int64_t, 1);
289 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
290
291 if (!key) {
292 goto end;
293 }
294
295 *((int64_t *) key) = vpid;
296
297 /* Exists? Return it */
298 proc_dbg_info_src = g_hash_table_lookup(ht, key);
299 if (proc_dbg_info_src) {
300 goto end;
301 }
302
303 /* Otherwise, create and return it */
304 proc_dbg_info_src = proc_debug_info_sources_create();
305 if (!proc_dbg_info_src) {
306 goto end;
307 }
308
309 g_hash_table_insert(ht, key, proc_dbg_info_src);
310 /* Ownership passed to ht */
311 key = NULL;
312end:
313 g_free(key);
314 return proc_dbg_info_src;
315}
316
ca9f27f3
FD
317static inline
318const bt_field *event_borrow_payload_field(const bt_event *event,
319 const char *field_name)
320{
321 const bt_field *event_payload, *field;
322
323 event_payload = bt_event_borrow_payload_field_const(event);
324 BT_ASSERT(event_payload);
325
326 field = bt_field_structure_borrow_member_field_by_name_const(
327 event_payload, field_name);
328 return field;
329}
330
331static inline
332const bt_field *event_borrow_common_context_field(const bt_event *event,
333 const char *field_name)
334{
335 const bt_field *event_common_ctx, *field = NULL;
336
337 event_common_ctx = bt_event_borrow_common_context_field_const(event);
338 if (!event_common_ctx) {
339 goto end;
340 }
341
342 field = bt_field_structure_borrow_member_field_by_name_const(
343 event_common_ctx, field_name);
344
345end:
346 return field;
347}
348
349static inline
350void event_get_common_context_signed_integer_field_value(
351 const bt_event *event, const char *field_name, int64_t *value)
352{
353 *value = bt_field_signed_integer_get_value(
354 event_borrow_common_context_field(event, field_name));
355}
356
357static inline
358int event_get_payload_build_id_length(const bt_event *event,
359 const char *field_name, uint64_t *build_id_len)
360{
361 const bt_field *build_id_field;
362 const bt_field_class *build_id_field_class;
363
364 build_id_field = event_borrow_payload_field(event, field_name);
365 build_id_field_class = bt_field_borrow_class_const(build_id_field);
366
367 BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
368 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
369 BT_ASSERT(bt_field_class_get_type(
370 bt_field_class_array_borrow_element_field_class_const(
371 build_id_field_class)) ==
372 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
373
374 *build_id_len = bt_field_array_get_length(build_id_field);
375
376 return 0;
377}
378
379static inline
380int event_get_payload_build_id_value(const bt_event *event,
381 const char *field_name, uint8_t *build_id)
382{
383 const bt_field *curr_field, *build_id_field;
384 const bt_field_class *build_id_field_class;
385 uint64_t i, build_id_len;
386 int ret;
387
388 ret = 0;
389
390 build_id_field = event_borrow_payload_field(event, field_name);
391 build_id_field_class = bt_field_borrow_class_const(build_id_field);
392
393 BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
394 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
395 BT_ASSERT(bt_field_class_get_type(
396 bt_field_class_array_borrow_element_field_class_const(
397 build_id_field_class)) ==
398 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
399
400 build_id_len = bt_field_array_get_length(build_id_field);
401
402 for (i = 0; i < build_id_len; i++) {
403 curr_field =
404 bt_field_array_borrow_element_field_by_index_const(
405 build_id_field, i);
406
407 build_id[i] = bt_field_unsigned_integer_get_value(curr_field);
408 }
409
410 return ret;
411}
412
413static
414void event_get_payload_unsigned_integer_field_value(const bt_event *event,
415 const char *field_name, uint64_t *value)
416{
417 *value = bt_field_unsigned_integer_get_value(
418 event_borrow_payload_field(event, field_name));
419}
420
421static
422void event_get_payload_string_field_value(const bt_event *event,
423 const char *field_name, const char **value)
424{
425 *value = bt_field_string_get_value(
426 event_borrow_payload_field(event, field_name));
427}
428
429static inline
430bool event_has_payload_field(const bt_event *event,
431 const char *field_name)
432{
433 return event_borrow_payload_field(event, field_name) != NULL;
434}
435
4f45f9bb
JD
436static
437struct debug_info_source *proc_debug_info_sources_get_entry(
438 struct proc_debug_info_sources *proc_dbg_info_src, uint64_t ip)
439{
440 struct debug_info_source *debug_info_src = NULL;
441 gpointer key = g_new0(uint64_t, 1);
442 GHashTableIter iter;
443 gpointer baddr, value;
444
445 if (!key) {
446 goto end;
447 }
448
449 *((uint64_t *) key) = ip;
450
451 /* Look in IP to debug infos hash table first. */
452 debug_info_src = g_hash_table_lookup(
453 proc_dbg_info_src->ip_to_debug_info_src,
454 key);
455 if (debug_info_src) {
456 goto end;
457 }
458
459 /* Check in all bin_infos. */
460 g_hash_table_iter_init(&iter, proc_dbg_info_src->baddr_to_bin_info);
461
462 while (g_hash_table_iter_next(&iter, &baddr, &value))
463 {
464 struct bin_info *bin = value;
465
466 if (!bin_info_has_address(value, ip)) {
467 continue;
468 }
469
470 /*
471 * Found; add it to cache.
472 *
473 * FIXME: this should be bounded in size (and implement
474 * a caching policy), and entries should be prunned when
475 * libraries are unmapped.
476 */
477 debug_info_src = debug_info_source_create_from_bin(bin, ip);
478 if (debug_info_src) {
479 g_hash_table_insert(
480 proc_dbg_info_src->ip_to_debug_info_src,
481 key, debug_info_src);
482 /* Ownership passed to ht. */
483 key = NULL;
484 }
485 break;
486 }
487
488end:
489 free(key);
490 return debug_info_src;
491}
492
493BT_HIDDEN
494struct debug_info_source *debug_info_query(struct debug_info *debug_info,
495 int64_t vpid, uint64_t ip)
496{
497 struct debug_info_source *dbg_info_src = NULL;
498 struct proc_debug_info_sources *proc_dbg_info_src;
499
500 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
501 debug_info->vpid_to_proc_dbg_info_src, vpid);
502 if (!proc_dbg_info_src) {
503 goto end;
504 }
505
506 dbg_info_src = proc_debug_info_sources_get_entry(proc_dbg_info_src, ip);
507
508end:
509 return dbg_info_src;
510}
511
512BT_HIDDEN
ca9f27f3
FD
513struct debug_info *debug_info_create(struct debug_info_component *comp,
514 const bt_trace *trace)
4f45f9bb
JD
515{
516 int ret;
517 struct debug_info *debug_info;
518
519 debug_info = g_new0(struct debug_info, 1);
520 if (!debug_info) {
521 goto end;
522 }
523
524 debug_info->vpid_to_proc_dbg_info_src = g_hash_table_new_full(
525 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
526 (GDestroyNotify) proc_debug_info_sources_destroy);
527 if (!debug_info->vpid_to_proc_dbg_info_src) {
528 goto error;
529 }
530
9d325e17 531 debug_info->comp = comp;
4f45f9bb
JD
532 ret = debug_info_init(debug_info);
533 if (ret) {
534 goto error;
535 }
536
ca9f27f3
FD
537 debug_info->input_trace = trace;
538
4f45f9bb
JD
539end:
540 return debug_info;
541error:
542 g_free(debug_info);
543 return NULL;
544}
545
546BT_HIDDEN
547void debug_info_destroy(struct debug_info *debug_info)
548{
ca9f27f3 549 bt_trace_status status;
4f45f9bb
JD
550 if (!debug_info) {
551 goto end;
552 }
553
554 if (debug_info->vpid_to_proc_dbg_info_src) {
555 g_hash_table_destroy(debug_info->vpid_to_proc_dbg_info_src);
556 }
557
ca9f27f3
FD
558 status = bt_trace_remove_destruction_listener(debug_info->input_trace,
559 debug_info->destruction_listener_id);
3b40fbf9
FD
560 if (status != BT_TRACE_STATUS_OK) {
561 BT_LOGD("Trace destruction listener removal failed.");
562 }
ca9f27f3 563
4f45f9bb
JD
564 g_free(debug_info);
565end:
566 return;
567}
568
569static
ca9f27f3 570void handle_event_statedump_build_id(struct debug_info *debug_info,
b19ff26f 571 const bt_event *event)
4f45f9bb
JD
572{
573 struct proc_debug_info_sources *proc_dbg_info_src;
ca9f27f3
FD
574 uint64_t build_id_len, baddr;
575 uint8_t *build_id = NULL;
576 struct bin_info *bin;
4f45f9bb 577 int64_t vpid;
ca9f27f3 578 int ret = 0;
4f45f9bb 579
ca9f27f3
FD
580 event_get_common_context_signed_integer_field_value(event,
581 VPID_FIELD_NAME, &vpid);
582 event_get_payload_unsigned_integer_field_value(event,
583 BADDR_FIELD_NAME, &baddr);
4f45f9bb
JD
584
585 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
586 debug_info->vpid_to_proc_dbg_info_src, vpid);
587 if (!proc_dbg_info_src) {
588 goto end;
589 }
590
591 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
592 (gpointer) &baddr);
593 if (!bin) {
594 /*
595 * The build_id event comes after the bin has been
596 * created. If it isn't found, just ignore this event.
597 */
598 goto end;
599 }
ca9f27f3
FD
600 ret = event_get_payload_build_id_length(event, BUILD_ID_FIELD_NAME,
601 &build_id_len);
602
603 build_id = g_new0(uint8_t, build_id_len);
604 if (!build_id) {
605 goto end;
606 }
4f45f9bb 607
ca9f27f3
FD
608 ret = event_get_payload_build_id_value(event, BUILD_ID_FIELD_NAME,
609 build_id);
4f45f9bb 610 if (ret) {
4f45f9bb
JD
611 goto end;
612 }
ca9f27f3
FD
613
614 ret = bin_info_set_build_id(bin, build_id, build_id_len);
615 if (ret) {
616 goto end;
445e79d6 617 }
4f45f9bb
JD
618
619 /*
620 * Reset the is_elf_only flag in case it had been set
621 * previously, because we might find separate debug info using
622 * the new build id information.
623 */
624 bin->is_elf_only = false;
625
4f45f9bb 626end:
ca9f27f3 627 g_free(build_id);
4f45f9bb
JD
628 return;
629}
630
631static
ca9f27f3 632void handle_event_statedump_debug_link(struct debug_info *debug_info,
b19ff26f 633 const bt_event *event)
4f45f9bb
JD
634{
635 struct proc_debug_info_sources *proc_dbg_info_src;
636 struct bin_info *bin = NULL;
637 int64_t vpid;
638 uint64_t baddr;
639 const char *filename = NULL;
640 uint32_t crc32;
ca9f27f3 641 uint64_t crc_field_value;
4f45f9bb 642
ca9f27f3 643 event_get_common_context_signed_integer_field_value(event,
c4838cef 644 VPID_FIELD_NAME, &vpid);
4f45f9bb 645
ca9f27f3
FD
646 event_get_payload_unsigned_integer_field_value(event,
647 BADDR_FIELD_NAME, &baddr);
4f45f9bb 648
ca9f27f3
FD
649 event_get_payload_unsigned_integer_field_value(event,
650 CRC32_FIELD_NAME, &crc_field_value);
4f45f9bb 651
ca9f27f3
FD
652 crc32 = (uint32_t) crc_field_value;
653
654 event_get_payload_string_field_value(event,
655 FILENAME_FIELD_NAME, &filename);
4f45f9bb
JD
656
657 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
658 debug_info->vpid_to_proc_dbg_info_src, vpid);
659 if (!proc_dbg_info_src) {
660 goto end;
661 }
662
663 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
664 (gpointer) &baddr);
665 if (!bin) {
666 /*
667 * The debug_link event comes after the bin has been
668 * created. If it isn't found, just ignore this event.
669 */
670 goto end;
671 }
672
673 bin_info_set_debug_link(bin, filename, crc32);
674
675end:
676 return;
677}
678
679static
ca9f27f3 680void handle_bin_info_event(struct debug_info *debug_info,
b19ff26f 681 const bt_event *event, bool has_pic_field)
4f45f9bb
JD
682{
683 struct proc_debug_info_sources *proc_dbg_info_src;
684 struct bin_info *bin;
685 uint64_t baddr, memsz;
686 int64_t vpid;
687 const char *path;
688 gpointer key = NULL;
689 bool is_pic;
4f45f9bb 690
ca9f27f3
FD
691 event_get_payload_unsigned_integer_field_value(event,
692 MEMSZ_FIELD_NAME, &memsz);
693 if (memsz == 0) {
694 /* Ignore VDSO. */
4f45f9bb
JD
695 goto end;
696 }
697
ca9f27f3
FD
698 event_get_payload_unsigned_integer_field_value(event,
699 BADDR_FIELD_NAME, &baddr);
4f45f9bb 700
65db8b88
JD
701 /*
702 * This field is not produced by the dlopen event emitted before
703 * lttng-ust 2.9.
704 */
ca9f27f3 705 if (!event_has_payload_field(event, PATH_FIELD_NAME)) {
4f45f9bb
JD
706 goto end;
707 }
ca9f27f3 708 event_get_payload_string_field_value(event, PATH_FIELD_NAME, &path);
4f45f9bb
JD
709
710 if (has_pic_field) {
ca9f27f3 711 uint64_t is_pic_field_value;
4f45f9bb 712
ca9f27f3
FD
713 event_get_payload_unsigned_integer_field_value(event,
714 IS_PIC_FIELD_NAME, &is_pic_field_value);
715 is_pic = is_pic_field_value == 1;
4f45f9bb
JD
716 } else {
717 /*
718 * dlopen has no is_pic field, because the shared
719 * object is always PIC.
720 */
721 is_pic = true;
722 }
723
ca9f27f3 724 event_get_common_context_signed_integer_field_value(event,
c4838cef 725 VPID_FIELD_NAME, &vpid);
4f45f9bb
JD
726
727 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
728 debug_info->vpid_to_proc_dbg_info_src, vpid);
729 if (!proc_dbg_info_src) {
730 goto end;
731 }
732
733 key = g_new0(uint64_t, 1);
734 if (!key) {
735 goto end;
736 }
737
738 *((uint64_t *) key) = baddr;
739
740 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
741 key);
742 if (bin) {
743 goto end;
744 }
745
9d325e17
PP
746 bin = bin_info_create(path, baddr, memsz, is_pic,
747 debug_info->comp->arg_debug_dir,
748 debug_info->comp->arg_target_prefix);
4f45f9bb
JD
749 if (!bin) {
750 goto end;
751 }
752
753 g_hash_table_insert(proc_dbg_info_src->baddr_to_bin_info,
754 key, bin);
755 /* Ownership passed to ht. */
756 key = NULL;
757
758end:
759 g_free(key);
760 return;
761}
762
763static inline
ca9f27f3 764void handle_event_statedump_bin_info(struct debug_info *debug_info,
b19ff26f 765 const bt_event *event)
4f45f9bb 766{
ca9f27f3 767 handle_bin_info_event(debug_info, event, true);
4f45f9bb
JD
768}
769
770static inline
ca9f27f3 771void handle_event_lib_load(struct debug_info *debug_info,
b19ff26f 772 const bt_event *event)
4f45f9bb 773{
ca9f27f3 774 handle_bin_info_event(debug_info, event, false);
4f45f9bb
JD
775}
776
ca9f27f3
FD
777static
778void handle_event_lib_unload(struct debug_info *debug_info,
b19ff26f 779 const bt_event *event)
4f45f9bb 780{
ca9f27f3 781 gboolean ret;
4f45f9bb
JD
782 struct proc_debug_info_sources *proc_dbg_info_src;
783 uint64_t baddr;
784 int64_t vpid;
4f45f9bb 785
ca9f27f3
FD
786 event_get_payload_unsigned_integer_field_value(event, BADDR_FIELD_NAME,
787 &baddr);
4f45f9bb 788
ca9f27f3
FD
789 event_get_common_context_signed_integer_field_value(event,
790 VPID_FIELD_NAME, &vpid);
4f45f9bb
JD
791
792 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
793 debug_info->vpid_to_proc_dbg_info_src, vpid);
794 if (!proc_dbg_info_src) {
ca9f27f3
FD
795 /*
796 * It's an unload event for a library for which no load event
797 * was previously received.
798 */
4f45f9bb
JD
799 goto end;
800 }
801
ca9f27f3
FD
802 ret = g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
803 (gpointer) &baddr);
804 BT_ASSERT(ret);
4f45f9bb
JD
805end:
806 return;
807}
808
809static
ca9f27f3 810void handle_event_statedump_start(struct debug_info *debug_info,
b19ff26f 811 const bt_event *event)
4f45f9bb
JD
812{
813 struct proc_debug_info_sources *proc_dbg_info_src;
814 int64_t vpid;
4f45f9bb 815
ca9f27f3
FD
816 event_get_common_context_signed_integer_field_value(
817 event, VPID_FIELD_NAME, &vpid);
4f45f9bb
JD
818
819 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
820 debug_info->vpid_to_proc_dbg_info_src, vpid);
821 if (!proc_dbg_info_src) {
822 goto end;
823 }
824
825 g_hash_table_remove_all(proc_dbg_info_src->baddr_to_bin_info);
826 g_hash_table_remove_all(proc_dbg_info_src->ip_to_debug_info_src);
827
828end:
829 return;
830}
831
ca9f27f3
FD
832void trace_debug_info_remove_func(const bt_trace *in_trace, void *data)
833{
834 struct debug_info_msg_iter *debug_it = data;
835 if (debug_it->debug_info_map) {
836 gboolean ret;
837 ret = g_hash_table_remove(debug_it->debug_info_map,
838 (gpointer) in_trace);
839 BT_ASSERT(ret);
840 }
841}
842
843static
844void handle_event_statedump(struct debug_info_msg_iter *debug_it,
845 const bt_event *event)
4f45f9bb 846{
b19ff26f 847 const bt_event_class *event_class;
4f45f9bb
JD
848 const char *event_name;
849 GQuark q_event_name;
ca9f27f3
FD
850 const bt_trace *trace;
851 struct debug_info *debug_info;
852
853 BT_ASSERT(debug_it);
854 BT_ASSERT(event);
855
856 event_class = bt_event_borrow_class_const(event);
4f45f9bb 857
50842bdc 858 event_name = bt_event_class_get_name(event_class);
ca9f27f3
FD
859
860 trace = bt_stream_borrow_trace_const(
861 bt_event_borrow_stream_const(event));
862
863 debug_info = g_hash_table_lookup(debug_it->debug_info_map, trace);
864 if (!debug_info) {
865 debug_info = debug_info_create(debug_it->debug_info_component,
866 trace);
867 g_hash_table_insert(debug_it->debug_info_map, (gpointer) trace,
868 debug_info);
869 bt_trace_add_destruction_listener(trace,
870 trace_debug_info_remove_func, debug_it,
871 &debug_info->destruction_listener_id);
4f45f9bb 872 }
ca9f27f3 873
4f45f9bb
JD
874 q_event_name = g_quark_try_string(event_name);
875
876 if (q_event_name == debug_info->q_statedump_bin_info) {
877 /* State dump */
ca9f27f3 878 handle_event_statedump_bin_info(debug_info, event);
4f45f9bb
JD
879 } else if (q_event_name == debug_info->q_dl_open ||
880 q_event_name == debug_info->q_lib_load) {
881 /*
882 * dl_open and lib_load events are both checked for since
883 * only dl_open was produced as of lttng-ust 2.8.
884 *
885 * lib_load, which is produced from lttng-ust 2.9+, is a lot
886 * more reliable since it will be emitted when other functions
887 * of the dlopen family are called (e.g. dlmopen) and when
888 * library are transitively loaded.
889 */
ca9f27f3 890 handle_event_lib_load(debug_info, event);
4f45f9bb
JD
891 } else if (q_event_name == debug_info->q_statedump_start) {
892 /* Start state dump */
ca9f27f3 893 handle_event_statedump_start(debug_info, event);
4f45f9bb
JD
894 } else if (q_event_name == debug_info->q_statedump_debug_link) {
895 /* Debug link info */
ca9f27f3 896 handle_event_statedump_debug_link(debug_info, event);
4f45f9bb
JD
897 } else if (q_event_name == debug_info->q_statedump_build_id) {
898 /* Build ID info */
ca9f27f3 899 handle_event_statedump_build_id(debug_info, event);
4f45f9bb 900 } else if (q_event_name == debug_info-> q_lib_unload) {
ca9f27f3
FD
901 handle_event_lib_unload(debug_info, event);
902 }
903
904 return;
905}
906
907static
908void destroy_debug_info_comp(struct debug_info_component *debug_info)
909{
910 free(debug_info->arg_debug_info_field_name);
911 g_free(debug_info);
912}
913
914static
915void fill_debug_info_bin_field(struct debug_info_source *dbg_info_src,
916 bool full_path, bt_field *curr_field)
917{
918 bt_field_status status;
919
920 BT_ASSERT(bt_field_get_class_type(curr_field) ==
921 BT_FIELD_CLASS_TYPE_STRING);
922
923 if (dbg_info_src) {
924 if (full_path) {
925 status = bt_field_string_set_value(curr_field,
926 dbg_info_src->bin_path);
927 } else {
928 status = bt_field_string_set_value(curr_field,
929 dbg_info_src->short_bin_path);
930 }
931 if (status != BT_FIELD_STATUS_OK) {
932 BT_LOGE("Cannot set path component of \"bin\" "
933 "curr_field field's value: str-fc-addr=%p",
934 curr_field);
935 }
936
937 status = bt_field_string_append(curr_field, ":");
938 if (status != BT_FIELD_STATUS_OK) {
939 BT_LOGE("Cannot set colon component of \"bin\" "
940 "curr_field field's value: str-fc-addr=%p",
941 curr_field);
942 }
943
944 status = bt_field_string_append(curr_field, dbg_info_src->bin_loc);
945 if (status != BT_FIELD_STATUS_OK) {
946 BT_LOGE("Cannot set bin location component of \"bin\" "
947 "curr_field field's value: str-fc-addr=%p",
948 curr_field);
949 }
950 } else {
951 status = bt_field_string_set_value(curr_field, "");
952 if (status != BT_FIELD_STATUS_OK) {
953 BT_LOGE("Cannot set \"bin\" curr_field field's value: "
954 "str-fc-addr=%p", curr_field);
955 }
956 }
957}
958
959static
960void fill_debug_info_func_field(struct debug_info_source *dbg_info_src,
961 bt_field *curr_field)
962{
963 bt_field_status status;
964
965 BT_ASSERT(bt_field_get_class_type(curr_field) ==
966 BT_FIELD_CLASS_TYPE_STRING);
967 if (dbg_info_src && dbg_info_src->func) {
968 status = bt_field_string_set_value(curr_field,
969 dbg_info_src->func);
970 } else {
971 status = bt_field_string_set_value(curr_field, "");
972 }
973 if (status != BT_FIELD_STATUS_OK) {
974 BT_LOGE("Cannot set \"func\" curr_field field's value: "
975 "str-fc-addr=%p", curr_field);
976 }
977}
978
979static
980void fill_debug_info_src_field(struct debug_info_source *dbg_info_src,
981 bool full_path, bt_field *curr_field)
982{
983 bt_field_status status;
984
985 BT_ASSERT(bt_field_get_class_type(curr_field) ==
986 BT_FIELD_CLASS_TYPE_STRING);
987
988 if (dbg_info_src && dbg_info_src->src_path) {
989 if (full_path) {
990 status = bt_field_string_set_value(curr_field,
991 dbg_info_src->src_path);
992 } else {
993 status = bt_field_string_set_value(curr_field,
994 dbg_info_src->short_src_path);
995 }
996 if (status != BT_FIELD_STATUS_OK) {
997 BT_LOGE("Cannot set path component of \"src\" "
998 "curr_field field's value: str-fc-addr=%p",
999 curr_field);
1000 }
1001
1002 status = bt_field_string_append(curr_field, ":");
1003 if (status != BT_FIELD_STATUS_OK) {
1004 BT_LOGE("Cannot set colon component of \"src\" "
1005 "curr_field field's value: str-fc-addr=%p",
1006 curr_field);
1007 }
1008
1009 status = bt_field_string_append(curr_field, dbg_info_src->line_no);
1010 if (status != BT_FIELD_STATUS_OK) {
1011 BT_LOGE("Cannot set line number component of \"src\" "
1012 "curr_field field's value: str-fc-addr=%p",
1013 curr_field);
1014 }
1015 } else {
1016 status = bt_field_string_set_value(curr_field, "");
1017 if (status != BT_FIELD_STATUS_OK) {
1018 BT_LOGE("Cannot set \"src\" curr_field field's value: "
1019 "str-fc-addr=%p", curr_field);
1020 }
1021 }
1022}
1023
1024void fill_debug_info_field_empty(bt_field *debug_info_field)
1025{
1026 bt_field_status status;
1027 bt_field *bin_field, *func_field, *src_field;
1028
1029 BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
1030 BT_FIELD_CLASS_TYPE_STRUCTURE);
1031
1032 bin_field = bt_field_structure_borrow_member_field_by_name(
1033 debug_info_field, "bin");
1034 func_field = bt_field_structure_borrow_member_field_by_name(
1035 debug_info_field, "func");
1036 src_field = bt_field_structure_borrow_member_field_by_name(
1037 debug_info_field, "src");
1038
1039 BT_ASSERT(bt_field_get_class_type(bin_field) ==
1040 BT_FIELD_CLASS_TYPE_STRING);
1041 BT_ASSERT(bt_field_get_class_type(func_field) ==
1042 BT_FIELD_CLASS_TYPE_STRING);
1043 BT_ASSERT(bt_field_get_class_type(src_field) ==
1044 BT_FIELD_CLASS_TYPE_STRING);
1045
1046 status = bt_field_string_set_value(bin_field, "");
1047 if (status != BT_FIELD_STATUS_OK) {
1048 BT_LOGE("Cannot set \"bin\" bin_field field's value: "
1049 "str-fc-addr=%p", bin_field);
1050 }
1051
1052 status = bt_field_string_set_value(func_field, "");
1053 if (status != BT_FIELD_STATUS_OK) {
1054 BT_LOGE("Cannot set \"func\" func_field field's value: "
1055 "str-fc-addr=%p", func_field);
1056 }
1057
1058 status = bt_field_string_set_value(src_field, "");
1059 if (status != BT_FIELD_STATUS_OK) {
1060 BT_LOGE("Cannot set \"src\" src_field field's value: "
1061 "str-fc-addr=%p", src_field);
1062 }
1063}
1064static
1065void fill_debug_info_field(struct debug_info *debug_info, int64_t vpid,
1066 uint64_t ip, bt_field *debug_info_field)
1067{
1068 struct debug_info_source *dbg_info_src;
1069 const bt_field_class *debug_info_fc;
1070
1071 BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
1072 BT_FIELD_CLASS_TYPE_STRUCTURE);
1073
1074 debug_info_fc = bt_field_borrow_class_const(debug_info_field);
1075
1076 BT_ASSERT(bt_field_class_structure_get_member_count(debug_info_fc) == 3);
1077
1078 dbg_info_src = debug_info_query(debug_info, vpid, ip);
1079
1080 fill_debug_info_bin_field(dbg_info_src, debug_info->comp->arg_full_path,
1081 bt_field_structure_borrow_member_field_by_name(
1082 debug_info_field, "bin"));
1083 fill_debug_info_func_field(dbg_info_src,
1084 bt_field_structure_borrow_member_field_by_name(
1085 debug_info_field, "func"));
1086 fill_debug_info_src_field(dbg_info_src, debug_info->comp->arg_full_path,
1087 bt_field_structure_borrow_member_field_by_name(
1088 debug_info_field, "src"));
1089}
1090
1091static
1092void fill_debug_info_event_if_needed(struct debug_info_msg_iter *debug_it,
1093 const bt_event *in_event, bt_event *out_event)
1094{
1095 bt_field *out_common_ctx_field, *out_debug_info_field;
1096 const bt_field *vpid_field, *ip_field, *in_common_ctx_field;
1097 const bt_field_class *in_common_ctx_fc;
1098 struct debug_info *debug_info;
1099 uint64_t vpid;
1100 int64_t ip;
1101 char *debug_info_field_name =
1102 debug_it->debug_info_component->arg_debug_info_field_name;
1103
1104 in_common_ctx_field = bt_event_borrow_common_context_field_const(
1105 in_event);
1106 if (!in_common_ctx_field) {
1107 /*
1108 * There is no event common context so no need to add debug
1109 * info field.
1110 */
1111 goto end;
1112 }
1113
1114 in_common_ctx_fc = bt_field_borrow_class_const(in_common_ctx_field);
1115 if (!is_event_common_ctx_dbg_info_compatible(in_common_ctx_fc,
1116 debug_it->ir_maps->debug_info_field_class_name)) {
1117 /*
1118 * The input event common context does not have the necessary
1119 * fields to resolve debug information.
1120 */
1121 goto end;
1122 }
1123
1124 /* Borrow the debug-info field. */
1125 out_common_ctx_field = bt_event_borrow_common_context_field(out_event);
1126 if (!out_common_ctx_field) {
1127 goto end;
4f45f9bb
JD
1128 }
1129
ca9f27f3
FD
1130 out_debug_info_field = bt_field_structure_borrow_member_field_by_name(
1131 out_common_ctx_field, debug_info_field_name);
1132
1133 vpid_field = bt_field_structure_borrow_member_field_by_name_const(
1134 out_common_ctx_field, VPID_FIELD_NAME);
1135 ip_field = bt_field_structure_borrow_member_field_by_name_const(
1136 out_common_ctx_field, IP_FIELD_NAME);
1137
1138 vpid = bt_field_signed_integer_get_value(vpid_field);
1139 ip = bt_field_unsigned_integer_get_value(ip_field);
1140
1141 /*
1142 * Borrow the debug_info structure needed for the source
1143 * resolving.
1144 */
1145 debug_info = g_hash_table_lookup(debug_it->debug_info_map,
1146 bt_stream_borrow_trace_const(
1147 bt_event_borrow_stream_const(in_event)));
1148
1149 if (debug_info) {
1150 /*
1151 * Perform the debug-info resolving and set the event fields
1152 * accordingly.
1153 */
1154 fill_debug_info_field(debug_info, vpid, ip, out_debug_info_field);
1155 } else {
1156 BT_LOGD("No debug information for this trace. Setting debug "
1157 "info fields to empty strings.");
1158 fill_debug_info_field_empty(out_debug_info_field);
1159 }
4f45f9bb
JD
1160end:
1161 return;
1162}
ca9f27f3
FD
1163
1164static
1165void update_event_statedump_if_needed(struct debug_info_msg_iter *debug_it,
1166 const bt_event *in_event)
1167{
1168 const bt_field *event_common_ctx;
1169 const bt_field_class *event_common_ctx_fc;
1170 const bt_event_class *in_event_class = bt_event_borrow_class_const(in_event);
1171
1172 /*
1173 * If the event is an lttng_ust_statedump event AND has the right event
1174 * common context fields update the debug-info view for this process.
1175 */
1176 event_common_ctx = bt_event_borrow_common_context_field_const(in_event);
1177 if (!event_common_ctx) {
1178 goto end;
1179 }
1180
1181 event_common_ctx_fc = bt_field_borrow_class_const(event_common_ctx);
1182 if (is_event_common_ctx_dbg_info_compatible(event_common_ctx_fc,
1183 debug_it->ir_maps->debug_info_field_class_name)) {
1184 /* Checkout if it might be a one of lttng ust statedump events. */
1185 const char *in_event_name = bt_event_class_get_name(in_event_class);
1186 if (strncmp(in_event_name, LTTNG_UST_STATEDUMP_PREFIX,
1187 strlen(LTTNG_UST_STATEDUMP_PREFIX)) == 0) {
1188 /* Handle statedump events. */
1189 handle_event_statedump(debug_it, in_event);
1190 }
1191 }
1192end:
1193 return;
1194}
1195
1196static
1197bt_message *handle_event_message(struct debug_info_msg_iter *debug_it,
1198 const bt_message *in_message)
1199{
1200 const bt_clock_snapshot *cs;
1201 const bt_clock_class *default_cc;
1202 const bt_packet *in_packet;
1203 bt_clock_snapshot_state cs_state;
1204 bt_event_class *out_event_class;
1205 bt_packet *out_packet;
1206 bt_event *out_event;
1207
1208 bt_message *out_message = NULL;
1209
1210 /* Borrow the input event and its event class. */
1211 const bt_event *in_event =
1212 bt_message_event_borrow_event_const(in_message);
1213 const bt_event_class *in_event_class =
1214 bt_event_borrow_class_const(in_event);
1215
1216 update_event_statedump_if_needed(debug_it, in_event);
1217
1218 out_event_class = trace_ir_mapping_borrow_mapped_event_class(
1219 debug_it->ir_maps, in_event_class);
1220 if (!out_event_class) {
1221 out_event_class = trace_ir_mapping_create_new_mapped_event_class(
1222 debug_it->ir_maps, in_event_class);
1223 }
1224 BT_ASSERT(out_event_class);
1225
1226 /* Borrow the input and output packets. */
1227 in_packet = bt_event_borrow_packet_const(in_event);
1228 out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps,
1229 in_packet);
1230
1231 default_cc = bt_stream_class_borrow_default_clock_class_const(
1232 bt_event_class_borrow_stream_class_const(in_event_class));
1233 if (default_cc) {
1234 /* Borrow event clock snapshot. */
1235 cs_state =
1236 bt_message_event_borrow_default_clock_snapshot_const(
1237 in_message, &cs);
1238
1239 /* Create an output event message. */
1240 BT_ASSERT (cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
1241 out_message = bt_message_event_create_with_default_clock_snapshot(
1242 debug_it->input_iterator,
1243 out_event_class, out_packet,
1244 bt_clock_snapshot_get_value(cs));
1245 } else {
1246 out_message = bt_message_event_create(debug_it->input_iterator,
1247 out_event_class, out_packet);
1248 }
1249
1250 if (!out_message) {
1251 BT_LOGE("Error creating output event message.");
1252 goto error;
1253 }
1254
1255 out_event = bt_message_event_borrow_event(out_message);
1256
1257 /* Copy the original fields to the output event. */
1258 copy_event_content(in_event, out_event);
1259
1260 /*
1261 * Try to set the debug-info fields based on debug information that is
1262 * gathered so far.
1263 */
1264 fill_debug_info_event_if_needed(debug_it, in_event, out_event);
1265
1266error:
1267 return out_message;
1268}
1269
1270static
1271bt_message *handle_stream_begin_message(struct debug_info_msg_iter *debug_it,
1272 const bt_message *in_message)
1273{
1274 const bt_stream *in_stream;
1275 bt_message *out_message;
1276 bt_stream *out_stream;
1277
1278 in_stream = bt_message_stream_beginning_borrow_stream_const(in_message);
1279 BT_ASSERT(in_stream);
1280
1281 /* Create a duplicated output stream. */
1282 out_stream = trace_ir_mapping_create_new_mapped_stream(
1283 debug_it->ir_maps, in_stream);
1284 if (!out_stream) {
1285 out_message = NULL;
1286 goto error;
1287 }
1288
1289 /* Create an output stream beginning message. */
1290 out_message = bt_message_stream_beginning_create(
1291 debug_it->input_iterator, out_stream);
1292 if (!out_message) {
1293 BT_LOGE("Error creating output stream beginning message: "
1294 "out-s-addr=%p", out_stream);
1295 }
1296error:
1297 return out_message;
1298}
1299
1300static
1301bt_message *handle_stream_end_message(struct debug_info_msg_iter *debug_it,
1302 const bt_message *in_message)
1303{
1304 const bt_stream *in_stream;
1305 bt_message *out_message = NULL;
1306 bt_stream *out_stream;
1307
1308 in_stream = bt_message_stream_end_borrow_stream_const(in_message);
1309 BT_ASSERT(in_stream);
1310
1311 out_stream = trace_ir_mapping_borrow_mapped_stream(
1312 debug_it->ir_maps, in_stream);
1313 BT_ASSERT(out_stream);
1314
1315 /* Create an output stream end message. */
1316 out_message = bt_message_stream_end_create(debug_it->input_iterator,
1317 out_stream);
1318 if (!out_message) {
1319 BT_LOGE("Error creating output stream end message: out-s-addr=%p",
1320 out_stream);
1321 }
1322
1323 /* Remove stream from trace mapping hashtable. */
1324 trace_ir_mapping_remove_mapped_stream(debug_it->ir_maps, in_stream);
1325
1326 return out_message;
1327}
1328
1329static
1330bt_message *handle_packet_begin_message(struct debug_info_msg_iter *debug_it,
1331 const bt_message *in_message)
1332{
1333 const bt_clock_class *default_cc;
1334 bt_clock_snapshot_state cs_state;
1335 const bt_clock_snapshot *cs;
1336 bt_message *out_message = NULL;
1337 bt_packet *out_packet;
1338
1339 const bt_packet *in_packet =
1340 bt_message_packet_beginning_borrow_packet_const(in_message);
1341 BT_ASSERT(in_packet);
1342
1343 /* This packet should not be already mapped. */
1344 BT_ASSERT(!trace_ir_mapping_borrow_mapped_packet(
1345 debug_it->ir_maps, in_packet));
1346
1347 out_packet = trace_ir_mapping_create_new_mapped_packet(debug_it->ir_maps,
1348 in_packet);
1349
1350 BT_ASSERT(out_packet);
1351
1352 default_cc = bt_stream_class_borrow_default_clock_class_const(
1353 bt_stream_borrow_class_const(
1354 bt_packet_borrow_stream_const(in_packet)));
1355 if (default_cc) {
1356 /* Borrow clock snapshot. */
1357 cs_state =
1358 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1359 in_message, &cs);
1360
1361 /* Create an output packet beginning message. */
1362 BT_ASSERT(cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
1363 out_message = bt_message_packet_beginning_create_with_default_clock_snapshot(
1364 debug_it->input_iterator, out_packet,
1365 bt_clock_snapshot_get_value(cs));
1366 } else {
1367 out_message = bt_message_packet_beginning_create(
1368 debug_it->input_iterator, out_packet);
1369 }
1370 if (!out_message) {
1371 BT_LOGE("Error creating output packet beginning message: "
1372 "out-p-addr=%p", out_packet);
1373 }
1374
1375 return out_message;
1376}
1377
1378static
1379bt_message *handle_packet_end_message(struct debug_info_msg_iter *debug_it,
1380 const bt_message *in_message)
1381{
1382 const bt_clock_snapshot *cs;
1383 const bt_packet *in_packet;
1384 const bt_clock_class *default_cc;
1385 bt_clock_snapshot_state cs_state;
1386 bt_message *out_message = NULL;
1387 bt_packet *out_packet;
1388
1389 in_packet = bt_message_packet_end_borrow_packet_const(in_message);
1390 BT_ASSERT(in_packet);
1391
1392 out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps, in_packet);
1393 BT_ASSERT(out_packet);
1394
1395 default_cc = bt_stream_class_borrow_default_clock_class_const(
1396 bt_stream_borrow_class_const(
1397 bt_packet_borrow_stream_const(in_packet)));
1398 if (default_cc) {
1399 /* Borrow clock snapshot. */
1400 cs_state =
1401 bt_message_packet_end_borrow_default_clock_snapshot_const(
1402 in_message, &cs);
1403
1404 /* Create an outpute packet end message. */
1405 BT_ASSERT(cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
1406 out_message = bt_message_packet_end_create_with_default_clock_snapshot(
1407 debug_it->input_iterator, out_packet,
1408 bt_clock_snapshot_get_value(cs));
1409 } else {
1410 out_message = bt_message_packet_end_create(
1411 debug_it->input_iterator, out_packet);
1412 }
1413
1414 if (!out_message) {
1415 BT_LOGE("Error creating output packet end message: "
1416 "out-p-addr=%p", out_packet);
1417 }
1418
1419 /* Remove packet from data mapping hashtable. */
1420 trace_ir_mapping_remove_mapped_packet(debug_it->ir_maps, in_packet);
1421
1422 return out_message;
1423}
1424
1425static
1426bt_message *handle_msg_iterator_inactivity(struct debug_info_msg_iter *debug_it,
1427 const bt_message *in_message)
1428{
1429 /*
1430 * This message type can be forwarded directly because it does
1431 * not refer to any objects in the trace class.
1432 */
1433 bt_message_get_ref(in_message);
1434 return (bt_message*) in_message;
1435}
1436
1437static
1438bt_message *handle_stream_act_begin_message(struct debug_info_msg_iter *debug_it,
1439 const bt_message *in_message)
1440{
1441 const bt_clock_snapshot *cs;
1442 const bt_clock_class *default_cc;
1443 bt_message *out_message = NULL;
1444 bt_stream *out_stream;
1445 uint64_t cs_value;
1446 bt_message_stream_activity_clock_snapshot_state cs_state;
1447
1448 const bt_stream *in_stream =
1449 bt_message_stream_activity_beginning_borrow_stream_const(
1450 in_message);
1451 BT_ASSERT(in_stream);
1452
1453 out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps,
1454 in_stream);
1455 BT_ASSERT(out_stream);
1456
1457 out_message = bt_message_stream_activity_beginning_create(
1458 debug_it->input_iterator, out_stream);
1459 if (!out_message) {
1460 BT_LOGE("Error creating output stream activity beginning "
1461 "message: out-s-addr=%p", out_stream);
1462 goto error;
1463 }
1464
1465 default_cc = bt_stream_class_borrow_default_clock_class_const(
1466 bt_stream_borrow_class_const(in_stream));
1467 if (default_cc) {
1468 /* Borrow clock snapshot. */
1469 cs_state =
1470 bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
1471 in_message, &cs);
1472
1473 if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN) {
1474 cs_value = bt_clock_snapshot_get_value(cs);
1475 bt_message_stream_activity_beginning_set_default_clock_snapshot(
1476 out_message, cs_value);
1477 } else {
1478 bt_message_stream_activity_beginning_set_default_clock_snapshot_state(
1479 out_message, cs_state);
1480 }
1481 }
1482
1483error:
1484 return out_message;
1485}
1486
1487static
1488bt_message *handle_stream_act_end_message(struct debug_info_msg_iter *debug_it,
1489 const bt_message *in_message)
1490{
1491 const bt_clock_snapshot *cs;
1492 const bt_clock_class *default_cc;
1493 const bt_stream *in_stream;
1494 bt_message *out_message;
1495 bt_stream *out_stream;
1496 uint64_t cs_value;
1497 bt_message_stream_activity_clock_snapshot_state cs_state;
1498
1499 in_stream = bt_message_stream_activity_end_borrow_stream_const(
1500 in_message);
1501 BT_ASSERT(in_stream);
1502
1503 out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps, in_stream);
1504 BT_ASSERT(out_stream);
1505
1506 out_message = bt_message_stream_activity_end_create(
1507 debug_it->input_iterator, out_stream);
1508 if (!out_message) {
1509 BT_LOGE("Error creating output stream activity end message: "
1510 "out-s-addr=%p", out_stream);
1511 goto error;
1512 }
1513
1514 default_cc = bt_stream_class_borrow_default_clock_class_const(
1515 bt_stream_borrow_class_const(in_stream));
1516
1517 if (default_cc) {
1518 cs_state =
1519 bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
1520 in_message, &cs);
1521
1522 if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN ) {
1523 cs_value = bt_clock_snapshot_get_value(cs);
1524 bt_message_stream_activity_end_set_default_clock_snapshot(
1525 out_message, cs_value);
1526 } else {
1527 bt_message_stream_activity_end_set_default_clock_snapshot_state(
1528 out_message, cs_state);
1529 }
1530 }
1531
1532error:
1533 return out_message;
1534}
1535
1536static
1537bt_message *handle_discarded_events_message(struct debug_info_msg_iter *debug_it,
1538 const bt_message *in_message)
1539{
1540 const bt_clock_snapshot *begin_cs, *end_cs;
1541 const bt_stream *in_stream;
1542 const bt_clock_class *default_cc;
1543 uint64_t discarded_events, begin_cs_value, end_cs_value;
1544 bt_clock_snapshot_state begin_cs_state, end_cs_state;
1545 bt_property_availability prop_avail;
1546 bt_message *out_message = NULL;
1547 bt_stream *out_stream;
1548
1549 in_stream = bt_message_discarded_events_borrow_stream_const(
1550 in_message);
1551 BT_ASSERT(in_stream);
1552
1553 out_stream = trace_ir_mapping_borrow_mapped_stream(
1554 debug_it->ir_maps, in_stream);
1555 BT_ASSERT(out_stream);
1556
1557 default_cc = bt_stream_class_borrow_default_clock_class_const(
1558 bt_stream_borrow_class_const(in_stream));
1559 if (default_cc) {
1560 begin_cs_state =
1561 bt_message_discarded_events_borrow_default_beginning_clock_snapshot_const(
1562 in_message, &begin_cs);
1563 end_cs_state =
1564 bt_message_discarded_events_borrow_default_end_clock_snapshot_const(
1565 in_message, &end_cs);
1566 /*
1567 * Both clock snapshots should be known as we check that the
1568 * all input stream classes have an always known clock. Unknown
1569 * clock is not yet supported.
1570 */
1571 BT_ASSERT(begin_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN &&
1572 end_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
1573
1574 begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
1575 end_cs_value = bt_clock_snapshot_get_value(end_cs);
1576
1577 out_message =
1578 bt_message_discarded_events_create_with_default_clock_snapshots(
1579 debug_it->input_iterator, out_stream,
1580 begin_cs_value, end_cs_value);
1581 } else {
1582 out_message = bt_message_discarded_events_create(
1583 debug_it->input_iterator, out_stream);
1584 }
1585 if (!out_message) {
1586 BT_LOGE("Error creating output discarded events message: "
1587 "out-s-addr=%p", out_stream);
1588 goto error;
1589 }
1590
1591 prop_avail = bt_message_discarded_events_get_count(in_message,
1592 &discarded_events);
1593
1594 if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1595 bt_message_discarded_events_set_count(out_message,
1596 discarded_events);
1597 }
1598
1599error:
1600 return out_message;
1601}
1602
1603static
1604bt_message *handle_discarded_packets_message(struct debug_info_msg_iter *debug_it,
1605 const bt_message *in_message)
1606{
1607 const bt_clock_snapshot *begin_cs, *end_cs;
1608 const bt_clock_class *default_cc;
1609 const bt_stream *in_stream;
1610 uint64_t discarded_packets, begin_cs_value, end_cs_value;
1611 bt_clock_snapshot_state begin_cs_state, end_cs_state;
1612 bt_property_availability prop_avail;
1613 bt_message *out_message = NULL;
1614 bt_stream *out_stream;
1615
1616 in_stream = bt_message_discarded_packets_borrow_stream_const(
1617 in_message);
1618 BT_ASSERT(in_stream);
1619
1620 out_stream = trace_ir_mapping_borrow_mapped_stream(
1621 debug_it->ir_maps, in_stream);
1622 BT_ASSERT(out_stream);
1623
1624 default_cc = bt_stream_class_borrow_default_clock_class_const(
1625 bt_stream_borrow_class_const(in_stream));
1626 if (default_cc) {
1627 begin_cs_state =
1628 bt_message_discarded_packets_borrow_default_beginning_clock_snapshot_const(
1629 in_message, &begin_cs);
1630
1631 end_cs_state =
1632 bt_message_discarded_packets_borrow_default_end_clock_snapshot_const(
1633 in_message, &end_cs);
1634
1635 /*
1636 * Both clock snapshots should be known as we check that the
1637 * all input stream classes have an always known clock. Unknown
1638 * clock is not yet supported.
1639 */
1640 BT_ASSERT(begin_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN &&
1641 end_cs_state == BT_CLOCK_SNAPSHOT_STATE_KNOWN);
1642
1643 begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
1644 end_cs_value = bt_clock_snapshot_get_value(end_cs);
1645
1646 out_message = bt_message_discarded_packets_create_with_default_clock_snapshots(
1647 debug_it->input_iterator, out_stream,
1648 begin_cs_value, end_cs_value);
1649 } else {
1650 out_message = bt_message_discarded_packets_create(
1651 debug_it->input_iterator, out_stream);
1652 }
1653 if (!out_message) {
1654 BT_LOGE("Error creating output discarded packet message: "
1655 "out-s-addr=%p", out_stream);
1656 goto error;
1657 }
1658
1659 prop_avail = bt_message_discarded_packets_get_count(in_message,
1660 &discarded_packets);
1661 if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1662 bt_message_discarded_packets_set_count(out_message,
1663 discarded_packets);
1664 }
1665
1666error:
1667 return out_message;
1668}
1669
1670static
1671const bt_message *handle_message(struct debug_info_msg_iter *debug_it,
1672 const bt_message *in_message)
1673{
1674 bt_message *out_message = NULL;
1675
1676 switch (bt_message_get_type(in_message)) {
1677 case BT_MESSAGE_TYPE_EVENT:
1678 out_message = handle_event_message(debug_it,
1679 in_message);
1680 break;
1681 case BT_MESSAGE_TYPE_PACKET_BEGINNING:
1682 out_message = handle_packet_begin_message(debug_it,
1683 in_message);
1684 break;
1685 case BT_MESSAGE_TYPE_PACKET_END:
1686 out_message = handle_packet_end_message(debug_it,
1687 in_message);
1688 break;
1689 case BT_MESSAGE_TYPE_STREAM_BEGINNING:
1690 out_message = handle_stream_begin_message(debug_it,
1691 in_message);
1692 break;
1693 case BT_MESSAGE_TYPE_STREAM_END:
1694 out_message = handle_stream_end_message(debug_it,
1695 in_message);
1696 break;
1697 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY:
1698 out_message = handle_msg_iterator_inactivity(debug_it,
1699 in_message);
1700 break;
1701 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING:
1702 out_message = handle_stream_act_begin_message(debug_it,
1703 in_message);
1704 break;
1705 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END:
1706 out_message = handle_stream_act_end_message(debug_it,
1707 in_message);
1708 break;
1709 case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
1710 out_message = handle_discarded_events_message(debug_it,
1711 in_message);
1712 break;
1713 case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
1714 out_message = handle_discarded_packets_message(debug_it,
1715 in_message);
1716 break;
1717 default:
1718 abort();
1719 break;
1720 }
1721
1722 return out_message;
1723}
1724
1725static
1726int init_from_params(struct debug_info_component *debug_info_component,
1727 const bt_value *params)
1728{
1729 const bt_value *value = NULL;
1730 int ret = 0;
1731
1732 BT_ASSERT(params);
1733
1734 value = bt_value_map_borrow_entry_value_const(params,
1735 "debug-info-field-name");
1736 if (value) {
1737 const char *debug_info_field_name;
1738
1739 debug_info_field_name = bt_value_string_get(value);
1740 debug_info_component->arg_debug_info_field_name =
1741 strdup(debug_info_field_name);
1742 } else {
1743 debug_info_component->arg_debug_info_field_name =
1744 malloc(strlen(DEFAULT_DEBUG_INFO_FIELD_NAME) + 1);
1745 if (!debug_info_component->arg_debug_info_field_name) {
1746 ret = BT_SELF_COMPONENT_STATUS_NOMEM;
1747 BT_LOGE_STR("Missing field name.");
1748 goto end;
1749 }
1750 sprintf(debug_info_component->arg_debug_info_field_name,
1751 DEFAULT_DEBUG_INFO_FIELD_NAME);
1752 }
1753 if (ret) {
1754 goto end;
1755 }
1756
1757 value = bt_value_map_borrow_entry_value_const(params, "debug-info-dir");
1758 if (value) {
1759 debug_info_component->arg_debug_dir = bt_value_string_get(value);
1760 }
1761
1762 value = bt_value_map_borrow_entry_value_const(params, "target-prefix");
1763 if (value) {
1764 debug_info_component->arg_target_prefix =
1765 bt_value_string_get(value);
1766 }
1767
1768 value = bt_value_map_borrow_entry_value_const(params, "full-path");
1769 if (value) {
1770 debug_info_component->arg_full_path = bt_value_bool_get(value);
1771 }
1772
1773end:
1774 return ret;
1775}
1776
1777BT_HIDDEN
1778bt_self_component_status debug_info_comp_init(
1779 bt_self_component_filter *self_comp,
1780 const bt_value *params, UNUSED_VAR void *init_method_data)
1781{
1782 int ret;
1783 struct debug_info_component *debug_info_comp;
1784 bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
1785
1786 BT_LOGD("Initializing debug_info component: "
1787 "comp-addr=%p, params-addr=%p", self_comp, params);
1788
1789 debug_info_comp = g_new0(struct debug_info_component, 1);
1790 if (!debug_info_comp) {
1791 BT_LOGE_STR("Failed to allocate one debug_info component.");
1792 goto error;
1793 }
1794
1795 bt_self_component_set_data(
1796 bt_self_component_filter_as_self_component(self_comp),
1797 debug_info_comp);
1798
1799 status = bt_self_component_filter_add_input_port(self_comp, "in",
1800 NULL, NULL);
1801 if (status != BT_SELF_COMPONENT_STATUS_OK) {
1802 goto error;
1803 }
1804
1805 status = bt_self_component_filter_add_output_port(self_comp, "out",
1806 NULL, NULL);
1807 if (status != BT_SELF_COMPONENT_STATUS_OK) {
1808 goto error;
1809 }
1810
1811 ret = init_from_params(debug_info_comp, params);
1812 if (ret) {
1813 BT_LOGE("Cannot configure debug_info component: "
1814 "debug_info-comp-addr=%p, params-addr=%p",
1815 debug_info_comp, params);
1816 goto error;
1817 }
1818
1819 goto end;
1820
1821error:
1822 destroy_debug_info_comp(debug_info_comp);
1823 bt_self_component_set_data(
1824 bt_self_component_filter_as_self_component(self_comp),
1825 NULL);
1826
1827 if (status == BT_SELF_COMPONENT_STATUS_OK) {
1828 status = BT_SELF_COMPONENT_STATUS_ERROR;
1829 }
1830end:
1831 return status;
1832}
1833
1834BT_HIDDEN
1835void debug_info_comp_finalize(bt_self_component_filter *self_comp)
1836{
1837 struct debug_info_component *debug_info =
1838 bt_self_component_get_data(
1839 bt_self_component_filter_as_self_component(
1840 self_comp));
1841 BT_LOGD("Finalizing debug_info self_component: comp-addr=%p",
1842 self_comp);
1843
1844 destroy_debug_info_comp(debug_info);
1845}
1846
1847BT_HIDDEN
1848bt_self_message_iterator_status debug_info_msg_iter_next(
1849 bt_self_message_iterator *self_msg_iter,
1850 const bt_message_array_const msgs, uint64_t capacity,
1851 uint64_t *count)
1852{
1853 bt_self_component_port_input_message_iterator *upstream_iterator = NULL;
1854 bt_message_iterator_status upstream_iterator_ret_status;
1855 struct debug_info_msg_iter *debug_info_msg_iter;
1856 struct debug_info_component *debug_info = NULL;
1857 bt_self_message_iterator_status status;
1858 bt_self_component *self_comp = NULL;
1859 bt_message_array_const input_msgs;
1860 const bt_message *out_message;
1861 uint64_t curr_msg_idx, i;
1862
1863 status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
1864
1865 self_comp = bt_self_message_iterator_borrow_component(self_msg_iter);
1866 BT_ASSERT(self_comp);
1867
1868 debug_info = bt_self_component_get_data(self_comp);
1869 BT_ASSERT(debug_info);
1870
1871 debug_info_msg_iter = bt_self_message_iterator_get_data(self_msg_iter);
1872 BT_ASSERT(debug_info_msg_iter);
1873
1874 upstream_iterator = debug_info_msg_iter->msg_iter;
1875 BT_ASSERT(upstream_iterator);
1876
1877 upstream_iterator_ret_status =
1878 bt_self_component_port_input_message_iterator_next(
1879 upstream_iterator, &input_msgs, count);
1880 if (upstream_iterator_ret_status != BT_MESSAGE_ITERATOR_STATUS_OK) {
1881 /*
1882 * No messages were returned. Not necessarily an error. Convert
1883 * the upstream message iterator status to a self status.
1884 */
1885 status = bt_common_message_iterator_status_to_self(
1886 upstream_iterator_ret_status);
1887 goto end;
1888 }
1889
1890 /*
1891 * There should never be more received messages than the capacity we
1892 * provided.
1893 */
1894 BT_ASSERT(*count <= capacity);
1895
1896 for (curr_msg_idx = 0; curr_msg_idx < *count; curr_msg_idx++) {
1897 out_message = handle_message(debug_info_msg_iter,
1898 input_msgs[curr_msg_idx]);
1899 if (!out_message) {
1900 goto handle_msg_error;
1901 }
1902
1903 msgs[curr_msg_idx] = out_message;
1904 /*
1905 * Drop our reference of the input message as we are done with
1906 * it and created a output copy.
1907 */
1908 bt_message_put_ref(input_msgs[curr_msg_idx]);
1909 }
1910
1911 goto end;
1912
1913handle_msg_error:
1914 /*
1915 * Drop references of all the output messages created before the
1916 * failure.
1917 */
1918 for (i = 0; i < curr_msg_idx; i++) {
1919 bt_message_put_ref(msgs[i]);
1920 }
1921
1922 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1923end:
1924 return status;
1925}
1926
1927BT_HIDDEN
1928bt_self_message_iterator_status debug_info_msg_iter_init(
1929 bt_self_message_iterator *self_msg_iter,
1930 bt_self_component_filter *self_comp,
1931 bt_self_component_port_output *self_port)
1932{
1933 bt_self_message_iterator_status status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
1934 struct bt_self_component_port_input *input_port;
1935 bt_self_component_port_input_message_iterator *upstream_iterator;
1936 struct debug_info_msg_iter *debug_info_msg_iter;
1937
1938 /* Borrow the upstream input port. */
1939 input_port = bt_self_component_filter_borrow_input_port_by_name(
1940 self_comp, "in");
1941 if (!input_port) {
1942 status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
1943 goto end;
1944 }
1945
1946 /* Create an iterator on the upstream component. */
1947 upstream_iterator = bt_self_component_port_input_message_iterator_create(
1948 input_port);
1949 if (!upstream_iterator) {
1950 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1951 goto end;
1952 }
1953
1954 debug_info_msg_iter = g_new0(struct debug_info_msg_iter, 1);
1955 if (!debug_info_msg_iter) {
1956 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1957 goto end;
1958 }
1959
1960 debug_info_msg_iter->debug_info_map = g_hash_table_new_full(
1961 g_direct_hash, g_direct_equal,
1962 (GDestroyNotify) NULL,
1963 (GDestroyNotify) debug_info_destroy);
1964 if (!debug_info_msg_iter->debug_info_map) {
1965 g_free(debug_info_msg_iter);
1966 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1967 goto end;
1968 }
1969
1970 debug_info_msg_iter->self_comp =
1971 bt_self_component_filter_as_self_component(self_comp);
1972
1973 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_MOVE_REF(
1974 debug_info_msg_iter->msg_iter, upstream_iterator);
1975
1976 debug_info_msg_iter->debug_info_component = bt_self_component_get_data(
1977 bt_self_component_filter_as_self_component(
1978 self_comp));
1979
1980 debug_info_msg_iter->ir_maps = trace_ir_maps_create(
1981 bt_self_component_filter_as_self_component(self_comp),
1982 debug_info_msg_iter->debug_info_component->arg_debug_info_field_name);
1983 if (!debug_info_msg_iter->ir_maps) {
1984 g_hash_table_destroy(debug_info_msg_iter->debug_info_map);
1985 g_free(debug_info_msg_iter);
1986 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1987 goto end;
1988 }
1989
1990 bt_self_message_iterator_set_data(self_msg_iter, debug_info_msg_iter);
1991
1992 debug_info_msg_iter->input_iterator = self_msg_iter;
1993
1994end:
1995 return status;
1996}
1997
1998BT_HIDDEN
1999bt_bool debug_info_msg_iter_can_seek_beginning(
2000 bt_self_message_iterator *self_msg_iter)
2001{
2002 struct debug_info_msg_iter *debug_info_msg_iter =
2003 bt_self_message_iterator_get_data(self_msg_iter);
2004 BT_ASSERT(debug_info_msg_iter);
2005
2006 return bt_self_component_port_input_message_iterator_can_seek_beginning(
2007 debug_info_msg_iter->msg_iter);
2008}
2009
2010BT_HIDDEN
2011bt_self_message_iterator_status debug_info_msg_iter_seek_beginning(
2012 bt_self_message_iterator *self_msg_iter)
2013{
2014 struct debug_info_msg_iter *debug_info_msg_iter =
2015 bt_self_message_iterator_get_data(self_msg_iter);
2016 bt_message_iterator_status status = BT_MESSAGE_ITERATOR_STATUS_OK;
2017
2018 BT_ASSERT(debug_info_msg_iter);
2019
2020 /* Ask the upstream component to seek to the beginning. */
2021 status = bt_self_component_port_input_message_iterator_seek_beginning(
2022 debug_info_msg_iter->msg_iter);
2023 if (status != BT_MESSAGE_ITERATOR_STATUS_OK) {
2024 goto end;
2025 }
2026
2027 /* Clear this iterator data. */
2028 trace_ir_maps_clear(debug_info_msg_iter->ir_maps);
2029 g_hash_table_remove_all(debug_info_msg_iter->debug_info_map);
2030end:
2031 return bt_common_message_iterator_status_to_self(status);
2032}
2033
2034BT_HIDDEN
2035void debug_info_msg_iter_finalize(bt_self_message_iterator *it)
2036{
2037 struct debug_info_msg_iter *debug_info_msg_iter;
2038
2039 debug_info_msg_iter = bt_self_message_iterator_get_data(it);
2040 BT_ASSERT(debug_info_msg_iter);
2041
2042 bt_self_component_port_input_message_iterator_put_ref(
2043 debug_info_msg_iter->msg_iter);
2044
2045 trace_ir_maps_destroy(debug_info_msg_iter->ir_maps);
2046 g_hash_table_destroy(debug_info_msg_iter->debug_info_map);
2047
2048 g_free(debug_info_msg_iter);
2049}
This page took 0.113758 seconds and 4 git commands to generate.