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 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 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 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 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 */ 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 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 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 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