1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1996-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #ifndef __ERROR_H__
22 #define __ERROR_H__
23 
24 #include "code_ix.h"
25 
26 /*
27  * There are three primary exception classes:
28  *
29  *	- exit			Process termination - not an error.
30  *	- error			Error (adds stacktrace; will be logged).
31  *	- thrown		Nonlocal return (turns into a 'nocatch'
32  *				error if not caught by the process).
33  *
34  * In addition, we define a number of exit codes as a convenient
35  * short-hand: instead of building the error descriptor term at the time
36  * the exception is raised, it is built as necessary when the exception
37  * is handled. Examples are EXC_NORMAL, EXC_BADARG, EXC_BADARITH, etc.
38  * Some of these have convenient aliases, like BADARG and BADARITH.
39  */
40 
41 /*
42  * Exception class tags (indices into the 'exception_tag' array)
43  */
44 #define EXTAG_OFFSET	0
45 #define EXTAG_BITS	2
46 
47 #define EXTAG_ERROR	0
48 #define EXTAG_EXIT	1
49 #define EXTAG_THROWN	2
50 
51 #define NUMBER_EXC_TAGS 3	/* The number of exception class tags */
52 
53 /*
54  * Index to the 'exception class tag' table.
55  */
56 #define EXC_CLASSBITS	((1<<EXTAG_BITS)-1)
57 #define GET_EXC_CLASS(x) ((x) & EXC_CLASSBITS)
58 
59 /*
60  * Exit code flags
61  *
62  * These flags make is easier and quicker to decide what to do with the
63  * exception in the early stages, before a handler is found, and also
64  * maintains some separation between the class tag and the actions.
65  */
66 #define EXF_OFFSET	EXTAG_BITS
67 #define EXF_BITS	8
68 
69 #define EXF_PANIC         (1<<(0+EXF_OFFSET)) /* ignore catches */
70 #define EXF_THROWN        (1<<(1+EXF_OFFSET)) /* nonlocal return */
71 #define EXF_LOG           (1<<(2+EXF_OFFSET)) /* write to logger on termination */
72 #define EXF_NATIVE        (1<<(3+EXF_OFFSET)) /* occurred in native code */
73 #define EXF_SAVETRACE     (1<<(4+EXF_OFFSET)) /* save stack trace in internal form */
74 #define EXF_ARGLIST       (1<<(5+EXF_OFFSET)) /* has arglist for top of trace */
75 #define EXF_RESTORE_NFUNC (1<<(6+EXF_OFFSET)) /* restore original bif/nif */
76 #define EXF_HAS_EXT_INFO  (1<<(7+EXF_OFFSET)) /* has arglist for top of trace */
77 
78 #define EXC_FLAGBITS	(((1<<(EXF_BITS+EXF_OFFSET))-1) \
79 			 & ~((1<<(EXF_OFFSET))-1))
80 
81 /*
82  * The primary fields of an exception code
83  */
84 #define EXF_PRIMARY	(EXF_PANIC | EXF_THROWN | EXF_LOG | EXF_NATIVE)
85 #define PRIMARY_EXCEPTION(x) ((x) & (EXF_PRIMARY | EXC_CLASSBITS))
86 #define NATIVE_EXCEPTION(x) ((x) | EXF_NATIVE)
87 
88 /*
89  * Error code used for indexing into
90  * the short-hand error descriptor table.
91  */
92 #define EXC_OFFSET	(EXF_OFFSET+EXF_BITS)
93 #define EXC_BITS	5
94 
95 #define EXC_INDEXBITS	(((1<<(EXC_BITS+EXC_OFFSET))-1) \
96 			 & ~((1<<(EXC_OFFSET))-1))
97 
98 #define GET_EXC_INDEX(x) (((x) & EXC_INDEXBITS) >> EXC_OFFSET)
99 
100 /*
101  * Exit codes used for raising a fresh exception. The primary exceptions
102  * share index 0 in the descriptor table. EXC_NULL signals that no
103  * exception has occurred. The primary exit codes EXC_EXIT, EXC_ERROR
104  * and EXC_THROWN are the basis for all other exit codes, and must
105  * always have the EXF_SAVETRACE flag set so that a trace is saved
106  * whenever a new exception occurs; the flag is then cleared.
107  */
108 #define EXC_NULL 0			/* Initial value for p->freason */
109 #define EXC_PRIMARY (0 | EXF_SAVETRACE)
110 #define EXC_ERROR  (EXC_PRIMARY | EXTAG_ERROR | EXF_LOG)
111 					/* Generic error (exit term
112 					 * in p->fvalue) */
113 #define EXC_EXIT   (EXC_PRIMARY | EXTAG_EXIT)
114 					/* Generic exit (exit term
115 					 * in p->fvalue) */
116 #define EXC_THROWN (EXC_PRIMARY | EXTAG_THROWN | EXF_THROWN)
117 					/* Generic nonlocal return
118 					 * (thrown term in p->fvalue) */
119 
120 #define EXC_ERROR_2 (EXC_ERROR | EXF_ARGLIST)
121 					/* Error with given arglist term
122 					 * (exit reason in p->fvalue) */
123 
124 #define EXC_ERROR_3 (EXC_ERROR | EXF_ARGLIST | EXF_HAS_EXT_INFO)
125                                         /* Error with given arglist term
126                                          * and extended error info
127                                          * (exit reason in p->fvalue) */
128 
129 #define EXC_NORMAL		((1 << EXC_OFFSET) | EXC_EXIT)
130 					/* Normal exit (reason 'normal') */
131 #define EXC_INTERNAL_ERROR	((2 << EXC_OFFSET) | EXC_ERROR | EXF_PANIC)
132 					/* Things that shouldn't happen */
133 #define EXC_BADARG		((3 << EXC_OFFSET) | EXC_ERROR)
134 					/* Bad argument to a BIF */
135 #define EXC_BADARITH		((4 << EXC_OFFSET) | EXC_ERROR)
136 					/* Bad arithmetic */
137 #define EXC_BADMATCH		((5 << EXC_OFFSET) | EXC_ERROR)
138 					/* Bad match in function body */
139 #define EXC_FUNCTION_CLAUSE	((6 << EXC_OFFSET) | EXC_ERROR)
140 					 /* No matching function head */
141 #define EXC_CASE_CLAUSE		((7 << EXC_OFFSET) | EXC_ERROR)
142 					/* No matching case clause */
143 #define EXC_IF_CLAUSE		((8 << EXC_OFFSET) | EXC_ERROR)
144 					/* No matching if clause */
145 #define EXC_UNDEF		((9 << EXC_OFFSET) | EXC_ERROR)
146 				 	/* No farity that matches */
147 #define EXC_BADFUN		((10 << EXC_OFFSET) | EXC_ERROR)
148 					/* Not an existing fun */
149 #define EXC_BADARITY		((11 << EXC_OFFSET) | EXC_ERROR)
150 					/* Attempt to call fun with
151 					 * wrong number of arguments. */
152 #define EXC_TIMEOUT_VALUE	((12 << EXC_OFFSET) | EXC_ERROR)
153 					/* Bad time out value */
154 #define EXC_NOPROC		((13 << EXC_OFFSET) | EXC_ERROR)
155 					/* No process or port */
156 #define EXC_NOTALIVE		((14 << EXC_OFFSET) | EXC_ERROR)
157 					/* Not distributed */
158 #define EXC_SYSTEM_LIMIT	((15 << EXC_OFFSET) | EXC_ERROR)
159 					/* Ran out of something */
160 #define EXC_TRY_CLAUSE		((16 << EXC_OFFSET) | EXC_ERROR)
161 					/* No matching try clause */
162 #define EXC_NOTSUP		((17 << EXC_OFFSET) | EXC_ERROR)
163 					/* Not supported */
164 #define EXC_BADMAP		((18 << EXC_OFFSET) | EXC_ERROR)
165 					/* Bad map */
166 #define EXC_BADKEY		((19 << EXC_OFFSET) | EXC_ERROR)
167 					/* Bad key in map */
168 
169 #define NUMBER_EXIT_CODES 20	/* The number of exit code indices */
170 
171 /*
172  * Internal pseudo-error codes.
173  */
174 #define TRAP		(1 << EXC_OFFSET)	/* BIF Trap to erlang code */
175 
176 /*
177  * Aliases for some common exit codes.
178  */
179 #define BADARG EXC_BADARG
180 #define BADARITH EXC_BADARITH
181 #define BADKEY EXC_BADKEY
182 #define BADMAP EXC_BADMAP
183 #define BADMATCH EXC_BADMATCH
184 #define SYSTEM_LIMIT EXC_SYSTEM_LIMIT
185 
186 /*
187  * Pseudo error codes (these are never seen by the user).
188  */
189 #define TLOAD_OK 0              /* The threaded code linking was successful */
190 #define TLOAD_MAGIC_NUMBER 1    /* Wrong kind of object file */
191 #define TLOAD_FORMAT 2          /* Format error while reading object code */
192 #define TLOAD_MODULE 3          /* Module name in object code does not match */
193 #define TLOAD_SIZE 4            /* Given size in object code differs from actual size */
194 
195 /*
196  * The exception stack trace parameters.
197  */
198 #define MAX_BACKTRACE_SIZE 64    /* whatever - just not too huge */
199 #define DEFAULT_BACKTRACE_SIZE 8
200 
201 /*
202  * The table translating an exception code to an atom.
203  */
204 extern Eterm error_atom[NUMBER_EXIT_CODES];
205 
206 /*
207  * The exception tag table.
208  */
209 extern Eterm exception_tag[NUMBER_EXC_TAGS];
210 
211 /*
212  * The quick-saved stack trace structure
213  */
214 struct StackTrace {
215     Eterm header;	/* bignum header - must be first in struct */
216     Eterm freason; /* original exception reason is saved in the struct */
217     ErtsCodePtr pc;
218     const ErtsCodeMFA* current;
219     int depth;	/* number of saved pointers in trace[] */
220     ErtsCodePtr trace[1];  /* varying size - must be last in struct */
221 };
222 
223 #endif /* __ERROR_H__ */
224