xref: /illumos-gate/usr/src/lib/libm/common/m9x/fex_log.c (revision 61679b0b)
125c28e83SPiotr Jasiukajtis /*
225c28e83SPiotr Jasiukajtis  * CDDL HEADER START
325c28e83SPiotr Jasiukajtis  *
425c28e83SPiotr Jasiukajtis  * The contents of this file are subject to the terms of the
525c28e83SPiotr Jasiukajtis  * Common Development and Distribution License (the "License").
625c28e83SPiotr Jasiukajtis  * You may not use this file except in compliance with the License.
725c28e83SPiotr Jasiukajtis  *
825c28e83SPiotr Jasiukajtis  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925c28e83SPiotr Jasiukajtis  * or http://www.opensolaris.org/os/licensing.
1025c28e83SPiotr Jasiukajtis  * See the License for the specific language governing permissions
1125c28e83SPiotr Jasiukajtis  * and limitations under the License.
1225c28e83SPiotr Jasiukajtis  *
1325c28e83SPiotr Jasiukajtis  * When distributing Covered Code, include this CDDL HEADER in each
1425c28e83SPiotr Jasiukajtis  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525c28e83SPiotr Jasiukajtis  * If applicable, add the following below this CDDL HEADER, with the
1625c28e83SPiotr Jasiukajtis  * fields enclosed by brackets "[]" replaced with your own identifying
1725c28e83SPiotr Jasiukajtis  * information: Portions Copyright [yyyy] [name of copyright owner]
1825c28e83SPiotr Jasiukajtis  *
1925c28e83SPiotr Jasiukajtis  * CDDL HEADER END
2025c28e83SPiotr Jasiukajtis  */
2125c28e83SPiotr Jasiukajtis 
2225c28e83SPiotr Jasiukajtis /*
2325c28e83SPiotr Jasiukajtis  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2425c28e83SPiotr Jasiukajtis  */
2525c28e83SPiotr Jasiukajtis /*
2625c28e83SPiotr Jasiukajtis  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2725c28e83SPiotr Jasiukajtis  * Use is subject to license terms.
2825c28e83SPiotr Jasiukajtis  */
2925c28e83SPiotr Jasiukajtis 
30*ddc0e0b5SRichard Lowe #pragma weak __fex_get_log = fex_get_log
31*ddc0e0b5SRichard Lowe #pragma weak __fex_set_log = fex_set_log
32*ddc0e0b5SRichard Lowe #pragma weak __fex_get_log_depth = fex_get_log_depth
33*ddc0e0b5SRichard Lowe #pragma weak __fex_set_log_depth = fex_set_log_depth
34*ddc0e0b5SRichard Lowe #pragma weak __fex_log_entry = fex_log_entry
3525c28e83SPiotr Jasiukajtis 
3625c28e83SPiotr Jasiukajtis #include <stdio.h>
3725c28e83SPiotr Jasiukajtis #include <stdlib.h>
3825c28e83SPiotr Jasiukajtis #include <unistd.h>
3925c28e83SPiotr Jasiukajtis #include <string.h>
4025c28e83SPiotr Jasiukajtis #include <signal.h>
4125c28e83SPiotr Jasiukajtis #include <ucontext.h>
4225c28e83SPiotr Jasiukajtis #include <sys/frame.h>
4325c28e83SPiotr Jasiukajtis #include <fenv.h>
4425c28e83SPiotr Jasiukajtis #include <sys/ieeefp.h>
4525c28e83SPiotr Jasiukajtis #include <thread.h>
4625c28e83SPiotr Jasiukajtis #include "fex_handler.h"
4725c28e83SPiotr Jasiukajtis 
4825c28e83SPiotr Jasiukajtis #if !defined(PC)
4925c28e83SPiotr Jasiukajtis #if defined(REG_PC)
5025c28e83SPiotr Jasiukajtis #define	PC	REG_PC
5125c28e83SPiotr Jasiukajtis #else
5225c28e83SPiotr Jasiukajtis #error Neither PC nor REG_PC is defined!
5325c28e83SPiotr Jasiukajtis #endif
5425c28e83SPiotr Jasiukajtis #endif
5525c28e83SPiotr Jasiukajtis 
5625c28e83SPiotr Jasiukajtis static FILE *log_fp = NULL;
5725c28e83SPiotr Jasiukajtis static mutex_t log_lock = DEFAULTMUTEX;
5825c28e83SPiotr Jasiukajtis static int log_depth = 100;
5925c28e83SPiotr Jasiukajtis 
fex_get_log(void)6025c28e83SPiotr Jasiukajtis FILE *fex_get_log(void)
6125c28e83SPiotr Jasiukajtis {
6225c28e83SPiotr Jasiukajtis 	FILE	*fp;
6325c28e83SPiotr Jasiukajtis 
6425c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
6525c28e83SPiotr Jasiukajtis 	fp = log_fp;
6625c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
6725c28e83SPiotr Jasiukajtis 	return fp;
6825c28e83SPiotr Jasiukajtis }
6925c28e83SPiotr Jasiukajtis 
fex_set_log(FILE * fp)7025c28e83SPiotr Jasiukajtis int fex_set_log(FILE *fp)
7125c28e83SPiotr Jasiukajtis {
7225c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
7325c28e83SPiotr Jasiukajtis 	log_fp = fp;
7425c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
7525c28e83SPiotr Jasiukajtis 	__fex_update_te();
7625c28e83SPiotr Jasiukajtis 	return 1;
7725c28e83SPiotr Jasiukajtis }
7825c28e83SPiotr Jasiukajtis 
fex_get_log_depth(void)7925c28e83SPiotr Jasiukajtis int fex_get_log_depth(void)
8025c28e83SPiotr Jasiukajtis {
8125c28e83SPiotr Jasiukajtis 	int	d;
8225c28e83SPiotr Jasiukajtis 
8325c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
8425c28e83SPiotr Jasiukajtis 	d = log_depth;
8525c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
8625c28e83SPiotr Jasiukajtis 	return d;
8725c28e83SPiotr Jasiukajtis }
8825c28e83SPiotr Jasiukajtis 
fex_set_log_depth(int d)8925c28e83SPiotr Jasiukajtis int fex_set_log_depth(int d)
9025c28e83SPiotr Jasiukajtis {
9125c28e83SPiotr Jasiukajtis 	if (d < 0)
9225c28e83SPiotr Jasiukajtis 		return 0;
9325c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
9425c28e83SPiotr Jasiukajtis 	log_depth = d;
9525c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
9625c28e83SPiotr Jasiukajtis 	return 1;
9725c28e83SPiotr Jasiukajtis }
9825c28e83SPiotr Jasiukajtis 
9925c28e83SPiotr Jasiukajtis static struct exc_list {
10025c28e83SPiotr Jasiukajtis 	struct exc_list		*next;
10125c28e83SPiotr Jasiukajtis 	char			*addr;
10225c28e83SPiotr Jasiukajtis 	unsigned long		code;
10325c28e83SPiotr Jasiukajtis 	int			nstack;
10425c28e83SPiotr Jasiukajtis 	char			*stack[1]; /* actual length is max(1,nstack) */
10525c28e83SPiotr Jasiukajtis } *list = NULL;
10625c28e83SPiotr Jasiukajtis 
10725c28e83SPiotr Jasiukajtis #ifdef __sparcv9
10825c28e83SPiotr Jasiukajtis #define FRAMEP(X)	(struct frame *)((char*)(X)+(((long)(X)&1)?2047:0))
10925c28e83SPiotr Jasiukajtis #else
11025c28e83SPiotr Jasiukajtis #define FRAMEP(X)	(struct frame *)(X)
11125c28e83SPiotr Jasiukajtis #endif
11225c28e83SPiotr Jasiukajtis 
11325c28e83SPiotr Jasiukajtis #ifdef _LP64
11425c28e83SPiotr Jasiukajtis #define PDIG		"16"
11525c28e83SPiotr Jasiukajtis #else
11625c28e83SPiotr Jasiukajtis #define PDIG		"8"
11725c28e83SPiotr Jasiukajtis #endif
11825c28e83SPiotr Jasiukajtis 
11925c28e83SPiotr Jasiukajtis /* look for a matching exc_list; return 1 if one is found,
12025c28e83SPiotr Jasiukajtis    otherwise add this one to the list and return 0 */
check_exc_list(char * addr,unsigned long code,char * stk,struct frame * fp)12125c28e83SPiotr Jasiukajtis static int check_exc_list(char *addr, unsigned long code, char *stk,
12225c28e83SPiotr Jasiukajtis     struct frame *fp)
12325c28e83SPiotr Jasiukajtis {
12425c28e83SPiotr Jasiukajtis 	struct exc_list	*l, *ll = NULL;
12525c28e83SPiotr Jasiukajtis 	struct frame	*f;
12625c28e83SPiotr Jasiukajtis 	int		i, n;
12725c28e83SPiotr Jasiukajtis 
12825c28e83SPiotr Jasiukajtis 	if (list) {
12925c28e83SPiotr Jasiukajtis 		for (l = list; l; ll = l, l = l->next) {
13025c28e83SPiotr Jasiukajtis 			if (l->addr != addr || l->code != code)
13125c28e83SPiotr Jasiukajtis 				continue;
13225c28e83SPiotr Jasiukajtis 			if (log_depth < 1 || l->nstack < 1)
13325c28e83SPiotr Jasiukajtis 				return 1;
13425c28e83SPiotr Jasiukajtis 			if (l->stack[0] != stk)
13525c28e83SPiotr Jasiukajtis 				continue;
13625c28e83SPiotr Jasiukajtis 			n = 1;
13725c28e83SPiotr Jasiukajtis 			for (i = 1, f = fp; i < log_depth && i < l->nstack &&
13825c28e83SPiotr Jasiukajtis 			    f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp))
13925c28e83SPiotr Jasiukajtis 				if (l->stack[i] != (char *)f->fr_savpc) {
14025c28e83SPiotr Jasiukajtis 					n = 0;
14125c28e83SPiotr Jasiukajtis 					break;
14225c28e83SPiotr Jasiukajtis 				}
14325c28e83SPiotr Jasiukajtis 			if (n)
14425c28e83SPiotr Jasiukajtis 				return 1;
14525c28e83SPiotr Jasiukajtis 		}
14625c28e83SPiotr Jasiukajtis 	}
14725c28e83SPiotr Jasiukajtis 
14825c28e83SPiotr Jasiukajtis 	/* create a new exc_list structure and tack it on the list */
14925c28e83SPiotr Jasiukajtis 	for (n = 1, f = fp; n < log_depth && f && f->fr_savpc;
15025c28e83SPiotr Jasiukajtis 	    n++, f = FRAMEP(f->fr_savfp)) ;
15125c28e83SPiotr Jasiukajtis 	if ((l = (struct exc_list *)malloc(sizeof(struct exc_list) +
15225c28e83SPiotr Jasiukajtis 	    (n - 1) * sizeof(char *))) != NULL) {
15325c28e83SPiotr Jasiukajtis 		l->next = NULL;
15425c28e83SPiotr Jasiukajtis 		l->addr = addr;
15525c28e83SPiotr Jasiukajtis 		l->code = code;
15625c28e83SPiotr Jasiukajtis 		l->nstack = ((log_depth < 1)? 0 : n);
15725c28e83SPiotr Jasiukajtis 		l->stack[0] = stk;
15825c28e83SPiotr Jasiukajtis 		for (i = 1; i < n; i++) {
15925c28e83SPiotr Jasiukajtis 			l->stack[i] = (char *)fp->fr_savpc;
16025c28e83SPiotr Jasiukajtis 			fp = FRAMEP(fp->fr_savfp);
16125c28e83SPiotr Jasiukajtis 		}
16225c28e83SPiotr Jasiukajtis 		if (list)
16325c28e83SPiotr Jasiukajtis 			ll->next = l;
16425c28e83SPiotr Jasiukajtis 		else
16525c28e83SPiotr Jasiukajtis 			list = l;
16625c28e83SPiotr Jasiukajtis 	}
16725c28e83SPiotr Jasiukajtis 	return 0;
16825c28e83SPiotr Jasiukajtis }
16925c28e83SPiotr Jasiukajtis 
17025c28e83SPiotr Jasiukajtis /*
17125c28e83SPiotr Jasiukajtis * Warning: cleverness ahead
17225c28e83SPiotr Jasiukajtis *
17325c28e83SPiotr Jasiukajtis * In the following code, the use of sprintf+write rather than fprintf
17425c28e83SPiotr Jasiukajtis * to send output to the log file is intentional.  The reason is that
17525c28e83SPiotr Jasiukajtis * fprintf is not async-signal-safe.  "But," you protest, "SIGFPE is
17625c28e83SPiotr Jasiukajtis * not an asynchronous signal!  It's always handled by the same thread
17725c28e83SPiotr Jasiukajtis * that executed the fpop that provoked it."  That's true, but a prob-
17825c28e83SPiotr Jasiukajtis * lem arises because (i) base conversion in fprintf can cause a fp
17925c28e83SPiotr Jasiukajtis * exception and (ii) my signal handler acquires a mutex lock before
18025c28e83SPiotr Jasiukajtis * sending output to the log file (so that outputs for entries from
18125c28e83SPiotr Jasiukajtis * different threads aren't interspersed).  Therefore, if the code
18225c28e83SPiotr Jasiukajtis * were to use fprintf, a deadlock could occur as follows:
18325c28e83SPiotr Jasiukajtis *
18425c28e83SPiotr Jasiukajtis *	Thread A			Thread B
18525c28e83SPiotr Jasiukajtis *
18625c28e83SPiotr Jasiukajtis *	Incurs a fp exception,		Calls fprintf,
18725c28e83SPiotr Jasiukajtis *	acquires log_lock		acquires file rmutex lock
18825c28e83SPiotr Jasiukajtis *
18925c28e83SPiotr Jasiukajtis *	Calls fprintf,			Incurs a fp exception,
19025c28e83SPiotr Jasiukajtis *	waits for file rmutex lock	waits for log_lock
19125c28e83SPiotr Jasiukajtis *
19225c28e83SPiotr Jasiukajtis * (I could just verify that fprintf doesn't hold the rmutex lock while
19325c28e83SPiotr Jasiukajtis * it's doing the base conversion, but since efficiency is of little
19425c28e83SPiotr Jasiukajtis * concern here, I opted for the safe and dumb route.)
19525c28e83SPiotr Jasiukajtis */
19625c28e83SPiotr Jasiukajtis 
print_stack(int fd,char * addr,struct frame * fp)19725c28e83SPiotr Jasiukajtis static void print_stack(int fd, char *addr, struct frame *fp)
19825c28e83SPiotr Jasiukajtis {
19925c28e83SPiotr Jasiukajtis 	int	i;
20025c28e83SPiotr Jasiukajtis 	char	*name, buf[30];
20125c28e83SPiotr Jasiukajtis 
20225c28e83SPiotr Jasiukajtis 	for (i = 0; i < log_depth && addr != NULL; i++) {
20325c28e83SPiotr Jasiukajtis 		if (__fex_sym(addr, &name) != NULL) {
20425c28e83SPiotr Jasiukajtis 			write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx  ",
20525c28e83SPiotr Jasiukajtis 			    (long)addr));
20625c28e83SPiotr Jasiukajtis 			write(fd, name, strlen(name));
20725c28e83SPiotr Jasiukajtis 			write(fd, "\n", 1);
20825c28e83SPiotr Jasiukajtis 			if (!strcmp(name, "main"))
20925c28e83SPiotr Jasiukajtis 				break;
21025c28e83SPiotr Jasiukajtis 		} else {
21125c28e83SPiotr Jasiukajtis 			write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx\n",
21225c28e83SPiotr Jasiukajtis 			    (long)addr));
21325c28e83SPiotr Jasiukajtis 		}
21425c28e83SPiotr Jasiukajtis 		if (fp == NULL)
21525c28e83SPiotr Jasiukajtis 			break;
21625c28e83SPiotr Jasiukajtis 		addr = (char *)fp->fr_savpc;
21725c28e83SPiotr Jasiukajtis 		fp = FRAMEP(fp->fr_savfp);
21825c28e83SPiotr Jasiukajtis 	}
21925c28e83SPiotr Jasiukajtis }
22025c28e83SPiotr Jasiukajtis 
fex_log_entry(const char * msg)22125c28e83SPiotr Jasiukajtis void fex_log_entry(const char *msg)
22225c28e83SPiotr Jasiukajtis {
22325c28e83SPiotr Jasiukajtis 	ucontext_t	uc;
22425c28e83SPiotr Jasiukajtis 	struct frame	*fp;
22525c28e83SPiotr Jasiukajtis 	char		*stk;
22625c28e83SPiotr Jasiukajtis 	int		fd;
22725c28e83SPiotr Jasiukajtis 
22825c28e83SPiotr Jasiukajtis 	/* if logging is disabled, just return */
22925c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
23025c28e83SPiotr Jasiukajtis 	if (log_fp == NULL) {
23125c28e83SPiotr Jasiukajtis 		mutex_unlock(&log_lock);
23225c28e83SPiotr Jasiukajtis 		return;
23325c28e83SPiotr Jasiukajtis 	}
23425c28e83SPiotr Jasiukajtis 
23525c28e83SPiotr Jasiukajtis 	/* get the frame pointer from the current context and
23625c28e83SPiotr Jasiukajtis 	   pop our own frame */
23725c28e83SPiotr Jasiukajtis 	getcontext(&uc);
23825c28e83SPiotr Jasiukajtis #if defined(__sparc) || defined(__amd64)
23925c28e83SPiotr Jasiukajtis 	fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]);
24025c28e83SPiotr Jasiukajtis #elif defined(__i386)	/* !defined(__amd64) */
24125c28e83SPiotr Jasiukajtis 	fp = FRAMEP(uc.uc_mcontext.gregs[EBP]);
24225c28e83SPiotr Jasiukajtis #else
24325c28e83SPiotr Jasiukajtis #error Unknown architecture
24425c28e83SPiotr Jasiukajtis #endif
24525c28e83SPiotr Jasiukajtis 	if (fp == NULL) {
24625c28e83SPiotr Jasiukajtis 		mutex_unlock(&log_lock);
24725c28e83SPiotr Jasiukajtis 		return;
24825c28e83SPiotr Jasiukajtis 	}
24925c28e83SPiotr Jasiukajtis 	stk = (char *)fp->fr_savpc;
25025c28e83SPiotr Jasiukajtis 	fp = FRAMEP(fp->fr_savfp);
25125c28e83SPiotr Jasiukajtis 
25225c28e83SPiotr Jasiukajtis 	/* if we've already logged this message here, don't make an entry */
25325c28e83SPiotr Jasiukajtis 	if (check_exc_list(stk, (unsigned long)msg, stk, fp)) {
25425c28e83SPiotr Jasiukajtis 		mutex_unlock(&log_lock);
25525c28e83SPiotr Jasiukajtis 		return;
25625c28e83SPiotr Jasiukajtis 	}
25725c28e83SPiotr Jasiukajtis 
25825c28e83SPiotr Jasiukajtis 	/* make an entry */
25925c28e83SPiotr Jasiukajtis 	fd = fileno(log_fp);
26025c28e83SPiotr Jasiukajtis 	write(fd, "fex_log_entry: ", 15);
26125c28e83SPiotr Jasiukajtis 	write(fd, msg, strlen(msg));
26225c28e83SPiotr Jasiukajtis 	write(fd, "\n", 1);
26325c28e83SPiotr Jasiukajtis 	__fex_sym_init();
26425c28e83SPiotr Jasiukajtis 	print_stack(fd, stk, fp);
26525c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
26625c28e83SPiotr Jasiukajtis }
26725c28e83SPiotr Jasiukajtis 
26825c28e83SPiotr Jasiukajtis static const char *exception[FEX_NUM_EXC] = {
26925c28e83SPiotr Jasiukajtis 	"inexact result",
27025c28e83SPiotr Jasiukajtis 	"division by zero",
27125c28e83SPiotr Jasiukajtis 	"underflow",
27225c28e83SPiotr Jasiukajtis 	"overflow",
27325c28e83SPiotr Jasiukajtis 	"invalid operation (0/0)",
27425c28e83SPiotr Jasiukajtis 	"invalid operation (inf/inf)",
27525c28e83SPiotr Jasiukajtis 	"invalid operation (inf-inf)",
27625c28e83SPiotr Jasiukajtis 	"invalid operation (0*inf)",
27725c28e83SPiotr Jasiukajtis 	"invalid operation (sqrt)",
27825c28e83SPiotr Jasiukajtis 	"invalid operation (snan)",
27925c28e83SPiotr Jasiukajtis 	"invalid operation (int)",
28025c28e83SPiotr Jasiukajtis 	"invalid operation (cmp)"
28125c28e83SPiotr Jasiukajtis };
28225c28e83SPiotr Jasiukajtis 
28325c28e83SPiotr Jasiukajtis void
__fex_mklog(ucontext_t * uap,char * addr,int f,enum fex_exception e,int m,void * p)28425c28e83SPiotr Jasiukajtis __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e,
28525c28e83SPiotr Jasiukajtis     int m, void *p)
28625c28e83SPiotr Jasiukajtis {
28725c28e83SPiotr Jasiukajtis 	struct	frame	*fp;
28825c28e83SPiotr Jasiukajtis 	char		*stk, *name, buf[30];
28925c28e83SPiotr Jasiukajtis 	int		fd;
29025c28e83SPiotr Jasiukajtis 
29125c28e83SPiotr Jasiukajtis 	/* if logging is disabled, just return */
29225c28e83SPiotr Jasiukajtis 	mutex_lock(&log_lock);
29325c28e83SPiotr Jasiukajtis 	if (log_fp == NULL) {
29425c28e83SPiotr Jasiukajtis 		mutex_unlock(&log_lock);
29525c28e83SPiotr Jasiukajtis 		return;
29625c28e83SPiotr Jasiukajtis 	}
29725c28e83SPiotr Jasiukajtis 
29825c28e83SPiotr Jasiukajtis 	/* get stack info */
29925c28e83SPiotr Jasiukajtis #if defined(__sparc)
30025c28e83SPiotr Jasiukajtis 	stk = (char*)uap->uc_mcontext.gregs[REG_PC];
30125c28e83SPiotr Jasiukajtis 	fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]);
30225c28e83SPiotr Jasiukajtis #elif defined(__amd64)
30325c28e83SPiotr Jasiukajtis 	stk = (char*)uap->uc_mcontext.gregs[REG_PC];
30425c28e83SPiotr Jasiukajtis 	fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]);
30525c28e83SPiotr Jasiukajtis #elif defined(__i386)	/* !defined(__amd64) */
30625c28e83SPiotr Jasiukajtis 	stk = (char*)uap->uc_mcontext.gregs[PC];
30725c28e83SPiotr Jasiukajtis 	fp = FRAMEP(uap->uc_mcontext.gregs[EBP]);
30825c28e83SPiotr Jasiukajtis #else
30925c28e83SPiotr Jasiukajtis #error Unknown architecture
31025c28e83SPiotr Jasiukajtis #endif
31125c28e83SPiotr Jasiukajtis 
31225c28e83SPiotr Jasiukajtis 	/* if the handling mode is the default and this exception's
31325c28e83SPiotr Jasiukajtis 	   flag is already raised, don't make an entry */
31425c28e83SPiotr Jasiukajtis 	if (m == FEX_NONSTOP) {
31525c28e83SPiotr Jasiukajtis 		switch (e) {
31625c28e83SPiotr Jasiukajtis 		case fex_inexact:
31725c28e83SPiotr Jasiukajtis 			if (f & FE_INEXACT) {
31825c28e83SPiotr Jasiukajtis 				mutex_unlock(&log_lock);
31925c28e83SPiotr Jasiukajtis 				return;
32025c28e83SPiotr Jasiukajtis 			}
32125c28e83SPiotr Jasiukajtis 			break;
32225c28e83SPiotr Jasiukajtis 		case fex_underflow:
32325c28e83SPiotr Jasiukajtis 			if (f & FE_UNDERFLOW) {
32425c28e83SPiotr Jasiukajtis 				mutex_unlock(&log_lock);
32525c28e83SPiotr Jasiukajtis 				return;
32625c28e83SPiotr Jasiukajtis 			}
32725c28e83SPiotr Jasiukajtis 			break;
32825c28e83SPiotr Jasiukajtis 		case fex_overflow:
32925c28e83SPiotr Jasiukajtis 			if (f & FE_OVERFLOW) {
33025c28e83SPiotr Jasiukajtis 				mutex_unlock(&log_lock);
33125c28e83SPiotr Jasiukajtis 				return;
33225c28e83SPiotr Jasiukajtis 			}
33325c28e83SPiotr Jasiukajtis 			break;
33425c28e83SPiotr Jasiukajtis 		case fex_division:
33525c28e83SPiotr Jasiukajtis 			if (f & FE_DIVBYZERO) {
33625c28e83SPiotr Jasiukajtis 				mutex_unlock(&log_lock);
33725c28e83SPiotr Jasiukajtis 				return;
33825c28e83SPiotr Jasiukajtis 			}
33925c28e83SPiotr Jasiukajtis 			break;
34025c28e83SPiotr Jasiukajtis 		default:
34125c28e83SPiotr Jasiukajtis 			if (f & FE_INVALID) {
34225c28e83SPiotr Jasiukajtis 				mutex_unlock(&log_lock);
34325c28e83SPiotr Jasiukajtis 				return;
34425c28e83SPiotr Jasiukajtis 			}
34525c28e83SPiotr Jasiukajtis 			break;
34625c28e83SPiotr Jasiukajtis 		}
34725c28e83SPiotr Jasiukajtis 	}
34825c28e83SPiotr Jasiukajtis 
34925c28e83SPiotr Jasiukajtis 	/* if we've already logged this exception at this address,
35025c28e83SPiotr Jasiukajtis 	   don't make an entry */
35125c28e83SPiotr Jasiukajtis 	if (check_exc_list(addr, (unsigned long)e, stk, fp)) {
35225c28e83SPiotr Jasiukajtis 		mutex_unlock(&log_lock);
35325c28e83SPiotr Jasiukajtis 		return;
35425c28e83SPiotr Jasiukajtis 	}
35525c28e83SPiotr Jasiukajtis 
35625c28e83SPiotr Jasiukajtis 	/* make an entry */
35725c28e83SPiotr Jasiukajtis 	fd = fileno(log_fp);
35825c28e83SPiotr Jasiukajtis 	write(fd, "Floating point ", 15);
35925c28e83SPiotr Jasiukajtis 	write(fd, exception[e], strlen(exception[e]));
36025c28e83SPiotr Jasiukajtis 	write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr));
36125c28e83SPiotr Jasiukajtis 	__fex_sym_init();
36225c28e83SPiotr Jasiukajtis 	if (__fex_sym(addr, &name) != NULL) {
36325c28e83SPiotr Jasiukajtis 		write(fd, " ", 1);
36425c28e83SPiotr Jasiukajtis 		write(fd, name, strlen(name));
36525c28e83SPiotr Jasiukajtis 	}
36625c28e83SPiotr Jasiukajtis 	switch (m) {
36725c28e83SPiotr Jasiukajtis 	case FEX_NONSTOP:
36825c28e83SPiotr Jasiukajtis 		write(fd, ", nonstop mode\n", 15);
36925c28e83SPiotr Jasiukajtis 		break;
37025c28e83SPiotr Jasiukajtis 
37125c28e83SPiotr Jasiukajtis 	case FEX_ABORT:
37225c28e83SPiotr Jasiukajtis 		write(fd, ", abort\n", 8);
37325c28e83SPiotr Jasiukajtis 		break;
37425c28e83SPiotr Jasiukajtis 
37525c28e83SPiotr Jasiukajtis 	case FEX_NOHANDLER:
37625c28e83SPiotr Jasiukajtis 		if (p == (void *)SIG_DFL) {
37725c28e83SPiotr Jasiukajtis 			write(fd, ", handler: SIG_DFL\n", 19);
37825c28e83SPiotr Jasiukajtis 			break;
37925c28e83SPiotr Jasiukajtis 		}
38025c28e83SPiotr Jasiukajtis 		else if (p == (void *)SIG_IGN) {
38125c28e83SPiotr Jasiukajtis 			write(fd, ", handler: SIG_IGN\n", 19);
38225c28e83SPiotr Jasiukajtis 			break;
38325c28e83SPiotr Jasiukajtis 		}
38425c28e83SPiotr Jasiukajtis 		/* fall through*/
38525c28e83SPiotr Jasiukajtis 	default:
38625c28e83SPiotr Jasiukajtis 		write(fd, ", handler: ", 11);
38725c28e83SPiotr Jasiukajtis 		if (__fex_sym((char *)p, &name) != NULL) {
38825c28e83SPiotr Jasiukajtis 			write(fd, name, strlen(name));
38925c28e83SPiotr Jasiukajtis 			write(fd, "\n", 1);
39025c28e83SPiotr Jasiukajtis 		} else {
39125c28e83SPiotr Jasiukajtis 			write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n",
39225c28e83SPiotr Jasiukajtis 			    (long)p));
39325c28e83SPiotr Jasiukajtis 		}
39425c28e83SPiotr Jasiukajtis 		break;
39525c28e83SPiotr Jasiukajtis 	}
39625c28e83SPiotr Jasiukajtis 	print_stack(fd, stk, fp);
39725c28e83SPiotr Jasiukajtis 	mutex_unlock(&log_lock);
39825c28e83SPiotr Jasiukajtis }
399