libddd.c
#include <stdio.h>
#include <string.h>
int fun_dll()
{
void *pTmp = NULL;
printf("In dll\n");
memcpy(pTmp, 0, sizeof(100));
return 1;
}
gdbso.c
#include <dlfcn.h>
#include <stdio.h>
typedef int (*LPFun) (void);
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;
}
编译:
gcc -g -shared -fPIC -o libddd.so libddd.c
gcc gdbso.c -o gdbso -L -lddd -ldl
开启coredump
#开启coredump
ulimit -c unlimited
#指定coredump保存的路径及命名格式
echo /tmp/core-%e-%p-%t.core.dump > /proc/sys/kernel/core_pattern
运行./gdbso
$ ./gdbso
open libddd.so success
In dll
Segmentation fault (core dumped)
coredump文件保存在了/tmp目录下:
/tmp/core-gdbso-8828-1647057254.core.dump
gdb调试coredump
gdb gdbso /tmp/core-gdbso-8828-1647057254.core.dump
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 "x86_64-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 gdbso...
(No debugging symbols found in gdbso)
[New LWP 8828]
Core was generated by `./gdbso'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f6e0be3f139 in fun_dll () at libddd.c:7
7 printf("In dll\n");
(gdb)
(gdb) bt
#0 0x00007f6e0be3f139 in fun_dll () at libddd.c:7
#1 0x000055c676202236 in main ()
通过bt能够直接定位到引起coredump代码为libdd.c的第7行。
通过disassemble查看PC指针位于反汇编代码中的位置:
(gdb) disassemble
Dump of assembler code for function fun_dll:
0x00007f6e0be3f119 <+0>: endbr64
0x00007f6e0be3f11d <+4>: push %rbp
0x00007f6e0be3f11e <+5>: mov %rsp,%rbp
0x00007f6e0be3f121 <+8>: sub $0x10,%rsp
0x00007f6e0be3f125 <+12>: movq $0x0,-0x8(%rbp)
0x00007f6e0be3f12d <+20>: lea 0xecc(%rip),%rdi # 0x7f6e0be40000
0x00007f6e0be3f134 <+27>: callq 0x7f6e0be3f050 <puts@plt>
=> 0x00007f6e0be3f139 <+32>: mov 0x0,%edx
0x00007f6e0be3f140 <+39>: mov -0x8(%rbp),%rax
0x00007f6e0be3f144 <+43>: mov %edx,(%rax)
0x00007f6e0be3f146 <+45>: mov $0x1,%eax
0x00007f6e0be3f14b <+50>: leaveq
0x00007f6e0be3f14c <+51>: retq
End of assembler dump.
fun_dll +32字节位置是mov 0x0,%edx, 将edx寄存器的值写0地址,这显然是有问题的。
通过objdump反汇编libddd.so
objdump -D libddd.so > libddd_dump.txt
在libddd_dump.txt找到fun_dll函数的反汇编代码:
0000000000001119 <fun_dll>:
1119: f3 0f 1e fa endbr64
111d: 55 push %rbp
111e: 48 89 e5 mov %rsp,%rbp
1121: 48 83 ec 10 sub $0x10,%rsp
1125: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
112c: 00
112d: 48 8d 3d cc 0e 00 00 lea 0xecc(%rip),%rdi # 2000 <_fini+0xeb0>
1134: e8 17 ff ff ff callq 1050 <puts@plt>
1139: 8b 14 25 00 00 00 00 mov 0x0,%edx
1140: 48 8b 45 f8 mov -0x8(%rbp),%rax
1144: 89 10 mov %edx,(%rax)
1146: b8 01 00 00 00 mov $0x1,%eax
114b: c9 leaveq
114c: c3 retq
fun_dll函数的地址为0x1119, 偏移32字节的地址为0x1139,对应的反汇编代码:
1139: 8b 14 25 00 00 00 00 mov 0x0,%edx
与前面通过gdb的disassemble指令得到的结果一致。
通过addr2line定位行号
addr2line -a 0x1139 -e libddd.so
0x0000000000001139
~/code/stack/libddd.c:7
与gdb bt指令得到的结果一致。
需要指出的是,libddd.so在编译时必须指定-g编译选项,否则addr2line无法解析出行号。
本文详细介绍了动态链接库(libddd.so)调用过程中出现的Segmentation fault问题,通过gdb进行coredump分析,定位到错误发生在`fun_dll`函数的第32字节指令,该指令尝试将edx寄存器的值写入0地址,导致非法内存访问。通过objdump反汇编和addr2line命令进一步确认了错误行号。解决此类问题的关键在于正确理解和调试动态链接库的调用过程。
168

被折叠的 条评论
为什么被折叠?



