X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fuserspace-probe.c;h=4cc881025656cb582ffbcbf701051539ed564809;hp=ac26a0c47411790b2a130067bcfe4821c1c73a1a;hb=refs%2Fheads%2Fsow-2019-0002-rev1;hpb=5d21f1435f208a26dee82e16e3f28df43e5df318 diff --git a/src/common/userspace-probe.c b/src/common/userspace-probe.c index ac26a0c47..4cc881025 100644 --- a/src/common/userspace-probe.c +++ b/src/common/userspace-probe.c @@ -1,18 +1,8 @@ /* - * Copyright (C) 2017 - Jérémie Galarneau + * Copyright (C) 2017 Jérémie Galarneau * - * 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 @@ -150,8 +140,43 @@ void lttng_userspace_probe_location_destroy( lttng_userspace_probe_location_tracepoint_destroy(location); break; default: - free(location); + abort(); + } +} + +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); + + /* The binary_fd is not checked since it does not hold "immutable" + * information. + */ + + 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 = true; +end: + return is_equal; } static struct lttng_userspace_probe_location * @@ -196,10 +221,13 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path, location->function_name = function_name_copy; location->binary_path = binary_path_copy; location->binary_fd = binary_fd; + location->instrumentation_type = + LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY; 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: @@ -214,6 +242,43 @@ 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); + + /* The binary_fd is not checked since it does not hold "immutable" + * information. + */ + + 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 = true; +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, @@ -269,11 +334,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"); @@ -400,32 +467,35 @@ lttng_userspace_probe_location_function_copy( 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 *function_name = NULL; - int fd; + const char *binary_path = NULL; + const char *function_name = NULL; + int fd, new_fd; assert(location); assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION); - /* Duplicate probe location fields */ - binary_path = - lttng_strndup(lttng_userspace_probe_location_function_get_binary_path(location), - LTTNG_PATH_MAX); + /* Get probe location fields */ + binary_path = lttng_userspace_probe_location_function_get_binary_path(location); if (!binary_path) { + ERR("Userspace probe binary path is NULL"); goto error; } - function_name = - lttng_strndup(lttng_userspace_probe_location_function_get_function_name(location), - LTTNG_SYMBOL_NAME_LEN); + function_name = lttng_userspace_probe_location_function_get_function_name(location); if (!function_name) { - PERROR("Error duplicating function name string"); + ERR("Userspace probe function name is NULL"); goto error; } /* Duplicate the binary fd */ - fd = dup(lttng_userspace_probe_location_function_get_binary_fd(location)); + fd = lttng_userspace_probe_location_function_get_binary_fd(location); if (fd == -1) { + ERR("Error getting file descriptor to binary"); + goto error; + } + + new_fd = dup(fd); + if (new_fd == -1) { PERROR("Error duplicating file descriptor to binary"); goto error; } @@ -451,13 +521,13 @@ lttng_userspace_probe_location_function_copy( /* Create the probe_location */ new_location = lttng_userspace_probe_location_function_create_no_check( - binary_path, function_name, lookup_method, true); + binary_path, function_name, lookup_method, false); if (!new_location) { goto destroy_lookup_method; } /* Set the duplicated fd to the new probe_location */ - if (lttng_userspace_probe_location_function_set_binary_fd(new_location, fd) < 0) { + if (lttng_userspace_probe_location_function_set_binary_fd(new_location, new_fd) < 0) { goto destroy_probe_location; } @@ -468,12 +538,10 @@ destroy_probe_location: destroy_lookup_method: lttng_userspace_probe_location_lookup_method_destroy(lookup_method); close_fd: - if (close(fd) < 0) { + if (close(new_fd) < 0) { PERROR("Error closing duplicated file descriptor in error path"); } error: - free(function_name); - free(binary_path); new_location = NULL; end: return new_location; @@ -486,43 +554,43 @@ lttng_userspace_probe_location_tracepoint_copy( 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; + const char *binary_path = NULL; + const char *probe_name = NULL; + const char *provider_name = NULL; + int fd, new_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); + /* Get probe location fields */ + binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location); if (!binary_path) { - PERROR("lttng_strndup"); + ERR("Userspace probe binary path is NULL"); goto error; } - probe_name = - lttng_strndup(lttng_userspace_probe_location_tracepoint_get_probe_name(location), - LTTNG_SYMBOL_NAME_LEN); + probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location); if (!probe_name) { - PERROR("lttng_strndup"); + ERR("Userspace probe probe name is NULL"); goto error; } - provider_name = - lttng_strndup(lttng_userspace_probe_location_tracepoint_get_provider_name(location), - LTTNG_SYMBOL_NAME_LEN); + provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location); if (!provider_name) { - PERROR("lttng_strndup"); + ERR("Userspace probe provider name is NULL"); goto error; } /* Duplicate the binary fd */ - fd = dup(lttng_userspace_probe_location_tracepoint_get_binary_fd(location)); + fd = lttng_userspace_probe_location_tracepoint_get_binary_fd(location); if (fd == -1) { - PERROR("dup"); + ERR("Error getting file descriptor to binary"); + goto error; + } + + new_fd = dup(fd); + if (new_fd == -1) { + PERROR("Error duplicating file descriptor to binary"); goto error; } @@ -547,13 +615,13 @@ lttng_userspace_probe_location_tracepoint_copy( /* Create the probe_location */ new_location = lttng_userspace_probe_location_tracepoint_create_no_check( - binary_path, provider_name, probe_name, lookup_method, true); + binary_path, provider_name, probe_name, lookup_method, false); 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) { + if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, new_fd) < 0) { goto destroy_probe_location; } @@ -564,13 +632,10 @@ destroy_probe_location: destroy_lookup_method: lttng_userspace_probe_location_lookup_method_destroy(lookup_method); close_fd: - if (close(fd) < 0) { - PERROR("close"); + if (close(new_fd) < 0) { + PERROR("Error closing duplicated file descriptor in error path"); } error: - free(provider_name); - free(probe_name); - free(binary_path); new_location = NULL; end: return new_location; @@ -692,6 +757,52 @@ end: return ret; } +enum lttng_userspace_probe_location_function_instrumentation_type +lttng_userspace_probe_location_function_get_instrumentation_type( + const struct lttng_userspace_probe_location *location) +{ + enum lttng_userspace_probe_location_function_instrumentation_type type; + struct lttng_userspace_probe_location_function *function_location; + + if (!location || lttng_userspace_probe_location_get_type(location) != + LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) { + ERR("Invalid argument(s)"); + type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN; + goto end; + } + + function_location = container_of(location, + struct lttng_userspace_probe_location_function, parent); + type = function_location->instrumentation_type; +end: + return type; +} + +enum lttng_userspace_probe_location_status +lttng_userspace_probe_location_function_set_instrumentation_type( + const struct lttng_userspace_probe_location *location, + enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type) +{ + enum lttng_userspace_probe_location_status status = + LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK; + struct lttng_userspace_probe_location_function *function_location; + + if (!location || lttng_userspace_probe_location_get_type(location) != + LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION || + instrumentation_type != + LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) { + ERR("Invalid argument(s)"); + status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID; + goto end; + } + + function_location = container_of(location, + struct lttng_userspace_probe_location_function, parent); + function_location->instrumentation_type = instrumentation_type; +end: + return status; +} + int lttng_userspace_probe_location_tracepoint_get_binary_fd( const struct lttng_userspace_probe_location *location) { @@ -1674,3 +1785,70 @@ struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy( err: return new_location; } + +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->type != b->type) { + goto end; + } + + if (a == b) { + is_equal = true; + goto end; + } + + is_equal = a->equal ? a->equal(a, b) : true; +end: + return is_equal; +} + +LTTNG_HIDDEN +int lttng_userspace_probe_location_set_binary_fd( + struct lttng_userspace_probe_location *location, int fd) +{ + int ret = 0; + const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; + /* + * Set the file descriptor received from the client through the unix + * socket in the probe location. + */ + lookup = lttng_userspace_probe_location_get_lookup_method(location); + if (!lookup) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + /* + * From the kernel tracer's perspective, all userspace probe event types + * are all the same: a file and an offset. + */ + switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: + ret = lttng_userspace_probe_location_function_set_binary_fd( + location, fd); + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: + ret = lttng_userspace_probe_location_tracepoint_set_binary_fd( + location, fd); + break; + default: + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + if (ret) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } +end: + return ret; +}