+/* Compare two file descriptors based on their inode and device numbers. */
+static bool fd_is_equal(int a, int b)
+{
+ int ret;
+ bool is_equal = false;
+ struct stat a_stat, b_stat;
+
+ if (a < 0 && b >= 0) {
+ goto end;
+ }
+
+ if (b < 0 && a >= 0) {
+ goto end;
+ }
+
+ if (a < 0 && b < 0) {
+ if (a == -1 && b == -1) {
+ is_equal = true;
+ goto end;
+ }
+
+ /* Invalid state, abort. */
+ abort();
+ }
+
+ /* Both are valid file descriptors. */
+ ret = fstat(a, &a_stat);
+ if (ret) {
+ PERROR("Failed to fstat userspace probe location binary fd %d",
+ a);
+ goto end;
+ }
+
+ ret = fstat(b, &b_stat);
+ if (ret) {
+ PERROR("Failed to fstat userspace probe location binary fd %d",
+ b);
+ goto end;
+ }
+
+ is_equal = (a_stat.st_ino == b_stat.st_ino) &&
+ (a_stat.st_dev == b_stat.st_dev);
+
+end:
+ return is_equal;
+}
+
+static bool lttng_userspace_probe_location_function_is_equal(
+ const struct lttng_userspace_probe_location *_a,
+ const struct lttng_userspace_probe_location *_b)
+{
+ bool is_equal = false;
+ struct lttng_userspace_probe_location_function *a, *b;
+
+ a = container_of(_a, struct lttng_userspace_probe_location_function,
+ parent);
+ b = container_of(_b, struct lttng_userspace_probe_location_function,
+ parent);
+
+ if (a->instrumentation_type != b->instrumentation_type) {
+ goto end;
+ }
+
+ assert(a->function_name);
+ assert(b->function_name);
+ if (strcmp(a->function_name, b->function_name)) {
+ goto end;
+ }
+
+ assert(a->binary_path);
+ assert(b->binary_path);
+ if (strcmp(a->binary_path, b->binary_path)) {
+ goto end;
+ }
+
+ is_equal = fd_is_equal(a->binary_fd_handle ? fd_handle_get_fd(a->binary_fd_handle) : -1,
+ b->binary_fd_handle ? fd_handle_get_fd(b->binary_fd_handle) : -1);
+end:
+ return is_equal;
+}
+