How GDB recovers dynamic library information from a coredump file

Source: Internet
Author: User

[Original] reprint please indicate from CSDN _xiao.

When Linux generates the Coredump file, the program does not specifically handle the dynamic-link library file information, but GDB loads all the dynamic-link libraries correctly when loading the Coredump file, including what the principle of the so file that calls Dlopen dynamically loaded in the program's run. This process is solved by a brief overview of the GDB source code.

[For information on how to set the library search path and the priority of the path search, refer to the GDB Dynamic Library search Path note]

GdB's rough Schema: the main function in GDB.C is the entry of the program, it simply calls Gdb_main, which then calls Captured_main,captured_main is the principal function of the execution. It parses the command-line parameter options, initializes all the variables and all the files, and finally a while loop, which constantly calls Captured_command_loop to get the input command and execute the action indicated by the command. When initialized, Gdb_init invokes the Initialize_all_files function to initialize all files, which is not visible until compiled, makefile scans all source files at compile time, and all types are Initialize_file_ The functions of ftype are collected, placed in the newly generated init.c file in the GDB directory, and the Initialize_all_files function is created in this file, which calls each _initialize_xxx function in turn. In addition to initializing itself, the module invokes Add_cmd or a similar function to register the command in its own _initialize_xxx function, and then invokes the module's handler function when the user enters the registered command. For example, the corefile.c file registers the "Core-file" command in the _initialize_core function, and the handler function of the command is Core_file_command, so that the user calls Coredump when it is typed into "core core_". The File_command function is processed ("core" is the alias of the "Core-file" command). The same EXEC.C registers the "file" directive, whose processing function is File_command. In general, the command "XXX" handler function named "Xxx_command", for example, "info sharedlibrary" command processing function is Info_sharedlibrary_command, according to this rule, you can quickly find the processing function of the command.

When a coredump file is loaded, it is handled by Core_file_command, first by Find_core_target to find the target that is capable of processing the "core" file and invoking the target's open function. CORELOW.C registers the target of that type at initialization, so it enters the corelow.c core_open function. The Core_open function calls the Bfd_fopen function to open the file (Bfd_fopen recognizes the format and opens in elf format) and then calls Build_section_ Table reads all sections information (that is, segments information) into the Coredump file and calls Push_ when it is complete Target adds the target operation of the core to the target list (so that some actions, like readmemory, can be done in the address space of the Coredump file). Finally call Post_create_inferior for post processing, call Init_thread_list to read the thread information in the Pt_note information segment, call Target_fetch_registers read the register information, and restore the call frame based on the register (frame), the last call to Print_stack_frame to print the frame information (i.e., backtrace), the entire Coredump file loading is complete.

We need to focus on the Post_create_inferior function for how to recover dynamic link library information. In this function, if the file or Exec_file command has been executed before the core instruction, that is, the information of the main execution program is already in order, then Solib_add will be called to add all the so libraries.

It can be seen that the dynamic link library information is restored on the premise that it must have a binary file of the Coredump file and the original main execution program, and if there is only one, the dynamic link library information cannot be restored.

Continue to look at the Solib_add function, which mainly calls Update_solib_list to update all the so library list, in the Update_solib_list function, the key is to call the Ops->current_sos function to get the so library information list , and the Current_sos function always rebuilds the so library list based on the current information.

The

has different Current_sos implementations on different operating systems and architectures. The Svr4_current_sos function is used to reconstruct the Linux system on the arm instruction and the MIPS instruction, which is commonly employed in engineering.

The

