Most of the time, we are studying how to read the source code. But in some cases, for example, if the source code is not open or the source code is very expensive, we have to understand the program behavior. In this case, it is very important to read binary files. Suppose there is a binary executable file, and we have the source code, but to understand its implementation, only a few common tools are listed here. There are two reading methods: static reading and dynamic reading.
Static reading
First, the file command can view the general information of the executable file. For example, the format, architecture, debugging information, and so on. These determine the version of the tool to be used for further viewing. For example, an executable file of the arm system can be used by tools in the arm toolchain, such as arm-Eabi-objdump and arm-Eabi-GDB.
As we all know, GNU binutils provides a series of tools for parsing and operating binary files, such as objdump. One of its main functions is disassembly:
Objdump-D libxxx. So
Other common options include:
-X print all header information
-S: print the content of all segments
-S: print the Disassembly and source code together.
-R: print the relocation table
-R print dynamic relocation table
-D print all segments, that is, not only the segments
-T print the symbol table, which is similar to the NM function, but in a different format
-T: only the symbolic table items with dynamic links are printed.
And so on.
The readelf command is used to view the meta information (such as segment information) of the ELF File ). For example, to view the header information of an executable file:
Readelf-H libxxx. So
Other common options include:
-S print symbol table
-R: print the relocation table
-L print the loading attributes
-S: print the field table
And so on.
In addition to the two most used tools, other auxiliary tools are sometimes necessary:
NM print symbol table
C ++ filt unmangle the C ++ symbol
Strip deletes debugging information
Strings: View strings in the file
LDD: View dependency
And so on.
Dynamic reading
To understand program behavior, the most reliable thing is to see how binary files run. In many cases, due to the complex running environment, especially multithreading, dynamic reading can discover many things that cannot be found in static reading.
First, the/proc/PID (PID is the process number) records a lot of information after the binary file is run, for example, you can use/proc/Pid/maps to know which libraries the program is linked to and where it is loaded (in this way, you know the error address, in theory, we can find the corresponding disassembly code of the corresponding library .), /Proc/Pid/MEM is the memory image used by the process, And/proc/Pid/STAT records the interrupt statistics. /Proc/Pid/cmdline records the command line for starting the program.
Secondly, you can use trace (strace, lstrace) to check which systems are called by the program. Strace is used to track system calls, And ltrace is used to track dynamic library calls.
For example, for some anonymous memory mappings seen in/proc/Pid/maps, you want to see when or where they are created:
Strace-F-P 3742-e trace = mmap2, open, mprotect | tee TMP. Trace
3742 indicates the process ID. Here, only the functions related to memory ing are filtered out.
Finally, the command-level dynamic reading artifacts are GDB.
View register information available in GDB:
(GDB) I r
The disassembly code is available during debugging.
(GDB) disass ADDR
Or
(GDB) x/10i ADDR
Then we can combine it with the disassembly compiled by objdump. Information such as got tables is meaningless during static reading and can only be viewed at this time.
Various break points allow us to quickly locate our concerns:
Watch point stops the program when the specified data is accessed.
The break point stops when the specified code is executed. In many cases, the database does not contain symbol, so you must directly set it to break * ADDR on the address.
The catch point program stops when a specified event occurs, such as process creation, dynamic link library loading, and exceptions.
Conditional breakpoint is sometimes useful: Break... If <condition>, but it is not a general slowness once it is set...
The BT and info frame commands in GDB are commonly used to view the relationship between stack information and function calls. But sometimes it is written down because of a bug stack, but if it is not written badly, you can often find some clues to view the stack content:
(GDB) x/40x $ sp
This command is used to view the memory content of 40 bytes that $ SP points to the region. This command can also be used to view the memory content of any specified address.
Common functions of GDB: http://wiki.ubuntu.org.cn/%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F
Some other GDB notes: http://blog.csdn.net/ariesjzj/article/details/6913671
Related information
Http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html
Http://bbs.chinaunix.net/thread-1972423-1-1.html
Elfutils-0.148: http://www.linux.it /~ Rubini/docs/binfmt/binfmt.html
GNU binutils & libbfd: http://www.gnu.org/software/binutils/