linux 嵌入式软件调试技巧

1 objcopy + gdb的使用

1.1 创建一个debug.c文件,内容如下:

#include 

int main (void)
{
        printf ("Hello world.\n");
        return 0;
}

1.1.1 编译release版本,该版本不支持gdb调试

gcc debug.c -o debug_release

1.1.2 编译debug版本

gcc -g debug.c -o debug_debug

$ ll
total 36
drwxr-xr-x 2 guang guang  4096 616 15:14 ./
drwxr-xr-x 6 guang guang  4096 616 15:10 ../
-rw-r--r-- 1 guang guang    79 616 15:13 debug.c
-rwxr-xr-x 1 guang guang 10744 616 15:14 debug_debug*
-rwxr-xr-x 1 guang guang  8296 616 15:14 debug_release*

1.1.3 使用objcopy从debug_debug里面提取debug信息

$ objcopy --only-keep-debug debug_debug debug.dbg
$ ls
debug.c  debug.dbg  debug_debug  debug_release

1.1.4 使用如下方法让release版本的elf文件支持gdb调试

$ gdb -q --symbol=debug.dbg --exec=debug_release
Reading symbols from debug.dbg...done.
(gdb) r
Starting program: /home/guang/Develop/trainning/debug/debug_release 
warning: Probes-based dynamic linker interface failed.
Reverting to original interface.
Hello world.
[Inferior 1 (process 3603) exited normally]
(gdb)  

1.1.5 也可以将debug.dbg合并到debug_release文件中

guang@guang-ubuntu:~/Develop/trainning/debug$ gdb debug_release 
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from debug_release...Reading symbols from /home/guang/Develop/trainning/debug/debug.dbg...done.
done.
(gdb) r
Starting program: /home/guang/Develop/trainning/debug/debug_release 
Hello world.
[Inferior 1 (process 3679) exited normally]
(gdb) 

2 printk

2.1 打印数据格式,不支持浮点型数据打印

2.2 打印指针

%p:打印指针地址
%pF:打印函数指针的函数名和偏移地址
%pf:只打印函数指针的函数名,不打印偏移地址

2.3 打印文件名、函数名、行号

2.4 打印等级

2.4.1 打印等级定义

include/linux/kern_levels.h
0  KERN_EMERG
1  KERN_ALERT
2  KERN_CRIT
3  KERN_ERR
4  KERN_WARNNING
5  KERN_NOTICE
6  KERN_INFO
7  KERN_DEBUG

2.4.2 控制台打印等级修改

方法1:echo 8 > /proc/sys/kernel/printk
方法2:dmesg –n 8

3 动态调试

3.1 menuconfig配置内核,使能动态打印

4 内核转储(core dump)

4.1 内核转储的功能

系统会将该程序运行时的:
内存
寄存器状态
堆栈指针
内存管理信息
各种函数的堆栈调用信息 保存在一个core文件中

4.2 造成core dump的原因

内存访问越界 // 数组访问越界
多线程读写的数据未加锁保护
非法指针    // 空指针、野指针
堆栈溢出    // 函数内使用大的数组、大的局部变量

4.2 core dump调试

4.2.1 core dump调试

ulimit –c    // 查看core dump文件记录是否开启
ulimit –c 0  // 关闭
ulimit –c <1~max> // 设置core文件大小
ulimit –c unlimited   // 文件大小不设限
// 调试程序实例
#include 

int main (void)
{
        char *p = "hello world";
        printf ("%s\n", p);

        char *np = NULL;
        printf ("%c\n", *np); //访问非法指针
        return 0;
}
guang@guang-net:~/develop/share/debug$ gcc -g -o dump dump.c 
guang@guang-net:~/develop/share/debug$ ./dump
hello world
Segmentation fault (core dumped)
guang@guang-net:~/develop/share/debug$ ls
core  dump  dump.c
guang@guang-net:~/develop/share/debug$ readelf -h core 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              CORE (Core file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         17
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

  guang@guang-net:~/develop/share/debug$ gdb dump core       // 启动core文件调试 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
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:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from dump...done.
[New LWP 3443]
Core was generated by `./dump'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x08048476 in main () at dump.c:9
9       printf ("%c\n", *np);
(gdb) bt                          //用bt指令调试,发现代码在dump.c第9行出现了问题
#0  0x08048476 in main () at dump.c:9
(gdb) 

4.2.2 core dump文件格式设置

查看文件格式:cat /proc/sys/kernel/core_pattern
设置文件格式:echo ./core.%e.%p> /proc/sys/kernel/core_pattern
    Core dump文件格式:
        %p 所dump进程的进程ID
        %u 所dump进程的实际用户ID
        %g 所dump进程的实际组ID
        %s 导致本次core dump的信号
        %t core dump的时间 (由1970年1月1日计起的秒数)
        %h 主机名
        %e 程序文件名

4.2.3 core dump文件系统自启动生效

系统自启动生效:/etc/rc.local //在文件中加入上述命令行即可

你可能感兴趣的:(嵌入式)