Filtering Syscalls
System call tracing generates a lot of output. A simple ls command can make hundreds of syscalls. Filtering lets you focus on what matters by showing only relevant syscalls.
Why Filter?
Without filtering:
$ renacer -- cat /etc/hostname
# ... 200+ lines of output ...
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {...}) = 0
mmap(NULL, 163352, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9a2c000000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0...", 832) = 832
# ... many more library loading syscalls ...
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "myserver\n", 131072) = 9
write(1, "myserver\n", 9) = 9
close(3) = 0
exit_group(0) = ?
With filtering (file operations only):
$ renacer -e 'trace=file' -- cat /etc/hostname
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "myserver\n", 131072) = 9
write(1, "myserver\n", 9) = 9
close(3) = 0
Result: 200+ lines reduced to 4 essential lines.
Basic Filtering Syntax
Use the -e flag with a filtering expression:
renacer -e 'trace=<filter>' -- command
The trace= specifies which syscalls to show.
Syscall Classes
Renacer provides predefined classes for common syscall groups:
Available Classes
| Class | Description | Example Syscalls |
|---|---|---|
file | File operations | open, openat, read, write, close, stat |
network | Network operations | socket, connect, send, recv, bind, listen |
process | Process management | fork, clone, execve, wait4, exit |
memory | Memory operations | mmap, munmap, brk, mprotect |
signal | Signal handling | kill, signal, sigaction, sigreturn |
ipc | Inter-process communication | pipe, shmget, msgget, semget |
desc | File descriptor operations | dup, fcntl, ioctl, select, poll |
Class Examples
File Operations Only
renacer -e 'trace=file' -- ls
Shows:
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, [...], 32768) = 1024
write(1, "file1.txt\nfile2.txt\n", 20) = 20
close(3) = 0
Network Operations Only
renacer -e 'trace=network' -- curl https://example.com
Shows:
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(443), ...}, 16) = 0
sendto(3, "\x16\x03\x01...", 517, MSG_NOSIGNAL, NULL, 0) = 517
recvfrom(3, "\x16\x03\x03...", 16384, 0, NULL, NULL) = 1234
close(3) = 0
Process Operations Only
renacer -e 'trace=process' -- sh -c 'echo hello'
Shows:
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD) = 12345
wait4(12345, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 12345
exit_group(0) = ?
Memory Operations Only
renacer -e 'trace=memory' -- python3 -c 'print("hi")'
Shows:
brk(NULL) = 0x55e8f1a00000
brk(0x55e8f1a21000) = 0x55e8f1a21000
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9a2c000000
munmap(0x7f9a2c000000, 262144) = 0
Literal Syscall Names
You can specify exact syscall names instead of classes:
Single Syscall
renacer -e 'trace=openat' -- ls
Shows only openat calls:
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
Multiple Syscalls
Use commas to separate multiple syscalls:
renacer -e 'trace=read,write' -- cat file.txt
Shows only read and write calls:
read(3, "file contents here\n", 131072) = 19
write(1, "file contents here\n", 19) = 19
Combining Filters
Class + Literal
renacer -e 'trace=file,socket' -- curl https://example.com
This shows:
- All file operations (via
fileclass) - Only
socketsyscalls (literal)
Multiple Classes
renacer -e 'trace=file,network' -- wget https://example.com/file.zip
This shows all file and network operations.
Negation (Excluding Syscalls)
Use ! to exclude specific syscalls from a broader filter.
Exclude Specific Syscall
renacer -e 'trace=file,!/fstat/' -- ls
Meaning: Show all file operations EXCEPT fstat.
Example Output:
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
# fstat calls are hidden
getdents64(3, [...], 32768) = 1024
write(1, "file.txt\n", 9) = 9
close(3) = 0
Multiple Exclusions
renacer -e 'trace=file,!/fstat/,!/close/' -- cat file
Meaning: Show file operations, but exclude fstat and close.
Exclude Class
renacer -e 'trace=!memory' -- command
Meaning: Show ALL syscalls EXCEPT memory operations.
Regex Patterns (Advanced)
Renacer supports regex patterns for powerful matching (Sprint 16 feature).
Regex Syntax
Enclose patterns in slashes: /pattern/
Prefix Matching
renacer -e 'trace=/^open.*/' -- ls
Meaning: Match syscalls starting with "open" (e.g., open, openat).
Shows:
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
Suffix Matching
renacer -e 'trace=/.*at$/' -- command
Meaning: Match syscalls ending with "at" (e.g., openat, fstatat, renameat).
OR Patterns
renacer -e 'trace=/read|write/' -- cat file
Meaning: Match syscalls containing "read" OR "write".
Shows:
read(3, "contents...", 131072) = 42
write(1, "contents...", 42) = 42
Case-Insensitive
renacer -e 'trace=/(?i)OPEN/' -- ls
Meaning: Match "open", "OPEN", "Open", etc. (case-insensitive).
Regex + Negation
renacer -e 'trace=/^open.*/,!/openat/' -- ls
Meaning: Match syscalls starting with "open", but exclude openat specifically.
Result: Shows open but not openat.
Combining Everything
You can mix classes, literals, regex, and negation:
renacer -e 'trace=file,/^recv.*/,!/fstat/,!memory' -- curl https://api.example.com
Breakdown:
file- Include all file operations/^recv.*/- Include syscalls starting with "recv"!/fstat/- Excludefstat!memory- Exclude memory class
Real-World Examples
Example 1: Debug File Access Issues
Problem: Your app can't find a config file.
renacer -e 'trace=openat' -- ./myapp
Look for:
- Paths being attempted
- Return values (
-ENOENT= file not found)
Example 2: Network Debugging
Problem: App can't connect to database.
renacer -e 'trace=network' -- ./db-client
Look for:
connectsyscalls with IP addresses- Return values (
-ECONNREFUSED,-ETIMEDOUT)
Example 3: Performance Analysis
Problem: App is slow during startup.
renacer -e 'trace=file' -c -- ./slow-app
Look for:
- High
Total Timefor specific file operations - Many
openatcalls (possible excessive file access)
Example 4: Security Audit
Problem: Verify sandboxed app doesn't access sensitive files.
renacer -e 'trace=file' -- ./untrusted-binary
Check for:
- Unexpected file paths (
/etc/shadow,~/.ssh/) - Permission errors (
-EACCES)
Example 5: Reduce Noise
Problem: Too many fstat and close calls in output.
renacer -e 'trace=file,!/fstat/,!/close/' -- command
Result: Cleaner output showing only meaningful file operations.
Performance Tips
Filter Early
# Fast: Filter at trace time
renacer -e 'trace=file' -- command
# Slow: Trace everything, filter later
renacer -- command | grep "openat"
Why: Filtering during tracing reduces overhead by not processing irrelevant syscalls.
Use Specific Filters
# Better: Specific
renacer -e 'trace=openat,read,write' -- command
# Worse: Broad
renacer -e 'trace=file' -- command
Why: Narrower filters process fewer syscalls, reducing overhead.
Combine with Statistics
renacer -e 'trace=file' -c -- command
Why: Statistics mode (-c) with filtering gives focused performance data without per-syscall output noise.
Common Pitfalls
Mistake 1: Forgetting Quotes
# Wrong (shell interprets '!' as history expansion)
renacer -e trace=file,!fstat -- ls
# Correct (quotes protect from shell interpretation)
renacer -e 'trace=file,!/fstat/' -- ls
Mistake 2: Incorrect Regex Syntax
# Wrong (missing slashes)
renacer -e 'trace=^open.*' -- ls
# Correct (regex must be in /.../)
renacer -e 'trace=/^open.*/' -- ls
Mistake 3: Over-Filtering
# Too restrictive (might miss relevant syscalls)
renacer -e 'trace=openat' -- complex-app
# Better (broader class)
renacer -e 'trace=file' -- complex-app
Tip: Start broad, then narrow down as you identify what's relevant.
Filter Expression Reference
Syntax
trace=<filter1>,<filter2>,<filter3>,...
Filter Types
| Type | Syntax | Example |
|---|---|---|
| Syscall class | class_name | file, network, process |
| Literal syscall | syscall_name | openat, read, write |
| Regex pattern | /regex/ | /^open.*/, /read|write/ |
| Negation | !/pattern/ or !class | !/fstat/, !memory |
Combining Rules
- Comma (
,) means OR:trace=file,network= file OR network syscalls - Negation (
!) excludes:trace=file,!/fstat/= file syscalls except fstat - Order matters: Negations apply to everything before them
Advanced Filtering Topics
For more detailed coverage, see:
- Syscall Classes - Complete list of all syscall classes and their members
- Negation Patterns - Advanced exclusion strategies
- Regex Patterns - Comprehensive regex filtering guide
Summary
Filtering makes syscall tracing practical:
- Classes - Predefined groups (file, network, process, memory, signal, ipc, desc)
- Literals - Exact syscall names (openat, read, write)
- Regex - Pattern matching (
/^open.*/,/read|write/) - Negation - Exclusion (
!/fstat/,!memory) - Combining - Mix all types with commas
Best Practices:
- Start with classes, narrow to literals
- Use negation to reduce noise
- Filter at trace time, not post-processing
- Combine with
-cfor focused statistics - Quote your filter expressions
Next Steps:
- DWARF Source Correlation - Map syscalls to source code
- Statistics Mode - Aggregate analysis with
-c - Output Formats - Export to JSON/CSV/HTML