Print this page
11210 libm should be cstyle(1ONBLD) clean


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */

  25 /*
  26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 #pragma weak __fex_get_log = fex_get_log
  31 #pragma weak __fex_set_log = fex_set_log
  32 #pragma weak __fex_get_log_depth = fex_get_log_depth
  33 #pragma weak __fex_set_log_depth = fex_set_log_depth
  34 #pragma weak __fex_log_entry = fex_log_entry
  35 
  36 #include <stdio.h>
  37 #include <stdlib.h>
  38 #include <unistd.h>
  39 #include <string.h>
  40 #include <signal.h>
  41 #include <ucontext.h>
  42 #include <sys/frame.h>
  43 #include <fenv.h>
  44 #include <sys/ieeefp.h>
  45 #include <thread.h>
  46 #include "fex_handler.h"
  47 
  48 #if !defined(PC)
  49 #if defined(REG_PC)
  50 #define PC      REG_PC
  51 #else
  52 #error Neither PC nor REG_PC is defined!
  53 #endif
  54 #endif
  55 
  56 static FILE *log_fp = NULL;
  57 static mutex_t log_lock = DEFAULTMUTEX;
  58 static int log_depth = 100;
  59 
  60 FILE *fex_get_log(void)
  61 {
  62         FILE    *fp;
  63 
  64         mutex_lock(&log_lock);
  65         fp = log_fp;
  66         mutex_unlock(&log_lock);
  67         return fp;
  68 }
  69 
  70 int fex_set_log(FILE *fp)

  71 {
  72         mutex_lock(&log_lock);
  73         log_fp = fp;
  74         mutex_unlock(&log_lock);
  75         __fex_update_te();
  76         return 1;
  77 }
  78 
  79 int fex_get_log_depth(void)

  80 {
  81         int     d;
  82 
  83         mutex_lock(&log_lock);
  84         d = log_depth;
  85         mutex_unlock(&log_lock);
  86         return d;
  87 }
  88 
  89 int fex_set_log_depth(int d)

  90 {
  91         if (d < 0)
  92                 return 0;

  93         mutex_lock(&log_lock);
  94         log_depth = d;
  95         mutex_unlock(&log_lock);
  96         return 1;
  97 }
  98 
  99 static struct exc_list {
 100         struct exc_list         *next;
 101         char                    *addr;
 102         unsigned long           code;
 103         int                     nstack;
 104         char                    *stack[1]; /* actual length is max(1,nstack) */
 105 } *list = NULL;
 106 
 107 #ifdef __sparcv9
 108 #define FRAMEP(X)       (struct frame *)((char*)(X)+(((long)(X)&1)?2047:0))

 109 #else
 110 #define FRAMEP(X)       (struct frame *)(X)
 111 #endif
 112 
 113 #ifdef _LP64
 114 #define PDIG            "16"
 115 #else
 116 #define PDIG            "8"
 117 #endif
 118 
 119 /* look for a matching exc_list; return 1 if one is found,
 120    otherwise add this one to the list and return 0 */
 121 static int check_exc_list(char *addr, unsigned long code, char *stk,
 122     struct frame *fp)


 123 {
 124         struct exc_list *l, *ll = NULL;
 125         struct frame    *f;
 126         int             i, n;
 127 
 128         if (list) {
 129                 for (l = list; l; ll = l, l = l->next) {
 130                         if (l->addr != addr || l->code != code)
 131                                 continue;

 132                         if (log_depth < 1 || l->nstack < 1)
 133                                 return 1;

 134                         if (l->stack[0] != stk)
 135                                 continue;

 136                         n = 1;

 137                         for (i = 1, f = fp; i < log_depth && i < l->nstack &&
 138                             f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp))
 139                                 if (l->stack[i] != (char *)f->fr_savpc) {
 140                                         n = 0;
 141                                         break;
 142                                 }

 143                         if (n)
 144                                 return 1;
 145                 }
 146         }
 147 
 148         /* create a new exc_list structure and tack it on the list */
 149         for (n = 1, f = fp; n < log_depth && f && f->fr_savpc;
 150             n++, f = FRAMEP(f->fr_savfp)) ;
 151         if ((l = (struct exc_list *)malloc(sizeof(struct exc_list) +
 152             (n - 1) * sizeof(char *))) != NULL) {


 153                 l->next = NULL;
 154                 l->addr = addr;
 155                 l->code = code;
 156                 l->nstack = ((log_depth < 1)? 0 : n);
 157                 l->stack[0] = stk;

 158                 for (i = 1; i < n; i++) {
 159                         l->stack[i] = (char *)fp->fr_savpc;
 160                         fp = FRAMEP(fp->fr_savfp);
 161                 }

 162                 if (list)
 163                         ll->next = l;
 164                 else
 165                         list = l;
 166         }
 167         return 0;

 168 }
 169 
 170 /*
 171 * Warning: cleverness ahead
 172 *
 173 * In the following code, the use of sprintf+write rather than fprintf
 174 * to send output to the log file is intentional.  The reason is that
 175 * fprintf is not async-signal-safe.  "But," you protest, "SIGFPE is
 176 * not an asynchronous signal!  It's always handled by the same thread
 177 * that executed the fpop that provoked it."  That's true, but a prob-
 178 * lem arises because (i) base conversion in fprintf can cause a fp
 179 * exception and (ii) my signal handler acquires a mutex lock before
 180 * sending output to the log file (so that outputs for entries from
 181 * different threads aren't interspersed).  Therefore, if the code
 182 * were to use fprintf, a deadlock could occur as follows:
 183 *
 184 *       Thread A                        Thread B
 185 *
 186 *       Incurs a fp exception,          Calls fprintf,
 187 *       acquires log_lock               acquires file rmutex lock
 188 *
 189 *       Calls fprintf,                  Incurs a fp exception,
 190 *       waits for file rmutex lock      waits for log_lock
 191 *
 192 * (I could just verify that fprintf doesn't hold the rmutex lock while
 193 * it's doing the base conversion, but since efficiency is of little
 194 * concern here, I opted for the safe and dumb route.)
 195 */
 196 
 197 static void print_stack(int fd, char *addr, struct frame *fp)
 198 {
 199         int     i;
 200         char    *name, buf[30];
 201 
 202         for (i = 0; i < log_depth && addr != NULL; i++) {
 203                 if (__fex_sym(addr, &name) != NULL) {
 204                         write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx  ",
 205                             (long)addr));
 206                         write(fd, name, strlen(name));
 207                         write(fd, "\n", 1);
 208                         if (!strcmp(name, "main"))

 209                                 break;
 210                 } else {
 211                         write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx\n",
 212                             (long)addr));
 213                 }

 214                 if (fp == NULL)
 215                         break;

 216                 addr = (char *)fp->fr_savpc;
 217                 fp = FRAMEP(fp->fr_savfp);
 218         }
 219 }
 220 
 221 void fex_log_entry(const char *msg)

 222 {
 223         ucontext_t      uc;
 224         struct frame    *fp;
 225         char            *stk;
 226         int             fd;
 227 
 228         /* if logging is disabled, just return */
 229         mutex_lock(&log_lock);

 230         if (log_fp == NULL) {
 231                 mutex_unlock(&log_lock);
 232                 return;
 233         }
 234 
 235         /* get the frame pointer from the current context and
 236            pop our own frame */


 237         getcontext(&uc);
 238 #if defined(__sparc) || defined(__amd64)
 239         fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]);
 240 #elif defined(__i386)   /* !defined(__amd64) */
 241         fp = FRAMEP(uc.uc_mcontext.gregs[EBP]);
 242 #else
 243 #error Unknown architecture
 244 #endif

 245         if (fp == NULL) {
 246                 mutex_unlock(&log_lock);
 247                 return;
 248         }

 249         stk = (char *)fp->fr_savpc;
 250         fp = FRAMEP(fp->fr_savfp);
 251 
 252         /* if we've already logged this message here, don't make an entry */
 253         if (check_exc_list(stk, (unsigned long)msg, stk, fp)) {
 254                 mutex_unlock(&log_lock);
 255                 return;
 256         }
 257 
 258         /* make an entry */
 259         fd = fileno(log_fp);
 260         write(fd, "fex_log_entry: ", 15);
 261         write(fd, msg, strlen(msg));
 262         write(fd, "\n", 1);
 263         __fex_sym_init();
 264         print_stack(fd, stk, fp);
 265         mutex_unlock(&log_lock);
 266 }
 267 
 268 static const char *exception[FEX_NUM_EXC] = {
 269         "inexact result",
 270         "division by zero",
 271         "underflow",
 272         "overflow",
 273         "invalid operation (0/0)",
 274         "invalid operation (inf/inf)",
 275         "invalid operation (inf-inf)",
 276         "invalid operation (0*inf)",
 277         "invalid operation (sqrt)",
 278         "invalid operation (snan)",
 279         "invalid operation (int)",
 280         "invalid operation (cmp)"
 281 };
 282 
 283 void
 284 __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e,
 285     int m, void *p)
 286 {
 287         struct  frame   *fp;
 288         char            *stk, *name, buf[30];
 289         int             fd;
 290 
 291         /* if logging is disabled, just return */
 292         mutex_lock(&log_lock);

 293         if (log_fp == NULL) {
 294                 mutex_unlock(&log_lock);
 295                 return;
 296         }
 297 
 298         /* get stack info */
 299 #if defined(__sparc)
 300         stk = (char*)uap->uc_mcontext.gregs[REG_PC];
 301         fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]);
 302 #elif defined(__amd64)
 303         stk = (char*)uap->uc_mcontext.gregs[REG_PC];
 304         fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]);
 305 #elif defined(__i386)   /* !defined(__amd64) */
 306         stk = (char*)uap->uc_mcontext.gregs[PC];
 307         fp = FRAMEP(uap->uc_mcontext.gregs[EBP]);
 308 #else
 309 #error Unknown architecture
 310 #endif
 311 
 312         /* if the handling mode is the default and this exception's
 313            flag is already raised, don't make an entry */


 314         if (m == FEX_NONSTOP) {
 315                 switch (e) {
 316                 case fex_inexact:

 317                         if (f & FE_INEXACT) {
 318                                 mutex_unlock(&log_lock);
 319                                 return;
 320                         }

 321                         break;
 322                 case fex_underflow:

 323                         if (f & FE_UNDERFLOW) {
 324                                 mutex_unlock(&log_lock);
 325                                 return;
 326                         }

 327                         break;
 328                 case fex_overflow:

 329                         if (f & FE_OVERFLOW) {
 330                                 mutex_unlock(&log_lock);
 331                                 return;
 332                         }

 333                         break;
 334                 case fex_division:

 335                         if (f & FE_DIVBYZERO) {
 336                                 mutex_unlock(&log_lock);
 337                                 return;
 338                         }

 339                         break;
 340                 default:

 341                         if (f & FE_INVALID) {
 342                                 mutex_unlock(&log_lock);
 343                                 return;
 344                         }

 345                         break;
 346                 }
 347         }
 348 
 349         /* if we've already logged this exception at this address,
 350            don't make an entry */


 351         if (check_exc_list(addr, (unsigned long)e, stk, fp)) {
 352                 mutex_unlock(&log_lock);
 353                 return;
 354         }
 355 
 356         /* make an entry */
 357         fd = fileno(log_fp);
 358         write(fd, "Floating point ", 15);
 359         write(fd, exception[e], strlen(exception[e]));
 360         write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr));
 361         __fex_sym_init();

 362         if (__fex_sym(addr, &name) != NULL) {
 363                 write(fd, " ", 1);
 364                 write(fd, name, strlen(name));
 365         }

 366         switch (m) {
 367         case FEX_NONSTOP:
 368                 write(fd, ", nonstop mode\n", 15);
 369                 break;
 370 
 371         case FEX_ABORT:
 372                 write(fd, ", abort\n", 8);
 373                 break;
 374 
 375         case FEX_NOHANDLER:

 376                 if (p == (void *)SIG_DFL) {
 377                         write(fd, ", handler: SIG_DFL\n", 19);
 378                         break;
 379                 }
 380                 else if (p == (void *)SIG_IGN) {
 381                         write(fd, ", handler: SIG_IGN\n", 19);
 382                         break;
 383                 }
 384                 /* fall through*/

 385         default:
 386                 write(fd, ", handler: ", 11);

 387                 if (__fex_sym((char *)p, &name) != NULL) {
 388                         write(fd, name, strlen(name));
 389                         write(fd, "\n", 1);
 390                 } else {
 391                         write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n",
 392                             (long)p));
 393                 }

 394                 break;
 395         }

 396         print_stack(fd, stk, fp);
 397         mutex_unlock(&log_lock);
 398 }


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 #pragma weak __fex_get_log = fex_get_log
  32 #pragma weak __fex_set_log = fex_set_log
  33 #pragma weak __fex_get_log_depth = fex_get_log_depth
  34 #pragma weak __fex_set_log_depth = fex_set_log_depth
  35 #pragma weak __fex_log_entry = fex_log_entry
  36 
  37 #include <stdio.h>
  38 #include <stdlib.h>
  39 #include <unistd.h>
  40 #include <string.h>
  41 #include <signal.h>
  42 #include <ucontext.h>
  43 #include <sys/frame.h>
  44 #include <fenv.h>
  45 #include <sys/ieeefp.h>
  46 #include <thread.h>
  47 #include "fex_handler.h"
  48 
  49 #if !defined(PC)
  50 #if defined(REG_PC)
  51 #define PC      REG_PC
  52 #else
  53 #error Neither PC nor REG_PC is defined!
  54 #endif
  55 #endif
  56 
  57 static FILE *log_fp = NULL;
  58 static mutex_t log_lock = DEFAULTMUTEX;
  59 static int log_depth = 100;
  60 FILE *
  61 fex_get_log(void)
  62 {
  63         FILE *fp;
  64 
  65         mutex_lock(&log_lock);
  66         fp = log_fp;
  67         mutex_unlock(&log_lock);
  68         return (fp);
  69 }
  70 
  71 int
  72 fex_set_log(FILE *fp)
  73 {
  74         mutex_lock(&log_lock);
  75         log_fp = fp;
  76         mutex_unlock(&log_lock);
  77         __fex_update_te();
  78         return (1);
  79 }
  80 
  81 int
  82 fex_get_log_depth(void)
  83 {
  84         int d;
  85 
  86         mutex_lock(&log_lock);
  87         d = log_depth;
  88         mutex_unlock(&log_lock);
  89         return (d);
  90 }
  91 
  92 int
  93 fex_set_log_depth(int d)
  94 {
  95         if (d < 0)
  96                 return (0);
  97 
  98         mutex_lock(&log_lock);
  99         log_depth = d;
 100         mutex_unlock(&log_lock);
 101         return (1);
 102 }
 103 
 104 static struct exc_list {
 105         struct exc_list *next;
 106         char *addr;
 107         unsigned long code;
 108         int nstack;
 109         char *stack[1];                 /* actual length is max(1,nstack) */
 110 } *list = NULL;
 111 
 112 #ifdef __sparcv9
 113 #define FRAMEP(X)               (struct frame *)((char *)(X) + (((long)(X) & \
 114         1) ? 2047 : 0))
 115 #else
 116 #define FRAMEP(X)               (struct frame *)(X)
 117 #endif
 118 
 119 #ifdef _LP64
 120 #define PDIG                    "16"
 121 #else
 122 #define PDIG                    "8"
 123 #endif
 124 
 125 /*
 126  * look for a matching exc_list; return 1 if one is found,
 127  * otherwise add this one to the list and return 0
 128  */
 129 static int
 130 check_exc_list(char *addr, unsigned long code, char *stk, struct frame *fp)
 131 {
 132         struct exc_list *l, *ll = NULL;
 133         struct frame *f;
 134         int i, n;
 135 
 136         if (list) {
 137                 for (l = list; l; ll = l, l = l->next) {
 138                         if (l->addr != addr || l->code != code)
 139                                 continue;
 140 
 141                         if (log_depth < 1 || l->nstack < 1)
 142                                 return (1);
 143 
 144                         if (l->stack[0] != stk)
 145                                 continue;
 146 
 147                         n = 1;
 148 
 149                         for (i = 1, f = fp; i < log_depth && i < l->nstack &&
 150                             f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp))
 151                                 if (l->stack[i] != (char *)f->fr_savpc) {
 152                                         n = 0;
 153                                         break;
 154                                 }
 155 
 156                         if (n)
 157                                 return (1);
 158                 }
 159         }
 160 
 161         /* create a new exc_list structure and tack it on the list */
 162         for (n = 1, f = fp; n < log_depth && f && f->fr_savpc;
 163             n++, f = FRAMEP(f->fr_savfp))
 164                 ;
 165 
 166         if ((l = (struct exc_list *)malloc(sizeof (struct exc_list) + (n - 1) *
 167             sizeof (char *))) != NULL) {
 168                 l->next = NULL;
 169                 l->addr = addr;
 170                 l->code = code;
 171                 l->nstack = ((log_depth < 1) ? 0 : n);
 172                 l->stack[0] = stk;
 173 
 174                 for (i = 1; i < n; i++) {
 175                         l->stack[i] = (char *)fp->fr_savpc;
 176                         fp = FRAMEP(fp->fr_savfp);
 177                 }
 178 
 179                 if (list)
 180                         ll->next = l;
 181                 else
 182                         list = l;
 183         }
 184 
 185         return (0);
 186 }
 187 
 188 /*
 189  * Warning: cleverness ahead
 190  *
 191  * In the following code, the use of sprintf+write rather than fprintf
 192  * to send output to the log file is intentional.  The reason is that
 193  * fprintf is not async-signal-safe.  "But," you protest, "SIGFPE is
 194  * not an asynchronous signal!  It's always handled by the same thread
 195  * that executed the fpop that provoked it."  That's true, but a prob-
 196  * lem arises because (i) base conversion in fprintf can cause a fp
 197  * exception and (ii) my signal handler acquires a mutex lock before
 198  * sending output to the log file (so that outputs for entries from
 199  * different threads aren't interspersed).  Therefore, if the code
 200  * were to use fprintf, a deadlock could occur as follows:
 201  *
 202  *      Thread A                        Thread B
 203  *
 204  *      Incurs a fp exception,          Calls fprintf,
 205  *      acquires log_lock               acquires file rmutex lock
 206  *
 207  *      Calls fprintf,                  Incurs a fp exception,
 208  *      waits for file rmutex lock      waits for log_lock
 209  *
 210  * (I could just verify that fprintf doesn't hold the rmutex lock while
 211  * it's doing the base conversion, but since efficiency is of little
 212  * concern here, I opted for the safe and dumb route.)
 213  */
 214 static void
 215 print_stack(int fd, char *addr, struct frame *fp)
 216 {
 217         int i;
 218         char *name, buf[30];
 219 
 220         for (i = 0; i < log_depth && addr != NULL; i++) {
 221                 if (__fex_sym(addr, &name) != NULL) {
 222                         write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx  ",
 223                             (long)addr));
 224                         write(fd, name, strlen(name));
 225                         write(fd, "\n", 1);
 226 
 227                         if (strcmp(name, "main") == 0)
 228                                 break;
 229                 } else {
 230                         write(fd, buf, sprintf(buf, "  0x%0" PDIG "lx\n",
 231                             (long)addr));
 232                 }
 233 
 234                 if (fp == NULL)
 235                         break;
 236 
 237                 addr = (char *)fp->fr_savpc;
 238                 fp = FRAMEP(fp->fr_savfp);
 239         }
 240 }
 241 
 242 void
 243 fex_log_entry(const char *msg)
 244 {
 245         ucontext_t uc;
 246         struct frame *fp;
 247         char *stk;
 248         int fd;
 249 
 250         /* if logging is disabled, just return */
 251         mutex_lock(&log_lock);
 252 
 253         if (log_fp == NULL) {
 254                 mutex_unlock(&log_lock);
 255                 return;
 256         }
 257 
 258         /*
 259          * get the frame pointer from the current context and
 260          * pop our own frame
 261          */
 262         getcontext(&uc);
 263 #if defined(__sparc) || defined(__amd64)
 264         fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]);
 265 #elif defined(__i386)                   /* !defined(__amd64) */
 266         fp = FRAMEP(uc.uc_mcontext.gregs[EBP]);
 267 #else
 268 #error Unknown architecture
 269 #endif
 270 
 271         if (fp == NULL) {
 272                 mutex_unlock(&log_lock);
 273                 return;
 274         }
 275 
 276         stk = (char *)fp->fr_savpc;
 277         fp = FRAMEP(fp->fr_savfp);
 278 
 279         /* if we've already logged this message here, don't make an entry */
 280         if (check_exc_list(stk, (unsigned long)msg, stk, fp)) {
 281                 mutex_unlock(&log_lock);
 282                 return;
 283         }
 284 
 285         /* make an entry */
 286         fd = fileno(log_fp);
 287         write(fd, "fex_log_entry: ", 15);
 288         write(fd, msg, strlen(msg));
 289         write(fd, "\n", 1);
 290         __fex_sym_init();
 291         print_stack(fd, stk, fp);
 292         mutex_unlock(&log_lock);
 293 }
 294 
 295 static const char *exception[FEX_NUM_EXC] = {
 296         "inexact result", "division by zero", "underflow", "overflow",
 297         "invalid operation (0/0)", "invalid operation (inf/inf)",
 298         "invalid operation (inf-inf)", "invalid operation (0*inf)",
 299         "invalid operation (sqrt)", "invalid operation (snan)",
 300         "invalid operation (int)", "invalid operation (cmp)"







 301 };
 302 
 303 void
 304 __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e, int m,
 305     void *p)
 306 {
 307         struct  frame *fp;
 308         char *stk, *name, buf[30];
 309         int fd;
 310 
 311         /* if logging is disabled, just return */
 312         mutex_lock(&log_lock);
 313 
 314         if (log_fp == NULL) {
 315                 mutex_unlock(&log_lock);
 316                 return;
 317         }
 318 
 319         /* get stack info */
 320 #if defined(__sparc)
 321         stk = (char *)uap->uc_mcontext.gregs[REG_PC];
 322         fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]);
 323 #elif defined(__amd64)
 324         stk = (char *)uap->uc_mcontext.gregs[REG_PC];
 325         fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]);
 326 #elif defined(__i386)                   /* !defined(__amd64) */
 327         stk = (char *)uap->uc_mcontext.gregs[PC];
 328         fp = FRAMEP(uap->uc_mcontext.gregs[EBP]);
 329 #else
 330 #error Unknown architecture
 331 #endif
 332 
 333         /*
 334          * if the handling mode is the default and this exception's
 335          * flag is already raised, don't make an entry
 336          */
 337         if (m == FEX_NONSTOP) {
 338                 switch (e) {
 339                 case fex_inexact:
 340 
 341                         if (f & FE_INEXACT) {
 342                                 mutex_unlock(&log_lock);
 343                                 return;
 344                         }
 345 
 346                         break;
 347                 case fex_underflow:
 348 
 349                         if (f & FE_UNDERFLOW) {
 350                                 mutex_unlock(&log_lock);
 351                                 return;
 352                         }
 353 
 354                         break;
 355                 case fex_overflow:
 356 
 357                         if (f & FE_OVERFLOW) {
 358                                 mutex_unlock(&log_lock);
 359                                 return;
 360                         }
 361 
 362                         break;
 363                 case fex_division:
 364 
 365                         if (f & FE_DIVBYZERO) {
 366                                 mutex_unlock(&log_lock);
 367                                 return;
 368                         }
 369 
 370                         break;
 371                 default:
 372 
 373                         if (f & FE_INVALID) {
 374                                 mutex_unlock(&log_lock);
 375                                 return;
 376                         }
 377 
 378                         break;
 379                 }
 380         }
 381 
 382         /*
 383          * if we've already logged this exception at this address,
 384          * don't make an entry
 385          */
 386         if (check_exc_list(addr, (unsigned long)e, stk, fp)) {
 387                 mutex_unlock(&log_lock);
 388                 return;
 389         }
 390 
 391         /* make an entry */
 392         fd = fileno(log_fp);
 393         write(fd, "Floating point ", 15);
 394         write(fd, exception[e], strlen(exception[e]));
 395         write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr));
 396         __fex_sym_init();
 397 
 398         if (__fex_sym(addr, &name) != NULL) {
 399                 write(fd, " ", 1);
 400                 write(fd, name, strlen(name));
 401         }
 402 
 403         switch (m) {
 404         case FEX_NONSTOP:
 405                 write(fd, ", nonstop mode\n", 15);
 406                 break;
 407 
 408         case FEX_ABORT:
 409                 write(fd, ", abort\n", 8);
 410                 break;
 411 
 412         case FEX_NOHANDLER:
 413 
 414                 if (p == (void *)SIG_DFL) {
 415                         write(fd, ", handler: SIG_DFL\n", 19);
 416                         break;
 417                 } else if (p == (void *)SIG_IGN) {

 418                         write(fd, ", handler: SIG_IGN\n", 19);
 419                         break;
 420                 }
 421 
 422         /* FALLTHROUGH */
 423         default:
 424                 write(fd, ", handler: ", 11);
 425 
 426                 if (__fex_sym((char *)p, &name) != NULL) {
 427                         write(fd, name, strlen(name));
 428                         write(fd, "\n", 1);
 429                 } else {
 430                         write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n",
 431                             (long)p));
 432                 }
 433 
 434                 break;
 435         }
 436 
 437         print_stack(fd, stk, fp);
 438         mutex_unlock(&log_lock);
 439 }