我对一个信号处理程序感兴趣,它可以识别导致问题的指令的地址.
我知道siginfo_t并且__builtin_return_address似乎都没有工作:
#include <iostream>
#include <signal.h>
void handler (int, siginfo_t *, void *);
int main ()
{
begin:
std :: cerr << &&begin << " ~ " << &&before << " ~ " << &&after << "\n";
struct sigaction s;
s .sa_flags = SA_SIGINFO;
sigemptyset (& s .sa_mask);
s .sa_sigaction = handler;
sigaction (SIGSEGV, &s, NULL);
int * i = NULL;
before:
*i = 0;
after:
std :: cout << "End.\n";
}
void handler (int, siginfo_t *si, void *)
{
std :: cerr << "si:" << si -> si_addr << "\n";
std :: cerr << "At: " << __builtin_return_address (0) << "\n";
std :: cerr << "At: " << __builtin_return_address (1) << "\n";
std :: cerr << "At: " << __builtin_return_address (2) << "\n";
std :: cerr << "At: " << __builtin_return_address (3) << "\n";
std :: cerr << "At: " << __builtin_return_address (4) << "\n";
std :: cerr << "At: " << __builtin_return_address (5) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这输出如下:
0x10978 ~ 0x10a4c ~ 0x10a54
si:0
At: 0xfb945364
At: 0xfb939e64
At: 0x10a40
At: 0x10740
At: 0
At: Segmentation Fault
Run Code Online (Sandbox Code Playgroud)
所以siginfo_t是NULL并且在命名标签之间的__builtin_return_address某处产生值.
我期待这两个都返回值&&before.我正确使用这些功能吗?
在Linux 2.6.9-89.0.9.Elsmp和SunOS上测试过.
安装的处理程序的第三个参数SA_SIGINFO(声明为的处理程序void *)是指向ucontext_t结构的指针.此结构的内容是体系结构和操作系统特定的,不是任何标准的一部分,但它们包含您需要的信息.这是适合使用它的程序版本(特定于Linux/x86-64;您将需要#ifdef针对每个感兴趣的架构和操作系统):
#define _GNU_SOURCE 1
#include <iostream>
#include <iomanip>
#include <signal.h>
#include <ucontext.h>
using std::cout;
static volatile int *causecrash;
static void handler(int, siginfo_t *si, void *ptr)
{
ucontext_t *uc = (ucontext_t *)ptr;
cout << "si:" << si->si_addr << '\n';
cout << "ip:" << std::hex << uc->uc_mcontext.gregs[REG_RIP] << '\n';
}
int main()
{
begin:
cout.setf(std::ios::unitbuf);
cout << &&begin << " ~ " << &&before << " ~ " << &&after << '\n';
struct sigaction s;
s.sa_flags = SA_SIGINFO|SA_RESETHAND;
s.sa_sigaction = handler;
sigemptyset(&s.sa_mask);
sigaction(SIGSEGV, &s, 0);
before:
*causecrash = 0;
after:
cout << "End.\n";
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,海湾合作委员会有这种讨厌的习惯,就是移动地址的标签,但不用于控制转移操作(据其所知).相比:
$ g++ -O0 -W -Wall test.cc && ./a.out
0x400a30 ~ 0x400acd ~ 0x400ada
si:0
ip:400ad4
Segmentation fault
$ g++ -O2 -W -Wall test.cc && ./a.out
0x4009f0 ~ 0x4009f0 ~ 0x4009f0
si:0
ip:400ab4
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
了解优化版本中所有标签如何位于同一地址?通过调整PC,这样可以避免任何尝试,例如从故障中恢复.IIRC有一种方法可以让海湾合作委员会不这样做,但我不知道它是什么,也无法在手册中找到它.
| 归档时间: |
|
| 查看次数: |
3728 次 |
| 最近记录: |