错误,还是 valgrind/gcc bug?
当在以下程序上运行 valgrind 时,断言失败:
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <wchar.h>
#include <assert.h>
#include <signal.h>
#include <stdlib.h>
#include <ucontext.h>
static size_t pageSize = 4096;
uint8_t *bs;
static void sig(int num,
siginfo_t *info, void *unused) {
ucontext *p = (ucontext *)unused;
uint8_t *addr = (uint8_t *)info->si_addr;
wprintf(L"rax=%lx\n", p->uc_mcontext.gregs[REG_RAX]);
wprintf(L"addr=%lx\n", addr);
assert(mprotect(bs, pageSize*4,
PROT_READ | PROT_WRITE) == 0);
}
bool setsig() {
sigset_t mask;
struct sigaction sa;
if (sigemptyset(&mask))
return false;
sa.sa_sigaction = sig;
sa.sa_mask = mask;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV,&sa, NULL) != 0)
return false;
return true;
}
int main() {
assert(setsig());
bs = (uint8_t *)mmap(NULL, pageSize*4,
PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(bs != MAP_FAILED);
bs[pageSize] = 3; // !!
assert(bs[pageSize] == 3);
return 0;
}
RAX 在错误指令处保留 (bs + pageSize),对应于代码中的 (!!)。但是,si_addr 与信号处理程序 ucontext 中的 RAX 不匹配(ucontext 中 RAX 的值等于“bs”)。当启用写入 RAX 后重新执行 (!!) 时,包含 (bs)。在 valgrind 外部执行可以按预期工作。
我是否做了一些导致未定义行为的事情,或者这可能是 GCC 或 valgrind 中的错误?
When running valgrind on the following program the assertion fails:
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <wchar.h>
#include <assert.h>
#include <signal.h>
#include <stdlib.h>
#include <ucontext.h>
static size_t pageSize = 4096;
uint8_t *bs;
static void sig(int num,
siginfo_t *info, void *unused) {
ucontext *p = (ucontext *)unused;
uint8_t *addr = (uint8_t *)info->si_addr;
wprintf(L"rax=%lx\n", p->uc_mcontext.gregs[REG_RAX]);
wprintf(L"addr=%lx\n", addr);
assert(mprotect(bs, pageSize*4,
PROT_READ | PROT_WRITE) == 0);
}
bool setsig() {
sigset_t mask;
struct sigaction sa;
if (sigemptyset(&mask))
return false;
sa.sa_sigaction = sig;
sa.sa_mask = mask;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV,&sa, NULL) != 0)
return false;
return true;
}
int main() {
assert(setsig());
bs = (uint8_t *)mmap(NULL, pageSize*4,
PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(bs != MAP_FAILED);
bs[pageSize] = 3; // !!
assert(bs[pageSize] == 3);
return 0;
}
RAX holds (bs + pageSize) at the faulting instruction, corresponding to (!!) in the code. However, si_addr does not match RAX in the ucontext of the signal handler (the value of RAX in the ucontext is equal to 'bs'). When (!!) is reexecuted after enabling writes RAX contains (bs). Executing outside valgrind works as expected.
Have I done something to cause undefined behaviour, or is it possible that this is a bug in GCC or valgrind?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您使用精确的异常,它将起作用。
此页面准确地描述了您要执行的操作: -))
It will work if you use precise exceptions.
This page precisely describes what you are trying to do :-))