272 lines
7.4 KiB
C
272 lines
7.4 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 */
|
|
|
|
/*
|
|
See issue :
|
|
|
|
See also :
|
|
http://stackoverflow.com/questions/5679267/how-to-resolve-reg-eip-undeclared-first-use-in-this-function-error-on-linux-3
|
|
*/
|
|
#define _GNU_SOURCE
|
|
|
|
|
|
|
|
#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 "gtmconfig.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 *) >msi->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(__i386)
|
|
# ifndef REG_EIP
|
|
# ifndef EIP
|
|
# error "EIP not defined"
|
|
# endif
|
|
# 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;
|
|
}
|
|
}
|
|
}
|
|
}
|