Segmentation fault 调试

gdb coredump 调试
1.#设置core大小为无限
ulimit -c unlimited
2.#设置文件大小为无限
ulimit unlimited
3. ./a.out 产生core文件
4. gdb ./a.out core
5.bt 栈回溯,找到发生段错误的函数

#include 
#include 
#include 

void func(void)
{
	int * p = 0x0;
	*p = 0x12345678;
}

int main(int argc, char const *argv[])
{
	int a = 0;
	int b = a;
	int c = 0;
	scanf("%d", &c);
	if (c) {

	}
	else
		func();
	return 0;
}

步骤如下所示:

root@ubuntu:/home/share/c++_code# ./a.out 
0 
Segmentation fault (core dumped)
root@ubuntu:/home/share/c++_code# ls -l core
-rw------- 1 root root 208896 Sep 26 02:13 core
root@ubuntu:/home/share/c++_code# 
root@ubuntu:/home/share/c++_code# gdb a.out core 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...(no debugging symbols found)...done.
[New LWP 10430]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0804844d in func ()
(gdb) bt
#0  0x0804844d in func ()
#1  0x08048497 in main ()
(gdb) 

backtrace 调试 – 使用API的方式 (backtrace、backtrace_symbols)

#include 
#include 
#include 
#include 

#define SIZE 100

void backtrace_dump(void)
{
   int j, nptrs;
   void *buffer[100];
   char **strings;

   nptrs = backtrace(buffer, SIZE);
   printf("backtrace() returned %d addresses\n", nptrs);

   /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
      would produce similar output to the following: */
   strings = backtrace_symbols(buffer, nptrs);
   if (strings == NULL) {
       perror("backtrace_symbols");
       exit(EXIT_FAILURE);
   }

   for (j = 0; j < nptrs; j++)
       printf("%s\n", strings[j]);

   free(strings);
}

static void seg_handler(int signo)
{
    printf("recv signale %d\n", signo);
    backtrace_dump();
    exit(EXIT_FAILURE);
}

void func(void)
{
	int * p = 0x0;
	*p = 0x12345678;
}

int main(int argc, char const *argv[])
{
	signal(SIGSEGV, seg_handler);
	func();
	return 0;
}

步骤如下所示:
可以看到段错误发生在:func+0x10这个地方,可以知道是挂在func函数里面

root@ubuntu:/home/share/c++_code# ./a.out 
recv signale 11
backtrace() returned 7 addresses
./a.out(backtrace_dump+0x1f) [0x80487dc]
./a.out() [0x80488a5]
[0xb7746404]
./a.out(func+0x10) [0x80488c1]
./a.out(main+0x22) [0x80488eb]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0xb7598af3]
./a.out() [0x80486e1]
root@ubuntu:/home/share/c++_code# 

backtrace 调试 – 不使用API的方式 ARM平台

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 


/*
此结构体,在版本比较新的编译器中都有包含了,就不用再定义了
看实际情况而定
*/
typedef struct {
   const char *dli_fname;  /* Pathname of shared object that
                              contains address */
   void       *dli_fbase;  /* Base address at which shared
                              object is loaded */
   const char *dli_sname;  /* Name of symbol whose definition
                              overlaps addr */
   void       *dli_saddr;  /* Exact address of symbol named
                              in dli_sname */
} Dl_info;





struct ucontext_ce123 {
	unsigned long	  uc_flags;
	struct ucontext  *uc_link;
	stack_t		  uc_stack;
	struct sigcontext uc_mcontext;
	sigset_t	  uc_sigmask;	/* mask last for extensibility */
}ucontext_ce123_;

struct sigframe_ce123 {  
    struct sigcontext sc;//保存一组寄存器上下文  
    unsigned long extramask[1];  
    unsigned long retcode;//保存返回地址  
    //struct aux_sigframe aux __attribute__((aligned(8)));  
}sigframe_ce123; 

