1 /* More subroutines needed by GCC output code on some machines. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
29 /* $FreeBSD: src/contrib/gcc/libgcc2.c,v 1.4 1999/10/27 09:45:47 obrien Exp $ */
30 /* $DragonFly: src/contrib/gcc/Attic/libgcc2.c,v 1.3 2003/12/10 22:25:04 dillon Exp $ */
32 /* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
38 /* We disable this when inhibit_libc, so that gcc can still be built without
39 needing header files first. */
40 /* ??? This is not a good solution, since prototypes may be required in
41 some cases for correct code. See also frame.c. */
43 /* fixproto guarantees these system headers exist. */
54 /* Don't use `fancy_abort' here even if config.h says to use it. */
59 #if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
63 /* In a cross-compilation situation, default to inhibiting compilation
64 of routines that use libc. */
66 #if defined(CROSS_COMPILE) && !defined(inhibit_libc)
70 /* Permit the tm.h file to select the endianness to use just for this
71 file. This is used when the endianness is determined when the
74 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
75 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
78 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
79 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
82 /* In the first part of this file, we are interfacing to calls generated
83 by the compiler itself. These calls pass values into these routines
84 which have very specific modes (rather than very specific types), and
85 these compiler-generated calls also expect any return values to have
86 very specific modes (rather than very specific types). Thus, we need
87 to avoid using regular C language type names in this part of the file
88 because the sizes for those types can be configured to be anything.
89 Instead we use the following special type names. */
91 typedef unsigned int UQItype __attribute__ ((mode (QI)));
92 typedef int SItype __attribute__ ((mode (SI)));
93 typedef unsigned int USItype __attribute__ ((mode (SI)));
94 typedef int DItype __attribute__ ((mode (DI)));
95 typedef unsigned int UDItype __attribute__ ((mode (DI)));
97 typedef float SFtype __attribute__ ((mode (SF)));
98 typedef float DFtype __attribute__ ((mode (DF)));
100 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
101 typedef float XFtype __attribute__ ((mode (XF)));
103 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
104 typedef float TFtype __attribute__ ((mode (TF)));
107 typedef int word_type __attribute__ ((mode (__word__)));
109 /* Make sure that we don't accidentally use any normal C language built-in
110 type names in the first part of this file. Instead we want to use *only*
111 the type names defined above. The following macro definitions insure
112 that if we *do* accidentally use some normal C language built-in type name,
113 we will get a syntax error. */
115 #define char bogus_type
116 #define short bogus_type
117 #define int bogus_type
118 #define long bogus_type
119 #define unsigned bogus_type
120 #define float bogus_type
121 #define double bogus_type
123 #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
125 /* DIstructs are pairs of SItype values in the order determined by
126 LIBGCC2_WORDS_BIG_ENDIAN. */
128 #if LIBGCC2_WORDS_BIG_ENDIAN
129 struct DIstruct {SItype high, low;};
131 struct DIstruct {SItype low, high;};
134 /* We need this union to unpack/pack DImode values, since we don't have
135 any arithmetic yet. Incoming DImode parameters are stored into the
136 `ll' field, and the unpacked result is read from the struct `s'. */
144 #if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
145 || defined (L_divdi3) || defined (L_udivdi3) \
146 || defined (L_moddi3) || defined (L_umoddi3))
148 #include "longlong.h"
150 #endif /* udiv or mul */
152 extern DItype __fixunssfdi (SFtype a);
153 extern DItype __fixunsdfdi (DFtype a);
154 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
155 extern DItype __fixunsxfdi (XFtype a);
157 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
158 extern DItype __fixunstfdi (TFtype a);
161 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
162 #if defined (L_divdi3) || defined (L_moddi3)
174 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
180 /* Unless shift functions are defined whith full ANSI prototypes,
181 parameter b will be promoted to int if word_type is smaller than an int. */
184 __lshrdi3 (DItype u, word_type b)
195 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
199 w.s.low = (USItype)uu.s.high >> -bm;
203 USItype carries = (USItype)uu.s.high << bm;
204 w.s.high = (USItype)uu.s.high >> b;
205 w.s.low = ((USItype)uu.s.low >> b) | carries;
214 __ashldi3 (DItype u, word_type b)
225 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
229 w.s.high = (USItype)uu.s.low << -bm;
233 USItype carries = (USItype)uu.s.low >> bm;
234 w.s.low = (USItype)uu.s.low << b;
235 w.s.high = ((USItype)uu.s.high << b) | carries;
244 __ashrdi3 (DItype u, word_type b)
255 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
258 /* w.s.high = 1..1 or 0..0 */
259 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
260 w.s.low = uu.s.high >> -bm;
264 USItype carries = (USItype)uu.s.high << bm;
265 w.s.high = uu.s.high >> b;
266 w.s.low = ((USItype)uu.s.low >> b) | carries;
280 w.s.low = ffs (uu.s.low);
283 w.s.low = ffs (uu.s.high);
286 w.s.low += BITS_PER_UNIT * sizeof (SItype);
295 __muldi3 (DItype u, DItype v)
303 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
304 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
305 + (USItype) uu.s.high * (USItype) vv.s.low);
312 #if defined (sdiv_qrnnd)
314 __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
321 if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
323 /* dividend, divisor, and quotient are nonnegative */
324 sdiv_qrnnd (q, r, a1, a0, d);
328 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
329 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
330 /* Divide (c1*2^32 + c0) by d */
331 sdiv_qrnnd (q, r, c1, c0, d);
332 /* Add 2^31 to quotient */
333 q += (USItype) 1 << (SI_TYPE_SIZE - 1);
338 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
339 c1 = a1 >> 1; /* A/2 */
340 c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
342 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
344 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
346 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
363 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
366 c0 = ~c0; /* logical NOT */
368 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
370 q = ~q; /* (A/2)/b1 */
373 r = 2*r + (a0 & 1); /* A/(2*b1) */
391 else /* Implies c1 = b1 */
392 { /* Hence a1 = d - 1 = 2*b1 - 1 */
410 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
412 __udiv_w_sdiv (USItype *rp __attribute__ ((__unused__)),
413 USItype a1 __attribute__ ((__unused__)),
414 USItype a0 __attribute__ ((__unused__)),
415 USItype d __attribute__ ((__unused__)))
422 #if (defined (L_udivdi3) || defined (L_divdi3) || \
423 defined (L_umoddi3) || defined (L_moddi3))
428 static const UQItype __clz_tab[] =
430 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
431 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
432 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
433 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
434 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
435 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
436 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
437 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
440 #if (defined (L_udivdi3) || defined (L_divdi3) || \
441 defined (L_umoddi3) || defined (L_moddi3))
445 __udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
450 USItype d0, d1, n0, n1, n2;
462 #if !UDIV_NEEDS_NORMALIZATION
469 udiv_qrnnd (q0, n0, n1, n0, d0);
472 /* Remainder in n0. */
479 d0 = 1 / d0; /* Divide intentionally by zero. */
481 udiv_qrnnd (q1, n1, 0, n1, d0);
482 udiv_qrnnd (q0, n0, n1, n0, d0);
484 /* Remainder in n0. */
495 #else /* UDIV_NEEDS_NORMALIZATION */
503 count_leading_zeros (bm, d0);
507 /* Normalize, i.e. make the most significant bit of the
511 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
515 udiv_qrnnd (q0, n0, n1, n0, d0);
518 /* Remainder in n0 >> bm. */
525 d0 = 1 / d0; /* Divide intentionally by zero. */
527 count_leading_zeros (bm, d0);
531 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
532 conclude (the most significant bit of n1 is set) /\ (the
533 leading quotient digit q1 = 1).
535 This special case is necessary, not an optimization.
536 (Shifts counts of SI_TYPE_SIZE are undefined.) */
545 b = SI_TYPE_SIZE - bm;
549 n1 = (n1 << bm) | (n0 >> b);
552 udiv_qrnnd (q1, n1, n2, n1, d0);
557 udiv_qrnnd (q0, n0, n1, n0, d0);
559 /* Remainder in n0 >> bm. */
569 #endif /* UDIV_NEEDS_NORMALIZATION */
580 /* Remainder in n1n0. */
592 count_leading_zeros (bm, d1);
595 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
596 conclude (the most significant bit of n1 is set) /\ (the
597 quotient digit q0 = 0 or 1).
599 This special case is necessary, not an optimization. */
601 /* The condition on the next line takes advantage of that
602 n1 >= d1 (true due to program flow). */
603 if (n1 > d1 || n0 >= d0)
606 sub_ddmmss (n1, n0, n1, n0, d1, d0);
625 b = SI_TYPE_SIZE - bm;
627 d1 = (d1 << bm) | (d0 >> b);
630 n1 = (n1 << bm) | (n0 >> b);
633 udiv_qrnnd (q0, n1, n2, n1, d1);
634 umul_ppmm (m1, m0, q0, d0);
636 if (m1 > n1 || (m1 == n1 && m0 > n0))
639 sub_ddmmss (m1, m0, m1, m0, d1, d0);
644 /* Remainder in (n1n0 - m1m0) >> bm. */
647 sub_ddmmss (n1, n0, n1, n0, m1, m0);
648 rr.s.low = (n1 << b) | (n0 >> bm);
649 rr.s.high = n1 >> bm;
663 UDItype __udivmoddi4 ();
666 __divdi3 (DItype u, DItype v)
677 uu.ll = __negdi2 (uu.ll);
680 vv.ll = __negdi2 (vv.ll);
682 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
691 UDItype __udivmoddi4 ();
693 __moddi3 (DItype u, DItype v)
704 uu.ll = __negdi2 (uu.ll);
706 vv.ll = __negdi2 (vv.ll);
708 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
717 UDItype __udivmoddi4 ();
719 __umoddi3 (UDItype u, UDItype v)
723 (void) __udivmoddi4 (u, v, &w);
730 UDItype __udivmoddi4 ();
732 __udivdi3 (UDItype n, UDItype d)
734 return __udivmoddi4 (n, d, (UDItype *) 0);
740 __cmpdi2 (DItype a, DItype b)
744 au.ll = a, bu.ll = b;
746 if (au.s.high < bu.s.high)
748 else if (au.s.high > bu.s.high)
750 if ((USItype) au.s.low < (USItype) bu.s.low)
752 else if ((USItype) au.s.low > (USItype) bu.s.low)
760 __ucmpdi2 (DItype a, DItype b)
764 au.ll = a, bu.ll = b;
766 if ((USItype) au.s.high < (USItype) bu.s.high)
768 else if ((USItype) au.s.high > (USItype) bu.s.high)
770 if ((USItype) au.s.low < (USItype) bu.s.low)
772 else if ((USItype) au.s.low > (USItype) bu.s.low)
778 #if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
779 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
780 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
783 __fixunstfdi (TFtype a)
791 /* Compute high word of result, as a flonum. */
792 b = (a / HIGH_WORD_COEFF);
793 /* Convert that to fixed (but not to DItype!),
794 and shift it into the high word. */
797 /* Remove high part from the TFtype, leaving the low part as flonum. */
799 /* Convert that to fixed (but not to DItype!) and add it in.
800 Sometimes A comes out negative. This is significant, since
801 A has more bits than a long int does. */
803 v -= (USItype) (- a);
810 #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
815 return - __fixunstfdi (-a);
816 return __fixunstfdi (a);
820 #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
821 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
822 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
825 __fixunsxfdi (XFtype a)
833 /* Compute high word of result, as a flonum. */
834 b = (a / HIGH_WORD_COEFF);
835 /* Convert that to fixed (but not to DItype!),
836 and shift it into the high word. */
839 /* Remove high part from the XFtype, leaving the low part as flonum. */
841 /* Convert that to fixed (but not to DItype!) and add it in.
842 Sometimes A comes out negative. This is significant, since
843 A has more bits than a long int does. */
845 v -= (USItype) (- a);
852 #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
857 return - __fixunsxfdi (-a);
858 return __fixunsxfdi (a);
863 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
864 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
867 __fixunsdfdi (DFtype a)
875 /* Compute high word of result, as a flonum. */
876 b = (a / HIGH_WORD_COEFF);
877 /* Convert that to fixed (but not to DItype!),
878 and shift it into the high word. */
881 /* Remove high part from the DFtype, leaving the low part as flonum. */
883 /* Convert that to fixed (but not to DItype!) and add it in.
884 Sometimes A comes out negative. This is significant, since
885 A has more bits than a long int does. */
887 v -= (USItype) (- a);
899 return - __fixunsdfdi (-a);
900 return __fixunsdfdi (a);
905 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
906 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
909 __fixunssfdi (SFtype original_a)
911 /* Convert the SFtype to a DFtype, because that is surely not going
912 to lose any bits. Some day someone else can write a faster version
913 that avoids converting to DFtype, and verify it really works right. */
914 DFtype a = original_a;
921 /* Compute high word of result, as a flonum. */
922 b = (a / HIGH_WORD_COEFF);
923 /* Convert that to fixed (but not to DItype!),
924 and shift it into the high word. */
927 /* Remove high part from the DFtype, leaving the low part as flonum. */
929 /* Convert that to fixed (but not to DItype!) and add it in.
930 Sometimes A comes out negative. This is significant, since
931 A has more bits than a long int does. */
933 v -= (USItype) (- a);
945 return - __fixunssfdi (-a);
946 return __fixunssfdi (a);
950 #if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
951 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
952 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
953 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
956 __floatdixf (DItype u)
960 d = (SItype) (u >> WORD_SIZE);
961 d *= HIGH_HALFWORD_COEFF;
962 d *= HIGH_HALFWORD_COEFF;
963 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
969 #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
970 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
971 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
972 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
975 __floatditf (DItype u)
979 d = (SItype) (u >> WORD_SIZE);
980 d *= HIGH_HALFWORD_COEFF;
981 d *= HIGH_HALFWORD_COEFF;
982 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
989 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
990 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
991 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
994 __floatdidf (DItype u)
998 d = (SItype) (u >> WORD_SIZE);
999 d *= HIGH_HALFWORD_COEFF;
1000 d *= HIGH_HALFWORD_COEFF;
1001 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
1008 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1009 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1010 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1011 #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
1013 /* Define codes for all the float formats that we know of. Note
1014 that this is copied from real.h. */
1016 #define UNKNOWN_FLOAT_FORMAT 0
1017 #define IEEE_FLOAT_FORMAT 1
1018 #define VAX_FLOAT_FORMAT 2
1019 #define IBM_FLOAT_FORMAT 3
1021 /* Default to IEEE float if not specified. Nearly all machines use it. */
1022 #ifndef HOST_FLOAT_FORMAT
1023 #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1026 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1031 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1036 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1042 __floatdisf (DItype u)
1044 /* Do the calculation in DFmode
1045 so that we don't lose any of the precision of the high word
1046 while multiplying it. */
1049 /* Protect against double-rounding error.
1050 Represent any low-order bits, that might be truncated in DFmode,
1051 by a bit that won't be lost. The bit can go in anywhere below the
1052 rounding position of the SFmode. A fixed mask and bit position
1053 handles all usual configurations. It doesn't handle the case
1054 of 128-bit DImode, however. */
1055 if (DF_SIZE < DI_SIZE
1056 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1058 #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1059 if (! (- ((DItype) 1 << DF_SIZE) < u
1060 && u < ((DItype) 1 << DF_SIZE)))
1062 if ((USItype) u & (REP_BIT - 1))
1066 f = (SItype) (u >> WORD_SIZE);
1067 f *= HIGH_HALFWORD_COEFF;
1068 f *= HIGH_HALFWORD_COEFF;
1069 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1075 #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
1076 /* Reenable the normal types, in case limits.h needs them. */
1089 __fixunsxfsi (XFtype a)
1091 if (a >= - (DFtype) LONG_MIN)
1092 return (SItype) (a + LONG_MIN) - LONG_MIN;
1098 /* Reenable the normal types, in case limits.h needs them. */
1111 __fixunsdfsi (DFtype a)
1113 if (a >= - (DFtype) LONG_MIN)
1114 return (SItype) (a + LONG_MIN) - LONG_MIN;
1120 /* Reenable the normal types, in case limits.h needs them. */
1133 __fixunssfsi (SFtype a)
1135 if (a >= - (SFtype) LONG_MIN)
1136 return (SItype) (a + LONG_MIN) - LONG_MIN;
1141 /* From here on down, the routines use normal data types. */
1143 #define SItype bogus_type
1144 #define USItype bogus_type
1145 #define DItype bogus_type
1146 #define UDItype bogus_type
1147 #define SFtype bogus_type
1148 #define DFtype bogus_type
1160 /* Like bcmp except the sign is meaningful.
1161 Result is negative if S1 is less than S2,
1162 positive if S1 is greater, 0 if S1 and S2 are equal. */
1165 __gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
1169 unsigned char c1 = *s1++, c2 = *s2++;
1186 #if defined(__svr4__) || defined(__alliant__)
1190 /* The Alliant needs the added underscore. */
1191 asm (".globl __builtin_saveregs");
1192 asm ("__builtin_saveregs:");
1193 asm (".globl ___builtin_saveregs");
1194 asm ("___builtin_saveregs:");
1196 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1197 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1198 area and also for a new va_list
1200 /* Save all argument registers in the arg reg save area. The
1201 arg reg save area must have the following layout (according
1213 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1214 asm (" fst.q %f12,16(%sp)");
1216 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1217 asm (" st.l %r17,36(%sp)");
1218 asm (" st.l %r18,40(%sp)");
1219 asm (" st.l %r19,44(%sp)");
1220 asm (" st.l %r20,48(%sp)");
1221 asm (" st.l %r21,52(%sp)");
1222 asm (" st.l %r22,56(%sp)");
1223 asm (" st.l %r23,60(%sp)");
1224 asm (" st.l %r24,64(%sp)");
1225 asm (" st.l %r25,68(%sp)");
1226 asm (" st.l %r26,72(%sp)");
1227 asm (" st.l %r27,76(%sp)");
1229 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1230 va_list structure. Put in into
1231 r16 so that it will be returned
1234 /* Initialize all fields of the new va_list structure. This
1235 structure looks like:
1238 unsigned long ireg_used;
1239 unsigned long freg_used;
1245 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1246 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1247 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1248 asm (" bri %r1"); /* delayed return */
1249 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1251 #else /* not __svr4__ */
1252 #if defined(__PARAGON__)
1254 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1255 * and we stand a better chance of hooking into libraries
1256 * compiled by PGI. [andyp@ssd.intel.com]
1260 asm (".globl __builtin_saveregs");
1261 asm ("__builtin_saveregs:");
1262 asm (".globl ___builtin_saveregs");
1263 asm ("___builtin_saveregs:");
1265 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1266 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1267 area and also for a new va_list
1269 /* Save all argument registers in the arg reg save area. The
1270 arg reg save area must have the following layout (according
1282 asm (" fst.q f8, 0(sp)");
1283 asm (" fst.q f12,16(sp)");
1284 asm (" st.l r16,32(sp)");
1285 asm (" st.l r17,36(sp)");
1286 asm (" st.l r18,40(sp)");
1287 asm (" st.l r19,44(sp)");
1288 asm (" st.l r20,48(sp)");
1289 asm (" st.l r21,52(sp)");
1290 asm (" st.l r22,56(sp)");
1291 asm (" st.l r23,60(sp)");
1292 asm (" st.l r24,64(sp)");
1293 asm (" st.l r25,68(sp)");
1294 asm (" st.l r26,72(sp)");
1295 asm (" st.l r27,76(sp)");
1297 asm (" adds 80,sp,r16"); /* compute the address of the new
1298 va_list structure. Put in into
1299 r16 so that it will be returned
1302 /* Initialize all fields of the new va_list structure. This
1303 structure looks like:
1306 unsigned long ireg_used;
1307 unsigned long freg_used;
1313 asm (" st.l r0, 0(r16)"); /* nfixed */
1314 asm (" st.l r0, 4(r16)"); /* nfloating */
1315 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1316 asm (" bri r1"); /* delayed return */
1317 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1318 #else /* not __PARAGON__ */
1322 asm (".globl ___builtin_saveregs");
1323 asm ("___builtin_saveregs:");
1324 asm (" mov sp,r30");
1325 asm (" andnot 0x0f,sp,sp");
1326 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1328 /* Fill in the __va_struct. */
1329 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1330 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1331 asm (" st.l r18, 8(sp)");
1332 asm (" st.l r19,12(sp)");
1333 asm (" st.l r20,16(sp)");
1334 asm (" st.l r21,20(sp)");
1335 asm (" st.l r22,24(sp)");
1336 asm (" st.l r23,28(sp)");
1337 asm (" st.l r24,32(sp)");
1338 asm (" st.l r25,36(sp)");
1339 asm (" st.l r26,40(sp)");
1340 asm (" st.l r27,44(sp)");
1342 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1343 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1345 /* Fill in the __va_ctl. */
1346 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1347 asm (" st.l r28,84(sp)"); /* pointer to more args */
1348 asm (" st.l r0, 88(sp)"); /* nfixed */
1349 asm (" st.l r0, 92(sp)"); /* nfloating */
1351 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1353 asm (" mov r30,sp");
1354 /* recover stack and pass address to start
1356 #endif /* not __PARAGON__ */
1357 #endif /* not __svr4__ */
1358 #else /* not __i860__ */
1360 asm (".global __builtin_saveregs");
1361 asm ("__builtin_saveregs:");
1362 asm (".global ___builtin_saveregs");
1363 asm ("___builtin_saveregs:");
1364 #ifdef NEED_PROC_COMMAND
1367 asm ("st %i0,[%fp+68]");
1368 asm ("st %i1,[%fp+72]");
1369 asm ("st %i2,[%fp+76]");
1370 asm ("st %i3,[%fp+80]");
1371 asm ("st %i4,[%fp+84]");
1373 asm ("st %i5,[%fp+88]");
1374 #ifdef NEED_TYPE_COMMAND
1375 asm (".type __builtin_saveregs,#function");
1376 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1378 #else /* not __sparc__ */
1379 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1383 asm (" .set nomips16");
1385 asm (" .ent __builtin_saveregs");
1386 asm (" .globl __builtin_saveregs");
1387 asm ("__builtin_saveregs:");
1388 asm (" sw $4,0($30)");
1389 asm (" sw $5,4($30)");
1390 asm (" sw $6,8($30)");
1391 asm (" sw $7,12($30)");
1393 asm (" .end __builtin_saveregs");
1394 #else /* not __mips__, etc. */
1397 __builtin_saveregs ()
1402 #endif /* not __mips__ */
1403 #endif /* not __sparc__ */
1404 #endif /* not __i860__ */
1408 #ifndef inhibit_libc
1410 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1412 /* This is used by the `assert' macro. */
1413 extern void __eprintf (const char *, const char *, unsigned int, const char *)
1414 __attribute__ ((__noreturn__));
1417 __eprintf (const char *string, const char *expression,
1418 unsigned int line, const char *filename)
1420 fprintf (stderr, string, expression, line, filename);
1430 /* Structure emitted by -a */
1434 const char *filename;
1438 const unsigned long *addresses;
1440 /* Older GCC's did not emit these fields. */
1442 const char **functions;
1443 const long *line_nums;
1444 const char **filenames;
1448 #ifdef BLOCK_PROFILER_CODE
1451 #ifndef inhibit_libc
1453 /* Simple minded basic block profiling output dumper for
1454 systems that don't provide tcov support. At present,
1455 it requires atexit and stdio. */
1457 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1461 #include "gbl-ctors.h"
1462 #include "gcov-io.h"
1465 static struct bb *bb_head;
1467 /* Return the number of digits needed to print a value */
1468 /* __inline__ */ static int num_digits (long value, int base)
1470 int minus = (value < 0 && base != 16);
1471 unsigned long v = (minus) ? -value : value;
1485 __bb_exit_func (void)
1487 FILE *da_file, *file;
1494 i = strlen (bb_head->filename) - 3;
1496 if (!strcmp (bb_head->filename+i, ".da"))
1498 /* Must be -fprofile-arcs not -a.
1499 Dump data in a form that gcov expects. */
1503 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1505 /* If the file exists, and the number of counts in it is the same,
1506 then merge them in. */
1508 if ((da_file = fopen (ptr->filename, "r")) != 0)
1512 if (__read_long (&n_counts, da_file, 8) != 0)
1514 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1519 if (n_counts == ptr->ncounts)
1523 for (i = 0; i < n_counts; i++)
1527 if (__read_long (&v, da_file, 8) != 0)
1529 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1533 ptr->counts[i] += v;
1537 if (fclose (da_file) == EOF)
1538 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1541 if ((da_file = fopen (ptr->filename, "w")) == 0)
1543 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1548 /* ??? Should first write a header to the file. Preferably, a 4 byte
1549 magic number, 4 bytes containing the time the program was
1550 compiled, 4 bytes containing the last modification time of the
1551 source file, and 4 bytes indicating the compiler options used.
1553 That way we can easily verify that the proper source/executable/
1554 data file combination is being used from gcov. */
1556 if (__write_long (ptr->ncounts, da_file, 8) != 0)
1559 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1565 long *count_ptr = ptr->counts;
1567 for (j = ptr->ncounts; j > 0; j--)
1569 if (__write_long (*count_ptr, da_file, 8) != 0)
1577 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1581 if (fclose (da_file) == EOF)
1582 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1589 /* Must be basic block profiling. Emit a human readable output file. */
1591 file = fopen ("bb.out", "a");
1600 /* This is somewhat type incorrect, but it avoids worrying about
1601 exactly where time.h is included from. It should be ok unless
1602 a void * differs from other pointer formats, or if sizeof (long)
1603 is < sizeof (time_t). It would be nice if we could assume the
1604 use of rationale standards here. */
1606 time ((void *) &time_value);
1607 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1609 /* We check the length field explicitly in order to allow compatibility
1610 with older GCC's which did not provide it. */
1612 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1615 int func_p = (ptr->nwords >= sizeof (struct bb)
1616 && ptr->nwords <= 1000
1618 int line_p = (func_p && ptr->line_nums);
1619 int file_p = (func_p && ptr->filenames);
1620 int addr_p = (ptr->addresses != 0);
1621 long ncounts = ptr->ncounts;
1627 int blk_len = num_digits (ncounts, 10);
1632 fprintf (file, "File %s, %ld basic blocks \n\n",
1633 ptr->filename, ncounts);
1635 /* Get max values for each field. */
1636 for (i = 0; i < ncounts; i++)
1641 if (cnt_max < ptr->counts[i])
1642 cnt_max = ptr->counts[i];
1644 if (addr_p && addr_max < ptr->addresses[i])
1645 addr_max = ptr->addresses[i];
1647 if (line_p && line_max < ptr->line_nums[i])
1648 line_max = ptr->line_nums[i];
1652 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1660 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1667 addr_len = num_digits (addr_max, 16);
1668 cnt_len = num_digits (cnt_max, 10);
1669 line_len = num_digits (line_max, 10);
1671 /* Now print out the basic block information. */
1672 for (i = 0; i < ncounts; i++)
1675 " Block #%*d: executed %*ld time(s)",
1677 cnt_len, ptr->counts[i]);
1680 fprintf (file, " address= 0x%.*lx", addr_len,
1684 fprintf (file, " function= %-*s", func_len,
1685 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1688 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1691 fprintf (file, " file= %s",
1692 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1694 fprintf (file, "\n");
1697 fprintf (file, "\n");
1701 fprintf (file, "\n\n");
1707 __bb_init_func (struct bb *blocks)
1709 /* User is supposed to check whether the first word is non-0,
1710 but just in case.... */
1712 if (blocks->zero_word)
1716 /* Initialize destructor. */
1718 ON_EXIT (__bb_exit_func, 0);
1721 /* Set up linked list. */
1722 blocks->zero_word = 1;
1723 blocks->next = bb_head;
1727 #ifndef MACHINE_STATE_SAVE
1728 #define MACHINE_STATE_SAVE(ID)
1730 #ifndef MACHINE_STATE_RESTORE
1731 #define MACHINE_STATE_RESTORE(ID)
1734 /* Number of buckets in hashtable of basic block addresses. */
1736 #define BB_BUCKETS 311
1738 /* Maximum length of string in file bb.in. */
1740 #define BBINBUFSIZE 500
1742 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1743 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
1745 #define BBINBUFSIZESTR "499"
1749 struct bb_edge *next;
1750 unsigned long src_addr;
1751 unsigned long dst_addr;
1752 unsigned long count;
1757 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1762 struct bb_func *next;
1765 enum bb_func_mode mode;
1768 /* This is the connection to the outside world.
1769 The BLOCK_PROFILER macro must set __bb.blocks
1770 and __bb.blockno. */
1773 unsigned long blockno;
1777 /* Vars to store addrs of source and destination basic blocks
1780 static unsigned long bb_src = 0;
1781 static unsigned long bb_dst = 0;
1783 static FILE *bb_tracefile = (FILE *) 0;
1784 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1785 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1786 static unsigned long bb_callcount = 0;
1787 static int bb_mode = 0;
1789 static unsigned long *bb_stack = (unsigned long *) 0;
1790 static size_t bb_stacksize = 0;
1792 static int reported = 0;
1795 Always : Print execution frequencies of basic blocks
1797 bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1798 bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1799 bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1800 bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1805 /*#include <sys/types.h>*/
1806 #include <sys/stat.h>
1807 /*#include <malloc.h>*/
1809 /* Commands executed by gopen. */
1811 #define GOPENDECOMPRESS "gzip -cd "
1812 #define GOPENCOMPRESS "gzip -c >"
1814 /* Like fopen but pipes through gzip. mode may only be "r" or "w".
1815 If it does not compile, simply replace gopen by fopen and delete
1816 '.gz' from any first parameter to gopen. */
1819 gopen (char *fn, char *mode)
1827 if (mode[0] != 'r' && mode[0] != 'w')
1830 p = fn + strlen (fn)-1;
1831 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1832 || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1839 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1840 + sizeof (GOPENDECOMPRESS));
1841 strcpy (s, GOPENDECOMPRESS);
1842 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1843 f = popen (s, mode);
1851 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1852 + sizeof (GOPENCOMPRESS));
1853 strcpy (s, GOPENCOMPRESS);
1854 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1855 if (!(f = popen (s, mode)))
1856 f = fopen (s, mode);
1863 return fopen (fn, mode);
1873 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1881 #endif /* HAVE_POPEN */
1883 /* Called once per program. */
1886 __bb_exit_trace_func ()
1888 FILE *file = fopen ("bb.out", "a");
1901 gclose (bb_tracefile);
1903 fclose (bb_tracefile);
1904 #endif /* HAVE_POPEN */
1907 /* Check functions in `bb.in'. */
1912 const struct bb_func *p;
1913 int printed_something = 0;
1917 /* This is somewhat type incorrect. */
1918 time ((void *) &time_value);
1920 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1922 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1924 if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1926 for (blk = 0; blk < ptr->ncounts; blk++)
1928 if (!strcmp (p->funcname, ptr->functions[blk]))
1933 if (!printed_something)
1935 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1936 printed_something = 1;
1939 fprintf (file, "\tFunction %s", p->funcname);
1941 fprintf (file, " of file %s", p->filename);
1942 fprintf (file, "\n" );
1947 if (printed_something)
1948 fprintf (file, "\n");
1954 if (!bb_hashbuckets)
1958 fprintf (stderr, "Profiler: out of memory\n");
1968 unsigned long addr_max = 0;
1969 unsigned long cnt_max = 0;
1973 /* This is somewhat type incorrect, but it avoids worrying about
1974 exactly where time.h is included from. It should be ok unless
1975 a void * differs from other pointer formats, or if sizeof (long)
1976 is < sizeof (time_t). It would be nice if we could assume the
1977 use of rationale standards here. */
1979 time ((void *) &time_value);
1980 fprintf (file, "Basic block jump tracing");
1982 switch (bb_mode & 12)
1985 fprintf (file, " (with call)");
1989 /* Print nothing. */
1993 fprintf (file, " (with call & ret)");
1997 fprintf (file, " (with ret)");
2001 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
2003 for (i = 0; i < BB_BUCKETS; i++)
2005 struct bb_edge *bucket = bb_hashbuckets[i];
2006 for ( ; bucket; bucket = bucket->next )
2008 if (addr_max < bucket->src_addr)
2009 addr_max = bucket->src_addr;
2010 if (addr_max < bucket->dst_addr)
2011 addr_max = bucket->dst_addr;
2012 if (cnt_max < bucket->count)
2013 cnt_max = bucket->count;
2016 addr_len = num_digits (addr_max, 16);
2017 cnt_len = num_digits (cnt_max, 10);
2019 for ( i = 0; i < BB_BUCKETS; i++)
2021 struct bb_edge *bucket = bb_hashbuckets[i];
2022 for ( ; bucket; bucket = bucket->next )
2024 fprintf (file, "Jump from block 0x%.*lx to "
2025 "block 0x%.*lx executed %*lu time(s)\n",
2026 addr_len, bucket->src_addr,
2027 addr_len, bucket->dst_addr,
2028 cnt_len, bucket->count);
2032 fprintf (file, "\n");
2040 /* Free allocated memory. */
2045 struct bb_func *old = f;
2048 if (old->funcname) free (old->funcname);
2049 if (old->filename) free (old->filename);
2060 for (i = 0; i < BB_BUCKETS; i++)
2062 struct bb_edge *old, *bucket = bb_hashbuckets[i];
2067 bucket = bucket->next;
2071 free (bb_hashbuckets);
2074 for (b = bb_head; b; b = b->next)
2075 if (b->flags) free (b->flags);
2078 /* Called once per program. */
2085 char buf[BBINBUFSIZE];
2088 enum bb_func_mode m;
2091 /* Initialize destructor. */
2092 ON_EXIT (__bb_exit_func, 0);
2095 if (!(file = fopen ("bb.in", "r")))
2098 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2110 if (!strcmp (p, "__bb_trace__"))
2112 else if (!strcmp (p, "__bb_jumps__"))
2114 else if (!strcmp (p, "__bb_hidecall__"))
2116 else if (!strcmp (p, "__bb_showret__"))
2120 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2124 f->next = bb_func_head;
2125 if ((pos = strchr (p, ':')))
2127 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2129 strcpy (f->funcname, pos+1);
2131 if ((f->filename = (char *) malloc (l+1)))
2133 strncpy (f->filename, p, l);
2134 f->filename[l] = '\0';
2137 f->filename = (char *) 0;
2141 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2143 strcpy (f->funcname, p);
2144 f->filename = (char *) 0;
2156 bb_tracefile = gopen ("bbtrace.gz", "w");
2161 bb_tracefile = fopen ("bbtrace", "w");
2163 #endif /* HAVE_POPEN */
2167 bb_hashbuckets = (struct bb_edge **)
2168 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2170 memset (bb_hashbuckets, 0, BB_BUCKETS * sizeof (struct bb_edge *));
2176 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2180 /* Initialize destructor. */
2181 ON_EXIT (__bb_exit_trace_func, 0);
2186 /* Called upon entering a basic block. */
2191 struct bb_edge *bucket;
2193 MACHINE_STATE_SAVE("1")
2195 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2198 bb_dst = __bb.blocks->addresses[__bb.blockno];
2199 __bb.blocks->counts[__bb.blockno]++;
2203 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2208 struct bb_edge **startbucket, **oldnext;
2210 oldnext = startbucket
2211 = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2212 bucket = *startbucket;
2214 for (bucket = *startbucket; bucket;
2215 oldnext = &(bucket->next), bucket = *oldnext)
2217 if (bucket->src_addr == bb_src
2218 && bucket->dst_addr == bb_dst)
2221 *oldnext = bucket->next;
2222 bucket->next = *startbucket;
2223 *startbucket = bucket;
2228 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2234 fprintf (stderr, "Profiler: out of memory\n");
2241 bucket->src_addr = bb_src;
2242 bucket->dst_addr = bb_dst;
2243 bucket->next = *startbucket;
2244 *startbucket = bucket;
2255 MACHINE_STATE_RESTORE("1")
2259 /* Called when returning from a function and `__bb_showret__' is set. */
2262 __bb_trace_func_ret ()
2264 struct bb_edge *bucket;
2266 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2271 struct bb_edge **startbucket, **oldnext;
2273 oldnext = startbucket
2274 = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2275 bucket = *startbucket;
2277 for (bucket = *startbucket; bucket;
2278 oldnext = &(bucket->next), bucket = *oldnext)
2280 if (bucket->src_addr == bb_dst
2281 && bucket->dst_addr == bb_src)
2284 *oldnext = bucket->next;
2285 bucket->next = *startbucket;
2286 *startbucket = bucket;
2291 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2297 fprintf (stderr, "Profiler: out of memory\n");
2304 bucket->src_addr = bb_dst;
2305 bucket->dst_addr = bb_src;
2306 bucket->next = *startbucket;
2307 *startbucket = bucket;
2320 /* Called upon entering the first function of a file. */
2323 __bb_init_file (struct bb *blocks)
2326 const struct bb_func *p;
2327 long blk, ncounts = blocks->ncounts;
2328 const char **functions = blocks->functions;
2330 /* Set up linked list. */
2331 blocks->zero_word = 1;
2332 blocks->next = bb_head;
2337 || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2340 for (blk = 0; blk < ncounts; blk++)
2341 blocks->flags[blk] = 0;
2343 for (blk = 0; blk < ncounts; blk++)
2345 for (p = bb_func_head; p; p = p->next)
2347 if (!strcmp (p->funcname, functions[blk])
2348 && (!p->filename || !strcmp (p->filename, blocks->filename)))
2350 blocks->flags[blk] |= p->mode;
2357 /* Called when exiting from a function. */
2363 MACHINE_STATE_SAVE("2")
2367 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2369 bb_src = bb_stack[bb_callcount];
2371 __bb_trace_func_ret ();
2377 MACHINE_STATE_RESTORE("2")
2381 /* Called when entering a function. */
2384 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2386 static int trace_init = 0;
2388 MACHINE_STATE_SAVE("3")
2390 if (!blocks->zero_word)
2397 __bb_init_file (blocks);
2407 if (bb_callcount >= bb_stacksize)
2409 size_t newsize = bb_callcount + 100;
2411 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2416 fprintf (stderr, "Profiler: out of memory\n");
2420 goto stack_overflow;
2422 bb_stacksize = newsize;
2424 bb_stack[bb_callcount] = bb_src;
2435 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2441 bb_stack[bb_callcount] = bb_src;
2444 MACHINE_STATE_RESTORE("3")
2447 #endif /* not inhibit_libc */
2448 #endif /* not BLOCK_PROFILER_CODE */
2452 unsigned int __shtab[] = {
2453 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2454 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2455 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2456 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2457 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2458 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2459 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2460 0x10000000, 0x20000000, 0x40000000, 0x80000000
2464 #ifdef L_clear_cache
2465 /* Clear part of an instruction cache. */
2467 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2470 __clear_cache (char *beg, char *end)
2472 #ifdef CLEAR_INSN_CACHE
2473 CLEAR_INSN_CACHE (beg, end);
2475 #ifdef INSN_CACHE_SIZE
2476 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2477 static int initialized;
2481 typedef (*function_ptr) ();
2483 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2484 /* It's cheaper to clear the whole cache.
2485 Put in a series of jump instructions so that calling the beginning
2486 of the cache will clear the whole thing. */
2490 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2491 & -INSN_CACHE_LINE_WIDTH);
2492 int end_ptr = ptr + INSN_CACHE_SIZE;
2494 while (ptr < end_ptr)
2496 *(INSTRUCTION_TYPE *)ptr
2497 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2498 ptr += INSN_CACHE_LINE_WIDTH;
2500 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2505 /* Call the beginning of the sequence. */
2506 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2507 & -INSN_CACHE_LINE_WIDTH))
2510 #else /* Cache is large. */
2514 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2515 & -INSN_CACHE_LINE_WIDTH);
2517 while (ptr < (int) array + sizeof array)
2519 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2520 ptr += INSN_CACHE_LINE_WIDTH;
2526 /* Find the location in array that occupies the same cache line as BEG. */
2528 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2529 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2530 & -INSN_CACHE_PLANE_SIZE)
2533 /* Compute the cache alignment of the place to stop clearing. */
2534 #if 0 /* This is not needed for gcc's purposes. */
2535 /* If the block to clear is bigger than a cache plane,
2536 we clear the entire cache, and OFFSET is already correct. */
2537 if (end < beg + INSN_CACHE_PLANE_SIZE)
2539 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2540 & -INSN_CACHE_LINE_WIDTH)
2541 & (INSN_CACHE_PLANE_SIZE - 1));
2543 #if INSN_CACHE_DEPTH > 1
2544 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2545 if (end_addr <= start_addr)
2546 end_addr += INSN_CACHE_PLANE_SIZE;
2548 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2550 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2551 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2553 while (addr != stop)
2555 /* Call the return instruction at ADDR. */
2556 ((function_ptr) addr) ();
2558 addr += INSN_CACHE_LINE_WIDTH;
2561 #else /* just one plane */
2564 /* Call the return instruction at START_ADDR. */
2565 ((function_ptr) start_addr) ();
2567 start_addr += INSN_CACHE_LINE_WIDTH;
2569 while ((start_addr % INSN_CACHE_SIZE) != offset);
2570 #endif /* just one plane */
2571 #endif /* Cache is large */
2572 #endif /* Cache exists */
2573 #endif /* CLEAR_INSN_CACHE */
2576 #endif /* L_clear_cache */
2580 /* Jump to a trampoline, loading the static chain address. */
2582 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
2594 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2598 mprotect (char *addr, int len, int prot)
2615 if (VirtualProtect (addr, len, np, &op))
2621 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
2623 #ifdef TRANSFER_FROM_TRAMPOLINE
2624 TRANSFER_FROM_TRAMPOLINE
2627 #if defined (NeXT) && defined (__MACH__)
2629 /* Make stack executable so we can call trampolines on stack.
2630 This is called from INITIALIZE_TRAMPOLINE in next.h. */
2634 #include <mach/mach.h>
2638 __enable_execute_stack (char *addr)
2641 char *eaddr = addr + TRAMPOLINE_SIZE;
2642 vm_address_t a = (vm_address_t) addr;
2644 /* turn on execute access on stack */
2645 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2646 if (r != KERN_SUCCESS)
2648 mach_error("vm_protect VM_PROT_ALL", r);
2652 /* We inline the i-cache invalidation for speed */
2654 #ifdef CLEAR_INSN_CACHE
2655 CLEAR_INSN_CACHE (addr, eaddr);
2657 __clear_cache ((int) addr, (int) eaddr);
2661 #endif /* defined (NeXT) && defined (__MACH__) */
2665 /* Make stack executable so we can call trampolines on stack.
2666 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2668 #include <sys/mman.h>
2669 #include <sys/vmparam.h>
2670 #include <machine/machparam.h>
2673 __enable_execute_stack ()
2676 static unsigned lowest = USRSTACK;
2677 unsigned current = (unsigned) &fp & -NBPG;
2679 if (lowest > current)
2681 unsigned len = lowest - current;
2682 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2686 /* Clear instruction cache in case an old trampoline is in it. */
2689 #endif /* __convex__ */
2693 /* Modified from the convex -code above. */
2695 #include <sys/param.h>
2697 #include <sys/m88kbcs.h>
2700 __enable_execute_stack ()
2703 static unsigned long lowest = USRSTACK;
2704 unsigned long current = (unsigned long) &save_errno & -NBPC;
2706 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2707 address is seen as 'negative'. That is the case with the stack. */
2710 if (lowest > current)
2712 unsigned len=lowest-current;
2713 memctl(current,len,MCT_TEXT);
2717 memctl(current,NBPC,MCT_TEXT);
2721 #endif /* __sysV88__ */
2725 #include <sys/signal.h>
2728 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
2729 so define it here, because we need it in __clear_insn_cache below */
2730 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
2731 hence we enable this stuff only if MCT_TEXT is #define'd. */
2746 /* Clear instruction cache so we can call trampolines on stack.
2747 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
2750 __clear_insn_cache ()
2755 /* Preserve errno, because users would be surprised to have
2756 errno changing without explicitly calling any system-call. */
2759 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2760 No need to use an address derived from _start or %sp, as 0 works also. */
2761 memctl(0, 4096, MCT_TEXT);
2766 #endif /* __sysV68__ */
2770 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
2772 #include <sys/mman.h>
2773 #include <sys/types.h>
2774 #include <sys/param.h>
2775 #include <sys/vmmac.h>
2777 /* Modified from the convex -code above.
2778 mremap promises to clear the i-cache. */
2781 __enable_execute_stack ()
2784 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2785 PROT_READ|PROT_WRITE|PROT_EXEC))
2787 perror ("mprotect in __enable_execute_stack");
2792 #endif /* __pyr__ */
2794 #if defined (sony_news) && defined (SYSTYPE_BSD)
2797 #include <sys/types.h>
2798 #include <sys/param.h>
2799 #include <syscall.h>
2800 #include <machine/sysnews.h>
2802 /* cacheflush function for NEWS-OS 4.2.
2803 This function is called from trampoline-initialize code
2804 defined in config/mips/mips.h. */
2807 cacheflush (char *beg, int size, int flag)
2809 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2811 perror ("cache_flush");
2817 #endif /* sony_news */
2818 #endif /* L_trampoline */
2823 #include "gbl-ctors.h"
2824 /* Some systems use __main in a way incompatible with its use in gcc, in these
2825 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2826 give the same symbol without quotes for an alternative entry point. You
2827 must define both, or neither. */
2829 #define NAME__MAIN "__main"
2830 #define SYMBOL__MAIN __main
2833 #ifdef INIT_SECTION_ASM_OP
2834 #undef HAS_INIT_SECTION
2835 #define HAS_INIT_SECTION
2838 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2839 /* Run all the global destructors on exit from the program. */
2842 __do_global_dtors ()
2844 #ifdef DO_GLOBAL_DTORS_BODY
2845 DO_GLOBAL_DTORS_BODY;
2847 static func_ptr *p = __DTOR_LIST__ + 1;
2857 #ifndef HAS_INIT_SECTION
2858 /* Run all the global constructors on entry to the program. */
2861 #define ON_EXIT(a, b)
2863 /* Make sure the exit routine is pulled in to define the globals as
2864 bss symbols, just in case the linker does not automatically pull
2865 bss definitions from the library. */
2867 extern int _exit_dummy_decl;
2868 int *_exit_dummy_ref = &_exit_dummy_decl;
2869 #endif /* ON_EXIT */
2872 __do_global_ctors ()
2874 DO_GLOBAL_CTORS_BODY;
2875 ON_EXIT (__do_global_dtors, 0);
2877 #endif /* no HAS_INIT_SECTION */
2879 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2880 /* Subroutine called automatically by `main'.
2881 Compiling a global function named `main'
2882 produces an automatic call to this function at the beginning.
2884 For many systems, this routine calls __do_global_ctors.
2885 For systems which support a .init section we use the .init section
2886 to run __do_global_ctors, so we need not do anything here. */
2891 /* Support recursive calls to `main': run initializers just once. */
2892 static int initialized;
2896 __do_global_ctors ();
2899 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2901 #endif /* L__main */
2902 #endif /* __CYGWIN__ */
2906 #include "gbl-ctors.h"
2908 /* Provide default definitions for the lists of constructors and
2909 destructors, so that we don't get linker errors. These symbols are
2910 intentionally bss symbols, so that gld and/or collect will provide
2911 the right values. */
2913 /* We declare the lists here with two elements each,
2914 so that they are valid empty lists if no other definition is loaded.
2916 If we are using the old "set" extensions to have the gnu linker
2917 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2918 must be in the bss/common section.
2920 Long term no port should use those extensions. But many still do. */
2921 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2922 #if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
2923 func_ptr __CTOR_LIST__[2] = {0, 0};
2924 func_ptr __DTOR_LIST__[2] = {0, 0};
2926 func_ptr __CTOR_LIST__[2];
2927 func_ptr __DTOR_LIST__[2];
2929 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2930 #endif /* L_ctors */
2934 #include "gbl-ctors.h"
2940 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2948 static func_ptr *atexit_chain = 0;
2949 static long atexit_chain_length = 0;
2950 static volatile long last_atexit_chain_slot = -1;
2952 int atexit (func_ptr func)
2954 if (++last_atexit_chain_slot == atexit_chain_length)
2956 atexit_chain_length += 32;
2958 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2959 * sizeof (func_ptr));
2961 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2962 * sizeof (func_ptr));
2965 atexit_chain_length = 0;
2966 last_atexit_chain_slot = -1;
2971 atexit_chain[last_atexit_chain_slot] = func;
2974 #endif /* NEED_ATEXIT */
2976 /* If we have no known way of registering our own __do_global_dtors
2977 routine so that it will be invoked at program exit time, then we
2978 have to define our own exit routine which will get this to happen. */
2980 extern void __do_global_dtors ();
2981 extern void __bb_exit_func ();
2982 extern void _cleanup ();
2983 extern void _exit () __attribute__ ((noreturn));
2988 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2992 for ( ; last_atexit_chain_slot-- >= 0; )
2994 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2995 atexit_chain[last_atexit_chain_slot + 1] = 0;
2997 free (atexit_chain);
3000 #else /* No NEED_ATEXIT */
3001 __do_global_dtors ();
3002 #endif /* No NEED_ATEXIT */
3003 #endif /* !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) */
3004 /* In gbl-ctors.h, ON_EXIT is defined if HAVE_ATEXIT is defined. In
3005 __bb_init_func and _bb_init_prg, __bb_exit_func is registered with
3006 ON_EXIT if ON_EXIT is defined. Thus we must not call __bb_exit_func here
3007 if HAVE_ATEXIT is defined. */
3009 #ifndef inhibit_libc
3012 #endif /* !HAVE_ATEXIT */
3021 #else /* ON_EXIT defined */
3022 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
3024 # ifndef HAVE_ATEXIT
3025 /* Provide a fake for atexit() using ON_EXIT. */
3026 int atexit (func_ptr func)
3028 return ON_EXIT (func, NULL);
3030 # endif /* HAVE_ATEXIT */
3031 #endif /* ON_EXIT defined */
3039 /* Shared exception handling support routines. */
3041 extern void __default_terminate (void) __attribute__ ((__noreturn__));
3044 __default_terminate ()
3049 void (*__terminate_func)() = __default_terminate;
3054 (*__terminate_func)();
3058 __throw_type_match (void *catch_type, void *throw_type, void *obj)
3061 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3062 catch_type, throw_type);
3064 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3075 /* Include definitions of EH context and table layout */
3077 #include "eh-common.h"
3078 #ifndef inhibit_libc
3082 /* Allocate and return a new EH context structure. */
3084 extern void __throw ();
3089 struct eh_full_context {
3090 struct eh_context c;
3092 } *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);
3097 memset (ehfc, 0, sizeof *ehfc);
3099 ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;
3101 /* This should optimize out entirely. This should always be true,
3102 but just in case it ever isn't, don't allow bogus code to be
3105 if ((void*)(&ehfc->c) != (void*)ehfc)
3112 static __gthread_key_t eh_context_key;
3114 /* Destructor for struct eh_context. */
3116 eh_context_free (void *ptr)
3118 __gthread_key_dtor (eh_context_key, ptr);
3124 /* Pointer to function to return EH context. */
3126 static struct eh_context *eh_context_initialize ();
3127 static struct eh_context *eh_context_static ();
3129 static struct eh_context *eh_context_specific ();
3132 static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
3134 /* Routine to get EH context.
3135 This one will simply call the function pointer. */
3140 return (void *) (*get_eh_context) ();
3143 /* Get and set the language specific info pointer. */
3148 struct eh_context *eh = (*get_eh_context) ();
3154 eh_threads_initialize ()
3156 /* Try to create the key. If it fails, revert to static method,
3157 otherwise start using thread specific EH contexts. */
3158 if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
3159 get_eh_context = &eh_context_specific;
3161 get_eh_context = &eh_context_static;
3163 #endif /* no __GTHREADS */
3165 /* Initialize EH context.
3166 This will be called only once, since we change GET_EH_CONTEXT
3167 pointer to another routine. */
3169 static struct eh_context *
3170 eh_context_initialize ()
3174 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
3175 /* Make sure that get_eh_context does not point to us anymore.
3176 Some systems have dummy thread routines in their libc that
3177 return a success (Solaris 2.6 for example). */
3178 if (__gthread_once (&once, eh_threads_initialize) != 0
3179 || get_eh_context == &eh_context_initialize)
3181 /* Use static version of EH context. */
3182 get_eh_context = &eh_context_static;
3185 #else /* no __GTHREADS */
3187 /* Use static version of EH context. */
3188 get_eh_context = &eh_context_static;
3190 #endif /* no __GTHREADS */
3192 return (*get_eh_context) ();
3195 /* Return a static EH context. */
3197 static struct eh_context *
3198 eh_context_static ()
3200 static struct eh_context eh;
3201 static int initialized;
3202 static void *top_elt[2];
3207 memset (&eh, 0, sizeof eh);
3208 eh.dynamic_handler_chain = top_elt;
3214 /* Return a thread specific EH context. */
3216 static struct eh_context *
3217 eh_context_specific ()
3219 struct eh_context *eh;
3220 eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
3223 eh = new_eh_context ();
3224 if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
3232 /* Support routines for setjmp/longjmp exception handling. */
3234 /* Calls to __sjthrow are generated by the compiler when an exception
3235 is raised when using the setjmp/longjmp exception handling codegen
3238 #ifdef DONT_USE_BUILTIN_SETJMP
3239 extern void longjmp (void *, int);
3242 /* Routine to get the head of the current thread's dynamic handler chain
3243 use for exception handling. */
3246 __get_dynamic_handler_chain ()
3248 struct eh_context *eh = (*get_eh_context) ();
3249 return &eh->dynamic_handler_chain;
3252 /* This is used to throw an exception when the setjmp/longjmp codegen
3253 method is used for exception handling.
3255 We call __terminate if there are no handlers left. Otherwise we run the
3256 cleanup actions off the dynamic cleanup stack, and pop the top of the
3257 dynamic handler chain, and use longjmp to transfer back to the associated
3260 extern void __sjthrow (void) __attribute__ ((__noreturn__));
3265 struct eh_context *eh = (*get_eh_context) ();
3266 void ***dhc = &eh->dynamic_handler_chain;
3268 void (*func)(void *, int);
3272 /* The cleanup chain is one word into the buffer. Get the cleanup
3274 cleanup = (void***)&(*dhc)[1];
3276 /* If there are any cleanups in the chain, run them now. */
3280 void **buf = (void**)store;
3285 #ifdef DONT_USE_BUILTIN_SETJMP
3286 if (! setjmp (&buf[2]))
3288 if (! __builtin_setjmp (&buf[2]))
3294 func = (void(*)(void*, int))cleanup[0][1];
3295 arg = (void*)cleanup[0][2];
3297 /* Update this before running the cleanup. */
3298 cleanup[0] = (void **)cleanup[0][0];
3311 /* We must call terminate if we try and rethrow an exception, when
3312 there is no exception currently active and when there are no
3314 if (! eh->info || (*dhc)[0] == 0)
3317 /* Find the jmpbuf associated with the top element of the dynamic
3318 handler chain. The jumpbuf starts two words into the buffer. */
3319 jmpbuf = &(*dhc)[2];
3321 /* Then we pop the top element off the dynamic handler chain. */
3322 *dhc = (void**)(*dhc)[0];
3324 /* And then we jump to the handler. */
3326 #ifdef DONT_USE_BUILTIN_SETJMP
3327 longjmp (jmpbuf, 1);
3329 __builtin_longjmp (jmpbuf, 1);
3333 /* Run cleanups on the dynamic cleanup stack for the current dynamic
3334 handler, then pop the handler off the dynamic handler stack, and
3335 then throw. This is used to skip the first handler, and transfer
3336 control to the next handler in the dynamic handler stack. */
3338 extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
3343 struct eh_context *eh = (*get_eh_context) ();
3344 void ***dhc = &eh->dynamic_handler_chain;
3345 void (*func)(void *, int);
3349 /* The cleanup chain is one word into the buffer. Get the cleanup
3351 cleanup = (void***)&(*dhc)[1];
3353 /* If there are any cleanups in the chain, run them now. */
3357 void **buf = (void**)store;
3362 #ifdef DONT_USE_BUILTIN_SETJMP
3363 if (! setjmp (&buf[2]))
3365 if (! __builtin_setjmp (&buf[2]))
3371 func = (void(*)(void*, int))cleanup[0][1];
3372 arg = (void*)cleanup[0][2];
3374 /* Update this before running the cleanup. */
3375 cleanup[0] = (void **)cleanup[0][0];
3388 /* Then we pop the top element off the dynamic handler chain. */
3389 *dhc = (void**)(*dhc)[0];
3394 /* Support code for all exception region-based exception handling. */
3397 __eh_rtime_match (void *rtime)
3400 __eh_matcher matcher;
3403 info = *(__get_eh_info ());
3404 matcher = ((__eh_info *)info)->match_function;
3407 #ifndef inhibit_libc
3408 fprintf (stderr, "Internal Compiler Bug: No runtime type matcher.");
3412 ret = (*matcher) (info, rtime, (void *)0);
3413 return (ret != NULL);
3416 /* This value identifies the place from which an exception is being
3419 #ifdef EH_TABLE_LOOKUP
3425 #ifdef DWARF2_UNWIND_INFO
3428 /* Return the table version of an exception descriptor */
3431 __get_eh_table_version (exception_descriptor *table)
3433 return table->lang.version;
3436 /* Return the originating table language of an exception descriptor */
3439 __get_eh_table_language (exception_descriptor *table)
3441 return table->lang.language;
3444 /* This routine takes a PC and a pointer to the exception region TABLE for
3445 its translation unit, and returns the address of the exception handler
3446 associated with the closest exception table handler entry associated
3447 with that PC, or 0 if there are no table entries the PC fits in.
3449 In the advent of a tie, we have to give the last entry, as it represents
3453 old_find_exception_handler (void *pc, old_exception_table *table)
3460 /* We can't do a binary search because the table isn't guaranteed
3461 to be sorted from function to function. */
3462 for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
3464 if (table[pos].start_region <= pc && table[pos].end_region > pc)
3466 /* This can apply. Make sure it is at least as small as
3467 the previous best. */
3468 if (best == -1 || (table[pos].end_region <= table[best].end_region
3469 && table[pos].start_region >= table[best].start_region))
3472 /* But it is sorted by starting PC within a function. */
3473 else if (best >= 0 && table[pos].start_region > pc)
3477 return table[best].exception_handler;
3483 /* find_exception_handler finds the correct handler, if there is one, to
3484 handle an exception.
3485 returns a pointer to the handler which controlled should be transferred
3486 to, or NULL if there is nothing left.
3488 PC - pc where the exception originates. If this is a rethrow,
3489 then this starts out as a pointer to the exception table
3490 entry we wish to rethrow out of.
3491 TABLE - exception table for the current module.
3492 EH_INFO - eh info pointer for this exception.
3493 RETHROW - 1 if this is a rethrow. (see incoming value of PC).
3494 CLEANUP - returned flag indicating whether this is a cleanup handler.
3497 find_exception_handler (void *pc, exception_descriptor *table,
3498 __eh_info *eh_info, int rethrow, int *cleanup)
3501 void *retval = NULL;
3506 /* The new model assumed the table is sorted inner-most out so the
3507 first region we find which matches is the correct one */
3509 exception_table *tab = &(table->table[0]);
3511 /* Subtract 1 from the PC to avoid hitting the next region */
3514 /* pc is actually the region table entry to rethrow out of */
3515 pos = ((exception_table *) pc) - tab;
3516 pc = ((exception_table *) pc)->end_region - 1;
3518 /* The label is always on the LAST handler entry for a region,
3519 so we know the next entry is a different region, even if the
3520 addresses are the same. Make sure its not end of table tho. */
3521 if (tab[pos].start_region != (void *) -1)
3527 /* We can't do a binary search because the table is in inner-most
3528 to outermost address ranges within functions */
3529 for ( ; tab[pos].start_region != (void *) -1; pos++)
3531 if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
3533 if (tab[pos].match_info)
3535 __eh_matcher matcher = eh_info->match_function;
3536 /* match info but no matcher is NOT a match */
3539 void *ret = (*matcher)((void *) eh_info,
3540 tab[pos].match_info, table);
3544 retval = tab[pos].exception_handler;
3553 retval = tab[pos].exception_handler;
3560 #endif /* DWARF2_UNWIND_INFO */
3561 #endif /* EH_TABLE_LOOKUP */
3563 #ifdef DWARF2_UNWIND_INFO
3564 /* Support code for exception handling using static unwind information. */
3568 /* This type is used in get_reg and put_reg to deal with ABIs where a void*
3569 is smaller than a word, such as the Irix 6 n32 ABI. We cast twice to
3570 avoid a warning about casting between int and pointer of different
3573 typedef int ptr_type __attribute__ ((mode (pointer)));
3575 #ifdef INCOMING_REGNO
3576 /* Is the saved value for register REG in frame UDATA stored in a register
3577 window in the previous frame? */
3579 /* ??? The Sparc INCOMING_REGNO references TARGET_FLAT. This allows us
3580 to use the macro here. One wonders, though, that perhaps TARGET_FLAT
3581 compiled functions won't work with the frame-unwind stuff here.
3582 Perhaps the entireity of in_reg_window should be conditional on having
3583 seen a DW_CFA_GNU_window_save? */
3584 #define target_flags 0
3587 in_reg_window (int reg, frame_state *udata)
3589 if (udata->saved[reg] == REG_SAVED_REG)
3590 return INCOMING_REGNO (reg) == reg;
3591 if (udata->saved[reg] != REG_SAVED_OFFSET)
3594 #ifdef STACK_GROWS_DOWNWARD
3595 return udata->reg_or_offset[reg] > 0;
3597 return udata->reg_or_offset[reg] < 0;
3601 static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
3602 #endif /* INCOMING_REGNO */
3604 /* Get the address of register REG as saved in UDATA, where SUB_UDATA is a
3605 frame called by UDATA or 0. */
3608 get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata)
3610 while (udata->saved[reg] == REG_SAVED_REG)
3612 reg = udata->reg_or_offset[reg];
3613 if (in_reg_window (reg, udata))
3619 if (udata->saved[reg] == REG_SAVED_OFFSET)
3620 return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);
3625 /* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
3626 frame called by UDATA or 0. */
3628 static inline void *
3629 get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
3631 return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);
3634 /* Overwrite the saved value for register REG in frame UDATA with VAL. */
3637 put_reg (unsigned reg, void *val, frame_state *udata)
3639 *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;
3642 /* Copy the saved value for register REG from frame UDATA to frame
3643 TARGET_UDATA. Unlike the previous two functions, this can handle
3644 registers that are not one word large. */
3647 copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
3649 word_type *preg = get_reg_addr (reg, udata, NULL);
3650 word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
3652 memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
3655 /* Retrieve the return address for frame UDATA. */
3657 static inline void *
3658 get_return_addr (frame_state *udata, frame_state *sub_udata)
3660 return __builtin_extract_return_addr
3661 (get_reg (udata->retaddr_column, udata, sub_udata));
3664 /* Overwrite the return address for frame UDATA with VAL. */
3667 put_return_addr (void *val, frame_state *udata)
3669 val = __builtin_frob_return_addr (val);
3670 put_reg (udata->retaddr_column, val, udata);
3673 /* Given the current frame UDATA and its return address PC, return the
3674 information about the calling frame in CALLER_UDATA. */
3677 next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
3679 caller_udata = __frame_state_for (pc, caller_udata);
3683 /* Now go back to our caller's stack frame. If our caller's CFA register
3684 was saved in our stack frame, restore it; otherwise, assume the CFA
3685 register is SP and restore it to our CFA value. */
3686 if (udata->saved[caller_udata->cfa_reg])
3687 caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
3689 caller_udata->cfa = udata->cfa;
3690 caller_udata->cfa += caller_udata->cfa_offset;
3692 return caller_udata;
3695 /* Hook to call before __terminate if only cleanup handlers remain. */
3697 __unwinding_cleanup ()
3701 /* throw_helper performs some of the common grunt work for a throw. This
3702 routine is called by throw and rethrows. This is pretty much split
3703 out from the old __throw routine. An addition has been added which allows
3704 for a dummy call to a routine __unwinding_cleanup() when there are nothing
3705 but cleanups remaining. This allows a debugger to examine the state
3706 at which the throw was executed, before any cleanups, rather than
3707 at the terminate point after the stack has been unwound.
3709 EH is the current eh_context structure.
3710 PC is the address of the call to __throw.
3711 MY_UDATA is the unwind information for __throw.
3712 OFFSET_P is where we return the SP adjustment offset. */
3715 throw_helper (eh, pc, my_udata, offset_p)
3716 struct eh_context *eh;
3718 frame_state *my_udata;
3721 frame_state ustruct2, *udata = &ustruct2;
3722 frame_state ustruct;
3723 frame_state *sub_udata = &ustruct;
3724 void *saved_pc = pc;
3728 frame_state saved_ustruct;
3731 int only_cleanup = 0;
3733 int saved_state = 0;
3735 __eh_info *eh_info = (__eh_info *)eh->info;
3737 /* Do we find a handler based on a re-throw PC? */
3738 if (eh->table_index != (void *) 0)
3741 memcpy (udata, my_udata, sizeof (*udata));
3743 handler = (void *) 0;
3746 frame_state *p = udata;
3747 udata = next_stack_level (pc, udata, sub_udata);
3750 /* If we couldn't find the next frame, we lose. */
3754 if (udata->eh_ptr == NULL)
3757 new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->
3758 runtime_id_field == NEW_EH_RUNTIME);
3763 handler = find_exception_handler (eh->table_index, udata->eh_ptr,
3764 eh_info, 1, &cleanup);
3765 eh->table_index = (void *)0;
3769 handler = find_exception_handler (pc, udata->eh_ptr, eh_info,
3772 handler = old_find_exception_handler (pc, udata->eh_ptr);
3774 /* If we found one, we can stop searching, if its not a cleanup.
3775 for cleanups, we save the state, and keep looking. This allows
3776 us to call a debug hook if there are nothing but cleanups left. */
3783 saved_ustruct = *udata;
3784 handler_p = handler;
3797 /* Otherwise, we continue searching. We subtract 1 from PC to avoid
3798 hitting the beginning of the next region. */
3799 pc = get_return_addr (udata, sub_udata) - 1;
3804 udata = &saved_ustruct;
3805 handler = handler_p;
3808 __unwinding_cleanup ();
3811 /* If we haven't found a handler by now, this is an unhandled
3816 eh->handler_label = handler;
3818 args_size = udata->args_size;
3821 /* We found a handler in the throw context, no need to unwind. */
3827 /* Unwind all the frames between this one and the handler by copying
3828 their saved register values into our register save slots. */
3830 /* Remember the PC where we found the handler. */
3831 void *handler_pc = pc;
3833 /* Start from the throw context again. */
3835 memcpy (udata, my_udata, sizeof (*udata));
3837 while (pc != handler_pc)
3839 frame_state *p = udata;
3840 udata = next_stack_level (pc, udata, sub_udata);
3843 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
3844 if (i != udata->retaddr_column && udata->saved[i])
3846 /* If you modify the saved value of the return address
3847 register on the SPARC, you modify the return address for
3848 your caller's frame. Don't do that here, as it will
3849 confuse get_return_addr. */
3850 if (in_reg_window (i, udata)
3851 && udata->saved[udata->retaddr_column] == REG_SAVED_REG
3852 && udata->reg_or_offset[udata->retaddr_column] == i)
3854 copy_reg (i, udata, my_udata);
3857 pc = get_return_addr (udata, sub_udata) - 1;
3860 /* But we do need to update the saved return address register from
3861 the last frame we unwind, or the handler frame will have the wrong
3863 if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
3865 i = udata->reg_or_offset[udata->retaddr_column];
3866 if (in_reg_window (i, udata))
3867 copy_reg (i, udata, my_udata);
3870 /* udata now refers to the frame called by the handler frame. */
3872 /* We adjust SP by the difference between __throw's CFA and the CFA for
3873 the frame called by the handler frame, because those CFAs correspond
3874 to the SP values at the two call sites. We need to further adjust by
3875 the args_size of the handler frame itself to get the handler frame's
3876 SP from before the args were pushed for that call. */
3877 #ifdef STACK_GROWS_DOWNWARD
3878 *offset_p = udata->cfa - my_udata->cfa + args_size;
3880 *offset_p = my_udata->cfa - udata->cfa - args_size;
3887 /* We first search for an exception handler, and if we don't find
3888 it, we call __terminate on the current stack frame so that we may
3889 use the debugger to walk the stack and understand why no handler
3892 If we find one, then we unwind the frames down to the one that
3893 has the handler and transfer control into the handler. */
3895 /*extern void __throw(void) __attribute__ ((__noreturn__));*/
3900 struct eh_context *eh = (*get_eh_context) ();
3904 /* XXX maybe make my_ustruct static so we don't have to look it up for
3906 frame_state my_ustruct, *my_udata = &my_ustruct;
3908 /* This is required for C++ semantics. We must call terminate if we
3909 try and rethrow an exception, when there is no exception currently
3914 /* Start at our stack frame. */
3916 my_udata = __frame_state_for (&&label, my_udata);
3920 /* We need to get the value from the CFA register. */
3921 my_udata->cfa = __builtin_dwarf_cfa ();
3923 /* Do any necessary initialization to access arbitrary stack frames.
3924 On the SPARC, this means flushing the register windows. */
3925 __builtin_unwind_init ();
3927 /* Now reset pc to the right throw point. */
3928 pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3930 handler = throw_helper (eh, pc, my_udata, &offset);
3934 __builtin_eh_return ((void *)eh, offset, handler);
3936 /* Epilogue: restore the handler frame's register values and return
3940 /*extern void __rethrow(void *) __attribute__ ((__noreturn__));*/
3946 struct eh_context *eh = (*get_eh_context) ();
3950 /* XXX maybe make my_ustruct static so we don't have to look it up for
3952 frame_state my_ustruct, *my_udata = &my_ustruct;
3954 /* This is required for C++ semantics. We must call terminate if we
3955 try and rethrow an exception, when there is no exception currently
3960 /* This is the table index we want to rethrow from. The value of
3961 the END_REGION label is used for the PC of the throw, and the
3962 search begins with the next table entry. */
3963 eh->table_index = index;
3965 /* Start at our stack frame. */
3967 my_udata = __frame_state_for (&&label, my_udata);
3971 /* We need to get the value from the CFA register. */
3972 my_udata->cfa = __builtin_dwarf_cfa ();
3974 /* Do any necessary initialization to access arbitrary stack frames.
3975 On the SPARC, this means flushing the register windows. */
3976 __builtin_unwind_init ();
3978 /* Now reset pc to the right throw point. */
3979 pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3981 handler = throw_helper (eh, pc, my_udata, &offset);
3985 __builtin_eh_return ((void *)eh, offset, handler);
3987 /* Epilogue: restore the handler frame's register values and return
3990 #endif /* DWARF2_UNWIND_INFO */
3995 #ifndef inhibit_libc
3996 /* This gets us __GNU_LIBRARY__. */
3997 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
4000 #ifdef __GNU_LIBRARY__
4001 /* Avoid forcing the library's meaning of `write' on the user program
4002 by using the "internal" name (for use within the library) */
4003 #define write(fd, buf, n) __write((fd), (buf), (n))
4005 #endif /* inhibit_libc */
4007 #define MESSAGE "pure virtual method called\n"
4012 #ifndef inhibit_libc
4013 write (2, MESSAGE, sizeof (MESSAGE) - 1);
4019 #ifdef L_stack_smash_handler
4025 #ifdef _POSIX_SOURCE
4029 #if defined(HAVE_SYSLOG)
4030 #include <sys/types.h>
4031 #include <sys/socket.h>
4034 #include <sys/syslog.h>
4036 #define _PATH_LOG "/dev/log"
4040 long __guard[8] = {0,0,0,0,0,0,0,0};
4041 static void __guard_setup (void) __attribute__ ((constructor)) ;
4042 static void __guard_setup (void)
4045 if (__guard[0]!=0) return;
4046 fd = open ("/dev/urandom", 0);
4048 ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
4050 if (size == sizeof(__guard)) return;
4052 /* If a random generator can't be used, the protector switches the guard
4053 to the "terminator canary" */
4054 ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
4055 ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
4057 void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED)
4059 #if defined (__GNU_LIBRARY__)
4060 extern char * __progname;
4062 const char message[] = ": stack smashing attack in function ";
4063 int bufsz = 256, len;
4065 #if defined(HAVE_SYSLOG)
4067 struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
4069 #ifdef _POSIX_SOURCE
4073 sigdelset(&mask, SIGABRT); /* Block all signal handlers */
4074 sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */
4078 strcpy(buf, "<2>"); len=3; /* send LOG_CRIT */
4079 #if defined (__GNU_LIBRARY__)
4080 strncat(buf, __progname, bufsz-len-1); len = strlen(buf);
4082 if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);}
4083 if (bufsz>len) {strncat(buf, func, bufsz-len-1); len = strlen(buf);}
4085 /* print error message */
4086 write (STDERR_FILENO, buf+3, len-3);
4087 #if defined(HAVE_SYSLOG)
4088 if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) {
4091 * Send "found" message to the "/dev/log" path
4093 SyslogAddr.sun_family = AF_UNIX;
4094 (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
4095 sizeof(SyslogAddr.sun_path) - 1);
4096 SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0';
4097 sendto(LogFile, buf, len, 0, (struct sockaddr *)&SyslogAddr,
4098 sizeof(SyslogAddr));
4102 #ifdef _POSIX_SOURCE
4103 { /* Make sure the default handler is associated with SIGABRT */
4104 struct sigaction sa;
4106 memset(&sa, 0, sizeof(struct sigaction));
4107 sigfillset(&sa.sa_mask); /* Block all signals */
4109 sa.sa_handler = SIG_DFL;
4110 sigaction(SIGABRT, &sa, NULL);
4111 (void)kill(getpid(), SIGABRT);
4118 #ifdef L_stack_smash_handler
4124 #ifdef _POSIX_SOURCE
4128 #if defined(HAVE_SYSLOG)
4129 #include <sys/types.h>
4130 #include <sys/socket.h>
4133 #include <sys/syslog.h>
4135 #define _PATH_LOG "/dev/log"
4139 long __guard[8] = {0,0,0,0,0,0,0,0};
4140 static void __guard_setup (void) __attribute__ ((constructor)) ;
4141 static void __guard_setup (void)
4144 if (__guard[0]!=0) return;
4145 fd = open ("/dev/urandom", 0);
4147 ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
4149 if (size == sizeof(__guard)) return;
4151 /* If a random generator can't be used, the protector switches the guard
4152 to the "terminator canary" */
4153 ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
4154 ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
4156 void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED)
4158 #if defined (__GNU_LIBRARY__)
4159 extern char * __progname;
4161 const char message[] = ": stack smashing attack in function ";
4162 int bufsz = 256, len;
4164 #if defined(HAVE_SYSLOG)
4166 struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
4168 #ifdef _POSIX_SOURCE
4172 sigdelset(&mask, SIGABRT); /* Block all signal handlers */
4173 sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */
4177 strcpy(buf, "<2>"); len=3; /* send LOG_CRIT */
4178 #if defined (__GNU_LIBRARY__)
4179 strncat(buf, __progname, bufsz-len-1); len = strlen(buf);
4181 if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);}
4182 if (bufsz>len) strncat(buf, func, bufsz-len-1);
4184 /* print error message */
4185 write (STDERR_FILENO, buf+3, len-3);
4186 #if defined(HAVE_SYSLOG)
4187 if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) {
4190 * Send "found" message to the "/dev/log" path
4192 SyslogAddr.sun_family = AF_UNIX;
4193 (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
4194 sizeof(SyslogAddr.sun_path) - 1);
4195 SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0';
4196 sendto(LogFile, buf, strlen(buf), 0, (struct sockaddr *)&SyslogAddr,
4197 sizeof(SyslogAddr));
4201 #ifdef _POSIX_SOURCE
4202 { /* Make sure the default handler is associated with SIGABRT */
4203 struct sigaction sa;
4205 memset(&sa, 0, sizeof(struct sigaction));
4206 sigfillset(&sa.sa_mask); /* Block all signals */
4208 sa.sa_handler = SIG_DFL;
4209 sigaction(SIGABRT, &sa, NULL);
4210 (void)kill(getpid(), SIGABRT);