This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Crash Feature to print dwarf debugging information


Hi
    I am working on a feature to provide crash tool an ability to print 
function arguments. Currently the best way, architecture independent and 
scalable, to implement the feature is through dwarf routines. I am 
facing some challenges with the implementation and need your advice and 
guidance to take it further from here.

I am facing challenges primarily in these 3 areas:
1. Design of the application:
    Since I was not able to find a good documentation I was not able to 
validate the code design. If some one can review and provide me guidance 
it will help me immensely.
     Challenges are
     a. Efficient way of accessing the function/subprogram DIE (Debug 
Information Entry) in an executable that contains multiple Complier 
Units (CU)
     b. Is the sequence of dwarf API calls appropriate
     c. Scalability of the application, especially architecture dependency
I am attaching the code that I have developed please review it and let 
me know if the design is appropriate. The code is not formatted but has 
been written purely for understanding purpose.

2. Converting the address mentioned in DW_AT_location to actual address 
of the local variable/arguments. System tap function 
literal_stmt_for_local() has an implementation for this, I am going 
thorough this some help in this direction will help me immensly.

3. Converting the address generated from DW_AT_location to actual 
address in vmcore dump. I am assuming the address we get from the dwarf 
tag will be a virtual address and that needs to be mapped to a location 
at vmocre file. crash tool has a routine readmem(), I am currently 
looking into it for probable solution.

Please let me know your thoughts and ideas on these and in general about 
the implementation

Thanks
Yeehaw



#include <stdio.h>
#include <libelf.h>
#include <elf.h>
#include <libdwarf.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dwarf.h>
#include <string.h>

int process_one_file(Elf *, char *, int);
int print_debug_info(Dwarf_Debug);

int main(int argc, char *argv[])
{
	Elf_Cmd cmd;
	Elf *arf, *elf_header;
	int fd;

	  (void) elf_version(EV_NONE);
	    if (elf_version(EV_CURRENT) == EV_NONE) {
		(void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n");
		exit(1);
	    }
	
	if(argc != 2){
		(void)fprintf(stderr, "not enough arguments being passed\n");
		exit(1);
	}
	cmd = ELF_C_READ;	
	fd = open(argv[1], O_RDONLY);
	arf = elf_begin(fd,  cmd, (Elf *) 0);
	/*elf_kind(arf) == FILE_TYPE (example:   ELF_K_AR)i*/

	while((elf_header = elf_begin(fd, cmd, arf))!= 0){  //Looping is required in case if it is archive
		Elf32_Ehdr *eh32;
		eh32 = elf32_getehdr(elf_header);
		if (eh32) 
			if (process_one_file(elf_header, argv[1], 0 /*config_file_data*/))
			/* Currently implemented only for i386 */
				(void)fprintf(stdout, "Test Success\n");
			else
				(void)fprintf(stderr, "Test Fails \n");
		else
			(void)fprintf(stderr, "Only for 32 bit header\n");
	cmd = elf_next(elf_header);
	elf_end(elf_header); //If it is archive: Not required here
	}
}


int process_one_file(Elf *elf_header, char *filename, int config_file)
{
	Dwarf_Debug dbg_header;
	Dwarf_Error error;
	int rdbg;
	rdbg = dwarf_elf_init(elf_header, DW_DLC_READ,NULL,NULL, \
				&dbg_header, &error);
	if ( rdbg == DW_DLV_NO_ENTRY){
		fprintf(stdout, "No DWARF debug information present");
		return 0;
	}
	if ( rdbg != DW_DLV_OK){
		fprintf(stdout, "No DWARF debug information not proper");
		return 0;
	}
	else {	
		fprintf(stdout, "DWARF debug information present\n");
		return print_debug_info(dbg_header);	
//		return 1;
	}
}

int print_debug_info(Dwarf_Debug dbg_header)
{
	Dwarf_Unsigned cu_header_length = 0;
	Dwarf_Unsigned abbrev_offset = 0;
	Dwarf_Half version_stamp = 0;
	Dwarf_Half address_size =0;
	Dwarf_Die cu_die =0;
	Dwarf_Unsigned next_cu_offset =0;
	int nres = DW_DLV_OK;

	/* Access different compiler Units by advancing the Dwarf_Debug header */
	while ((nres = dwarf_next_cu_header(dbg_header, &cu_header_length, &version_stamp,
		&abbrev_offset, &address_size, &next_cu_offset, NULL))
		!= DW_DLV_NO_ENTRY) {                                  
        		
			/* Read the compiler unit */
			if ((dwarf_siblingof(dbg_header,NULL,&cu_die,NULL))!=DW_DLV_OK){
				fprintf(stderr, "dwarf_siblingof fails\n");
				return 0;	
			}			
			Dwarf_Signed cnt;
			char **srcfiles;
		      	
			/* In each of the cu it tries to read DIE with specific function name */	
			print_die_and_children(dbg_header,cu_die,srcfiles,cnt);
			int index;
			for(index =0; index < cnt; index++)
				dwarf_dealloc(dbg_header, srcfiles[index], DW_DLA_STRING);
			dwarf_dealloc(dbg_header, srcfiles, DW_DLA_LIST);
			dwarf_dealloc(dbg_header,cu_die,DW_DLA_DIE);
	}
}

int print_die_and_children(Dwarf_Debug dbg, Dwarf_Die cu_die, char **srcfiles, Dwarf_Signed cnt)
{
	Dwarf_Die scope;
	Dwarf_Die child;
	Dwarf_Half tag;
	int found = 0;
	char **name;
	name = malloc(sizeof(unsigned int));
	name[0]= malloc(255 * sizeof(unsigned int));
	
	/* Access the first the child DIE of each CU */
	if(dwarf_child(cu_die,&child,NULL) == 0){
	        do
	        {
			/* Read dwarf type of each chile DIE */
			if ( dwarf_tag(child,&tag,NULL) != DW_DLV_OK){
			  	fprintf(stderr, "\n dwarf_tag failed");
			   	exit(0);
			}
        	        switch (tag)
       	        	{
               	        	case DW_TAG_subprogram: 
	       	                	if(dwarf_diename(child, name, NULL) == DW_DLV_OK){ //Function Name
					 printf("\n Die Name:%s \n", name[0]);
					 if(strcmp(name[0], "main") == 0)
						found = 1;			
					}
				     break;
       	        	}
	        } while(dwarf_siblingof(dbg,child,&child,NULL) != DW_DLV_NO_ENTRY);
		/* Find different Siblings of the Child DIE */		
	
		if (found)
			fprintf(stdout, "DWARF die found\n");
		else
			fprintf(stdout, "DWARF die not found\n");
		
		/* We have identified the Function DIE and now we need to access
 		* local vairables and function arguments */
       		        /*literal_stmt_for_local(scope_die)*/
       } 
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]