+static
+struct lttng_ust_dl_node *alloc_dl_node(const struct bin_info_data *bin_data)
+{
+ struct lttng_ust_dl_node *e;
+
+ e = zmalloc(sizeof(struct lttng_ust_dl_node));
+ if (!e)
+ return NULL;
+ if (bin_data->dbg_file) {
+ e->bin_data.dbg_file = strdup(bin_data->dbg_file);
+ if (!e->bin_data.dbg_file)
+ goto error;
+ }
+ if (bin_data->build_id) {
+ e->bin_data.build_id = zmalloc(bin_data->build_id_len);
+ if (!e->bin_data.build_id)
+ goto error;
+ memcpy(e->bin_data.build_id, bin_data->build_id,
+ bin_data->build_id_len);
+ }
+ e->bin_data.base_addr_ptr = bin_data->base_addr_ptr;
+ memcpy(e->bin_data.resolved_path, bin_data->resolved_path, PATH_MAX);
+ e->bin_data.memsz = bin_data->memsz;
+ e->bin_data.build_id_len = bin_data->build_id_len;
+ e->bin_data.vdso = bin_data->vdso;
+ e->bin_data.crc = bin_data->crc;
+ e->bin_data.is_pic = bin_data->is_pic;
+ e->bin_data.has_build_id = bin_data->has_build_id;
+ e->bin_data.has_debug_link = bin_data->has_debug_link;
+ return e;
+
+error:
+ free(e->bin_data.build_id);
+ free(e->bin_data.dbg_file);
+ free(e);
+ return NULL;
+}
+
+static
+void free_dl_node(struct lttng_ust_dl_node *e)
+{
+ free(e->bin_data.build_id);
+ free(e->bin_data.dbg_file);
+ free(e);
+}
+
+/* Return 0 if same, nonzero if not. */
+static
+int compare_bin_data(const struct bin_info_data *a,
+ const struct bin_info_data *b)
+{
+ if (a->base_addr_ptr != b->base_addr_ptr)
+ return -1;
+ if (strcmp(a->resolved_path, b->resolved_path) != 0)
+ return -1;
+ if (a->dbg_file && !b->dbg_file)
+ return -1;
+ if (!a->dbg_file && b->dbg_file)
+ return -1;
+ if (a->dbg_file && strcmp(a->dbg_file, b->dbg_file) != 0)
+ return -1;
+ if (a->build_id && !b->build_id)
+ return -1;
+ if (!a->build_id && b->build_id)
+ return -1;
+ if (a->build_id_len != b->build_id_len)
+ return -1;
+ if (a->build_id &&
+ memcmp(a->build_id, b->build_id, a->build_id_len) != 0)
+ return -1;
+ if (a->memsz != b->memsz)
+ return -1;
+ if (a->vdso != b->vdso)
+ return -1;
+ if (a->crc != b->crc)
+ return -1;
+ if (a->is_pic != b->is_pic)
+ return -1;
+ if (a->has_build_id != b->has_build_id)
+ return -1;
+ if (a->has_debug_link != b->has_debug_link)
+ return -1;
+ return 0;
+}
+
+static
+struct lttng_ust_dl_node *find_or_create_dl_node(struct bin_info_data *bin_data)
+{
+ struct cds_hlist_head *head;
+ struct lttng_ust_dl_node *e;
+ unsigned int hash;
+ bool found = false;
+
+ hash = jhash(&bin_data->base_addr_ptr,
+ sizeof(bin_data->base_addr_ptr), 0);
+ head = &dl_state_table[hash & (UST_DL_STATE_TABLE_SIZE - 1)];
+ cds_hlist_for_each_entry_2(e, head, node) {
+ if (compare_bin_data(&e->bin_data, bin_data) != 0)
+ continue;
+ found = true;
+ break;
+ }
+ if (!found) {
+ /* Create */
+ e = alloc_dl_node(bin_data);
+ if (!e)
+ return NULL;
+ cds_hlist_add_head(&e->node, head);
+ }
+ return e;
+}
+
+static
+void remove_dl_node(struct lttng_ust_dl_node *e)
+{
+ cds_hlist_del(&e->node);
+}
+