Add SDT userspace probe location
[lttng-tools.git] / src / common / userspace-probe.c
index 78cf43b27e50d666a6b0cd2aeef3295bed497e7c..ea3c93bcde840242d4871084394f6ebe0d75ec11 100644 (file)
@@ -47,6 +47,14 @@ void lttng_userspace_probe_location_lookup_method_destroy(
                free(elf_method);
                break;
        }
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+       {
+               struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method =
+                       container_of(lookup_method,
+                               struct lttng_userspace_probe_location_lookup_method_sdt, parent);
+               free(sdt_method);
+               break;
+       }
        default:
                break;
        }
@@ -70,6 +78,24 @@ end:
        return ret;
 }
 
+struct lttng_userspace_probe_location_lookup_method *
+lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
+{
+       struct lttng_userspace_probe_location_lookup_method *ret = NULL;
+       struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
+
+       sdt_method = zmalloc(sizeof(*sdt_method));
+       if (!sdt_method) {
+               PERROR("zmalloc");
+               goto end;
+       }
+
+       ret = &sdt_method->parent;
+       ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
+end:
+       return ret;
+}
+
 enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
                const struct lttng_userspace_probe_location *location)
 {
@@ -100,6 +126,31 @@ void lttng_userspace_probe_location_function_destroy(
        free(location);
 }
 
+static
+void lttng_userspace_probe_location_tracepoint_destroy(
+               struct lttng_userspace_probe_location *location)
+{
+       struct lttng_userspace_probe_location_tracepoint *location_tracepoint = NULL;
+
+       assert(location);
+
+       location_tracepoint = container_of(location,
+                       struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+
+       assert(location_tracepoint);
+
+       free(location_tracepoint->probe_name);
+       free(location_tracepoint->provider_name);
+       free(location_tracepoint->binary_path);
+       if (location_tracepoint->binary_fd >= 0) {
+               if (close(location_tracepoint->binary_fd)) {
+                       PERROR("close");
+               }
+       }
+       free(location);
+}
+
 void lttng_userspace_probe_location_destroy(
                struct lttng_userspace_probe_location *location)
 {
@@ -114,6 +165,9 @@ void lttng_userspace_probe_location_destroy(
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
                lttng_userspace_probe_location_function_destroy(location);
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+               lttng_userspace_probe_location_tracepoint_destroy(location);
+               break;
        default:
                free(location);
        }
@@ -179,6 +233,75 @@ end:
        return ret;
 }
 
+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,
+               struct lttng_userspace_probe_location_lookup_method *lookup_method,
+               bool open_binary)
+{
+       int binary_fd = -1;
+       char *probe_name_copy = NULL;
+       char *provider_name_copy = NULL;
+       char *binary_path_copy = NULL;
+       struct lttng_userspace_probe_location *ret = NULL;
+       struct lttng_userspace_probe_location_tracepoint *location;
+
+       if (open_binary) {
+               binary_fd = open(binary_path, O_RDONLY);
+               if (binary_fd < 0) {
+                       PERROR("open");
+                       goto error;
+               }
+       } else {
+               binary_fd = -1;
+       }
+
+       probe_name_copy = lttng_strndup(probe_name, LTTNG_SYMBOL_NAME_LEN);
+       if (!probe_name_copy) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       provider_name_copy = lttng_strndup(provider_name, LTTNG_SYMBOL_NAME_LEN);
+       if (!provider_name_copy) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
+       if (!binary_path_copy) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       location = zmalloc(sizeof(*location));
+       if (!location) {
+               PERROR("zmalloc");
+               goto error;
+       }
+
+       location->probe_name = probe_name_copy;
+       location->provider_name = provider_name_copy;
+       location->binary_path = binary_path_copy;
+       location->binary_fd = binary_fd;
+
+       ret = &location->parent;
+       ret->lookup_method = lookup_method;
+       ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
+       goto end;
+
+error:
+       free(probe_name_copy);
+       free(provider_name_copy);
+       if (binary_fd >= 0) {
+               if (close(binary_fd)) {
+                       PERROR("Error closing binary fd in error path");
+               }
+       }
+end:
+       return ret;
+}
+
 struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_function_create(const char *binary_path,
                const char *function_name,
@@ -207,6 +330,33 @@ end:
        return ret;
 }
 
+struct lttng_userspace_probe_location *
+lttng_userspace_probe_location_tracepoint_create(const char *binary_path,
+               const char *provider_name, const char *probe_name,
+               struct lttng_userspace_probe_location_lookup_method *lookup_method)
+{
+       struct lttng_userspace_probe_location *ret = NULL;
+
+       if (!binary_path || !probe_name || !provider_name) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       switch (lttng_userspace_probe_location_lookup_method_get_type(
+                       lookup_method)) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+               break;
+       default:
+               /* Invalid probe location lookup method. */
+               goto end;
+       }
+
+       ret = lttng_userspace_probe_location_tracepoint_create_no_check(
+                       binary_path, provider_name, probe_name, lookup_method, true);
+end:
+       return ret;
+}
+
 static struct lttng_userspace_probe_location_lookup_method *
 lttng_userspace_probe_location_lookup_method_function_elf_copy(
                const struct lttng_userspace_probe_location_lookup_method *lookup_method)
