X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Flttng-syscall.cpp;h=821bbaa34f80b6e1c6d572192909c0ec0257aab2;hb=HEAD;hp=3f09090cb37a6821fe61e6a1de68e3a049c46467;hpb=28ab034a2c3582d07d3423d2d746731f87d3969f;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/lttng-syscall.cpp b/src/bin/lttng-sessiond/lttng-syscall.cpp index 3f09090cb..a89a3bff4 100644 --- a/src/bin/lttng-sessiond/lttng-syscall.cpp +++ b/src/bin/lttng-sessiond/lttng-syscall.cpp @@ -13,14 +13,12 @@ #include #include +#include #include /* Global syscall table. */ -struct syscall *syscall_table; - -/* Number of entry in the syscall table. */ -static size_t syscall_table_nb_entry; +std::vector syscall_table; /* * Populate the system call table using the kernel tracer. @@ -31,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]; @@ -59,14 +55,6 @@ int syscall_init_table(int tracer_fd) goto error_fp; } - nbmem = SYSCALL_TABLE_INIT_SIZE; - syscall_table = calloc(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 "[^;]; \ @@ -74,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 = NULL; - 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 = NULL; + 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; @@ -150,28 +104,24 @@ error_ioctl: * syscall hashtable used to track duplicate between 32 and 64 bit arch. * * This empty the hash table and destroys it after. After this, the pointer is - * unsuable. RCU read side lock MUST be acquired before calling this. + * unsuable. RCU read side lock MUST NOT be acquired before calling this. */ static void destroy_syscall_ht(struct lttng_ht *ht) { - struct lttng_ht_iter iter; - struct syscall *ksyscall; - - ASSERT_RCU_READ_LOCKED(); - DBG3("Destroying syscall hash table."); if (!ht) { return; } - cds_lfht_for_each_entry (ht->ht, &iter.iter, ksyscall, node.node) { - int ret; - - ret = lttng_ht_del(ht, &iter); + for (auto *ksyscall : lttng::urcu::lfht_iteration_adapter(*ht->ht)) { + const auto ret = cds_lfht_del(ht->ht, &ksyscall->node.node); LTTNG_ASSERT(!ret); - free(ksyscall); + delete ksyscall; } + lttng_ht_destroy(ht); } @@ -197,19 +147,21 @@ static int init_syscall_ht(struct lttng_ht **ht) /* * Lookup a syscall in the given hash table by name. * + * RCU read lock MUST be acquired by the callers of this function. + * * Return syscall object if found or else NULL. */ static struct syscall *lookup_syscall(struct lttng_ht *ht, const char *name) { struct lttng_ht_node_str *node; struct lttng_ht_iter iter; - struct syscall *ksyscall = NULL; + struct syscall *ksyscall = nullptr; LTTNG_ASSERT(ht); LTTNG_ASSERT(name); lttng_ht_lookup(ht, (void *) name, &iter); - node = lttng_ht_iter_get_node_str(&iter); + node = lttng_ht_iter_get_node(&iter); if (node) { ksyscall = lttng::utils::container_of(node, &syscall::node); } @@ -248,16 +200,16 @@ static int add_syscall_to_ht(struct lttng_ht *ht, unsigned int index, unsigned i LTTNG_ASSERT(ht); - ksyscall = zmalloc(); - 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; @@ -277,20 +229,18 @@ ssize_t syscall_table_list(struct lttng_event **_events) ssize_t ret; struct lttng_event *events; /* Hash table used to filter duplicate out. */ - struct lttng_ht *syscalls_ht = NULL; + struct lttng_ht *syscalls_ht = nullptr; LTTNG_ASSERT(_events); DBG("Syscall table listing."); - rcu_read_lock(); - /* * Allocate at least the number of total syscall we have even if some of * them might not be valid. The count below will make sure to return the * right size of the events array. */ - events = calloc(syscall_table_nb_entry); + events = calloc(syscall_table.size()); if (!events) { PERROR("syscall table list zmalloc"); ret = -LTTNG_ERR_NOMEM; @@ -302,18 +252,21 @@ ssize_t syscall_table_list(struct lttng_event **_events) goto error; } - for (i = 0; i < syscall_table_nb_entry; i++) { - struct syscall *ksyscall; - + for (i = 0; i < syscall_table.size(); i++) { /* Skip empty syscalls. */ if (*syscall_table[i].name == '\0') { continue; } - ksyscall = lookup_syscall(syscalls_ht, syscall_table[i].name); - if (ksyscall) { - update_event_syscall_bitness(events, i, ksyscall->index); - continue; + { + const lttng::urcu::read_lock_guard read_lock; + struct syscall *ksyscall; + + ksyscall = lookup_syscall(syscalls_ht, syscall_table[i].name); + if (ksyscall) { + update_event_syscall_bitness(events, i, ksyscall->index); + continue; + } } ret = add_syscall_to_ht(syscalls_ht, i, index); @@ -332,12 +285,10 @@ ssize_t syscall_table_list(struct lttng_event **_events) destroy_syscall_ht(syscalls_ht); *_events = events; - rcu_read_unlock(); return index; error: destroy_syscall_ht(syscalls_ht); free(events); - rcu_read_unlock(); return ret; }