summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/error.h
blob: 64c08b1570263678d13d080a8ee78649aeb3e011 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 1996-2016. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * %CopyrightEnd%
 */

#ifndef __ERROR_H__
#define __ERROR_H__

#include "code_ix.h"

/*
 * There are three primary exception classes:
 *
 *	- exit			Process termination - not an error.
 *	- error			Error (adds stacktrace; will be logged).
 *	- thrown		Nonlocal return (turns into a 'nocatch'
 *				error if not caught by the process).
 *
 * In addition, we define a number of exit codes as a convenient
 * short-hand: instead of building the error descriptor term at the time
 * the exception is raised, it is built as necessary when the exception
 * is handled. Examples are EXC_NORMAL, EXC_BADARG, EXC_BADARITH, etc.
 * Some of these have convenient aliases, like BADARG and BADARITH.
 */

/*
 * Exception class tags (indices into the 'exception_tag' array)
 */
#define EXTAG_OFFSET	0
#define EXTAG_BITS	2

#define EXTAG_ERROR	0
#define EXTAG_EXIT	1
#define EXTAG_THROWN	2

#define NUMBER_EXC_TAGS 3	/* The number of exception class tags */

/*
 * Index to the 'exception class tag' table.
 */
#define EXC_CLASSBITS	((1<<EXTAG_BITS)-1)
#define GET_EXC_CLASS(x) ((x) & EXC_CLASSBITS)

/*
 * Exit code flags
 *
 * These flags make is easier and quicker to decide what to do with the
 * exception in the early stages, before a handler is found, and also
 * maintains some separation between the class tag and the actions.
 */
#define EXF_OFFSET	EXTAG_BITS
#define EXF_BITS	7

#define EXF_PANIC	(1<<(0+EXF_OFFSET))	/* ignore catches */
#define EXF_THROWN	(1<<(1+EXF_OFFSET))	/* nonlocal return */
#define EXF_LOG		(1<<(2+EXF_OFFSET))	/* write to logger on termination */
#define EXF_NATIVE	(1<<(3+EXF_OFFSET))	/* occurred in native code */
#define EXF_SAVETRACE	(1<<(4+EXF_OFFSET))	/* save stack trace in internal form */
#define EXF_ARGLIST	(1<<(5+EXF_OFFSET))	/* has arglist for top of trace */
#define EXF_RESTORE_NIF	(1<<(6+EXF_OFFSET))	/* restore original bif/nif */

#define EXC_FLAGBITS	(((1<<(EXF_BITS+EXF_OFFSET))-1) \
			 & ~((1<<(EXF_OFFSET))-1))

/*
 * The primary fields of an exception code
 */
#define EXF_PRIMARY	(EXF_PANIC | EXF_THROWN | EXF_LOG | EXF_NATIVE)
#define PRIMARY_EXCEPTION(x) ((x) & (EXF_PRIMARY | EXC_CLASSBITS))
#define NATIVE_EXCEPTION(x) ((x) | EXF_NATIVE)

/*
 * Error code used for indexing into
 * the short-hand error descriptor table.
 */
#define EXC_OFFSET	(EXF_OFFSET+EXF_BITS)
#define EXC_BITS	5

#define EXC_INDEXBITS	(((1<<(EXC_BITS+EXC_OFFSET))-1) \
			 & ~((1<<(EXC_OFFSET))-1))

#define GET_EXC_INDEX(x) (((x) & EXC_INDEXBITS) >> EXC_OFFSET)

/*
 * Exit codes used for raising a fresh exception. The primary exceptions
 * share index 0 in the descriptor table. EXC_NULL signals that no
 * exception has occurred. The primary exit codes EXC_EXIT, EXC_ERROR
 * and EXC_THROWN are the basis for all other exit codes, and must
 * always have the EXF_SAVETRACE flag set so that a trace is saved
 * whenever a new exception occurs; the flag is then cleared.
 */
#define EXC_NULL 0			/* Initial value for p->freason */
#define EXC_PRIMARY (0 | EXF_SAVETRACE)
#define EXC_ERROR  (EXC_PRIMARY | EXTAG_ERROR | EXF_LOG)
					/* Generic error (exit term
					 * in p->fvalue) */
#define EXC_EXIT   (EXC_PRIMARY | EXTAG_EXIT)
					/* Generic exit (exit term
					 * in p->fvalue) */
#define EXC_THROWN (EXC_PRIMARY | EXTAG_THROWN | EXF_THROWN)
					/* Generic nonlocal return
					 * (thrown term in p->fvalue) */

