sessiond: manage syscall table allocation using std::vector
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 18 Jul 2024 17:37:43 +0000 (17:37 +0000)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 30 Jul 2024 01:26:51 +0000 (01:26 +0000)
Transitioning to the use of std::vector to manage the allocation and
resizing of the syscall table allows us to do away with memset() of the
syscall structure. The memset becomes problematic when lttng_ht_node_*
becomes non-POD in a follow-up change.

Change-Id: I94096782360f85ffffb0f72d188224af15e54d07
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/kernel.cpp
src/bin/lttng-sessiond/lttng-syscall.cpp
src/bin/lttng-sessiond/lttng-syscall.hpp

index 2d60fdca06dd54426a6550856ace66333dd57a4e..0fd9a6ebda077e73defd5d87b34112ecc233a393 100644 (file)
@@ -2228,7 +2228,6 @@ void cleanup_kernel_tracer()
        }
 
        kernel_tracer_status = nonstd::nullopt;
-       free(syscall_table);
 }
 
 bool kernel_tracer_is_initialized()
index 42eb0e7eed707a9c874a7e1b9f07716de67aefb5..598574e659d646bd39bdfe624aa28416c77fb27e 100644 (file)
 #include <stdbool.h>
 
 /* Global syscall table. */
-struct syscall *syscall_table;
-
-/* Number of entry in the syscall table. */
-static size_t syscall_table_nb_entry;
+std::vector<struct syscall> syscall_table;
 
 /*
  * Populate the system call table using the kernel tracer.
@@ -32,11 +29,9 @@ static size_t syscall_table_nb_entry;
 int syscall_init_table(int tracer_fd)
 {
        int ret, fd, err;
-       size_t nbmem;
        FILE *fp;
        /* Syscall data from the kernel. */
        size_t index = 0;
-       bool at_least_one_syscall = false;
        uint32_t bitness;
        char name[SYSCALL_NAME_LEN];
 
@@ -60,14 +55,6 @@ int syscall_init_table(int tracer_fd)
                goto error_fp;
        }
 
-       nbmem = SYSCALL_TABLE_INIT_SIZE;
-       syscall_table = calloc<struct syscall>(nbmem);
-       if (!syscall_table) {
-               ret = -errno;
-               PERROR("syscall list zmalloc");
-               goto error;
-       }
-
        while (fscanf(fp,
                      "syscall { index = %zu; \
                                name = %" SYSCALL_NAME_LEN_SCANF_IS_A_BROKEN_API "[^;]; \
@@ -75,56 +62,22 @@ int syscall_init_table(int tracer_fd)
                      &index,
                      name,
                      &bitness) == 3) {
-               at_least_one_syscall = true;
-               if (index >= nbmem) {
-                       struct syscall *new_list;
-                       size_t new_nbmem;
-
-                       /* Double memory size. */
-                       new_nbmem = std::max(index + 1, nbmem << 1);
-                       if (new_nbmem > (SIZE_MAX / sizeof(*new_list))) {
-                               /* Overflow, stop everything, something went really wrong. */
-                               ERR("Syscall listing memory size overflow. Stopping");
-                               free(syscall_table);
-                               syscall_table = nullptr;
-                               ret = -EINVAL;
-                               goto error;
-                       }
-
-                       DBG("Reallocating syscall table from %zu to %zu entries", nbmem, new_nbmem);
-                       new_list = (struct syscall *) realloc(syscall_table,
-                                                             new_nbmem * sizeof(*new_list));
-                       if (!new_list) {
-                               ret = -errno;
-                               PERROR("syscall list realloc");
-                               goto error;
-                       }
-
-                       /* Zero out the new memory. */
-                       memset(new_list + nbmem, 0, (new_nbmem - nbmem) * sizeof(*new_list));
-                       nbmem = new_nbmem;
-                       syscall_table = new_list;
-               }
-               syscall_table[index].index = index;
-               syscall_table[index].bitness = bitness;
-               if (lttng_strncpy(
-                           syscall_table[index].name, name, sizeof(syscall_table[index].name))) {
-                       ret = -EINVAL;
-                       free(syscall_table);
-                       syscall_table = nullptr;
+               try {
+                       syscall_table.emplace_back(index, bitness, name);
+               } catch (const std::bad_alloc&) {
+                       ERR_FMT("Failed to add syscall to syscall table: table_current_element_count={}, syscall_name=`{}`",
+                               syscall_table.size(),
+                               name);
+                       ret = ENOMEM;
+                       goto error;
+               } catch (const lttng::invalid_argument_error& ex) {
+                       ERR_FMT("Failed to add syscall to syscall table: table_current_element_count={}, reason=`{}`",
+                               syscall_table.size(),
+                               name,
+                               ex.what());
+                       ret = EINVAL;
                        goto error;
                }
-               /*
-               DBG("Syscall name '%s' at index %" PRIu32 " of bitness %u",
-                               syscall_table[index].name,
-                               syscall_table[index].index,
-                               syscall_table[index].bitness);
-               */
-       }
-
-       /* Index starts at 0. */
-       if (at_least_one_syscall) {
-               syscall_table_nb_entry = index + 1;
        }
 
        ret = 0;
@@ -172,7 +125,7 @@ static void destroy_syscall_ht(struct lttng_ht *ht)
 
                        ret = lttng_ht_del(ht, &iter);
                        LTTNG_ASSERT(!ret);
-                       free(ksyscall);
+                       delete ksyscall;
                }
        }
 
