Gdb debugging coredump (principle)

In the previous blog, we introduced some commonly used commands and positioning methods when gdb debugs coredump through 3 examples. In this content, we will try to explore the principles of gdb debugging coredump and some of the things behind them.

 

Coredump principle

  1. Introduction to coredump

In the previous blog, we also mentioned that coredump is called core dump, which is actually a memory snapshot during the process of running. When a process crashes, after the operating system receives an abnormal instruction, it will do the process before the process crashes. A memory snapshot saves this information in a file, which is a coredump file.

This file contains address information, register information, stack call information, etc. in the memory of the process.

 

The signals that can cause process coredump are:

first name

Description

ANSI C  POSIX.1

SVR4 4.3 + BSD

Default action

SIGABRT

Abort (abort)

  .       .

  .      .

Terminate w/core

SIGBUS

hardware malfunction

          .

  .      .

Terminate w/core

SIGEMT

hardware malfunction

 

  .      .

Terminate w/core

SIGFPE

Arithmetic exception

  .       .

  .      .

Terminate w/core

SEAL

Illegal hardware instruction

  .       .

  .      .

Terminate w/core

SIGIOT

hardware malfunction

 

  .      .

Terminate w/core

SIGQUIT

Terminal exit

          .

  .      .

Terminate w/core

SIGSEGV

Invalid storage access

  .       .

  .      .

Terminate w/core

SIGSYS

Invalid system call

 

  .      .

Terminate w/core

SIGTRAP

hardware malfunction

 

  .      .

Terminate w/core

SIGXCPU

CPU limit exceeded (setrlimit)

 

  .      .

Terminate w/core

SIGXFSZ

Exceed the file length limit (setrlimit)

 

  .      .

Terminate w/core

 

For example, our most common segmentfault corresponds to the above SIGSEGV, which is the signal corresponding to the kill command 11.

All the above signals correspond to the kill command.

 

 

  2. Coredump file format

1) Use the file command to view

root@ubuntu:/var/core_log# file core_DumpNewTest_1483768078_6527

core_DumpNewTest_1483768078_6527: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './DumpNewTest'

 

 

As above, through the file command, you can see that this file is a core file and which process is generated at the same time

 

  2) Try readelf to view

  Readelf -h core* You can see that the type of core file is marked as

 

 

The following is the definition of the ELF.h header file

 

 

As shown in the figure, there is a byte that identifies the ELF file type.

 

 

As above, there are mainly 4 types of files in the ELF format. The value of e_type corresponding to the Core file is 4.

 

3) View the content of the core file

readelf -a core*

 

 

 

 

Use objdump -t to view,

objdump -t core*

 

 

 

As above, through readelf and objdump, we can see that compared with other ELF format files, the core file has a lot less head node information, and there is no symbol table information and debugging information.

But it records the loading address and address offset before the program, as well as information such as stack and register.

 

The principle of gdb

 GDB consists of three parts:
 (1) User interface, in addition to the traditional CLI interface, it also supports the mi interface (used by tools such as ddd)
 (2) Symbol handling at the symbol handling layer, when gdb ./debugme, GDB will read The symbol information of the file, the following original code, the display of variables/functions/types are all performed by this part (everything you can do without live process).
 (3) Target system handling. Operations including execution control, breakpoint setting, single-step execution, stack analysis, etc. are all performed in this part.

 

 

 

BFD provides support for gdb in several ways:

identifying executable and core files

BFD will identify a variety of file types, including a.out, coff, and several variants

thereof, as well as several kinds of core files.

access to sections of files

BFD parses the file headers to determine the names, virtual addresses, sizes,

and file locations of all the various named sections in files (such as the text

section or the data section). gdb simply calls BFD to read or write section x

at byte offset y for length z.

specialized core file support

BFD provides routines to determine the failing command name stored in a core

file, the signal with which the program failed, and whether a core file matches

(i.e. could be a core dump of) a particular executable file.

locating the symbol information

gdb uses an internal interface of BFD to determine where to find the symbol

information in an executable file or symbol-file. gdb itself handles the reading of symbols, since BFD does not “understand” debug symbols, but gdb uses

BFD’s cached information to find the symbols, string table, etc.

 

As above, in the official user manual of gdb, it is stated that gdb recognizes the core file through BFD, and at the same time determines the program crash command in the core file and the signal related to the crash through a set of existing mechanisms provided by BFD, and can determine Whether a core file matches an executable program. BFD also provides a set of interfaces for gdb to read symbol information in executable files.

 

 

 

As shown in the screenshot above, the regset_from_core_section interface provides the ability to read and parse the correct register information.

 

 

 

As above, gdb uses BFD and encapsulates and implements some interfaces by itself, which can identify and read core file information in combination with the executable file, and read the call stack, crash signals and commands from the core file. Register information and other content, and then find the matching symbol information from the executable file, so that when gdb debugs the core file, we can see the symbol corresponding to the address and the address offset instead of the hexadecimal number.

 

Gdb's dependence on BFD

According to the GDB official user manual above, gdb reads the stack, register and other information of the core file through BFD, so from this point of view, gdb is dependent on bfd.

 

From the header file:

 

 

Judging from the header file reference, gdb refers to the BFD header file. So I think it can be understood that GDB needs to rely on the BFD library.

 

But through ldd, but no dependencies are seen

 

 

As shown in the screenshot above, objudmp depends on bfd, but gdb cannot see the dependency of bfd. What's going on?

 

At the beginning, I thought it might be that gdb is indirectly dependent on bfd. I checked all the libraries that gdb depends on by ldd, but none of them depend on bfd, and even indirect dependencies should be seen through ldd. This problem has been troubled for a long time. Finally, I took a look at the source directory structure of gdb and found that there is actually BFD in the gdb source code, which means that gdb directly includes bfd.

 

 

 

As shown above, there is a separate BFD directory in the gdb source code, which contains the complete implementation of BFD. Therefore, gdb does not depend on the bfd library in the system, but it directly contains the complete implementation of bfd.

 

 

The following figure is the overall structure of gdb:

 

Guess you like

Origin blog.csdn.net/sunlin972913894/article/details/113001810