#define EXC_ERROR_2 (EXC_ERROR | EXF_ARGLIST)
					/* Error with given arglist term
					 * (exit reason in p->fvalue) */

#define EXC_NORMAL		((1 << EXC_OFFSET) | EXC_EXIT)
					/* Normal exit (reason 'normal') */
#define EXC_INTERNAL_ERROR	((2 << EXC_OFFSET) | EXC_ERROR | EXF_PANIC)
					/* Things that shouldn't happen */
#define EXC_BADARG		((3 << EXC_OFFSET) | EXC_ERROR)
					/* Bad argument to a BIF */
#define EXC_BADARITH		((4 << EXC_OFFSET) | EXC_ERROR)
					/* Bad arithmetic */
#define EXC_BADMATCH		((5 << EXC_OFFSET) | EXC_ERROR)
					/* Bad match in function body */
#define EXC_FUNCTION_CLAUSE	((6 << EXC_OFFSET) | EXC_ERROR)
					 /* No matching function head */
#define EXC_CASE_CLAUSE		((7 << EXC_OFFSET) | EXC_ERROR)
					/* No matching case clause */
#define EXC_IF_CLAUSE		((8 << EXC_OFFSET) | EXC_ERROR)
					/* No matching if clause */
#define EXC_UNDEF		((9 << EXC_OFFSET) | EXC_ERROR)
				 	/* No farity that matches */
#define EXC_BADFUN		((10 << EXC_OFFSET) | EXC_ERROR)
					/* Not an existing fun */
#define EXC_BADARITY		((11 << EXC_OFFSET) | EXC_ERROR)
					/* Attempt to call fun with
					 * wrong number of arguments. */
#define EXC_TIMEOUT_VALUE	((12 << EXC_OFFSET) | EXC_ERROR)
					/* Bad time out value */
#define EXC_NOPROC		((13 << EXC_OFFSET) | EXC_ERROR)
					/* No process or port */
#define EXC_NOTALIVE		((14 << EXC_OFFSET) | EXC_ERROR)
					/* Not distributed */
#define EXC_SYSTEM_LIMIT	((15 << EXC_OFFSET) | EXC_ERROR)
					/* Ran out of something */
#define EXC_TRY_CLAUSE		((16 << EXC_OFFSET) | EXC_ERROR)
					/* No matching try clause */
#define EXC_NOTSUP		((17 << EXC_OFFSET) | EXC_ERROR)
					/* Not supported */

#define EXC_BADMAP		((18 << EXC_OFFSET) | EXC_ERROR)
					/* Bad map */

#define EXC_BADKEY		((19 << EXC_OFFSET) | EXC_ERROR)
					/* Bad key in map */

#define NUMBER_EXIT_CODES 20	/* The number of exit code indices */

/*
 * Internal pseudo-error codes.
 */
#define TRAP		(1 << EXC_OFFSET)	/* BIF Trap to erlang code */

/*
 * Aliases for some common exit codes.
 */
#define BADARG EXC_BADARG
#define BADARITH EXC_BADARITH
#define BADKEY EXC_BADKEY
#define BADMAP EXC_BADMAP
#define BADMATCH EXC_BADMATCH
#define SYSTEM_LIMIT EXC_SYSTEM_LIMIT


/*
 * Pseudo error codes (these are never seen by the user).
 */
#define TLOAD_OK 0              /* The threaded code linking was successful */
#define TLOAD_MAGIC_NUMBER 1    /* Wrong kind of object file */
#define TLOAD_FORMAT 2          /* Format error while reading object code */
#define TLOAD_MODULE 3          /* Module name in object code does not match */
#define TLOAD_SIZE 4            /* Given size in object code differs from actual size */

/*
 * The exception stack trace parameters.
 */
#define MAX_BACKTRACE_SIZE 64    /* whatever - just not too huge */
#define DEFAULT_BACKTRACE_SIZE 8

/*
 * The table translating an exception code to an atom.
 */
extern Eterm error_atom[NUMBER_EXIT_CODES];

/*
 * The exception tag table.
 */
extern Eterm exception_tag[NUMBER_EXC_TAGS];

/* 
 * The quick-saved stack trace structure
 */
struct StackTrace {
    Eterm header;	/* bignum header - must be first in struct */
    Eterm freason; /* original exception reason is saved in the struct */
    BeamInstr* pc;
    ErtsCodeMFA* current;
    int depth;	/* number of saved pointers in trace[] */
    BeamInstr *trace[1];  /* varying size - must be last in struct */
};

#endif /* __ERROR_H__ */