]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/cxx/lib/base/include/exceptions
Update
[l4.git] / l4 / pkg / l4re-core / cxx / lib / base / include / exceptions
1 // vi:ft=cpp
2 /**
3  * \file
4  * \brief Base exceptions
5  * \ingroup l4cxx_exceptions
6  */
7 /*
8  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9  *               Alexander Warg <warg@os.inf.tu-dresden.de>
10  *     economic rights: Technische Universität Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction.  Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License.  This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25
26 #pragma once
27
28 #include <l4/cxx/l4types.h>
29 #include <l4/cxx/basic_ostream>
30 #include <l4/sys/err.h>
31 #include <l4/sys/capability>
32
33
34 /**
35  * \defgroup l4cxx_exceptions C++ Exceptions
36  * \ingroup api_l4re
37  */
38 /*@{*/
39
40 #ifndef L4_CXX_NO_EXCEPTION_BACKTRACE
41 # define L4_CXX_EXCEPTION_BACKTRACE 20  ///< Number of instruction pointers in backtrace
42 #endif
43
44 #if defined(L4_CXX_EXCEPTION_BACKTRACE)
45 #include <l4/util/backtrace.h>
46 #endif
47
48 /*@}*/
49 namespace L4
50 {
51   /**
52    * \addtogroup l4cxx_exceptions
53    */
54   /*@{*/
55   /**
56    * \brief Back-trace support for exceptions.
57    * \headerfile l4/cxx/exceptions
58    *
59    * This class holds an array of at most #L4_CXX_EXCEPTION_BACKTRACE
60    * instruction pointers containing the call trace at the instant when an
61    * exception was thrown.
62    */
63   class Exception_tracer
64   {
65 #if defined(L4_CXX_EXCEPTION_BACKTRACE)
66   private:
67     void *_pc_array[L4_CXX_EXCEPTION_BACKTRACE];
68     int   _frame_cnt;
69
70   protected:
71     /**
72      * \brief Create a back trace.
73      */
74 #if defined(__PIC__)
75     Exception_tracer() throw() : _frame_cnt(0) {}
76 #else
77     Exception_tracer() throw() : _frame_cnt(l4util_backtrace(_pc_array, L4_CXX_EXCEPTION_BACKTRACE)) {}
78 #endif
79
80   public:
81     /**
82      * \brief Get the array containing the call trace.
83      */
84     void const *const *pc_array() const throw() { return _pc_array; }
85     /**
86      * \brief Get the number of entries that are valid in the call trace.
87      */
88     int frame_count() const throw() { return _frame_cnt; }
89 #else
90   protected:
91     /**
92      * \brief Create a back trace.
93      */
94     Exception_tracer() throw() {}
95
96   public:
97     /**
98      * \brief Get the array containing the call trace.
99      */
100     void const *const *pc_array() const throw() { return 0; }
101     /**
102      * \brief Get the number of entries that are valid in the call trace.
103      */
104     int frame_count() const throw() { return 0; }
105 #endif
106   };
107
108   /**
109    * \brief Base class for all exceptions, thrown by the L4Re framework.
110    * \headerfile l4/cxx/exceptions
111    *
112    * This is the abstract base of all exceptions thrown within the
113    * L4Re framework. It is basically also a good idea to use it as base of
114    * all user defined exceptions.
115    */
116   class Base_exception : public Exception_tracer
117   {
118   protected:
119     /// Create a base exception.
120     Base_exception() throw() {}
121
122   public:
123     /**
124      * Return a human readable string for the exception.
125      */
126     virtual char const *str() const throw () = 0;
127
128     /// Destruction
129     virtual ~Base_exception() throw () {}
130   };
131
132   /**
133    * \brief Exception for an abstract runtime error.
134    * \headerfile l4/cxx/exceptions
135    *
136    * This is the base class for a set of exceptions that cover all errors
137    * that have a C error value (see #l4_error_code_t).
138    */
139   class Runtime_error : public Base_exception
140   {
141   private:
142     long _errno;
143     char _extra[80];
144
145   public:
146     /**
147      * Create a new Runtime_error.
148      *
149      * \param err_no  Error value for this runtime error.
150      * \param extra   Description of what was happening while the error occured.
151      */
152     explicit Runtime_error(long err_no, char const *extra = 0) throw ()
153       : _errno(err_no)
154     {
155       if (!extra)
156         _extra[0] = 0;
157       else
158         {
159           unsigned i = 0;
160           for (; i < sizeof(_extra) && extra[i]; ++i)
161             _extra[i] = extra[i];
162           _extra[i < sizeof(_extra) ? i : sizeof(_extra) - 1] = 0;
163         }
164     }
165     char const *str() const throw ()
166     { return l4sys_errtostr(_errno); }
167
168     /**
169      * Get the description text for this runtime error.
170      *
171      * \return  Pointer to the description string.
172      */
173     char const *extra_str() const { return _extra; }
174     ~Runtime_error() throw () {}
175
176     /**
177      * Get the error value for this runtime error.
178      *
179      * \return  Error value.
180      */
181     long err_no() const throw() { return _errno; }
182   };
183
184   /**
185    * \brief Exception signalling insufficient memory.
186    * \headerfile l4/cxx/exceptions
187    */
188   class Out_of_memory : public Runtime_error
189   {
190   public:
191     /// Create an out-of-memory exception.
192     explicit Out_of_memory(char const *extra = "") throw()
193     : Runtime_error(-L4_ENOMEM, extra) {}
194     /// Destruction
195     ~Out_of_memory() throw() {}
196   };
197
198
199   /**
200    * \brief Exception for duplicate element insertions.
201    * \headerfile l4/cxx/exceptions
202    */
203   class Element_already_exists : public Runtime_error
204   {
205   public:
206     explicit Element_already_exists(char const *e = "") throw()
207     : Runtime_error(-L4_EEXIST, e) {}
208     ~Element_already_exists() throw() {}
209   };
210
211   /**
212    * \brief Exception for an unknown condition.
213    * \headerfile l4/cxx/exceptions
214    *
215    * This error is usually used when a server returns an unknown return state
216    * to the client, this may indicate incompatible messages used by the client
217    * and the server.
218    */
219   class Unknown_error : public Base_exception
220   {
221   public:
222     Unknown_error() throw() {}
223     char const *str() const throw() { return "unknown error"; }
224     ~Unknown_error() throw() {}
225   };
226
227   
228   /**
229    * \brief Exception for a failed lookup (element not found).
230    * \headerfile l4/cxx/exceptions
231    */
232   class Element_not_found : public Runtime_error
233   {
234   public:
235     explicit Element_not_found(char const *e = "") throw()
236     : Runtime_error(-L4_ENOENT, e) {}
237   };
238
239   /**
240    * \brief Indicates that an invalid object was invoked.
241    * \headerfile l4/cxx/exceptions
242    *
243    * An Object is invalid if it has L4_INVALID_ID as server L4 UID,
244    * or if the server does not know the object ID.
245    */
246   class Invalid_capability : public Base_exception
247   {
248   private:
249     Cap<void> const _o;
250
251   public:
252     /**
253      * \brief Create an Invalid_obejct exception for the Object o.
254      * \param o The object that caused the server side error.
255      */
256     explicit Invalid_capability(Cap<void> const &o) throw() : _o(o) {}
257     template< typename T>
258     explicit Invalid_capability(Cap<T> const &o) throw() : _o(o.cap()) {}
259     char const *str() const throw() { return "invalid object"; }
260
261     /**
262      * \brief Get the object that caused the error.
263      * \return The object that caused the error on invocation.
264      */
265     Cap<void> const &cap() const throw() { return _o; }
266     ~Invalid_capability() throw() {}
267   };
268
269   /**
270    * \brief Error conditions during IPC.
271    * \headerfile l4/cxx/exceptions
272    *
273    * This exception encapsulates all IPC error conditions of L4 IPC.
274    */
275   class Com_error : public Runtime_error
276   {
277   public:
278     /**
279      * \brief Create a Com_error for the givel L4 IPC error code.
280      * \param err The L4 IPC error code (l4_ipc... return value).
281      */
282     explicit Com_error(long err) throw() : Runtime_error(err) {}
283
284     ~Com_error() throw() {}
285   };
286
287   /**
288    * \brief Access out of bounds.
289    */
290   class Bounds_error : public Runtime_error
291   {
292   public:
293     explicit Bounds_error(char const *e = "") throw()
294     : Runtime_error(-L4_ERANGE, e) {}
295     ~Bounds_error() throw() {}
296   };
297   /*@}*/
298 };
299
300 inline
301 L4::BasicOStream &
302 operator << (L4::BasicOStream &o, L4::Base_exception const &e)
303 {
304   o << "Exception: " << e.str() << ", backtrace ...\n";
305   for (int i = 0; i < e.frame_count(); ++i)
306     o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n';
307
308   return o;
309 }
310
311 inline
312 L4::BasicOStream &
313 operator << (L4::BasicOStream &o, L4::Runtime_error const &e)
314 {
315   o << "Exception: " << e.str() << ": ";
316   if (e.extra_str())
317     o << e.extra_str() << ": ";
318   o << "backtrace ...\n";
319   for (int i = 0; i < e.frame_count(); ++i)
320     o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n';
321
322   return o;
323 }
324