int backtrace_ce123 (void **array, int size)
{
	if (size <= 0)
		return 0;

	int *fp = 0, *next_fp = 0;
	int cnt = 0;
	int ret = 0;

	__asm__(
		"mov %0, fp\n" 
		: "=r"(fp)
	);


	array[cnt++] = (void *)(*(fp-1));

	next_fp = (int *)(*(fp-3));
	while((cnt <= size) && (next_fp != 0))
	{
		array[cnt++] = (void *)*(next_fp - 1);
		next_fp = (int *)(*(next_fp-3));
	}


	ret = ((cnt <= size)?cnt:size);
	printf("Backstrace (%d deep)\n", ret);

	return ret;
}

char ** backtrace_symbols_ce123 (void *const *array, int size)
{
# define WORD_WIDTH 8
	Dl_info info[size];
	int status[size];
	int cnt;
	size_t total = 0;
	char **result;

	/* Fill in the information we can get from `dladdr'.  */
	for (cnt = 0; cnt < size; ++cnt)
	{
		status[cnt] = dladdr (array[cnt], &info[cnt]);
		if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0')
		/* We have some info, compute the length of the string which will be
		"() [+offset].  */
		total += (strlen (info[cnt].dli_fname ?: "")
			+ (info[cnt].dli_sname ? strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3 : 1)
			+ WORD_WIDTH + 5);
		else
			total += 5 + WORD_WIDTH;
	}


	/* Allocate memory for the result.  */
	result = (char **) malloc (size * sizeof (char *) + total);
	if (result != NULL)
	{
		char *last = (char *) (result + size);

		for (cnt = 0; cnt < size; ++cnt)
		{
			result[cnt] = last;

			if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0')
			{
				char buf[20];

				if (array[cnt] >= (void *) info[cnt].dli_saddr)
					sprintf (buf, "+%#lx", \
						(unsigned long)(array[cnt] - (unsigned long)(info[cnt].dli_saddr)));
				else
					sprintf (buf, "-%#lx", \
						(unsigned long)(info[cnt].dli_saddr -(unsigned long)(array[cnt])));

				last += 1 + sprintf (last, "%s%s%s%s%s[%p]",
					info[cnt].dli_fname ?: "",
					info[cnt].dli_sname ? "(" : "",
					info[cnt].dli_sname ?: "",
					info[cnt].dli_sname ? buf : "",
					info[cnt].dli_sname ? ") " : " ",
					array[cnt]);
			}
			else
				last += 1 + sprintf (last, "[%p]", array[cnt]);
		}
		assert (last <= (char *) result + size * sizeof (char *) + total);
	}

	return result;
}

/* SIGSEGV信号的处理函数,回溯栈,打印函数的调用关系*/
void DebugBacktrace(unsigned int sn , siginfo_t  *si , void *ptr)
{
	/*int *ip = 0;
	__asm__(
		"mov %0, ip\n" 
		: "=r"(ip)
	);
	printf("sp = 0x%x\n", ip);
	struct sigframe_ce123 * sigframe = (struct sigframe_ce123 * )ip;*/

	if(NULL != ptr)
	{
		printf("\n\nunhandled page fault (%d) at: 0x%08x\n", si->si_signo,si->si_addr);

		struct ucontext_ce123 *ucontext = (struct ucontext_ce123 *)ptr;
		int pc = ucontext->uc_mcontext.arm_pc;		

		void *pc_array[1]; 
		pc_array[0] = (void *)pc;
		char **pc_name = backtrace_symbols_ce123(pc_array, 1);
		printf("%d: %s\n", 0, *pc_name);

#define SIZE 100
		void *array[SIZE];
		int size, i;
		char **strings;
		size = backtrace_ce123(array, SIZE);
		strings = backtrace_symbols_ce123(array, size);	

		for(i=0;i<size;i++)
			printf("%d: %s\n", i+1, strings[i]);
		free(strings);
	}
	else
		printf("error!\n");
	exit(-1);
}

void test_func(void)
{
	int * p = 0x0;
	*p = 0x12345678;
}


int main(int argc, char **argv)
{   

	struct sigaction s;
	s.sa_flags = SA_SIGINFO;
	s.sa_sigaction = (void (*)(int, siginfo_t*, void*))DebugBacktrace;
	sigaction (SIGSEGV, &s, NULL);
	test_func();

	return 0;

}

部分资料来源于网络,若有侵权,请联系作者删除

你可能感兴趣的:(linux系统编程和API详解)