1. Overview
The strace command is a powerful tool for tracing system calls of a process. It’s useful for process monitoring, diagnostics, and troubleshooting.
strace abbreviates the argument of a system call if the length of the argument string is long.
In this tutorial, we’ll discuss how to prevent strace from abbreviating the arguments of system calls. Firstly, we’ll introduce the problem with an example. Then, we’ll learn the -s and -v options of strace.
2. Introduction to the Problem
We’ll see how strace abbreviates long parameters of system calls in this section.
2.1. Example Code
We’ll use the following C program, syscall_example.c, to analyze the problem:
#include <stdio.h>
#include <unistd.h>
void main(int ac, char **av)
{
for(;;) {
printf("A long statement that reports that the process will sleep for one second\n");
sleep(1);
printf("After sleep\n");
}
}
This program runs in an infinite for loop. Within the for loop, firstly, it prints “A long statement that reports that the process will sleep for one second” using printf(), then sleeps for one second using sleep(1), and finally prints “After sleep”.
2.2. Compiling and Running the Example
Let’s build the program using gcc:
$ gcc -o syscall_example syscall_example.c
The name of the executable file is syscall_example, which we specify using the -o option of gcc.
Having built the executable file, let’s run it:
$ ./ syscall_example
A long statement that reports that the process will sleep for one second
After sleep
A long statement that reports that the process will sleep for one second
After sleep
A long statement that reports that the process will sleep for one second
After sleep
A long statement that reports that the process will sleep for one second
The program runs as expected. The PID of the process is 4471:
$ ps -ef | grep syscall_example | grep -v grep
centos 4471 2700 0 10:03 pts/0 00:00:00 ./syscall_example
2.3. Analyzing the Example Using strace
Now, we’ll examine the interaction of the process with the Linux kernel using the strace command:
$ sudo strace -p 4471
strace: Process 4471 attached
restart_syscall(<... resuming interrupted read ...>) = 0
write(1, "After sleep\n", 12) = 12
write(1, "A long statement that reports th"..., 73) = 73
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 0x7ffc6e707630) = 0
write(1, "After sleep\n", 12) = 12
write(1, "A long statement that reports th"..., 73) = 73
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 0x7ffc6e707630) = 0
write(1, "After sleep\n", 12) = 12
We must run the strace command with root privileges, so we use it together with the sudo command. The -p option of strace specifies the PID of the process to attach.
Once strace attaches to the running process with PID 4471, we see the write() system calls in the output. The printf() function in the standard C library calls write() internally.
The write() system call corresponding to the first printf() call is write(1, “A long statement that reports th”…, 73) = 73 in the output. The first argument of write() is 1 since printf() writes to the standard output whose file descriptor is 1. The second argument is “A long statement that reports th”…. This argument is abbreviated as it’s long. Finally, the third argument, 73, is the length of the second argument.
The write() system call corresponding to the second printf() call is write(1, “After sleep\n”, 12) = 12. The first argument is again 1, as expected. In this case, since the string is short, all the string is printed without abbreviation. Finally, the last parameter, 12, is the length of the string.
We’ll discuss the solution for printing the arguments of system calls without abbreviation in strace output in the next section.
3. Using the -s and -v Options of strace
The maximum size of a string printed by strace is 32 by default. That is why strace abbreviates arguments with lengths longer than 32. However, we can use the -s option of strace to prevent the abbreviation of strings:
$ sudo strace -s 100 -p 4471
strace: Process 4471 attached
restart_syscall(<... resuming interrupted read ...>) = 0
write(1, "After sleep\n", 12) = 12
write(1, "A long statement that reports that the process will sleep for one second\n", 73) = 73
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 0x7ffc91056ef0) = 0
write(1, "After sleep\n", 12) = 12
write(1, "A long statement that reports that the process will sleep for one second\n", 73) = 73
As is apparent from the output of strace, we see the whole message “A long statement that reports that the process will sleep for one second” this time. We set the maximum string length to 100 using -s 100. We can use the –string-limit option instead of -s. They’re the same.
strace doesn’t consider filenames as strings, so it doesn’t abbreviate them.
The -s option is enough to prevent the abbreviation of strings. However, depending on the version of strace and the system call, the -v option might also be useful. For example, the ioctl() system call used for accessing device files may take a structure as an argument. The -v option may prevent the abbreviation of the elements of these structures.
Alternatively, we can use the –no-abbrev option instead of -v. They’re the same.
4. Conclusion
In this article, we discussed how to prevent strace from abbreviating the arguments of system calls. Firstly, we looked at an example demonstrating the problem. Then, we saw that the -s option of strace is useful for preventing the abbreviation of arguments. Finally, we learned that the -v option of strace might also be useful for preventing the abbreviation of the gory details in some system calls depending on the version of strace.