Gdb 使用ptrace时检测tracee是否在信号处理程序中
我在Linux上对此进行了测试,似乎当tracee位于信号处理程序中时,跟踪器可以像往常一样使用ptrace()附加到它。但由于tracee位于信号处理程序中,由于asyn信号安全问题,某些函数可能无法正常调用。那么,在调用ptrace()之后,是否有任何方法可以检测这种情况呢?这可能会引起您的兴趣 简单的回答是,您可以通过展开信号处理程序的堆栈并查找条目来判断SUPER(tracee)是否在信号处理程序中 这是GDB打印为Gdb 使用ptrace时检测tracee是否在信号处理程序中,gdb,signals,ptrace,Gdb,Signals,Ptrace,我在Linux上对此进行了测试,似乎当tracee位于信号处理程序中时,跟踪器可以像往常一样使用ptrace()附加到它。但由于tracee位于信号处理程序中,由于asyn信号安全问题,某些函数可能无法正常调用。那么,在调用ptrace()之后,是否有任何方法可以检测这种情况呢?这可能会引起您的兴趣 简单的回答是,您可以通过展开信号处理程序的堆栈并查找条目来判断SUPER(tracee)是否在信号处理程序中 这是GDB打印为的条目 然而,问题是:你为什么在意 大概是为了防止调试器在最终用户要求您
的条目
然而,问题是:你为什么在意
大概是为了防止调试器在最终用户要求您执行与调用malloc(10)相当的操作时调用tracee
请注意:
void handler(int signo)
{
while (1)
{
char *p = malloc(20); // perfectly safe (but only in this program)
free(p);
}
}
int main()
{
signal(SIGINT, handler);
kill(getpid(), SIGINT);
return 0; // control never reaches here
}
的条目
然而,问题是:你为什么在意
大概是为了防止调试器在最终用户要求您执行与调用malloc(10)相当的操作时调用tracee
请注意:
void handler(int signo)
{
while (1)
{
char *p = malloc(20); // perfectly safe (but only in this program)
free(p);
}
}
int main()
{
signal(SIGINT, handler);
kill(getpid(), SIGINT);
return 0; // control never reaches here
}
事实证明,使用libunwind确定您当前是否在信号处理程序中非常简单: 假设您已正确构建libunwind:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* assume that you have build libunwind properly */
#include "./libunwindout/include/libunwind.h"
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
void show_backtrace(void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while(unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
/* Upon unwinding to a signal handler, you get a "1" */
printf("Is in a signal handler [%d]\n",
unw_is_signal_frame(&cursor));
printf("ip = %lx, sp = %lx \n", (long)ip, (long)sp);
}
}
struct sigaction act;
/* Upon receiving a SIGQUIT, this signal handler will be invoked */
void sighandler(int signum, siginfo_t *info, void *ptr) {
printf("Received signal: %d\n", signum);
printf("signal originate from pid[%d]\n", info->si_pid);
printf("Inside a signal handler...\n");
show_backtrace();
while(1)
;
printf("[FATAL] quiting the signal handler\n");
}
int main(int argc, char *argv[]) {
{
printf("Pid of the current process: %d\n", getpid());
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGQUIT, &act, NULL);
while(1)
;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
/*假设您已经正确构建libunnd*/
#include“/libundout/include/libund.h”
/*简单的错误处理函数*/
#定义句柄\u错误\u en(en,msg)\
do{errno=en;perror(msg);exit(exit_FAILURE);}while(0)
void show_backtrace(void){
unw_光标;unw_上下文光标;
联合国世界知识产权组织;
unw_getcontext(&uc);
unw_init_local(&cursor,&uc);
while(卸载步骤和光标)>0){
unw_get_reg(&cursor,unw_reg_IP,&IP);
unw_get_reg(&cursor,unw_reg_SP,&SP);
/*退绕到信号处理器时,您会得到一个“1”*/
printf(“位于信号处理程序[%d]\n]中”,
unw_是信号_帧(&光标));
printf(“ip=%lx,sp=%lx\n”,(长)ip,(长)sp);
}
}
结构动作法;
/*收到SIGQUIT后,将调用此信号处理程序*/
无效信号处理器(内部信号、信号信息\u t*info、无效*ptr){
printf(“收到的信号:%d\n”,信号);
printf(“信号源于pid[%d]\n”,信息->si_pid);
printf(“信号处理器内部…\n”);
show_backtrace();
而(1)
;
printf(“[FATAL]退出信号处理程序\n”);
}
int main(int argc,char*argv[]){
{
printf(“当前进程的Pid:%d\n”,getpid());
memset(&act,0,sizeof(act));
act.sa_sigaction=sighandler;
act.sa_flags=sa_SIGINFO;
sigaction(SIGQUIT,&act,NULL);
而(1)
;
返回0;
}
因此,您应该运行此程序,然后在收到
SIGQUIT时,将调用信号处理程序并调用show_backtrace()函数
将被调用,这将展开堆栈并最终找到信号
处理程序框架,报告1
更有趣的是,libunwind允许您使用其
libunwindptrace模块。通过“远程”,它只是意味着您可以使用
ptrace(2)连接到进程,然后可以使用libunwind ptrace
检测远程进程是否在信号处理程序中运行
有关更多信息,请参阅libunwind的。事实证明,使用libunwind确定您当前是否在信号处理程序中并不重要: 假设您已正确构建libunwind:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* assume that you have build libunwind properly */
#include "./libunwindout/include/libunwind.h"
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
void show_backtrace(void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while(unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
/* Upon unwinding to a signal handler, you get a "1" */
printf("Is in a signal handler [%d]\n",
unw_is_signal_frame(&cursor));
printf("ip = %lx, sp = %lx \n", (long)ip, (long)sp);
}
}
struct sigaction act;
/* Upon receiving a SIGQUIT, this signal handler will be invoked */
void sighandler(int signum, siginfo_t *info, void *ptr) {
printf("Received signal: %d\n", signum);
printf("signal originate from pid[%d]\n", info->si_pid);
printf("Inside a signal handler...\n");
show_backtrace();
while(1)
;
printf("[FATAL] quiting the signal handler\n");
}
int main(int argc, char *argv[]) {
{
printf("Pid of the current process: %d\n", getpid());
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGQUIT, &act, NULL);
while(1)
;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
/*假设您已正确构建libunwind*/
#include“/libundout/include/libund.h”
/*简单的错误处理函数*/
#定义句柄\u错误\u en(en,msg)\
do{errno=en;perror(msg);exit(exit_FAILURE);}while(0)
void show_backtrace(void){
unw_光标;unw_上下文光标;
联合国世界知识产权组织;
unw_getcontext(&uc);
unw_init_local(&cursor,&uc);
while(卸载步骤和光标)>0){
unw_get_reg(&cursor,unw_reg_IP,&IP);
unw_get_reg(&cursor,unw_reg_SP,&SP);
/*退绕到信号处理器时,您会得到一个“1”*/
printf(“位于信号处理程序[%d]\n]中”,
unw_是信号_帧(&光标));
printf(“ip=%lx,sp=%lx\n”,(长)ip,(长)sp);
}
}
结构动作法;
/*收到SIGQUIT后,将调用此信号处理程序*/
无效信号处理器(内部信号、信号信息\u t*info、无效*ptr){
printf(“收到的信号:%d\n”,信号);
printf(“信号源于pid[%d]\n”,信息->si_pid);
printf(“信号处理器内部…\n”);
show_backtrace();
而(1)
;
printf(“[FATAL]退出信号处理程序\n”);
}
int main(int argc,char*argv[]){
{
printf(“当前进程的Pid:%d\n”,getpid());
memset(&act,0,sizeof(act));
act.sa_sigaction=sighandler;
act.sa_flags=sa_SIGINFO;
sigaction(SIGQUIT,&act,NULL)