fis-gtm/sr_unix/extract_signal_info.c

263 lines
7.3 KiB
C

/****************************************************************
* *
* Copyright 2001, 2010 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
/* For the various Unix/Posix flavors, extract and fill in the appropriate information */
#include "mdef.h"
#include "gtm_string.h"
#include <sys/types.h>
#ifndef __MVS__
# include <sys/param.h>
#endif
#include "gtm_inet.h"
#include "gtm_stdlib.h"
#include "gtm_stdio.h"
#include "gtm_unistd.h"
#if defined(__ia64) && defined(__hpux)
#include <sys/uc_access.h>
#include <machine/sys/reg_struct.h>
#endif /* __ia64 */
#include <signal.h>
#include "gtmsiginfo.h"
/* OS/390 (R7) does not define SI_USER but for code expansions purposes, define the value it uses
in its place */
#if !defined(SI_USER) && defined(__MVS__)
# define SI_USER 0
#endif
void extract_signal_info(int sig, siginfo_t *info, gtm_sigcontext_t *context, gtmsiginfo_t *gtmsi)
{
error_def(ERR_SIGILLOPC);
error_def(ERR_SIGILLOPN);
error_def(ERR_SIGILLADR);
error_def(ERR_SIGILLTRP);
error_def(ERR_SIGPRVOPC);
error_def(ERR_SIGPRVREG);
error_def(ERR_SIGCOPROC);
error_def(ERR_SIGBADSTK);
error_def(ERR_SIGADRALN);
error_def(ERR_SIGADRERR);
error_def(ERR_SIGOBJERR);
error_def(ERR_SIGINTDIV);
error_def(ERR_SIGINTOVF);
error_def(ERR_SIGFLTDIV);
error_def(ERR_SIGFLTOVF);
error_def(ERR_SIGFLTUND);
error_def(ERR_SIGFLTRES);
error_def(ERR_SIGFLTINV);
error_def(ERR_SIGMAPERR);
error_def(ERR_SIGACCERR);
memset(gtmsi, 0, SIZEOF(*gtmsi));
gtmsi->signal = sig;
if (NULL != info)
{
switch(info->si_code)
{
case SI_USER:
gtmsi->send_pid = info->si_pid;
gtmsi->send_uid = info->si_uid;
gtmsi->infotype |= GTMSIGINFO_USER;
break;
default:
# if defined(__osf__)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
if (NULL != context)
{
gtmsi->int_iadr = (caddr_t)context->sc_pc;
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
break;
# elif defined(__hpux)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
if (NULL != context)
{
#ifndef __ia64
if (0 == (context->uc_mcontext.ss_flags & SS_NARROWISINVALID))
{
/* Interrupt location is in narrow area */
gtmsi->int_iadr = (caddr_t)(context->uc_mcontext.ss_narrow.ss_pcoq_head & ~3);
} else
{
/* Interupt location is in wide area */
gtmsi->int_iadr =
(caddr_t)(context->uc_mcontext.ss_wide.ss_32.ss_pcoq_head_hi & ~3);
}
#else /* __ia64 */
__uc_get_ip(context, (uint64_t *) &gtmsi->int_iadr);
#endif /* __ia64 */
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
break;
# elif defined(__linux__)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
if (NULL != context)
{
# ifdef __ia64
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.sc_ip;
# elif defined(__arm__)
# ifndef REG_EIP
# define REG_EIP EIP
# endif
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.arm_pc;
# elif defined(__i386)
# ifndef REG_EIP
# define REG_EIP EIP
# endif
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.gregs[REG_EIP];
# elif defined(__x86_64__)
# ifndef REG_RIP
# define REG_RIP EIP
# endif
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.gregs[REG_RIP];
# elif defined(__s390__)
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.psw.addr;
# else
# error "Unsupported Linux Platform"
# endif
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
break;
# elif defined(__sparc)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
if (NULL != context)
{
gtmsi->int_iadr = (caddr_t)context->uc_mcontext.gregs[REG_PC];
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
break;
# elif defined(__CYGWIN__)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
break;
# elif defined(__MVS__)
if (0 > info->si_code)
{ /* sent from another process */
gtmsi->send_pid = info->si_pid;
gtmsi->send_uid = info->si_uid;
gtmsi->infotype |= GTMSIGINFO_USER;
} else
{
gtmsi->subcode = info->si_code;
if ((SIGBUS == sig) || (SIGFPE == sig) || (SIGILL == sig) || (SIGSEGV == sig))
{ /* address of faulting instruction */
gtmsi->int_iadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
/* we don't know the format of the mcontext structure yet
if (context != NULL)
{
gtmsi->bad_vadr = (caddr_t)context->uc_mcontext[0];
gtmsi->infotype |= GTMSIGINFO_BADR;
}
*/
}
break;
# elif defined(_AIX)
gtmsi->subcode = info->si_code;
gtmsi->bad_vadr = info->si_addr;
gtmsi->infotype |= GTMSIGINFO_BADR;
if (context != NULL)
{
gtmsi->int_iadr = (caddr_t)context->sc_context.iar;
gtmsi->infotype |= GTMSIGINFO_ILOC;
}
break;
# else
# error "Unsupported Platform"
# endif
}
/* See if additional information can be gleaned from the subcode */
if (0 != gtmsi->subcode)
{
switch (sig)
{
case SIGILL :
switch (gtmsi->subcode)
{
case ILL_ILLOPC : gtmsi->sig_err = ERR_SIGILLOPC;
break;
case ILL_ILLOPN : gtmsi->sig_err = ERR_SIGILLOPN;
break;
case ILL_ILLADR : gtmsi->sig_err = ERR_SIGILLADR;
break;
case ILL_ILLTRP : gtmsi->sig_err = ERR_SIGILLTRP;
break;
case ILL_PRVOPC : gtmsi->sig_err = ERR_SIGPRVOPC;
break;
case ILL_PRVREG : gtmsi->sig_err = ERR_SIGPRVREG;
break;
case ILL_COPROC : gtmsi->sig_err = ERR_SIGCOPROC;
break;
case ILL_BADSTK : gtmsi->sig_err = ERR_SIGBADSTK;
break;
}
break;
case SIGBUS :
switch (gtmsi->subcode)
{
case BUS_ADRALN : gtmsi->sig_err = ERR_SIGADRALN;
break;
case BUS_ADRERR : gtmsi->sig_err = ERR_SIGADRERR;
break;
case BUS_OBJERR : gtmsi->sig_err = ERR_SIGOBJERR;
break;
}
break;
case SIGFPE :
switch (gtmsi->subcode)
{
case FPE_INTDIV : gtmsi->sig_err = ERR_SIGINTDIV;
break;
case FPE_INTOVF : gtmsi->sig_err = ERR_SIGINTOVF;
break;
case FPE_FLTDIV : gtmsi->sig_err = ERR_SIGFLTDIV;
break;
case FPE_FLTOVF : gtmsi->sig_err = ERR_SIGFLTOVF;
break;
case FPE_FLTUND : gtmsi->sig_err = ERR_SIGFLTUND;
break;
case FPE_FLTRES : gtmsi->sig_err = ERR_SIGFLTRES;
break;
case FPE_FLTINV : gtmsi->sig_err = ERR_SIGFLTINV;
break;
}
break;
case SIGSEGV :
switch (gtmsi->subcode)
{
case SEGV_MAPERR : gtmsi->sig_err = ERR_SIGMAPERR;
break;
case SEGV_ACCERR : gtmsi->sig_err = ERR_SIGACCERR;
break;
}
break;
}
}
}
}