File: gen-syscall-events.cpp

package info (click to toggle)
ltt-control 2.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,744 kB
  • sloc: cpp: 207,706; sh: 28,837; python: 18,952; ansic: 11,636; makefile: 3,362; java: 109; xml: 46
file content (132 lines) | stat: -rw-r--r-- 3,056 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * SPDX-FileCopyrightText: 2017 Francis Deslauriers <francis.deslauriers@efficios.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-only
 *
 */

#include "utils.h"

#include <common/align.hpp>
#include <common/error.hpp>

#include <fcntl.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>

#define MAX_LEN 16

/*
 * The LTTng system call tracing facilities can't handle page faults at the
 * moment. If a fault would occur while reading a syscall argument, the
 * tracer will report an empty string (""). Since the proper execution of the
 * tests which use this generator depends on some syscall string arguments being
 * present, this util allows us to mitigate the page-fault risk.
 *
 * This isn't a proper fix; it is simply the best we can do for now.
 * See bug #1261 for more context.
 */
static void prefault_string(const char *p)
{
	const char *const end = p + strlen(p) + 1;

	while (p < end) {
		/*
		 * Trigger a read attempt on *p, faulting-in the pages
		 * for reading.
		 */
		asm volatile("" : : "m"(*p));
		p += sysconf(_SC_PAGE_SIZE);
	}
}

static int open_read_close(const char *path)
{
	int fd, ret;
	char buf[MAX_LEN];

	/*
	 * Start generating syscalls. We use syscall(2) to prevent libc from
	 * changing the underlying syscall (e.g. calling openat(2) instead of
	 * open(2)).
	 */
	prefault_string(path);
	fd = syscall(SYS_openat, AT_FDCWD, path, O_RDONLY);
	if (fd < 0) {
		PERROR_NO_LOGGER("Failed to open file with openat(): path = '%s'", path);
		ret = -1;
		goto error;
	}

	ret = syscall(SYS_read, fd, buf, MAX_LEN);
	if (ret < 0) {
		PERROR_NO_LOGGER("Failed to read file: path = '%s', fd = %d, length = %d",
				 path,
				 fd,
				 MAX_LEN);
		ret = -1;
		goto error;
	}

	ret = syscall(SYS_close, fd);
	if (ret == -1) {
		PERROR_NO_LOGGER("Failed to close file: path = '%s', fd = %d", path, fd);
		ret = -1;
		goto error;
	}

error:
	return ret;
}

/*
 * The process waits for the creation of a file passed as argument from an
 * external processes to execute a syscall and exiting. This is useful for tests
 * in combinaison with LTTng's PID tracker feature where we can trace the kernel
 * events generated by our test process only.
 */
int main(int argc, char **argv)
{
	int ret;
	const char *start_file, *path1, *path2;

	if (argc != 4) {
		fprintf(stderr, "Error: Missing argument\n");
		fprintf(stderr, "USAGE: %s PATH_WAIT_FILE PATH1_TO_OPEN PATH2_TO_OPEN\n", argv[0]);
		ret = -1;
		goto error;
	}

	start_file = argv[1];
	path1 = argv[2];
	path2 = argv[3];

	/*
	 * Wait for the start_file to be created by an external process
	 * (typically the test script) before executing the syscalls.
	 */
	ret = wait_on_file(start_file);
	if (ret != 0) {
		goto error;
	}

	/*
	 * Start generating syscalls. We use syscall(2) to prevent libc to change
	 * the underlying syscall. e.g. calling openat(2) instead of open(2).
	 */
	ret = open_read_close(path1);
	if (ret == -1) {
		ret = -1;
		goto error;
	}

	ret = open_read_close(path2);
	if (ret == -1) {
		ret = -1;
		goto error;
	}

error:
	return ret;
}