L4Re - L4 Runtime Environment
exceptions
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
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