* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#define _GNU_SOURCE
#define _LGPL_SOURCE
+#include <stdbool.h>
+
#include <common/bitfield.h>
#include <common/common.h>
#include <common/kernel-ctl/kernel-ctl.h>
size_t nbmem;
FILE *fp;
/* Syscall data from the kernel. */
- size_t index;
+ size_t index = 0;
+ bool at_least_one_syscall = false;
uint32_t bitness;
char name[SYSCALL_NAME_LEN];
fd = kernctl_syscall_list(kernel_tracer_fd);
if (fd < 0) {
- ret = -errno;
+ ret = fd;
PERROR("kernelctl syscall list");
goto error_ioctl;
}
name = %" XSTR(SYSCALL_NAME_LEN) "[^;]; \
bitness = %u; };\n",
&index, name, &bitness) == 3) {
- if (index >= nbmem ) {
+ at_least_one_syscall = true;
+ if (index >= nbmem) {
struct syscall *new_list;
size_t new_nbmem;
/* Double memory size. */
- new_nbmem = max(index, nbmem << 1);
- if (new_nbmem < nbmem) {
+ new_nbmem = 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[index].index = index;
syscall_table[index].bitness = bitness;
- strncpy(syscall_table[index].name, name,
- sizeof(syscall_table[index].name));
+ if (lttng_strncpy(syscall_table[index].name, name,
+ sizeof(syscall_table[index].name))) {
+ ret = -EINVAL;
+ free(syscall_table);
+ syscall_table = NULL;
+ goto error;
+ }
/*
DBG("Syscall name '%s' at index %" PRIu32 " of bitness %u",
syscall_table[index].name,
*/
}
- syscall_table_nb_entry = index;
+ /* Index starts at 0. */
+ if (at_least_one_syscall) {
+ syscall_table_nb_entry = index + 1;
+ }
ret = 0;
rcu_read_unlock();
return ret;
}
-
-/*
- * Add enabled syscall to the events list using the given kernel channel.
- *
- * Return the number of entry of the events array that is different from size
- * if the array grows. On error, return negative value and events is untouched.
- */
-ssize_t syscall_list_channel(struct ltt_kernel_channel *kchan,
- struct lttng_event **_events, size_t size)
-{
- int err, i;
- size_t new_size;
- ssize_t ret, count;
- char *mask = NULL;
- uint32_t len;
- struct lttng_event *events = NULL;
- /* Hash table used to filter duplicate out. */
- struct lttng_ht *syscalls_ht = NULL;
-
- assert(kchan);
-
- /* Get syscall mask from the kernel tracer. */
- err = kernel_syscall_mask(kchan->fd, &mask, &len);
- if (err < 0) {
- ret = err;
- goto error;
- }
-
- ret = init_syscall_ht(&syscalls_ht);
- if (ret < 0) {
- goto error;
- }
-
- count = new_size = size;
- events = *_events;
-
- for (i = 0; i < len; i++) {
- unsigned char val;
- struct syscall *ksyscall;
-
- bitfield_read_be(mask, unsigned char, i, 1, &val);
- if (!val) {
- /* Syscall is disabled, continue the loop. */
- continue;
- }
-
- /* Skip empty syscall. */
- if (*syscall_table[i].name == '\0') {
- continue;
- }
-
- /* Syscall is enabled thus add it to the events list. */
-
- if (count >= new_size) {
- struct lttng_event *new_events;
-
- /* Get the maximum here since count can be 0. */
- new_size = max(count << 1, 1);
- DBG3("Listing syscall realloc events array from %zu to %zu", count,
- new_size);
- new_events = realloc(events, new_size * sizeof(*new_events));
- if (!new_events) {
- PERROR("realloc kernel events list");
- ret = -ENOMEM;
- goto error;
- }
- memset(new_events + count, 0,
- (new_size - count) * sizeof(*new_events));
- events = new_events;
- }
-
- rcu_read_lock();
- ksyscall = lookup_syscall(syscalls_ht, syscall_table[i].name);
- if (ksyscall) {
- update_event_syscall_bitness(events, i, ksyscall->index);
- rcu_read_unlock();
- continue;
- }
- ksyscall = NULL;
- rcu_read_unlock();
-
- ret = add_syscall_to_ht(syscalls_ht, i, count);
- if (ret < 0) {
- goto error;
- }
-
- update_event_syscall_bitness(events, i, count);
- strncpy(events[count].name, syscall_table[i].name,
- sizeof(events[count].name));
- events[count].enabled = 1;
- events[count].type = LTTNG_EVENT_SYSCALL;
- count++;
- }
-
- *_events = events;
-
- return count;
-
-error:
- rcu_read_lock();
- destroy_syscall_ht(syscalls_ht);
- rcu_read_unlock();
-
- free(events);
- return ret;
-}