enters the Svr4_current_sos function, first calling Locate_base to get the base address of the debug information. It calls the Elf file that Elf_locate_base parses the main execution program to get that information. Elf_locate_base calls Scan_dyntag to find dynamic information of type Dt_mips_rld_map (0x70000016) First, and then calls Scan_dyntag to find dynamic information of type Dt_debug (21) if it fails. For MIPS, compiler with dt_mips_rld_map information to store debugging information, and dt_debug information is meaningless, for other platforms such as ARM, then use dt_debug information to store debugging information, no dt_mips_rld_map information. San_dyntag read the section named ". Dynamic" and scan it one by one, and the section consists of a dynamic section structure array, each structure consisting of two integers, The first integer is the type of the dynamic (for example, Dt_debug), the second integer is the value of the dynamic, and the value is related to the type. Scan_dyntag scans, finds dynamic information of type Dt_mips_rld_map, and returns its value. This value is calculated at compile time, and in fact its value is always the address of the section named ". Rld_map". Elf_locate_base reads what the value returned by Scan_dyntag is pointing to, which is the content of the ". Rld_map" section. The ". Rld_map" section is only 4 bytes long, and its content is the base address of the debug information, pointing to the dynamic linker structs. At compile time, the value of ". Rld_map" is 0, at run time, the loader fills in its value, and the loader maintains a dynamic linker structs, and the address is placed in ". Rld_map". In Linux, loaders are usually ld.so or ld_linux.so. Locate_base assigns the value returned by Elf_locate_base to the global variable debug_base so that debug_base points to the dynamic linker structs. Since this information is available at runtime, GDB can only restore the linked list if it is loaded with both the master and Coredump files.

Svr4_current_sos calls Solib_svr4_r_map to get the link map list from dynamic linker structs, and GDB calls Svr4_fetch when it reads information due to different organization of data on different platforms. _link_map_offsets functions to get the offset address and size of each variable, and in MIPS, it will eventually parse the structure's data through the information provided by Svr4_ilp32_fetch_link_map_offsets. The R_map_offset information here is 4, so solib_svr4_r_map reads the link map list information from Debug_base + 4, so that the entire link map table's header pointer is obtained.

Then Svr4_current_sos starts traversing the link map list, where each element of the list is 20 bytes, and its approximate structure is as follows (its size and position are different on different platforms):

U32 l_addr; 4 bytes

U32 L_name; 4 bytes

U32 L_ld; 4 bytes

U32 L_next; 4 bytes

U32 L_prev; 4 bytes

GdB reads the value of the linked list in memory from the Coredump file, L_name is the address of the module name, the name of so library file can be read from the address, L_ADDR is the load address of the module, L_next is the address of the next module link information, Svr4_current_ SOS iterates through the names and information of all so library files into a linked list of struct so_list structures and returns the list.

After returning to the Update_solib_list function, this function scans the so library list returned from Current_sos, checks which so libraries have been loaded, which so libraries need to be reloaded, which loaded so libraries need to be unloaded, and then calls for every so library that needs to be loaded Solib The _map_sections maps these so libraries to the memory space of target. When the so library is loaded, Tilde_expand and Solib_open are called to extend the library file name, and if the correct sys_root path and library search path are set, the library can be found and loaded correctly.

After all the libraries are loaded into Target's memory space, the memory image of the entire process reverts to coredump, and then the variables and status information at Coredump are observed.

The process for GDB to load dynamic library information is shown in Figure 1.

Figure (1) schematic diagram of library file information loading process

A test example is used to describe the recovery process for library information.

The example program consists of two files, a main program, a dynamic so library, the main program calls a function in the dynamic so library, the function in the dynamic library operates a null pointer to generate Coredump.

Main program, build GDBSO after compiling:

int main ()
{
	int ires = 0;

	Lpfun lpfun = NULL;

	void *phandle = Dlopen ("./libddd.so", rtld_lazy);

	if (NULL = = Phandle)
	{
		printf ("Open libddd.so failed\n");
		return 1;
	}
	else
	{
		printf ("Open libddd.so success\n");
	}

	Lpfun = (lpfun) dlsym (Phandle, "Fun_dll");
	if (NULL = = Lpfun)
	{
		printf ("Dlsym failed\n");
		return 2;
	}

	Ires = Lpfun ();

	Dlclose (phandle);

	return 0;
}

The dynamic library program generates libddd.so after compiling:

int Fun_dll ()
{
	void *ptmp = NULL;
	printf ("in dll\n");

	memcpy (ptmp, 0, sizeof);

	return 1;
}