@@ -234,6 +384,34 @@ end:
        return parent;
 }
 
+static struct lttng_userspace_probe_location_lookup_method *
+lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
+               struct lttng_userspace_probe_location_lookup_method *lookup_method)
+{
+       struct lttng_userspace_probe_location_lookup_method *parent = NULL;
+       struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
+
+       assert(lookup_method);
+       assert(lookup_method->type ==
+                       LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT);
+
+       sdt_method = zmalloc(sizeof(*sdt_method));
+       if (!sdt_method) {
+               PERROR("zmalloc");
+               goto error;
+       }
+
+       sdt_method->parent.type = lookup_method->type;
+       parent = &sdt_method->parent;
+
+       goto end;
+
+error:
+       parent = NULL;
+end:
+       return parent;
+}
+
 static struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_function_copy(
                const struct lttng_userspace_probe_location *location)
@@ -320,6 +498,103 @@ end:
        return new_location;
 }
 
+static struct lttng_userspace_probe_location *
+lttng_userspace_probe_location_tracepoint_copy(
+               const struct lttng_userspace_probe_location *location)
+{
+       enum lttng_userspace_probe_location_lookup_method_type lookup_type;
+       struct lttng_userspace_probe_location *new_location = NULL;
+       struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
+       char *binary_path = NULL;
+       char *probe_name = NULL;
+       char *provider_name = NULL;
+       int fd;
+
+       assert(location);
+       assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
+
+        /* Duplicate probe location fields */
+       binary_path =
+               lttng_strndup(lttng_userspace_probe_location_tracepoint_get_binary_path(location),
+                               LTTNG_PATH_MAX);
+       if (!binary_path) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       probe_name =
+               lttng_strndup(lttng_userspace_probe_location_tracepoint_get_probe_name(location),
+                               LTTNG_SYMBOL_NAME_LEN);
+       if (!probe_name) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       provider_name =
+               lttng_strndup(lttng_userspace_probe_location_tracepoint_get_provider_name(location),
+                               LTTNG_SYMBOL_NAME_LEN);
+       if (!provider_name) {
+               PERROR("lttng_strndup");
+               goto error;
+       }
+
+       /* Duplicate the binary fd */
+       fd = dup(lttng_userspace_probe_location_tracepoint_get_binary_fd(location));
+       if (fd == -1) {
+               PERROR("dup");
+               goto error;
+       }
+
+       /*
+        * Duplicate probe location method fields
+        */
+       lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
+                       location->lookup_method);
+       switch (lookup_type) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+               lookup_method =
+                       lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
+                                       location->lookup_method);
+               if (!lookup_method) {
+                       goto close_fd;
+               }
+               break;
+       default:
+               /* Invalid probe location lookup method. */
+               goto close_fd;
+       }
+
+       /* Create the probe_location */
+       new_location = lttng_userspace_probe_location_tracepoint_create_no_check(
+                       binary_path, provider_name, probe_name, lookup_method, true);
+       if (!new_location) {
+               goto destroy_lookup_method;
+       }
+
+       /* Set the duplicated fd to the new probe_location */
+       if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, fd) < 0) {
+               goto destroy_probe_location;
+       }
+
+       goto end;
+
+destroy_probe_location:
+       lttng_userspace_probe_location_destroy(new_location);
+destroy_lookup_method:
+       lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
+close_fd:
+       if (close(fd) < 0) {
+               PERROR("close");
+       }
+error:
+       free(provider_name);
+       free(probe_name);
+       free(binary_path);
+       new_location = NULL;
+end:
+       return new_location;
+}
+
 const char *lttng_userspace_probe_location_function_get_binary_path(
                const struct lttng_userspace_probe_location *location)
 {
@@ -340,6 +615,26 @@ end:
        return ret;
 }
 
