+ trace_statedump_event(trace_start_cb, owner, NULL);
+}
+
+static
+void trace_statedump_end(void *owner)
+{
+ trace_statedump_event(trace_end_cb, owner, NULL);
+}
+
+static
+void iter_begin(struct dl_iterate_data *data)
+{
+ unsigned int i;
+
+ /*
+ * UST lock nests within dynamic loader lock.
+ *
+ * Hold this lock across handling of the module listing to
+ * protect memory allocation at early process start, due to
+ * interactions with libc-wrapper lttng malloc instrumentation.
+ */
+ if (ust_lock()) {
+ data->cancel = true;
+ return;
+ }
+
+ /* Ensure all entries are unmarked. */
+ for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
+ struct cds_hlist_head *head;
+ struct lttng_ust_dl_node *e;
+
+ head = &dl_state_table[i];
+ cds_hlist_for_each_entry_2(e, head, node)
+ assert(!e->marked);
+ }
+}
+
+static
+void trace_lib_load(const struct bin_info_data *bin_data, void *ip)
+{
+ tracepoint(lttng_ust_lib, load,
+ ip, bin_data->base_addr_ptr, bin_data->resolved_path,
+ bin_data->memsz, bin_data->has_build_id,
+ bin_data->has_debug_link);
+
+ if (bin_data->has_build_id) {
+ tracepoint(lttng_ust_lib, build_id,
+ ip, bin_data->base_addr_ptr, bin_data->build_id,
+ bin_data->build_id_len);
+ }
+
+ if (bin_data->has_debug_link) {
+ tracepoint(lttng_ust_lib, debug_link,
+ ip, bin_data->base_addr_ptr, bin_data->dbg_file,
+ bin_data->crc);
+ }
+}
+
+static
+void trace_lib_unload(const struct bin_info_data *bin_data, void *ip)
+{
+ tracepoint(lttng_ust_lib, unload, ip, bin_data->base_addr_ptr);
+}
+
+static
+void iter_end(struct dl_iterate_data *data, void *ip)
+{
+ unsigned int i;
+
+ if (data->cancel)
+ goto end;
+ /*
+ * Iterate on hash table.
+ * For each marked, traced, do nothing.
+ * For each marked, not traced, trace lib open event. traced = true.
+ * For each unmarked, traced, trace lib close event. remove node.
+ * For each unmarked, not traced, remove node.
+ */
+ for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
+ struct cds_hlist_head *head;
+ struct lttng_ust_dl_node *e;
+
+ head = &dl_state_table[i];
+ cds_hlist_for_each_entry_2(e, head, node) {
+ if (e->marked) {
+ if (!e->traced) {
+ trace_lib_load(&e->bin_data, ip);
+ e->traced = true;
+ }
+ e->marked = false;
+ } else {
+ if (e->traced)
+ trace_lib_unload(&e->bin_data, ip);
+ remove_dl_node(e);
+ free_dl_node(e);
+ }
+ }
+ }
+end:
+ ust_unlock();
+}
+
+static
+int extract_bin_info_events(struct dl_phdr_info *info, size_t size, void *_data)
+{
+ int j, ret = 0;