@@ -254,16 +207,16 @@ static int add_syscall_to_ht(struct lttng_ht *ht, unsigned int index, unsigned i
 
        LTTNG_ASSERT(ht);
 
-       ksyscall = zmalloc<struct syscall>();
-       if (!ksyscall) {
+       try {
+               ksyscall = new struct syscall(
+                       syscall_index, syscall_table[index].bitness, syscall_table[index].name);
+       } catch (const std::bad_alloc& ex) {
+               ERR_FMT("Failed to allocate syscall entry when adding it to the global syscall hash table: syscall name=`{}`",
+                       syscall_table[index].name);
                ret = -LTTNG_ERR_NOMEM;
                goto error;
        }
 
-       strncpy(ksyscall->name, syscall_table[index].name, sizeof(ksyscall->name));
-       ksyscall->bitness = syscall_table[index].bitness;
-       ksyscall->index = syscall_index;
-       lttng_ht_node_init_str(&ksyscall->node, ksyscall->name);
        lttng_ht_add_unique_str(ht, &ksyscall->node);
        ret = 0;
 
@@ -294,7 +247,7 @@ ssize_t syscall_table_list(struct lttng_event **_events)
         * them might not be valid. The count below will make sure to return the
         * right size of the events array.
         */
-       events = calloc<lttng_event>(syscall_table_nb_entry);
+       events = calloc<lttng_event>(syscall_table.size());
        if (!events) {
                PERROR("syscall table list zmalloc");
                ret = -LTTNG_ERR_NOMEM;
@@ -306,7 +259,7 @@ ssize_t syscall_table_list(struct lttng_event **_events)
                goto error;
        }
 
-       for (i = 0; i < syscall_table_nb_entry; i++) {
+       for (i = 0; i < syscall_table.size(); i++) {
                /* Skip empty syscalls. */
                if (*syscall_table[i].name == '\0') {
                        continue;
index 8ba8c7ea095294448511091dc8cf75b8c2f54afc..877f59390f7f0e491a2388566aaddc377b0cb1ae 100644 (file)
 
 #include "trace-kernel.hpp"
 
+#include <common/exception.hpp>
 #include <common/hashtable/hashtable.hpp>
+#include <common/macros.hpp>
+#include <common/string-utils/c-string-view.hpp>
 
 #include <lttng/event.h>
 
  * list.
  */
 struct syscall {
-       uint32_t index;
-       uint32_t bitness;
-       char name[SYSCALL_NAME_LEN];
+       syscall(std::uint32_t index_, std::uint32_t bitness_, const lttng::c_string_view name_) :
+               index(index_), bitness(bitness_)
+       {
+               if (lttng_strncpy(name, name_.data(), sizeof(name))) {
+                       LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
+                               "Invalid syscall name: name=`{}`, length={}, max_length={}",
+                               name_.data(),
+                               name_.len(),
+                               sizeof(name)));
+               }
+
+               lttng_ht_node_init_str(&node, name);
+       }
+
+       std::uint32_t index = 0;
+       std::uint32_t bitness = 0;
+       char name[SYSCALL_NAME_LEN] = {};
        /* Used by the list syscalls command. */
-       struct lttng_ht_node_str node;
+       struct lttng_ht_node_str node = {};
 };
 
 /*
  * Allocated once when listing all syscalls at boot time. This is an array
  * indexed by the syscall index provided in the listing.
  */
-extern struct syscall *syscall_table;
+extern std::vector<struct syscall> syscall_table;
 
 /* Use to list kernel system calls. */
 int syscall_init_table(int tracer_fd);
This page took 0.029941 seconds and 4 git commands to generate.