* gdb foo core GDB: Gnu Debugger. Can be used to symbolically debug a program: set breakpoints, single step through instructions. Very useful for debugging complex programs. Cmd is "gdb" Arg1 is "foo" -- name of program binary that you want to debug. But you need to have compiled the binary with a special flag (-g) that tells the compiler to include in the binary all sorts oof symbols that help debugging (in fact, even many parts of the code, may be included in the binary). Arg2 [optional], is the name of a "core" file that the OS dumped, which matches the binary "foo". That way you can load a program and its core file into gdb, and inspect exactly where the core was dumped (i.e., some failure that causes the OS to terminate your process). What's a core file? When an OS detects that a program did something "bad", the OS will terminate that program/process. The OS may save ("dump") a memory image of the running process in a file called "core". The image contains the executable and its state in memory: heap, stack, variables, CPU states and registers, etc. The OS has many reasons to abort programs: dividing by 0, accessing a device or memory region that you don't have permission to (aka "segmentation violation" or "bus error"), any sort of bad pointer manipulation, etc. By including debugging symbols, the binary becomes larger, meaning it takes up more memory, slows system down. There's a program called "strip" that's used to remove debugging symbols from a binary, as if you compiled the binary w/o -g. Indeed if you distribute binaries to users with debugging symbols, hackers could see much of your code, maybe even find bugs that can be exploited. Today, companies don't release binaries with debug symbols to customers. Instead, companies might build different versions of the same program: one with debugging statements and another w/o any debugging. Debug statements are generally all sorts of printf's that can be enabled or disabled as needed, they may be recorded to a log file, showing the activity of a program at different stages of the program, useful for programmers to trace the program's activity over time. Best to load a program + core file on the same architecture, OS and OS version, and of course the same program binary version. Symbolic debugging changes the timing of a program: you're single stepping or have breakpoints in the program. Some programs would be more difficult to debug with symbolic debuggers: any program that has built in timeouts (e.g., wait N seconds before resending a message), all sorts of network and distributed programs, any time you suspect a race condition bug, etc. Races can be difficult to debug even w/o a symbolic debugger: just adding printf's can slow a program down, and hence mask a bug or make a bug more likely to occur. These behaviors are often called a "Heisenbug". * gcc -W main.c -o bar -lwrap gcc: GNU C Compiler - many vendors have their own compilers - llvm is another that grows in popularity -W: enable (some) warnings There are many flags for gcc to enable various sorts of warnings. e.g., do more processing at compile time, looking for more possible bugs. variable may be used uninitialized return type doesn't match exactly what you're assigning it to -Wall: enable "all" warnings, meaning many more, but not truly all Look at gcc man page or docs for full list of warnings. Generally, it's a good idea to enable as many compile-time checks as you can. It's common to enable also -Werror, which turns all warnings into errors (i.e., compiler returns a failure code, and won't produce an object file). main.c: name of C file to compile -o bar: write the output executable into a file named "bar" instead of the default "a.out". -lwarp: look for a libary called libwrap.so or libwrap.a in any standard library paths (e.g., /lib, /usr/lib, etc.), or as listed in your $LIBPATH variable, or in other GCC flags (e.g., -L). * stat(2) syscall? In UNIX, there'a a convention of stating the section of the documentation (or manual pages) after the name of the program or library that you want to looup. "(2)" after "stat" means "the stat system call in section 2 of the man(ual) pages". # get info on stat system call $ man 2 stat # get info on stat user command $ man 1 stat $ man stat stat(2) gives you info about a file: permissions, ownership, size, timestamps, etc. It also tells you that a file exists. If you get back an error from stat(2), and the error is "ENOENT" -- it means the file does not exist. If you get an error code ("errno" in libc) of EPERM or EACCES, it means the file exists but you don't have permission to access it. You can find docs on UNIX using the cmd line program "man". Common sections of the manual pages are; 1: user programs avaiable to all 2: system calls (inside the kernel) 3: library functions (in libc or other libraries) 5: configuration files 8: sysadmin programs that often require sudo/superuser/root privileges (e.g., to format a disk or change the host's IP address). * mmap(2) syscall? Memory mapping system call: allows you to take an existing file and "map" it into your virtual address space, so the file looks like a big memory region. Often used for more efficient access to files than regular read(2) and write(2) system calls. Also allows you to create shared and anonymous memory regions (not mapped to a specific file).