捕捉细分违规行为并继续生活 [英] Catching Segmentation Violations and Getting on with Life
问题描述
我正在编写一个检查其自身地址空间的程序.
I'm writing a program that's examining its own address space.
具体来说,我关心所有malloc分配的数据块.如果有一些系统调用来获取它们的列表,那就太好了(对于我的应用程序,我不能使用LD_PRELOAD,-wrap或任何其他命令行选项).如果有办法做到这一点,我很想听听它,而不仅仅是在下面对我陈述的问题的答案.
Specifically, I care about all malloc-ed data blocks. If there some system call to get a list of them, that would be fantastic (for my application, I cannot use LD_PRELOAD, -wrap, nor any extra command line options). If there's a way to do this, I'd love to hear it even more than an answer to my stated problem, below.
代替此,我当前的方法是仅取消引用所有内容并环顾四周.显然,所有可能的指针的集合都是等待发生段错误的雷区,因此我尝试注册信号处理程序并使用setjmp/longjmp(通过使处理程序不执行任何操作来忽略段错误都是无限循环,因为处理程序将返回到错误的指令).一些示例代码如下:
In lieu of this, my current approach is to just dereference everything and look around. Obviously, the set of all possible pointers is a minefield of segfaults waiting to happen, so I tried registering a signal handler and using setjmp/longjmp (simply ignoring the segfault by making the handler do nothing is an infinite loop because the handler will return to the faulting instruction). Some example code goes like so:
static jmp_buf buf;
void handler(int i) {
printf(" Segfaulted!\n");
longjmp(buf,-1);
}
void segfault(void) {
int* x = 0x0;
int y = *x;
}
void test_function(void) {
signal(11,handler);
while (1) {
if (setjmp(buf)==0) {
printf("Segfaulting:\n");
segfault();
}
else {
printf("Recovered and not segfaulting!\n");
}
printf("\n");
}
}
输出为:
Segfaulting:
Segfaulted!
Recovered and not segfaulting!
Segfaulting:
Segmentation fault
因此,处理程序第二次没有工作.我不知道为什么,但是我推测这与不清除原始信号有关.我不知道该怎么办.
So, the handler didn't work the second time around. I don't know why this is, but I speculated it had something to do with not clearing the original signal. I don't know how to do that.
顺便说一句,我首先尝试了sigsetjmp/siglongjmp,但是由于某种原因在setjmp.h中未对其进行定义.我有一个模糊的共鸣,认为需要传递一些额外的编译标志,但是像以前一样,此应用程序不允许这样做.
As an aside, I tried sigsetjmp/siglongjmp first, but they weren't defined for some reason in setjmp.h. I got vague vibes that one needed to pass some extra compile flags, but, as before, that is not allowed for this application.
正在使用的系统是Ubuntu Linux 10.04 x86-64,并且 都不需要任何解决方案.
The system being used is Ubuntu Linux 10.04 x86-64, and any solution does not need to be portable.
谢谢!
伊恩[
Thanks!
Ian[
处理程序中的sigrelse清除信号,并有效解决问题.现在的问题与提出的其他问题有关-是否有更好的方法(即获取malloc的块)? sigsetjmp/siglongjmp怎么了?为什么我需要重置信号?]
sigrelse in the handler clears the signal, and fixes the problem effectively. Question now concerns the other issues raised--is there a better way (i.e., get the blocks of malloc)? What's up with sigsetjmp/siglongjmp? Why do I need to reset the signal?]
推荐答案
当调用SIGSEGV
的信号处理程序时,SIGSEGV
信号将被sigprocmask
屏蔽.对于任何信号都是如此.通常,从信号处理程序返回将取消屏蔽它,但是由于您不返回,因此永远不会发生.有两种可能的解决方案:
When the signal handler for SIGSEGV
is invoked, the SIGSEGV
signal will be masked as if by sigprocmask
. This is true for any signal. Normally returning from the signal handler would unmask it, but since you're not returning, that never happens. There are a couple possible solutions:
- 您可以在
longjmp
之前或之后致电sigprocmask
自己取消屏蔽. - 您可以使用
sigaction
(无论如何首选的方式)安装信号处理程序,并使用SA_NODEFER
标志来防止其被屏蔽. - 您可以使用
sigsetjmp
和siglongjmp
函数,它们自己负责保存和恢复信号掩码.
- You can call
sigprocmask
either before or after thelongjmp
to unmask it yourself. - You can install the signal handler with
sigaction
(the preferred way to do it anyway) and use theSA_NODEFER
flag to prevent it from being masked. - You can use the
sigsetjmp
andsiglongjmp
functions, which themselves take responsibility for saving and restoring the signal mask.
这篇关于捕捉细分违规行为并继续生活的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!