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#pragma once 26 27#include <l4/cxx/l4types.h> 28#include <l4/cxx/basic_ostream> 29#include <l4/sys/err.h> 30#include <l4/sys/capability> 31 32 33/** 34 * \defgroup l4cxx_exceptions C++ Exceptions 35 * \ingroup api_l4re 36 */ 37/*@{*/ 38 39#ifndef L4_CXX_NO_EXCEPTION_BACKTRACE 40# define L4_CXX_EXCEPTION_BACKTRACE 20 ///< Number of instruction pointers in backtrace 41#endif 42 43#if defined(L4_CXX_EXCEPTION_BACKTRACE) 44#include <l4/util/backtrace.h> 45#endif 46 47/*@}*/ 48namespace L4 49{ 50 /** 51 * \addtogroup l4cxx_exceptions 52 */ 53 /*@{*/ 54 /** 55 * \brief Back-trace support for exceptions. 56 * \headerfile l4/cxx/exceptions 57 * 58 * This class holds an array of at most #L4_CXX_EXCEPTION_BACKTRACE 59 * instruction pointers containing the call trace at the instant when an 60 * exception was thrown. 61 */ 62 class Exception_tracer 63 { 64#if defined(L4_CXX_EXCEPTION_BACKTRACE) 65 private: 66 void *_pc_array[L4_CXX_EXCEPTION_BACKTRACE]; 67 int _frame_cnt; 68 69 protected: 70 /** 71 * \brief Create a back trace. 72 */ 73#if defined(__PIC__) 74 Exception_tracer() throw() : _frame_cnt(0) {} 75#else 76 Exception_tracer() throw() 77 : _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 * \brief Exception for a failed lookup (element not found). 229 * \headerfile l4/cxx/exceptions 230 */ 231 class Element_not_found : public Runtime_error 232 { 233 public: 234 explicit Element_not_found(char const *e = "") throw() 235 : Runtime_error(-L4_ENOENT, e) {} 236 }; 237 238 /** 239 * \brief Indicates that an invalid object was invoked. 240 * \headerfile l4/cxx/exceptions 241 * 242 * An Object is invalid if it has L4_INVALID_ID as server L4 UID, 243 * or if the server does not know the object ID. 244 */ 245 class Invalid_capability : public Base_exception 246 { 247 private: 248 Cap<void> const _o; 249 250 public: 251 /** 252 * \brief Create an Invalid_object exception for the Object o. 253 * \param o The object that caused the server side error. 254 */ 255 explicit Invalid_capability(Cap<void> const &o) throw() : _o(o) {} 256 template< typename T> 257 explicit Invalid_capability(Cap<T> const &o) throw() : _o(o.cap()) {} 258 char const *str() const throw() { return "invalid object"; } 259 260 /** 261 * \brief Get the object that caused the error. 262 * \return The object that caused the error on invocation. 263 */ 264 Cap<void> const &cap() const throw() { return _o; } 265 ~Invalid_capability() throw() {} 266 }; 267 268 /** 269 * \brief Error conditions during IPC. 270 * \headerfile l4/cxx/exceptions 271 * 272 * This exception encapsulates all IPC error conditions of L4 IPC. 273 */ 274 class Com_error : public Runtime_error 275 { 276 public: 277 /** 278 * \brief Create a Com_error for the given L4 IPC error code. 279 * \param err The L4 IPC error code (l4_ipc... return value). 280 */ 281 explicit Com_error(long err) throw() : Runtime_error(err) {} 282 283 ~Com_error() throw() {} 284 }; 285 286 /** 287 * \brief Access out of bounds. 288 */ 289 class Bounds_error : public Runtime_error 290 { 291 public: 292 explicit Bounds_error(char const *e = "") throw() 293 : Runtime_error(-L4_ERANGE, e) {} 294 ~Bounds_error() throw() {} 295 }; 296 /*@}*/ 297}; 298 299inline 300L4::BasicOStream & 301operator << (L4::BasicOStream &o, L4::Base_exception const &e) 302{ 303 o << "Exception: " << e.str() << ", backtrace ...\n"; 304 for (int i = 0; i < e.frame_count(); ++i) 305 o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n'; 306 307 return o; 308} 309 310inline 311L4::BasicOStream & 312operator << (L4::BasicOStream &o, L4::Runtime_error const &e) 313{ 314 o << "Exception: " << e.str() << ": "; 315 if (e.extra_str()) 316 o << e.extra_str() << ": "; 317 o << "backtrace ...\n"; 318 for (int i = 0; i < e.frame_count(); ++i) 319 o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n'; 320 321 return o; 322} 323