Compile the main program and the dynamic library, run the build Coredump on the MIPS platform, then use GDB to load the main program GDBSO and Coredump files, and set the correct library search path using Set Sys_root and set Solib_search_path before loading.

In GDB, using Set debug target 10, you can open debug information when the target is loaded and see how GDB loads the file.

Depending on the core loading process, GDB reads the ". Dynamic" section of the main program GDBSO, and we use the OBJDUMP–H directive to view the section information for the GDBSO, as shown in Figure 2.

Figure (2) objdump results of GDBSO

From the results of objdump, the. Dynamic section has an offset address of 0x017c in the file, and in the loaded memory the address is 0x0040017c, and the data is read-only, so the data in memory is the same as the data in the file. We view the contents of the. Dynamic section in GDB through "x/28w 0x0040017c", as shown in Figure 3.

Figure (3). Contents of dynamic section

As seen from the contents of the. Dynmaic section, the address 0X004001DC is the Dt_mips_rld_map information, the type is 0x70000016, and the value is 0X00410AC0, which is exactly. Rld_map the address of section, Consistent with the previous article.

Then use "x/w 0x00410ac0" to view the contents of the. Rld_map section, as shown in Figure 4.

Figure (4). Rld_map section Content

As you can see, the contents of the. Rld_map section are 0X2AAD7A10 (the sections are writable, the value in the file is 0x00000000, the value in memory after Coredump is loaded is 0x2aad7a10), so the dynamic The base address of linker structs is 0X2AAD7A10.

Use "x/4w 0x2aad7a10" to view the contents of the dynamic linker structs, as shown in Figure 5.

Figure (5) Some contents of dynamic linker structs

According to the previous analysis, in dynamic linker structs, the address of the link map list is where the offset address is 4. So the head pointer of the link map list in Figure 5 is 0x2aad7a28. Each element of the list is 20 bytes, using "x/8w 0x2aad7a28" to view the contents of the first linked list element, as shown in Figure 6, noting that only the first 20 bytes are valid.

Figure (6) The content of the first element of link map

As seen from Figure 6, the first list element of L_ADDR is 0x00000000,l_name for 0x2aac47e8,l_ld 0x0040017c,l_next for 0x2aac75f8,l_prev for 0x00000000. The loading address of this module is 0x00000000, which means that it is the module information of the main program GDBSO, so ignore it and look at the next list element.

Use "x/8w 0x2aac75f8" to view the contents of the second linked list element, as shown in Figure 7.

Figure (7) The content of the second element of link map

As you can see from Figure 7, the second list element has a l_addr of 0x2aad8000,l_name for 0x2aac75e8,l_ld 0x2aad818c,l_next 0x2aac7958,l_prev for 0x2aad7a28. The module's load address is 0x2aad8000 and the module name address is 0x2aac75e8. Using "x/4w 0x2aac75e8" and "x/s 0x2aac75e8" to view the contents of this address, as shown in Figure 8, you can see that the module is named "/lib/librt.so.1".

Figure (8) The name of the module for the second element of link map

Proceed as above to browse through each module in the linked list according to L_next until L_next is 0x00000000, as shown in Figure 9.

Figure (9) analysis of the subsequent elements of link map

As seen in Figure 9, the entire link map list contains "/lib/librt.so.1", "/lib/libm.so.6", "/lib/libpthread.so.0", "/lib/libc.so.6", "/lib/ Libdl.so.2 ","/lib/ld.so.1 ","./libddd.so "a total of 7 modules of information.

As seen from the last element, the dynamic library libddd.so is loaded at address 0x2ad1a000, which is the load address of the entire module, not the load address of its code snippet. We use Objdump to view the offset information for the. Text segment of libddd.so, as shown in Figure 10.

Figure (objdump result of libddd.so)

As you can see from Figure 10, libddd.so. Text is offset to 0x0590 in memory, so the module loads into the address 0x2ad1a000 after its code snippet is loaded to 0x2ad1a590.

We use "info sharedlibrary" to see the results of GDB parsing, which is consistent with our analysis, as shown in Figure 11.

Figure (one) GDB's info sharedlibrary results

Thus, the entire so library information loading process is complete.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.