gdb 定位coredump中so库的位置

本文详细介绍了动态链接库(libddd.so)调用过程中出现的Segmentation fault问题,通过gdb进行coredump分析,定位到错误发生在`fun_dll`函数的第32字节指令,该指令尝试将edx寄存器的值写入0地址,导致非法内存访问。通过objdump反汇编和addr2line命令进一步确认了错误行号。解决此类问题的关键在于正确理解和调试动态链接库的调用过程。
摘要由CSDN通过智能技术生成

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无法解析出行号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值