Low Orbit Flux Logo 2 F

Linux System Calls, strace, ltrace, gdb

System calls provide an interface between user space and the kernel. They allow programs to access hardware and system resources safely without directly interacting with the kernel.

Process Management



fork()     # Creates a child process by duplicating the calling (parent) process.
execve()   # Replaces the current process image with a new process image.
wait()     # Makes the parent process wait until one of its child processes finishes (terminates).

File Operations



open()    # Opens a file or device and returns a file descriptor.
read()    # Reads data from a file descriptor into a buffer.
write()   # Writes data from a buffer to a file descriptor.
close()   # Closes a file descriptor.

Memory Management



mmap()     # Maps files or devices into memory, creating a memory region.
brk()      # Increases or decreases the data segment size (heap) of a process.
munmap()   # Unmaps a region of memory previously mapped with mmap()

Networking



socket()   # Creates a new socket (endpoint for communication).
connect()  # Initiates a connection on a socket to a specified address.
send()     # Sends data over a socket
recv()     # Receives data from a socket.

Permissions & Users



getuid()   # Retrieves the user ID (UID) of the calling process.
setuid()   # Sets the user ID (UID) of the calling process.
chmod()    # Changes the file permissions.
chown()    # Changes the ownership of a file or directory.

System Control



ioctl()     # Performs device-specific input/output operations.
sysinfo()   # Retrieves system information.
uname()     # Retrieves system information.

open() Opens a file or device and returns a file descriptor.
read() Reads data from a file descriptor into a buffer.
write() Writes data from a buffer to a file descriptor.
close() Closes an open file descriptor.
lseek() Moves the file offset (seek position) of a file descriptor.
stat() / fstat() Retrieves metadata about a file (size, permissions, timestamps).
mmap() Maps a file or device into memory (used for memory-mapped I/O).
munmap() Unmaps a memory region mapped with mmap().
fork() Creates a new child process (copy of the current process).
execve() Replaces the current process with a new program.
waitpid() Waits for a child process to finish and collects its exit status.
exit() Terminates a process and returns an exit code.
kill() Sends a signal to a process (e.g., terminate or stop it).
getpid() Returns the process ID (PID) of the calling process.
getppid() Returns the parent process ID (PPID).
brk() / sbrk() Adjusts the program’s heap memory size (used for dynamic memory allocation).
ioctl() Sends control commands to a device (e.g., network interfaces, disks).
fcntl() Modifies properties of an open file descriptor (e.g., set locks, make non-blocking).
select() Waits for multiple file descriptors to be ready for I/O operations.
poll() Similar to select(), monitors multiple file descriptors for events.
epoll() Efficient I/O event notification mechanism (Linux-specific, better than poll()).
socket() Creates a network socket for communication.
connect() Establishes a connection to a remote socket (used in TCP/IP networking).
bind() Binds a socket to an IP address and port (for servers).
listen() Marks a socket as ready to accept connections (used for TCP servers).
accept() Accepts an incoming connection on a listening socket.
send() / recv() Sends or receives data over a network socket.
sendto() / recvfrom() Sends or receives data over a socket with a specific destination address.
getsockopt() / setsockopt() Gets or sets options on a socket (e.g., timeout settings).
shmget() Allocates a shared memory segment.
shmat() Attaches a shared memory segment to the process’s address space.
shmdt() Detaches a shared memory segment.
semget() Creates or accesses a semaphore set (used for process synchronization).
semop() Performs operations on semaphores.
pipe() Creates a unidirectional communication channel between processes.
dup() / dup2() Duplicates a file descriptor.
chdir() Changes the current working directory.
mkdir() Creates a new directory.
rmdir() Removes an empty directory.
unlink() Deletes a file.
chmod() Changes file permissions.
chown() Changes file ownership (user and group).
gettimeofday() Retrieves the current system time.
time() Returns the current time in seconds since the Unix Epoch (Jan 1, 1970).
clock_gettime() Gets precise system time with nanosecond resolution.
nanosleep() Puts the process to sleep for a specified duration.
sched_yield() Gives up the CPU to another process (used in cooperative multitasking).
clone() Creates a new process or thread (lower-level than fork()).
sysinfo() Retrieves system information (total RAM, uptime, load average).
uname() Gets system name, version, and architecture details.
mount() / umount() Mounts or unmounts a filesystem.
reboot() Reboots or shuts down the system.

Example codde to use a system call in C:



#include <unistd.h>

int main() {
    write(1, "Hello, World!\n", 14); // FD 1 = stdout
    return 0;
}

Tools:

strace Command trace system calls made by a process
ptrace API Controlling and debugging processes at a low level - Low-level debugging and security research (used by strace, gdb, ltrace).
ltrace Command Tracing library function calls (e.g., printf(), malloc()) - Debugging dynamic library issues.
ftrace Kernel Feature - Tracing function calls inside the Linux kernel - Kernel debugging, performance analysis, and understanding kernel behavior.
pstack Command Printing the stack trace of a running process. Analyzing stuck processes and debugging crashes.
truss Command (Solaris) Tracing system calls (like strace) but mostly on Solaris/BSD.
gdb Command Full debugging of a program (breakpoints, memory inspection, register modification).

strace

strace ls # run and trace a command strace -p 5572 # attach to running process strace -o output.txt ls # output file strace -c ls # count system calls, total for each call

ltrace

sudo apt install ltrace

ltrace ls ltrace -p 5572 -e malloc ltrace -p 5572 -e read

ftrace

echo function > /sys/kernel/debug/tracing/current_tracer # enable function tracing echo 1 > /sys/kernel/debug/tracing/tracing_on # start tracing cat /sys/kernel/debug/tracing/trace # view trace logs echo 0 > /sys/kernel/debug/tracing/tracing_on # stop tracing

pstack

sudo apt install pstack sudo pstack 5572

GDB

Compile with debugging info so gdb can show source lines and other info:



gcc -g test.c

Use GDB:



gdb ./a.out                     # run process
gdb --args ./a.out arg1 arg2    # run process with args
gdb -p 5572                     # attach to process


detach                    # detach from process
quit                      # exit the debugger
q                         # also quits

info functions       # list of all functions with address and names
info functions main  # functions with "main" in name
list                 # source code around current program counter
list function_name   # show code for a function
info symbol <address> # symbol or address info, eg check which function at address

run                       # start process
break main                # breakpoint at this function
break myfile.c:42         # breakpoint at this line
delete 1                # delete breakpoint
info breakpoints        # list breakpoints

step         # execute next line, step into a function
next         # execute next line, step over a function
             # ( function runs but you are placed at next line after function )

continue     # continue until next breakpoint
finish       # finish current function and return

backtrace    # view the call stack
bt           # view the call stack
frame        # info about current stack frame
frame 0      # switch to this frame
up           # move up one frame
down         # move down one frame

print myVar       # print variable's value
print *ptr        # print pointer's dereferenced value
info locals       # list local variables
info registers    # view registers

x/10xw 0x7fffffffde30   # show mem at this address ( 10 words in hex )

ulimit -c unlimited       # enable core dumps
gdb ./a.out core          # load coredump into gdb
backtrace                 # find where it crashed, show which function caused the crash


Check symbols in file:



nm <program> | grep ' T '   #  lists all text (function) symbols in the program.