JIAJIA can not catch the fault address correctly in sigsevg_handler for x86_64
http://us.generation-nt.com/answer/sigsegv-signal-handler-help-183484481.html
http://sourceware.org/ml/libc-help/2009-10/msg00021.html
http://comp.os.linux.development.apps.narkive.com/wH6d4yNJ/fail-to-get-the-fault-address-from-sigcontext-cr2
In JIAJIA/src/mem.c line 462
In 32-bit system, sigctx_cr2 record the fault address 200000, but not in 64-bit.
sigsegv.c
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
void my_sigsegv(int signo, struct sigcontext sigctx)
{
printf("Produce sigsegv %d\n",signo);
printf("%ld:\n",sigctx.cr2);
return ;
}
int main()
{
struct sigaction act;
act.sa_handler = my_sigsegv ;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGSEGV , &act , NULL);
char *pstr = 200000;
strcpy(pstr , "hello");
}
Solution (man sigaction for details)
In mem.c line 170
#ifdef LINUX
jiamapfd=open("/dev/zero", O_RDWR,0);
{
/*struct sigaction act;
act.sa_handler = (void_func_handler)sigsegv_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_NOMASK;
if (sigaction(SIGSEGV, &act, NULL))
assert0(0,"segv sigaction problem");*/
//xiao
struct sigaction act;
// act.sa_handler = (void_func_handler)sigsegv_handler;
act.sa_sigaction = sigsegv_handler;
sigemptyset(&act.sa_mask);
// act.sa_flags = SA_NOMASK;
act.sa_flags = SA_NOMASK | SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL))
assert0(0,"segv sigaction problem");
}
In mem.c line 481
#ifdef LINUX
//void sigsegv_handler(int signo, struct sigcontext sigctx)
//xiao_bug
//void sigsegv_handler( int sig, siginfo_t *sip,struct sigcontext *scp)
//xiao_bug:
void sigsegv_handler (int signo, struct siginfo *info, void *data)
//http://comp.os.linux.development.apps.narkive.com/wH6d4yNJ/fail-to-get-the-fault-address-from-sigcontext-cr2
#endif
In mem.c line 75
#ifdef LINUX
//void sigsegv_handler(int, struct sigcontext);
//xiao
//void sigsegv_handler( int sig, siginfo_t *sip,struct sigcontext *scp);
//xiao
void sigsegv_handler (int signo, struct siginfo *info, void *data);
#endif
In mem.c line 526
#ifdef LINUX
/*faultaddr = (address_t) sigctx.cr2;
faultaddr = (address_t) ((unsigned long) faultaddr/Pagesize*Pagesize);
writefault = (int) sigctx.err & 2;*/
//xiao
DPRINTF("Come to linux\n");
DPRINTF("errno:%d code:%d addr:0x%x\n",info->si_errno,info->si_code,info->si_addr);
faultaddr = (address_t)info->si_addr;
DPRINTF("faultaddr=%lx\n",(long)faultaddr);
faultaddr = (address_t) ((unsigned long) faultaddr/Pagesize*Pagesize);
//how to get the writfualt
//writefault = (int) info->si_errno & 2;
#endif
http://computer-programming-forum.com/46-asm/81c68464056ab13a.htm
In /usr/include/x86_64-linux-gnu/sys/ucontext.h 40 line (For user space to use the register)
//xiao
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#include <sys/ucontext.h>
void my_sigsegv(int signo, struct siginfo * info, void * data)
{
printf("Produce sigsegv %d\n",signo);
printf("%ld\n",(long)info->si_addr);
struct ucontext *ucp = (struct ucontext *)data;
printf("REG_ERR:%d\n",ucp->uc_mcontext.gregs[REG_ERR]);
int type = ucp->uc_mcontext.gregs[REG_ERR] & 2;
printf("type=%d\n",type);
if(type == 2) {
printf("write\n");
}else {
printf("read\n");
}
return ;
}
int main()
{
struct sigaction act;
act.sa_sigaction = my_sigsegv;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL);
char *pstr = 200000;
// *pstr = 31;
// *pstr = 0;
printf("%c\n", *pstr);
// strcpy(pstr,"hello");
}
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#include <sys/ucontext.h>
#include <sys/mman.h>
#include <fcntl.h>
long jiamapfd = 0;
void my_sigsegv(int signo, struct siginfo * info, void * data)
{
printf("Produce sigsegv %d\n",signo);
printf("faultaddr:%lx\n",(long)info->si_addr);
long faultaddr = (long)info->si_addr;
struct ucontext *ucp = (struct ucontext *)data;
// printf("REG_ERR:%d\n",ucp->uc_mcontext.gregs[REG_ERR]);
int type = ucp->uc_mcontext.gregs[REG_ERR] & 2;
type = (type==0)?0:1;
if(type == 1) {
printf("write fault\n");
}else {
printf("read fault\n");
}
long mapad= (long)mmap(faultaddr,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,jiamapfd,0);
printf("Map:0x%lx\n",mapad);
return ;
}
int main()
{
struct sigaction act;
act.sa_sigaction = my_sigsegv;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL);
jiamapfd = open("/dev/zero",O_RDWR,0);
char * p = 0x70000000;
*p = *p + 3;
printf("%c\n",*p);
char *s = 0x70003000;
*s = 5;
}
Produce sigsegv 11
faultaddr:70000000
read fault
Map:0x70000000
Produce sigsegv 11
faultaddr:70003000
write fault
Map:0x70003000