背景介绍
在小内存的嵌入式设备中,为了压缩进程的大小,通常是去掉符号表后在设备上运行,此时进程崩溃后生成的core文件和对应的二进制文件是不带符号表的,使用gdb进行查看时无法获取到准确信息。
但是我们可以单独保存被删掉的符号表,在gdb的时候进行导入来进行调试。
例子
以一个二进制进程链接一个动态库为例
动态链接库为命名为b.c
#include <stdio.h>
int b(int (*a)(void))
{
return a() + 100;
}
主程序命名为a.c
#include <stdio.h>
extern int b(int (*a)(void));
int a()
{
int *a = NULL;
*a=0;
return 1;
}
int c()
{
return b(a) + 1000;
}
int main()
{
c();
return 0;
}
- 生成动态链接库及主程序
gcc -g b.c -fPIC -shared -o libb.so
gcc -g a.c -o a.out -L. -lb - 提取主程序及动态链接库的符号表
strip –only-keep-debug -o a.sym a.out
strip –only-keep-debug -o libb.sym libb.so - 删除主程序及动态链接库的符号表
strip a.out
strip libb.so - 运行程序产生core文件
root@oa:/home/share/gdb# ./a.out
Segmentation fault (core dumped)
默认未导入符号表的情况下,进行gdb,看到一堆的??和No symbol
root@oa:/home/share/gdb# gdb a.out core-a.out-4156
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0804854d in ?? ()
(gdb) bt fu
#0 0x0804854d in ?? ()
No symbol table info available.
#1 0xb775a4f6 in b () from /home/share/gdb/libb.so
No symbol table info available.
#2 0x0804856c in ?? ()
No symbol table info available.
#3 0x0804857e in ?? ()
No symbol table info available.
#4 0xb75afa83 in __libc_start_main (main=0x8048573, argc=1, argv=0xbfd86fd4, init=0x8048590, fini=0x8048600, rtld_fini=0xb776f180 <_dl_fini>, stack_end=0xbfd86fcc) at libc-start.c:287
#5 0x08048461 in ?? ()
No symbol table info available.
这时候使用-symbols参数的gdb命令,导入主程序符号表并启动gdb
root@oa:/home/share/gdb# gdb --exec=a.out --core=core-a.out-4156 -symbols=a.sym
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0804854d in a () at a.c:8
8 *a=0;
(gdb) bt fu
#0 0x0804854d in a () at a.c:8
a = <error reading variable a (can't compute CFA for this frame)>
#1 0xb775a4f6 in b () from /home/share/gdb/libb.so
No symbol table info available.
#2 0x0804856c in c () at a.c:14
No locals.
#3 0x0804857e in main () at a.c:19
No locals.
此时发现主程序的函数有符号表了,但是动态库还只有函数,没有变量符号,还是提示No symbol。
导入动态库的符号表,需要先使用info shared命令找到动态库链接的位置:
(gdb) info shared
From To Syms Read Shared Object Library
0xb775a3c0 0xb775a4fb Yes (*) /home/share/gdb/libb.so
0xb75ad420 0xb76df68e Yes /lib/i386-linux-gnu/libc.so.6
0xb7760860 0xb77787ac Yes /lib/ld-linux.so.2
(*): Shared library is missing debugging information.
然后使用add-symbol-file命令将动态库的符号表导入,此时所有的符号表都有了。
(gdb) add-symbol-file libb.sym 0xb775a3c0
add symbol table from file "libb.sym" at
.text_addr = 0xb775a3c0
(y or n) y
Reading symbols from libb.sym...done.
(gdb) bt fu
#0 0x0804854d in a () at a.c:8
a = <error reading variable a (can't compute CFA for this frame)>
#1 0xb775a4f6 in b (a=0x804853d <a>) at b.c:5
No locals.
#2 0x0804856c in c () at a.c:14
No locals.
#3 0x0804857e in main () at a.c:19
No locals.
如果提示找不到动态库的链接路径,则可以使用set solib-search-path <path>命令来设置动态库的链接路径。
相关命令
- strip –only-keep-debug -o <bin.sym> <bin>
- strip <bin>
- gdb –exec=<bin> –core=<core> -symbols=<bin.sym>
- info shared
- add-symbol-file <lib.sym> <address>
- set solib-search-path <path>
- show solib-search-path