Understanding Output
Once you've traced a program with Renacer, you'll see lines showing system calls. This chapter explains how to read and interpret that output.
Output Format
Every traced system call follows this format:
syscall_name(arg1, arg2, arg3, ...) = return_value
Example Breakdown
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
Parts:
openat: Syscall name (opens a file)AT_FDCWD: First argument (use current working directory)"/etc/passwd": Second argument (file path to open)O_RDONLY|O_CLOEXEC: Third argument (flags - read-only + close-on-exec)= 3: Return value (new file descriptor number)
Common Syscalls and Their Arguments
File Operations
openat - Open a File
openat(AT_FDCWD, "/path/to/file", O_RDONLY) = 3
- arg1: Directory FD (
AT_FDCWD= current directory) - arg2: Path to open
- arg3: Flags (
O_RDONLY,O_WRONLY,O_CREAT, etc.) - return: New file descriptor, or
-ENOENTon error
read - Read from File
read(3, "file contents...", 4096) = 42
- arg1: File descriptor to read from
- arg2: Buffer (contents shown as string if printable)
- arg3: Maximum bytes to read
- return: Actual bytes read
write - Write to File
write(1, "Hello\n", 6) = 6
- arg1: File descriptor (1 = stdout, 2 = stderr)
- arg2: Buffer contents to write
- arg3: Number of bytes
- return: Bytes actually written
close - Close File
close(3) = 0
- arg1: File descriptor to close
- return: 0 on success, -errno on error
Memory Operations
mmap - Memory Mapping
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8a2c000000
- arg1: Preferred address (NULL = let kernel choose)
- arg2: Size in bytes
- arg3: Protection flags (read/write/execute)
- arg4: Mapping type (private/shared, file/anonymous)
- arg5: File descriptor (or -1 for anonymous)
- arg6: Offset in file
- return: Address of mapped memory
brk - Change Data Segment Size
brk(0x55e8f1a2d000) = 0x55e8f1a2d000
- arg1: New end address of data segment
- return: New break address on success
Process Operations
clone - Create Child Process/Thread
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD) = 12345
- child_stack: Stack for new process/thread
- flags: Control behavior (process vs thread, signal handling, etc.)
- return: PID of child (in parent), 0 (in child)
wait4 - Wait for Process
wait4(12345, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 12345
- arg1: PID to wait for (-1 = any child)
- arg2: Status information (exit code, signal)
- arg3: Options (e.g.,
WNOHANG) - arg4: Resource usage (or NULL)
- return: PID of terminated child
execve - Execute Program
execve("/bin/ls", ["ls", "-la"], [/* 48 vars */]) = 0
- arg1: Path to executable
- arg2: Argument array
- arg3: Environment variables
- return: Doesn't return on success (replaces process)
Network Operations
socket - Create Socket
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
- arg1: Address family (
AF_INET= IPv4,AF_INET6= IPv6) - arg2: Socket type (
SOCK_STREAM= TCP,SOCK_DGRAM= UDP) - arg3: Protocol (usually 0 for default)
- return: Socket file descriptor
connect - Connect to Address
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("93.184.216.34")}, 16) = 0
- arg1: Socket file descriptor
- arg2: Address structure (IP + port)
- arg3: Address structure size
- return: 0 on success, -errno on error
sendto / recvfrom - Send/Receive Data
sendto(3, "GET / HTTP/1.1\r\n", 16, 0, NULL, 0) = 16
recvfrom(3, "HTTP/1.1 200 OK\r\n...", 4096, 0, NULL, NULL) = 1234
Return Values
Success
Positive numbers or zero indicate success. The meaning depends on the syscall:
| Return Value | Meaning |
|---|---|
= 0 | Success with no data (e.g., close, execve) |
= 3 | File descriptor number (e.g., open, socket) |
= 42 | Bytes read/written (e.g., read, write) |
= 12345 | Process ID (e.g., fork, clone) |
= 0x7f8a... | Memory address (e.g., mmap) |
Errors
Negative values are errno codes (errors):
| Error Code | Meaning | Common Causes |
|---|---|---|
-ENOENT | No such file/directory | File doesn't exist |
-EACCES | Permission denied | Insufficient permissions |
-EAGAIN | Try again | Resource temporarily unavailable |
-EINTR | Interrupted | Signal interrupted syscall |
-ENOMEM | Out of memory | System out of RAM |
-ECONNREFUSED | Connection refused | Server not listening |
Example:
openat(AT_FDCWD, "/nonexistent", O_RDONLY) = -ENOENT
This means: Attempted to open "/nonexistent", but file doesn't exist.
Flags and Constants
File Open Flags
| Flag | Meaning |
|---|---|
O_RDONLY | Open read-only |
O_WRONLY | Open write-only |
O_RDWR | Open read-write |
O_CREAT | Create if doesn't exist |
O_TRUNC | Truncate to zero length |
O_APPEND | Append to end |
O_NONBLOCK | Non-blocking I/O |
O_CLOEXEC | Close on exec() |
Combined with OR (|):
O_RDWR|O_CREAT|O_TRUNC = open for read/write, create if missing, truncate if exists
Memory Protection Flags
| Flag | Meaning |
|---|---|
PROT_READ | Pages may be read |
PROT_WRITE | Pages may be written |
PROT_EXEC | Pages may be executed |
PROT_NONE | Pages may not be accessed |
Special File Descriptors
| FD | Standard Name | Purpose |
|---|---|---|
| 0 | stdin | Standard input |
| 1 | stdout | Standard output |
| 2 | stderr | Standard error |
| 3+ | - | Opened files/sockets |
Data Representation
Strings
Readable strings are shown in quotes:
write(1, "Hello, World!\n", 14) = 14
Binary data is shown in hex or abbreviated:
read(3, "\x7fELF\x02\x01\x01...", 4096) = 4096
Structs
Complex structures are abbreviated:
fstat(3, {st_mode=S_IFREG|0644, st_size=1234, ...}) = 0
Use -v (verbose) flag for full struct details (not yet implemented in v0.4.1).
Arrays
Arrays and buffers are shown as:
getdents64(3, [{d_ino=123, d_name="file1.txt"}, ...], 32768) = 1024
Large arrays are abbreviated with [...].
Timing Information
With statistics mode (-c), see timing:
System Call Summary:
====================
Syscall Calls Errors Total Time Avg Time
openat 5 1 2.345ms 0.469ms
read 150 0 45.123ms 0.301ms
write 150 0 12.456ms 0.083ms
Columns:
- Calls: Number of times called
- Errors: Number of failed calls
- Total Time: Cumulative time spent
- Avg Time: Average per call
Source Correlation (with --source)
When tracing Rust binaries with debug symbols:
renacer --source -- ./my-program
Enhanced output:
read(3, buf, 1024) = 42 [src/main.rs:15 in my_function]
write(1, "result", 6) = 6 [src/main.rs:20 in my_function]
The [filename:line in function] shows where in your source code the syscall originated.
Filtering Output
Showing only certain syscalls makes output more readable:
File Operations Only
renacer -e 'trace=file' -- ls
Output:
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
close(3) = 0
Specific Syscalls
renacer -e 'trace=open,read,write' -- cat file.txt
Only shows open, read, and write calls.
Multi-Process Output
With -f (follow forks):
[pid 12345] clone(...) = 12346
[pid 12346] execve("/bin/ls", ...) = 0
[pid 12346] openat(...) = 3
[pid 12345] wait4(12346, ...) = 12346
Each line is prefixed with [pid XXXXX] to distinguish processes.
Common Patterns
Successful File Read
openat(AT_FDCWD, "/path/file", O_RDONLY) = 3
read(3, "contents...", 4096) = 1234
close(3) = 0
Interpretation: Opened file successfully (fd=3), read 1234 bytes, closed cleanly.
Failed File Access
openat(AT_FDCWD, "/missing/file", O_RDONLY) = -ENOENT
Interpretation: Tried to open file, but it doesn't exist.
Memory Allocation
brk(NULL) = 0x55e8f1a00000
brk(0x55e8f1a21000) = 0x55e8f1a21000
Interpretation: Check current heap end, then extend it by ~132KB.
Network Connection
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(80), ...}, 16) = 0
sendto(3, "GET / HTTP/1.1\r\n", 16, 0, NULL, 0) = 16
recvfrom(3, "HTTP/1.1 200 OK\r\n...", 4096, 0, NULL, NULL) = 512
close(3) = 0
Interpretation: Created TCP socket, connected to port 80, sent HTTP request, received response, closed connection.
Tips for Reading Output
- Start from the top: Syscalls are sequential - read chronologically
- Look for patterns: Repeated sequences often indicate loops
- Check return values: Negative values are errors
- Note file descriptors: Track which FDs are open/closed
- Use filtering: Too much output? Filter to what matters
- Enable source correlation:
--sourcehelps understand "why"
Next Steps
- Filtering Syscalls - Focus on specific syscalls
- Statistics Mode - Aggregate analysis
- DWARF Source Correlation - Map to source code
- Examples - Real-world usage patterns