There are a couple of tools that allow us to look into program behavior at a more closer level. Lets look at some of these:
These programs trace system calls a program makes as it makes them.
Useful options:
-f (follow fork)
-ffo filename (output trace to filename.pid for forking)
-i (Print instruction pointer for each system call)
This utility is extremely useful. It traces ALL library calls made by a program.
Useful options:
-S (display syscalls too)
-f (follow fork)
-o filename (output trace to filename)
-C (demangle C++ function call names)
-n 2 (indent each nested call 2 spaces)
-i (prints instruction pointer of caller)
-p pid (attaches to specified pid)
This is an environment variable that allows us to add a library to the execution of a particular program. Any functions in this library automatically override standard library functions. Sorry, you can't use this with suid programs.
Example:
% gcc -o preload.so -shared preload.c -ldl
% LD_PRELOAD=preload.so ssh students.uiuc.edu
gdb is the GNU debugger. It is very intimidating to most people, but there really is no reason for it to be. It is very well done for a command line debugger. There is a nice GUI front end to it known as DDD, but our purposes will require a closer relationship with the command line.
gdb has a nice built-in help system organized by topic. typing help will show you the catagories. The main commands we will be interested in are run, break, cont, stepi, finish, disassemble, bt, info [registers/frame], and x. Every command in gdb can be followed by a number N, which means repeat N times. For example, stepi 1000 will step over 1000 assembly instructions.
-> Example using gdb to set breakpoints in functions with and without debugging symbols.