X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fuserspace-probe.c;h=61ba309dfa38e2f863dd277ddb90590057720f2c;hp=b6e5083a2907c35836c4b856882004b669feee5b;hb=e368fb4396b9bdb22de16f0c93512c9f6d7ab0b4;hpb=7c86453b0149b861845b368aa83b16c3891536c9 diff --git a/src/common/userspace-probe.c b/src/common/userspace-probe.c index b6e5083a2..61ba309df 100644 --- a/src/common/userspace-probe.c +++ b/src/common/userspace-probe.c @@ -1,27 +1,23 @@ /* - * 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 "lttng/lttng-error.h" #include +#include #include #include -#include +#include +#include #include #include #include +#include +#include +#include enum lttng_userspace_probe_location_lookup_method_type lttng_userspace_probe_location_lookup_method_get_type( @@ -154,6 +150,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 +278,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 +293,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,6 +384,7 @@ 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: @@ -818,7 +932,7 @@ lttng_userspace_probe_location_get_lookup_method( static int lttng_userspace_probe_location_lookup_method_serialize( struct lttng_userspace_probe_location_lookup_method *method, - struct lttng_dynamic_buffer *buffer) + struct lttng_payload *payload) { int ret; struct lttng_userspace_probe_location_lookup_method_comm @@ -826,8 +940,8 @@ int lttng_userspace_probe_location_lookup_method_serialize( lookup_method_comm.type = (int8_t) (method ? method->type : LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT); - if (buffer) { - ret = lttng_dynamic_buffer_append(buffer, &lookup_method_comm, + if (payload) { + ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm, sizeof(lookup_method_comm)); if (ret) { goto end; @@ -841,8 +955,7 @@ end: static int lttng_userspace_probe_location_function_serialize( const struct lttng_userspace_probe_location *location, - struct lttng_dynamic_buffer *buffer, - int *binary_fd) + struct lttng_payload *payload) { int ret; size_t function_name_len, binary_path_len; @@ -861,15 +974,11 @@ int lttng_userspace_probe_location_function_serialize( goto end; } - if (binary_fd && location_function->binary_fd < 0) { + if (payload && 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; @@ -884,28 +993,34 @@ int lttng_userspace_probe_location_function_serialize( 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, + if (payload) { + ret = lttng_dynamic_buffer_append(&payload->buffer, &location_function_comm, sizeof(location_function_comm)); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } - ret = lttng_dynamic_buffer_append(buffer, + ret = lttng_dynamic_buffer_append(&payload->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, + ret = lttng_dynamic_buffer_append(&payload->buffer, location_function->binary_path, location_function_comm.binary_path_len); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } + ret = lttng_payload_push_fd( + payload, location_function->binary_fd); + if (ret) { + ret = -LTTNG_ERR_INVALID; + goto end; + } } ret = sizeof(location_function_comm) + location_function_comm.function_name_len + @@ -917,8 +1032,7 @@ end: static int lttng_userspace_probe_location_tracepoint_serialize( const struct lttng_userspace_probe_location *location, - struct lttng_dynamic_buffer *buffer, - int *binary_fd) + struct lttng_payload *payload) { int ret; size_t probe_name_len, provider_name_len, binary_path_len; @@ -939,15 +1053,11 @@ int lttng_userspace_probe_location_tracepoint_serialize( goto end; } - if (binary_fd && location_tracepoint->binary_fd < 0) { + if (payload && location_tracepoint->binary_fd < 0) { ret = -LTTNG_ERR_INVALID; goto end; } - if (binary_fd) { - *binary_fd = location_tracepoint->binary_fd; - } - probe_name_len = strlen(location_tracepoint->probe_name); if (probe_name_len == 0) { ret = -LTTNG_ERR_INVALID; @@ -970,36 +1080,43 @@ int lttng_userspace_probe_location_tracepoint_serialize( 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, + if (payload) { + ret = lttng_dynamic_buffer_append(&payload->buffer, &location_tracepoint_comm, sizeof(location_tracepoint_comm)); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } - ret = lttng_dynamic_buffer_append(buffer, + ret = lttng_dynamic_buffer_append(&payload->buffer, location_tracepoint->probe_name, location_tracepoint_comm.probe_name_len); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } - ret = lttng_dynamic_buffer_append(buffer, + ret = lttng_dynamic_buffer_append(&payload->buffer, location_tracepoint->provider_name, location_tracepoint_comm.provider_name_len); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } - ret = lttng_dynamic_buffer_append(buffer, + ret = lttng_dynamic_buffer_append(&payload->buffer, location_tracepoint->binary_path, location_tracepoint_comm.binary_path_len); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } + ret = lttng_payload_push_fd( + payload, location_tracepoint->binary_fd); + if (ret) { + ret = -LTTNG_ERR_INVALID; + goto end; + } } + ret = sizeof(location_tracepoint_comm) + location_tracepoint_comm.probe_name_len + location_tracepoint_comm.provider_name_len + @@ -1011,8 +1128,7 @@ end: LTTNG_HIDDEN int lttng_userspace_probe_location_serialize( const struct lttng_userspace_probe_location *location, - struct lttng_dynamic_buffer *buffer, - int *binary_fd) + struct lttng_payload *payload) { int ret, buffer_use = 0; struct lttng_userspace_probe_location_comm location_generic_comm; @@ -1026,8 +1142,9 @@ int lttng_userspace_probe_location_serialize( memset(&location_generic_comm, 0, sizeof(location_generic_comm)); location_generic_comm.type = (int8_t) location->type; - if (buffer) { - ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm, + if (payload) { + ret = lttng_dynamic_buffer_append(&payload->buffer, + &location_generic_comm, sizeof(location_generic_comm)); if (ret) { goto end; @@ -1038,11 +1155,11 @@ int lttng_userspace_probe_location_serialize( switch (lttng_userspace_probe_location_get_type(location)) { case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION: ret = lttng_userspace_probe_location_function_serialize( - location, buffer, binary_fd); + location, payload); break; case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT: ret = lttng_userspace_probe_location_tracepoint_serialize( - location, buffer, binary_fd); + location, payload); break; default: ERR("Unsupported probe location type"); @@ -1055,7 +1172,7 @@ int lttng_userspace_probe_location_serialize( buffer_use += ret; ret = lttng_userspace_probe_location_lookup_method_serialize( - location->lookup_method, buffer); + location->lookup_method, payload); if (ret < 0) { goto end; } @@ -1065,32 +1182,42 @@ end: } static -int lttng_userspace_probe_location_function_create_from_buffer( - const struct lttng_buffer_view *buffer, +int lttng_userspace_probe_location_function_create_from_payload( + struct lttng_payload_view *view, struct lttng_userspace_probe_location **location) { struct lttng_userspace_probe_location_function_comm *location_function_comm; const char *function_name_src, *binary_path_src; char *function_name = NULL, *binary_path = NULL; int ret = 0; + size_t expected_size; + const int binary_fd = lttng_payload_view_pop_fd(view); - assert(buffer); - assert(buffer->data); assert(location); + if (binary_fd < 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (view->buffer.size < sizeof(*location_function_comm)) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + location_function_comm = - (struct lttng_userspace_probe_location_function_comm *) buffer->data; + (typeof(location_function_comm)) view->buffer.data; - const size_t expected_size = sizeof(*location_function_comm) + + expected_size = sizeof(*location_function_comm) + location_function_comm->function_name_len + location_function_comm->binary_path_len; - if (buffer->size < expected_size) { + if (view->buffer.size < expected_size) { ret = -LTTNG_ERR_INVALID; goto end; } - function_name_src = buffer->data + sizeof(*location_function_comm); + function_name_src = view->buffer.data + sizeof(*location_function_comm); binary_path_src = function_name_src + location_function_comm->function_name_len; @@ -1106,12 +1233,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; } @@ -1122,6 +1251,18 @@ int lttng_userspace_probe_location_function_create_from_buffer( goto end; } + ret = lttng_userspace_probe_location_function_set_binary_fd( + *location, binary_fd); + if (ret) { + const int close_ret = close(binary_fd); + + if (close_ret) { + PERROR("Failed to close userspace probe function binary fd"); + } + ret = -LTTNG_ERR_INVALID; + goto end; + } + ret = (int) expected_size; end: free(function_name); @@ -1130,33 +1271,43 @@ end: } static -int lttng_userspace_probe_location_tracepoint_create_from_buffer( - const struct lttng_buffer_view *buffer, +int lttng_userspace_probe_location_tracepoint_create_from_payload( + struct lttng_payload_view *view, 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; + size_t expected_size; + const int binary_fd = lttng_payload_view_pop_fd(view); - assert(buffer); - assert(buffer->data); assert(location); + if (binary_fd < 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (view->buffer.size < sizeof(*location_tracepoint_comm)) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + location_tracepoint_comm = - (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data; + (typeof(location_tracepoint_comm)) view->buffer.data; - const size_t expected_size = sizeof(*location_tracepoint_comm) + + 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) { + if (view->buffer.size < expected_size) { ret = -LTTNG_ERR_INVALID; goto end; } - probe_name_src = buffer->data + sizeof(*location_tracepoint_comm); + probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm); provider_name_src = probe_name_src + location_tracepoint_comm->probe_name_len; binary_path_src = provider_name_src + @@ -1201,6 +1352,18 @@ int lttng_userspace_probe_location_tracepoint_create_from_buffer( goto end; } + ret = lttng_userspace_probe_location_tracepoint_set_binary_fd( + *location, binary_fd); + if (ret) { + const int close_ret = close(binary_fd); + + if (close_ret) { + PERROR("Failed to close userspace probe tracepoint binary fd"); + } + ret = -LTTNG_ERR_INVALID; + goto end; + } + ret = (int) expected_size; end: free(probe_name); @@ -1210,25 +1373,23 @@ end: } static -int lttng_userspace_probe_location_lookup_method_create_from_buffer( - struct lttng_buffer_view *buffer, +int lttng_userspace_probe_location_lookup_method_create_from_payload( + struct lttng_payload_view *view, struct lttng_userspace_probe_location_lookup_method **lookup_method) { int ret; struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm; enum lttng_userspace_probe_location_lookup_method_type type; - assert(buffer); - assert(buffer->data); + assert(view); assert(lookup_method); - if (buffer->size < sizeof(*lookup_comm)) { + if (view->buffer.size < sizeof(*lookup_comm)) { ret = -LTTNG_ERR_INVALID; goto end; } - lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *) - buffer->data; + lookup_comm = (typeof(lookup_comm)) view->buffer.data; type = (enum lttng_userspace_probe_location_lookup_method_type) lookup_comm->type; switch (type) { @@ -1262,42 +1423,39 @@ end: } LTTNG_HIDDEN -int lttng_userspace_probe_location_create_from_buffer( - const struct lttng_buffer_view *buffer, +int lttng_userspace_probe_location_create_from_payload( + struct lttng_payload_view *view, struct lttng_userspace_probe_location **location) { struct lttng_userspace_probe_location_lookup_method *lookup_method; struct lttng_userspace_probe_location_comm *probe_location_comm; enum lttng_userspace_probe_location_type type; - struct lttng_buffer_view lookup_method_view; int consumed = 0; int ret; - - assert(buffer); - assert(buffer->data); + assert(view); assert(location); lookup_method = NULL; - if (buffer->size <= sizeof(*probe_location_comm)) { + if (view->buffer.size <= sizeof(*probe_location_comm)) { ret = -LTTNG_ERR_INVALID; goto end; } - probe_location_comm = - (struct lttng_userspace_probe_location_comm *) buffer->data; + probe_location_comm = (typeof(probe_location_comm)) view->buffer.data; type = (enum lttng_userspace_probe_location_type) probe_location_comm->type; consumed += sizeof(*probe_location_comm); switch (type) { case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION: { - struct lttng_buffer_view view = lttng_buffer_view_from_view( - buffer, consumed, buffer->size - consumed); + struct lttng_payload_view location_view = + lttng_payload_view_from_view( + view, consumed, -1); - ret = lttng_userspace_probe_location_function_create_from_buffer( - &view, location); + ret = lttng_userspace_probe_location_function_create_from_payload( + &location_view, location); if (ret < 0) { goto end; } @@ -1305,11 +1463,11 @@ int lttng_userspace_probe_location_create_from_buffer( } case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT: { - struct lttng_buffer_view view = lttng_buffer_view_from_view( - buffer, consumed, buffer->size - consumed); + struct lttng_payload_view location_view = + lttng_payload_view_from_view(view, consumed, -1); - ret = lttng_userspace_probe_location_tracepoint_create_from_buffer( - &view, location); + ret = lttng_userspace_probe_location_tracepoint_create_from_payload( + &location_view, location); if (ret < 0) { goto end; } @@ -1321,15 +1479,19 @@ int lttng_userspace_probe_location_create_from_buffer( } consumed += ret; - if (buffer->size <= consumed) { + if (view->buffer.size <= consumed) { ret = -LTTNG_ERR_INVALID; goto end; } - lookup_method_view = lttng_buffer_view_from_view(buffer, consumed, - buffer->size - consumed); - ret = lttng_userspace_probe_location_lookup_method_create_from_buffer( - &lookup_method_view, &lookup_method); + { + struct lttng_payload_view lookup_method_view = + lttng_payload_view_from_view( + view, consumed, -1); + + ret = lttng_userspace_probe_location_lookup_method_create_from_payload( + &lookup_method_view, &lookup_method); + } if (ret < 0) { ret = -LTTNG_ERR_INVALID; goto end; @@ -1721,3 +1883,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; +}