Fix: uprobe: missing error code on allocation failure
[lttng-tools.git] / src / common / userspace-probe.c
index e764d137b9f3b8c8c7b973a1a3787c84986ccc9e..8c6adaca620b62d6fb7a47a94cbf67bffb051d7f 100644 (file)
@@ -1,27 +1,20 @@
 /*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <assert.h>
+#include <common/compat/string.h>
 #include <common/error.h>
 #include <common/macros.h>
-#include <common/compat/string.h>
 #include <fcntl.h>
 #include <lttng/constant.h>
 #include <lttng/userspace-probe-internal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/unistd.h>
 
 enum lttng_userspace_probe_location_lookup_method_type
 lttng_userspace_probe_location_lookup_method_get_type(
@@ -154,6 +147,86 @@ void lttng_userspace_probe_location_destroy(
        }
 }
 
+/* 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, b->binary_fd);
+end:
+       return is_equal;
+}
+
 static struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
                const char *function_name,
@@ -202,6 +275,7 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
        ret = &location->parent;
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
+       ret->equal = lttng_userspace_probe_location_function_is_equal;
        goto end;
 
 error:
@@ -216,6 +290,42 @@ end:
        return ret;
 }
 
+static bool lttng_userspace_probe_location_tracepoint_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_tracepoint *a, *b;
+
+       a = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+       b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+
+       assert(a->probe_name);
+       assert(b->probe_name);
+       if (strcmp(a->probe_name, b->probe_name)) {
+               goto end;
+       }
+
+       assert(a->provider_name);
+       assert(b->provider_name);
+       if (strcmp(a->provider_name, b->provider_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, b->binary_fd);
+
+end:
+       return is_equal;
+}
+
 static struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path,
                const char *provider_name, const char *probe_name,
@@ -271,11 +381,13 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
        ret = &location->parent;
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
+       ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
        goto end;
 
 error:
        free(probe_name_copy);
        free(provider_name_copy);
+       free(binary_path_copy);
        if (binary_fd >= 0) {
                if (close(binary_fd)) {
                        PERROR("Error closing binary fd in error path");
@@ -1105,12 +1217,14 @@ int lttng_userspace_probe_location_function_create_from_buffer(
        function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
        if (!function_name) {
                PERROR("lttng_strndup");
+               ret = -LTTNG_ERR_NOMEM;
                goto end;
        }
 
        binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
        if (!binary_path) {
                PERROR("lttng_strndup");
+               ret = -LTTNG_ERR_NOMEM;
                goto end;
        }
 
@@ -1720,3 +1834,58 @@ struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
 err:
        return new_location;
 }
+
+LTTNG_HIDDEN
+bool lttng_userspace_probe_location_lookup_method_is_equal(
+               const struct lttng_userspace_probe_location_lookup_method *a,
+               const struct lttng_userspace_probe_location_lookup_method *b)
+{
+       bool is_equal = false;
+
+       if (!a || !b) {
+               goto end;
+       }
+
+       if (a == b) {
+               is_equal = true;
+               goto end;
+       }
+
+       if (a->type != b->type) {
+               goto end;
+       }
+
+       is_equal = true;
+end:
+       return is_equal;
+}
+
+LTTNG_HIDDEN
+bool lttng_userspace_probe_location_is_equal(
+               const struct lttng_userspace_probe_location *a,
+               const struct lttng_userspace_probe_location *b)
+{
+       bool is_equal = false;
+
+       if (!a || !b) {
+               goto end;
+       }
+
+       if (a == b) {
+               is_equal = true;
+               goto end;
+       }
+
+       if (!lttng_userspace_probe_location_lookup_method_is_equal(
+                           a->lookup_method, b->lookup_method)) {
+               goto end;
+       }
+
+       if (a->type != b->type) {
+               goto end;
+       }
+
+       is_equal = a->equal ? a->equal(a, b) : true;
+end:
+       return is_equal;
+}
This page took 0.025528 seconds and 4 git commands to generate.