Friday, April 23, 2010

Debugging with LINUX environment

Introduction Linux environment generally used the GNU debugger, or gdb to the shell. Gdb lets you see the internal structure of a program, print out variable values, set breakpoints and single step through source code. It makes an extremely powerful tool for fixing problems in program code. In this article , Let's discuss how to use the . The Linux development environment has several debugging alternatives. This article I also explore debugging tools available for debugging applications, ranging from simple print-statement to specialized tools (e.g. memory-debugging). Print statements Addition of printf() statements to your code is a traditional and time-honored way to debug code. Downside is that you will need to modify and recompile the code whenever you want more or less debug information. Strace utility Strace will output all the kernel calls that the application does and is a great way to find e.g. what file the program is trying to access and whether it succeeded. For instance calls to read() and write() will show how much data program tried to read/write and how much actually was transferred, it also shows the beginning of the data in question. You can use this without recompilations and it works on any program which you can run. Ltrace utility Ltrace will output all the dynamic library function calls that the application does. It can also show system calls like ’strace’. Using GDB debugger With gdb debugger you can examine all the symbols in the program and program runtime state and follow program function calls. If trace utilities and the source code don’t give you enough information to solve the problem, debugger is the next step. Gdb is a console tool, but there are some nice debugging GUIs available that work on top of gdb. One such is ddd. Gdb can help with debugging programs written in C, C++, Fortran, Java, Chill, assembly and Modula-2. You need to have compiled these programs with the gnu compiler collection (gcc) tools. Besides supporting multiple languages gdb also supports multiple hardware architectures, including several embedded hardware architectures. It’s also possible to compile a special version of GDB for debugging (Linux) kernel code. Running gdb Gdb is run from the shell with the command 'gdb' with the program name as a parameter, for example 'gdb file, or you can use the file command once inside gdb to load a program for debugging, for example 'file file. Both of these assume you execute the commands from the same directory as the program. Once loaded, the program can be started with the gdb command 'run'. Preparing for GDB use You need to compile all the C/C++ code you want to debug with debugging information included into the binary (use ’-g’ and do not use ’-fomit-frame-pointer’ option when compiling the code) and the code may not be stripped of symbols (do not use ’-s’ flag in the compilation). Note that all the libraries used by the program should also be compiled this way as missing stack frame pointer can confuse GDB. It’s better if you use static linking (e.g. use ’-static’ option in your Makefile) because that way gdb won’t have trouble finding the symbols for the libraries program uses (for example if you use different libraries with your program than what your compilation machine normally uses). Before you can get started, the program you want to debug has to be compiled with debugging information in it. This is so gdb can work out the variables, lines and functions being used. To do this, compile your program under gcc (or g++) with an extra '-g' option: gcc -g file.cpp -o file Using GDB There are two ways to use a debugger: - Using debugger to examine the code runtime behavior. You start ’gdb’ with the program binary (’gdb ’) in the program directory. Then you can either run the program inside the gdb with ’run ’ or attach to an already running instance of the program with ’attach ’. Latter is handy when you don’t have working gdb inside the debugging environment. Then you can set breakpoints, examine the code, variables, stack etc and call the program functions. - Using debugger to examine a process post-mortem ’core’ dump. You start ’gdb’ with the program binary and core dump (’gdb ’) in the program code directory. You can examine where the program crashed and what was the state of all the program variables. If your program crashes, but doesn’t produce a core file, check ’ulimit -a’ to see whether your environment allows core files and fix it with ’ulimit -c unlimited’. The downside of debugger approach is that debug versions of the binaries are large and statically linked debug ones are huge. If the target doesn’t have enough memory for this, you can use ’gdbserver’ and stripped binaries on the target. On the host on which you do the debugging, you use gdb with ’target remote’ option and give the host gdb the binary with all the debugging symbols. Short introduction to use of gdb You get back to GDB prompt when your program either: - Crashes. - Code execution reaches a breakpoint. - You suspend or otherwise send a signal to the program. On latter two cases you can use ’cont’ to continue the program execution. In the GDB prompt you can do one of the following: - Set a breakpoint with ’break ’. You can delete breakpoint by saying ’delete ’. - Examine current program execution trace with ’bt’, which will show you where the program execution was interrupted (see above), how it got there and what were the function arguments. - Move up and down in the execution stack frame by typing ’up’ or ’down’. - Examine program state with either ’info locals’ which shows you the state of variables in the current context (function) or use ’print ’ to show you a value of given variable or function. Any valid C expression can be used, even function calls! - View your program code with ’list ’ which will list code of the given function. You can ’step’ through the program code with following commands: - ’step’ will execute the current line and go to next command. If code line is a function call, step will enter the function. - ’next’ works like ’step’ but function calls are executed as single instruction. - ’finish’ will execute to the end of current scope (function). - ’cont’ will continue program execution. Typing return will repeat the previous command. Gdb can also complete function and variable names with TAB key. Gdb problems When optimization is used in code compilation, variable values shown by gdb may sometimes be valid only for variables used on the line that program executed lastly 1, not for the whole scope in where the variables are declared. Use of inlines especially in C++ code (e.g. methods with their body in the header file) may confuse gdb so that it shows either a wrong filename or line for the fault. In these cases it’s better not to optimize the code so much, use only ’-O’ optimization flag, and forbid inlining completely with the ’-fno-default-inline’ compilation flag.

No comments:

Post a Comment

Health Benefits of Cashews

  Benefits of Cashews. Healthy food is an integral part of healthy body. Regular exercises such as Yoga and healthy diet is important to...