改造strace以赋予它暂停某进程的能力

本文介绍如何改造strace,在遇到execve系统调用时暂停进程,以便在崩溃前进行调试。通过修改strace源码并添加回调脚本,可以在新进程启动时发送暂停信号,为GDB提供附加时间进行attach。文章还讨论了已有解决方案的局限性,并提供了改造后的使用方法。
摘要由CSDN通过智能技术生成

目录

引言

新strace效果preview

已有解决方案

解决方案一:循环检测

解决方案二:gdb-helpers

改造strace

简单的fork程序

下载strace源码

修改strace源码

回调脚本举例:

编译&构建strace

头脑风暴


引言

曾经在stackoverflow看到过一篇求助帖子《Is there any way to tell GDB to wait for a process to start and attach to it?》,大体问题:工具链上调用关系很长,父进程调用子进程,子进程调用孙进程,如此下去,最后有一个进程崩溃了,提问者期望在崩溃之前用GDB attach上去调试调试,好找到崩溃原因。

问题是崩溃进程可能崩溃的很快,以至于没有时间attach。

本文将对strace源代码做轻微改动,以赋予它遇到execve系统调用时(真正执行前)可以回调shell脚本的能力。我会先preview下改造的效果,然后简单讲下Stack Overflow上给出的两个解决方案,最后讲述如何修改strace源码。

新strace效果preview

[root@strace]# ./src/strace -f --syscall_callback_script=./test.sh ./exe1
[pid 2218037] execve("./exe2", ["./exe2"], 0x7ffe32765268 /* 61 vars */./src/strace: Process 2218037 detached
 <detached ...>

[root@strace]# ps -ef|grep exe2
root     2218037 2218029  0 05:23 pts/1    00:00:00 ./exe2
root     2218041 2201850  0 05:23 pts/1    00:00:00 grep --color=auto exe2

[root@strace]# gdb -p 2218037
Attaching to process 2218037
Reading symbols from /min/strace/exe2...done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
0x00007fb0944dacb0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) where
#0  0x00007fb0944dacb0 in _start () from /lib64/ld-linux-x86-64.so.2
#1  0x0000000000000001 in ?? ()
#2  0x00007ffcde850947 in ?? ()
#3  0x0000000000000000 in ?? ()
(gdb) b main
Breakpoint 1 at 0x40058a: file exe2.c, line 5.

(gdb) c
Continuing.

Program received signal SIGSTOP, Stopped (signal).
0x00007fb0944dacb0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) where
#0  0x00007fb0944dacb0 in _start () from /lib64/ld-linux-x86-64.so.2
#1  0x0000000000000001 in ?? ()
#2  0x00007ffcde850947 in ?? ()
#3  0x0000000000000000 in ?? ()
(gdb) c
Continuing.

Breakpoint 1, main () at exe2.c:5
5               printf("I am exe2\n");
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-236.el8.7.x86_64

(gdb) where
#0  main () at exe2.c:5

已有解决方案

帖子上给出了几种解决方案,列出其中两种

解决方案一:循环检测

写一个shell脚本,不停的检测目标(按进程名字)存在不存在,一旦存在就attach上去。

#!/bin/sh
progstr=$1
progpid=`pgrep -o $progstr`
while [ "$progpid" = "" ]; do
  progpid=`pgrep -o $progstr`
done
gdb -ex continue -p $progpid

Usage: 

gdbwait my_program

问题:这个脚本不能100%保证能抓住目标,特别是目标转瞬即逝的情况。我们下面给出的exe2就几乎抓不到。

解决方案二:gdb-helpers

有人在Github上有个repo:gdb-helpers ,里面有个工具叫preattach.

问题:不过它依赖systemtap,没安装systemtap 是用不了的。

改造strace

基本想法是strace既然能检测到系统调用,而Linux是用fork-execv*(syscall execve)来发起子进程的,那能不能在execve时让目标暂停然后给GDB时间去attach哪?

简单的fork程序

先写一个简单的fork程序,便于测试

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深山老宅

鸡蛋不错的话,要不要激励下母鸡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值