Indicate the source and author's contact information during reprinting.
Article Source: http://www.limodev.cn/blog
Contact information of the author: Li xianjing <xianjimli at Hotmail dot com>
With the popularity of XP, people are paying more and more attention to the preliminary design, implementation in the later stage, and testing work throughout the software. After this process, it is naturally high-quality software. Some people even claim that XP will eliminate the debugger! Of course, this is true. However, from the current reality, this is still an ideal. Debugging tools are indispensable in daily work. In Linux, debugging tools are not only GDB, but also many other debugging tools. They all have their own strengths and have different focuses. This article introduces several common debugging tools:
1. mtrace
Most applications are developed in C/C ++ in Linux. Memory leaks, memory out-of-bounds, and other memory errors are undoubtedly one of the biggest headaches. Glibc provides two solutions to solve memory errors:
One is the hook memory management function. After you hook the memory management function, you can record the memory allocation history and check whether there is any memory leakage at the end of the program. In this way, you can find out where the memory is leaked. You can also write a special flag at the beginning and end of the allocated memory to check whether the flag is damaged when the memory is released. In this way, you can check for out-of-bounds memory issues.
Another method is simpler. glibc has provided the default implementation for the first solution. All you need to do is call the mtrace/muntrace functions at a specific location. Their function prototype is as follows:
# Include
Void mtrace (void );
Void muntrace (void );
You may ask, where is the best way to call these two functions? There is no fixed answer, depending on the situation. For small programs, mtrace is called when the main function is entered, and muntrace is called when the main function is exited. For large software, this may record too much information, and the analysis of these records will be slow. In this case, you can call the code at both ends of your suspect code.
In addition, you also need to set an environment variable malloc_trace, which is a file name, to ensure that the current user has the permission to create and write the file. The memory manager of glibc writes the historical information of memory allocation to the file specified by malloc_trace.
After running the program, use mtrace to analyze the memory allocation history and locate the memory error (mtrace is in glibc-utils package ).
2. strace
It is a good habit to check the return value of a function during programming. For standard C functions such as glibc, it is not enough to check the returned value of the light, but also the value of errno. Such programs are often lengthy and not concise. At the same time, it may be because of laziness that most programs do not perform such checks.
Once an error occurs in such a program, you can use the debugger to locate the error step by step, and then find out the cause of the Error. However, this is troublesome. It is not desirable for the debugger to be a little useful. In this case, the strace command may be more convenient. It displays the execution process and results of calls/signals of various systems. For example, if a file opening error occurs, you can see at a glance that the cause of the error (errno) is known.
3. binutil
Binutil is a series of tools. You may not know the existence of these tools at all, but it is hard for you to move without them. Binutil includes the following tools:
* LD-the GNU linker.
* As-the GNU extends er.
* Addr2line-converts addresses into filenames and line numbers.
* Ar-a utility for creating, modifying and extracting from archives.
* C ++ Filt-filter to demangle encoded C ++ symbols.
* GPROF-displays profiling information.
* Nlmconv-converts object code into an NLM.
* NM-lists symbols from object files.
* Objcopy-copys and translates object files.
* Objdump-displays information from object files.
* Ranlib-generates an index to the contents of an archive.
* Readelf-displays information from any ELF format object file.
* Size-lists the Section Sizes of an object or archive file.
* Strings-lists printable strings from files.
* Strip-discards symbols.
* Windres-a compiler for Windows resource files.
Some of these tools are very helpful for debugging, such:
You can use objdump disassembly to view the internal information of the target file or executable file.
You can use addr2line to convert the machine address to the corresponding location of the Code.
You can use nm to view various symbols in the target file or executable file.
You can use GPROF to analyze the usage of each function and find out the performance bottleneck (this requires compilation options ).
4. LD-Linux
Now the work of loading the elf executable file has come to the ld-linux.so.2 head. You may ask, does this have something to do with debugging programs? Yes. For example, in Linux, all non-static functions/global variables in the shared library are export. Worse, the C language does not have the concept of namespace, which leads to very easy conflict of function names. In multiple shared libraries, it is difficult to query bugs caused by name conflicts. In this case, you can set the LD _ debug environment variable to observe the process of loading executable files in the ld-linux.so, and get a lot of help information. The value of LD _ debug is as follows:
* Libs display library search paths
* Reloc display relocation Processing
* Files display progress for input file
* Symbols display symbol table Processing
* Bindings display information about symbol binding
* Versions display version Dependencies
* All all previous options combined
* Statistics display relocation statistics
* Unused determined unused DSOs
* Help display this help message and exit
5. GDB
For a true debugger, GDB is unique in Linux. It has a variety of packages, character interfaces, graphical interfaces, separate operations, and integration into the IDE. GDB is powerful, and it is easy to use GDB in the graphic interface, but its functions are undoubtedly limited. I believe most experts are willing to use the character interface. GDB is too common.
6. GCC/boundschecker
I believe many people have used boundschecker (compuware) and purify (IBM) Tools under Win32. Their functions are so powerful that they cannot be achieved through heavy-load memory management functions. They insert their own debugging code during compilation.
GCC also has an extension to implement more powerful check functions by inserting debugging code during compilation. Of course this requires recompiling GCC, you can go to the http://sourceforge.net/projects/boundschecking/ to download the gcc patch. Its portability is very good. I have used it in an ARM platform project, and the results are good.
7. valgrind
The best things are often seen at the end. Valgrind is my favorite. I get used to it. The programs I write don't run under valgrind, just like I didn't write a unit test program. It has the boundschecker/purify function and is faster.
Unfortunately, valgrind currently only supports the X86 platform, which is sufficient in most cases.
You can go to http://valgrind.org/to download the latest version.
Source: http://www.limodev.cn/blog? P = 120