+const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
+               const struct lttng_userspace_probe_location *location)
+{
+       const char *ret = NULL;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
+
+       if (!location || lttng_userspace_probe_location_get_type(location) !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       tracepoint_location = container_of(location,
+               struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+       ret = tracepoint_location->binary_path;
+end:
+       return ret;
+}
+
 const char *lttng_userspace_probe_location_function_get_function_name(
                const struct lttng_userspace_probe_location *location)
 {
@@ -359,6 +654,44 @@ end:
        return ret;
 }
 
+const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
+               const struct lttng_userspace_probe_location *location)
+{
+       const char *ret = NULL;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
+
+       if (!location || lttng_userspace_probe_location_get_type(location) !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       tracepoint_location = container_of(location,
+               struct lttng_userspace_probe_location_tracepoint, parent);
+       ret = tracepoint_location->probe_name;
+end:
+       return ret;
+}
+
+const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
+               const struct lttng_userspace_probe_location *location)
+{
+       const char *ret = NULL;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
+
+       if (!location || lttng_userspace_probe_location_get_type(location) !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       tracepoint_location = container_of(location,
+               struct lttng_userspace_probe_location_tracepoint, parent);
+       ret = tracepoint_location->provider_name;
+end:
+       return ret;
+}
+
 int lttng_userspace_probe_location_function_get_binary_fd(
                const struct lttng_userspace_probe_location *location)
 {
@@ -378,6 +711,25 @@ end:
        return ret;
 }
 
+int lttng_userspace_probe_location_tracepoint_get_binary_fd(
+               const struct lttng_userspace_probe_location *location)
+{
+       int ret = -1;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
+
+       if (!location || lttng_userspace_probe_location_get_type(location) !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       tracepoint_location = container_of(location,
+               struct lttng_userspace_probe_location_tracepoint, parent);
+       ret = tracepoint_location->binary_fd;
+end:
+       return ret;
+}
+
 static struct lttng_userspace_probe_location_lookup_method *
 lttng_userspace_probe_location_function_get_lookup_method(
                const struct lttng_userspace_probe_location *location)
@@ -395,6 +747,23 @@ end:
        return ret;
 }
 
+static struct lttng_userspace_probe_location_lookup_method *
+lttng_userspace_probe_location_tracepoint_get_lookup_method(
+               const struct lttng_userspace_probe_location *location)
+{
+       struct lttng_userspace_probe_location_lookup_method *ret = NULL;
+
+       if (!location || lttng_userspace_probe_location_get_type(location) !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
+               ERR("Invalid argument(s)");
+               goto end;
+       }
+
+       ret = location->lookup_method;
+end:
+       return ret;
+}
+
 struct lttng_userspace_probe_location_lookup_method *
 lttng_userspace_probe_location_get_lookup_method(
                const struct lttng_userspace_probe_location *location)
@@ -407,6 +776,10 @@ lttng_userspace_probe_location_get_lookup_method(
        ret = lttng_userspace_probe_location_function_get_lookup_method(
                        location);
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+       ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
+                       location);
+               break;
        default:
                ERR("Unknowned lookup method.");
                break;
@@ -432,83 +805,177 @@ int lttng_userspace_probe_location_lookup_method_serialize(
                        goto end;
                }
        }
-       ret = sizeof(lookup_method_comm);
+       ret = sizeof(lookup_method_comm);
+end:
+       return ret;
+}
+
+static
+int lttng_userspace_probe_location_function_serialize(
+               const struct lttng_userspace_probe_location *location,
+               struct lttng_dynamic_buffer *buffer,
+               int *binary_fd)
+{
+       int ret;
+       size_t function_name_len, binary_path_len;
+       struct lttng_userspace_probe_location_function *location_function;
+       struct lttng_userspace_probe_location_function_comm location_function_comm;
+
+       assert(location);
+       assert(lttng_userspace_probe_location_get_type(location) ==
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
+
+       location_function = container_of(location,
+                       struct lttng_userspace_probe_location_function,
+                       parent);
+       if (!location_function->function_name || !location_function->binary_path) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (binary_fd && location_function->binary_fd < 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (binary_fd) {
+               *binary_fd = location_function->binary_fd;
+       }
+
+       function_name_len = strlen(location_function->function_name);
+       if (function_name_len == 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+       binary_path_len = strlen(location_function->binary_path);
+       if (binary_path_len == 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       location_function_comm.function_name_len = function_name_len + 1;
+       location_function_comm.binary_path_len = binary_path_len + 1;
+
+       if (buffer) {
+               ret = lttng_dynamic_buffer_append(buffer,
+                               &location_function_comm,
+                               sizeof(location_function_comm));
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+               ret = lttng_dynamic_buffer_append(buffer,
+                               location_function->function_name,
+                               location_function_comm.function_name_len);
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+               ret = lttng_dynamic_buffer_append(buffer,
+                               location_function->binary_path,
+                               location_function_comm.binary_path_len);
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+       }
+       ret = sizeof(location_function_comm) +
+                       location_function_comm.function_name_len +
+                       location_function_comm.binary_path_len;
 end:
        return ret;
 }
 
 static
-int lttng_userspace_probe_location_function_serialize(
+int lttng_userspace_probe_location_tracepoint_serialize(
                const struct lttng_userspace_probe_location *location,
                struct lttng_dynamic_buffer *buffer,
                int *binary_fd)
 {
        int ret;
-       size_t function_name_len, binary_path_len;
-       struct lttng_userspace_probe_location_function *location_function;
-       struct lttng_userspace_probe_location_function_comm location_function_comm;
+       size_t probe_name_len, provider_name_len, binary_path_len;
+       struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
+       struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
 
        assert(location);
        assert(lttng_userspace_probe_location_get_type(location) ==
-                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
+                       LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
 
-       location_function = container_of(location,
-                       struct lttng_userspace_probe_location_function,
+       location_tracepoint = container_of(location,
+                       struct lttng_userspace_probe_location_tracepoint,
                        parent);
-       if (!location_function->function_name || !location_function->binary_path) {
+       if (!location_tracepoint->probe_name ||
+                       !location_tracepoint->provider_name ||
+                       !location_tracepoint->binary_path) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       if (binary_fd && location_function->binary_fd < 0) {
+       if (binary_fd && location_tracepoint->binary_fd < 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
        if (binary_fd) {
-               *binary_fd = location_function->binary_fd;
+               *binary_fd = location_tracepoint->binary_fd;
        }
 
-       function_name_len = strlen(location_function->function_name);
-       if (function_name_len == 0) {
+       probe_name_len = strlen(location_tracepoint->probe_name);
+       if (probe_name_len == 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
-       binary_path_len = strlen(location_function->binary_path);
+
+       provider_name_len = strlen(location_tracepoint->provider_name);
+       if (provider_name_len == 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       binary_path_len = strlen(location_tracepoint->binary_path);
        if (binary_path_len == 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       location_function_comm.function_name_len = function_name_len + 1;
-       location_function_comm.binary_path_len = binary_path_len + 1;
+       location_tracepoint_comm.probe_name_len = probe_name_len + 1;
+       location_tracepoint_comm.provider_name_len = provider_name_len + 1;
+       location_tracepoint_comm.binary_path_len = binary_path_len + 1;
 
        if (buffer) {
                ret = lttng_dynamic_buffer_append(buffer,
-                               &location_function_comm,
-                               sizeof(location_function_comm));
+                               &location_tracepoint_comm,
+                               sizeof(location_tracepoint_comm));
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
                ret = lttng_dynamic_buffer_append(buffer,
-                               location_function->function_name,
-                               location_function_comm.function_name_len);
+                               location_tracepoint->probe_name,
+                               location_tracepoint_comm.probe_name_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
                ret = lttng_dynamic_buffer_append(buffer,
-                               location_function->binary_path,
-                               location_function_comm.binary_path_len);
+                               location_tracepoint->provider_name,
+                               location_tracepoint_comm.provider_name_len);
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+               ret = lttng_dynamic_buffer_append(buffer,
+                               location_tracepoint->binary_path,
+                               location_tracepoint_comm.binary_path_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
        }
-       ret = sizeof(location_function_comm) +
-                       location_function_comm.function_name_len +
-                       location_function_comm.binary_path_len;
+       ret = sizeof(location_tracepoint_comm) +
+                       location_tracepoint_comm.probe_name_len +
+                       location_tracepoint_comm.provider_name_len +
+                       location_tracepoint_comm.binary_path_len;
 end:
        return ret;
 }
@@ -545,6 +1012,10 @@ int lttng_userspace_probe_location_serialize(
                ret = lttng_userspace_probe_location_function_serialize(
                                location, buffer, binary_fd);
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+               ret = lttng_userspace_probe_location_tracepoint_serialize(
+                               location, buffer, binary_fd);
+               break;
        default:
                ERR("Unsupported probe location type");
                ret = -LTTNG_ERR_INVALID;
@@ -630,6 +1101,86 @@ end:
        return ret;
 }
 
+static
+int lttng_userspace_probe_location_tracepoint_create_from_buffer(
+               const struct lttng_buffer_view *buffer,
+               struct lttng_userspace_probe_location **location)
+{
+       struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
+       const char *probe_name_src, *provider_name_src, *binary_path_src;
+       char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
+       int ret = 0;
+
+       assert(buffer);
+       assert(buffer->data);
+       assert(location);
+
+       location_tracepoint_comm =
+               (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
+
+       const size_t expected_size = sizeof(*location_tracepoint_comm) +
+                       location_tracepoint_comm->probe_name_len +
+                       location_tracepoint_comm->provider_name_len +
+                       location_tracepoint_comm->binary_path_len;
+
+       if (buffer->size < expected_size) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
+       provider_name_src = probe_name_src +
+                       location_tracepoint_comm->probe_name_len;
+       binary_path_src = provider_name_src +
+                       location_tracepoint_comm->provider_name_len;
+
+       if (probe_name_src[location_tracepoint_comm->probe_name_len - 1] != '\0') {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (provider_name_src[location_tracepoint_comm->provider_name_len - 1] != '\0') {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (binary_path_src[location_tracepoint_comm->binary_path_len - 1] != '\0') {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
+       if (!probe_name) {
+               PERROR("lttng_strndup");
+               goto end;
+       }
+       provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
+       if (!provider_name) {
+               PERROR("lttng_strndup");
+               goto end;
+       }
+
+       binary_path = lttng_strndup(binary_path_src, LTTNG_SYMBOL_NAME_LEN);
+       if (!binary_path) {
+               PERROR("lttng_strndup");
+               goto end;
+       }
+
+       *location = lttng_userspace_probe_location_tracepoint_create_no_check(
+                       binary_path, provider_name, probe_name, NULL, false);
+       if (!(*location)) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       ret = (int) expected_size;
+end:
+       free(probe_name);
+       free(provider_name);
+       free(binary_path);
+       return ret;
+}
+
 static
 int lttng_userspace_probe_location_lookup_method_create_from_buffer(
                struct lttng_buffer_view *buffer,
@@ -664,6 +1215,14 @@ int lttng_userspace_probe_location_lookup_method_create_from_buffer(
                        goto end;
                }
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+               *lookup_method =
+                       lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
+               if (!(*lookup_method)) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+               break;
        default:
                ret = -LTTNG_ERR_INVALID;
                goto end;
@@ -716,6 +1275,18 @@ int lttng_userspace_probe_location_create_from_buffer(
                }
                break;
        }
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+       {
+               struct lttng_buffer_view view = lttng_buffer_view_from_view(
+                       buffer, consumed, buffer->size - consumed);
+
+               ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
+                               &view, location);
+               if (ret < 0) {
+                       goto end;
+               }
+               break;
+       }
        default:
                ret = -LTTNG_ERR_INVALID;
                goto end;
@@ -770,6 +1341,32 @@ end:
        return ret;
 }
 
+LTTNG_HIDDEN
+int lttng_userspace_probe_location_tracepoint_set_binary_fd(
+               struct lttng_userspace_probe_location *location, int binary_fd)
+{
+       int ret = 0;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
+
+       assert(location);
+       assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
+
+       tracepoint_location = container_of(location,
+                       struct lttng_userspace_probe_location_tracepoint, parent);
+       if (tracepoint_location->binary_fd >= 0) {
+               ret = close(tracepoint_location->binary_fd);
+               if (ret) {
+                       PERROR("close");
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
+       }
+
+       tracepoint_location->binary_fd = binary_fd;
+end:
+       return ret;
+}
+
 static
 int lttng_userspace_probe_location_function_flatten(
                const struct lttng_userspace_probe_location *location,
@@ -894,6 +1491,146 @@ end:
        return ret;
 }
 
+static
+int lttng_userspace_probe_location_tracepoint_flatten(
+               const struct lttng_userspace_probe_location *location,
+               struct lttng_dynamic_buffer *buffer)
+{
+       struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
+       struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
+       struct lttng_userspace_probe_location_tracepoint flat_probe;
+       size_t probe_name_len, provider_name_len, binary_path_len;
+       size_t padding_needed = 0;
+       int storage_needed = 0;
+       char *flat_probe_start;
+       int ret = 0;
+
+       assert(location);
+
+       /* Only SDT tracepoints are supported at the moment */
+       if (location->lookup_method && location->lookup_method->type !=
+                       LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+       probe_tracepoint = container_of(location,
+                       struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+       assert(probe_tracepoint->probe_name);
+       assert(probe_tracepoint->provider_name);
+       assert(probe_tracepoint->binary_path);
+
+       /* Compute the storage space needed to flatten the probe location */
+       storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
+
+       probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
+       provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
+       binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
+
+       storage_needed += probe_name_len + provider_name_len + binary_path_len;
+
+       /*
+        * The lookup method is aligned to 64-bit within the buffer.
+        * This is needed even if there is no lookup method since
+        * the next structure in the buffer probably needs to be
+        * aligned too (depending on the arch).
+        */
+       padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
+       storage_needed += padding_needed;
+
+       if (location->lookup_method) {
+               /* NOTE: elf look-up method is assumed here. */
+               storage_needed +=
+                       sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
+       }
+
+       /*
+        * If the caller set buffer to NULL, return the size of the needed buffer.
+        */
+       if (!buffer) {
+               ret = storage_needed;
+               goto end;
+       }
+
+       if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
+               ret = lttng_dynamic_buffer_set_capacity(buffer,
+                               buffer->size + storage_needed);
+               if (ret) {
+                       goto end;
+               }
+       }
+
+       memset(&flat_probe, 0, sizeof(flat_probe));
+
+       flat_probe_start = buffer->data + buffer->size;
+       flat_probe.parent.type = location->type;
+
+       /*
+        * The lookup method, if present, is the last element in the flat
+        * representation of the probe.
+        */
+       if (location->lookup_method) {
+               flat_probe.parent.lookup_method =
+                               (struct lttng_userspace_probe_location_lookup_method *)
+                                       (flat_probe_start + sizeof(flat_probe) +
+                                       probe_name_len + provider_name_len +
+                                       binary_path_len + padding_needed);
+       } else {
+               flat_probe.parent.lookup_method = NULL;
+       }
+
+       flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
+       flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
+       flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
+       flat_probe.binary_fd = -1;
+       ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
+       if (ret) {
+               goto end;
+       }
+
+       /* Append all the fields to the buffer */
+       ret = lttng_dynamic_buffer_append(buffer,
+                       probe_tracepoint->probe_name, probe_name_len);
+       if (ret) {
+               goto end;
+       }
+       ret = lttng_dynamic_buffer_append(buffer,
+                       probe_tracepoint->provider_name, provider_name_len);
+       if (ret) {
+               goto end;
+       }
+       ret = lttng_dynamic_buffer_append(buffer,
+                       probe_tracepoint->binary_path, binary_path_len);
+       if (ret) {
+               goto end;
+       }
+
+       /* Insert padding before the lookup method. */
+       ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
+       if (ret) {
+               goto end;
+       }
+
+       if (!location->lookup_method) {
+               /* Not an error, the default method is used. */
+               ret = storage_needed;
+               goto end;
+       }
+
+       memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
+
+       flat_lookup_method.parent.type =
+                       LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
+       ret = lttng_dynamic_buffer_append(buffer,
+                       &flat_lookup_method, sizeof(flat_lookup_method));
+       if (ret) {
+               goto end;
+       }
+       ret = storage_needed;
+end:
+       return ret;
+}
+
 LTTNG_HIDDEN
 int lttng_userspace_probe_location_flatten(
                const struct lttng_userspace_probe_location *location,
@@ -910,6 +1647,9 @@ int lttng_userspace_probe_location_flatten(
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
                ret = lttng_userspace_probe_location_function_flatten(location, buffer);
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+               ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
+               break;
        default:
                ret = -LTTNG_ERR_INVALID;
                goto end;
@@ -939,6 +1679,13 @@ struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
                        goto err;
                }
                break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+               new_location =
+                       lttng_userspace_probe_location_tracepoint_copy(location);
+               if (!new_location) {
+                       goto err;
+               }
+               break;
        default:
                new_location = NULL;
                goto err;
This page took 0.033174 seconds and 4 git commands to generate.