00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BOOSTER_BACKTRACE_H
00009 #define BOOSTER_BACKTRACE_H
00010
00011 #include <booster/config.h>
00012 #include <stdexcept>
00013 #include <typeinfo>
00014 #include <string>
00015 #include <vector>
00016 #include <iosfwd>
00017
00018 namespace booster {
00019
00024 namespace stack_trace {
00033 BOOSTER_API int trace(void **addresses,int size);
00039 BOOSTER_API void write_symbols(void *const *addresses,int size,std::ostream &);
00043 BOOSTER_API std::string get_symbol(void *address);
00047 BOOSTER_API std::string get_symbols(void * const *address,int size);
00048 }
00049
00055
00056 class backtrace {
00057 public:
00058
00062 static size_t const default_stack_size = 32;
00063
00067 backtrace(size_t frames_no = default_stack_size)
00068 {
00069 if(frames_no == 0)
00070 return;
00071 frames_.resize(frames_no,0);
00072 int size = stack_trace::trace(&frames_.front(),frames_no);
00073 frames_.resize(size);
00074 }
00075
00076 virtual ~backtrace() throw()
00077 {
00078 }
00079
00083 size_t stack_size() const
00084 {
00085 return frames_.size();
00086 }
00087
00091 void *return_address(unsigned frame_no) const
00092 {
00093 if(frame_no < stack_size())
00094 return frames_[frame_no];
00095 return 0;
00096 }
00097
00101 void trace_line(unsigned frame_no,std::ostream &out) const
00102 {
00103 if(frame_no < frames_.size())
00104 stack_trace::write_symbols(&frames_[frame_no],1,out);
00105 }
00106
00110 std::string trace_line(unsigned frame_no) const
00111 {
00112 if(frame_no < frames_.size())
00113 return stack_trace::get_symbol(frames_[frame_no]);
00114 return std::string();
00115 }
00116
00120 std::string trace() const
00121 {
00122 if(frames_.empty())
00123 return std::string();
00124 return stack_trace::get_symbols(&frames_.front(),frames_.size());
00125 }
00126
00130 void trace(std::ostream &out) const
00131 {
00132 if(frames_.empty())
00133 return;
00134 stack_trace::write_symbols(&frames_.front(),frames_.size(),out);
00135 }
00136
00137 private:
00138 std::vector<void *> frames_;
00139 };
00140
00144 class exception : public std::exception, public backtrace {
00145 public:
00146 };
00147
00151 class bad_cast : public std::bad_cast, public backtrace {
00152 public:
00153 };
00154
00158 class runtime_error: public std::runtime_error, public backtrace {
00159 public:
00160 explicit runtime_error(std::string const &s) : std::runtime_error(s)
00161 {
00162 }
00163 };
00164
00168 class range_error: public std::range_error, public backtrace {
00169 public:
00170 explicit range_error(std::string const &s) : std::range_error(s)
00171 {
00172 }
00173 };
00174
00178 class overflow_error: public std::overflow_error, public backtrace {
00179 public:
00180 explicit overflow_error(std::string const &s) : std::overflow_error(s)
00181 {
00182 }
00183 };
00184
00188 class underflow_error: public std::underflow_error, public backtrace {
00189 public:
00190 explicit underflow_error(std::string const &s) : std::underflow_error(s)
00191 {
00192 }
00193 };
00194
00198 class logic_error: public std::logic_error, public backtrace {
00199 public:
00200 explicit logic_error(std::string const &s) : std::logic_error(s)
00201 {
00202 }
00203 };
00204
00208 class domain_error: public std::domain_error, public backtrace {
00209 public:
00210 explicit domain_error(std::string const &s) : std::domain_error(s)
00211 {
00212 }
00213 };
00214
00218 class length_error: public std::length_error, public backtrace {
00219 public:
00220 explicit length_error(std::string const &s) : std::length_error(s)
00221 {
00222 }
00223 };
00224
00228 class invalid_argument : public std::invalid_argument, public backtrace {
00229 public:
00230 explicit invalid_argument(std::string const &s) : std::invalid_argument(s)
00231 {
00232 }
00233 };
00234
00238 class out_of_range : public std::out_of_range, public backtrace {
00239 public:
00240 explicit out_of_range(std::string const &s) : std::out_of_range(s)
00241 {
00242 }
00243 };
00244
00246 namespace details {
00247 class trace_manip {
00248 public:
00249 trace_manip(backtrace const *tr) :
00250 tr_(tr)
00251 {
00252 }
00253 std::ostream &write(std::ostream &out) const
00254 {
00255 if(tr_)
00256 tr_->trace(out);
00257 return out;
00258 }
00259 private:
00260 backtrace const *tr_;
00261 };
00262
00263 inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t)
00264 {
00265 return t.write(out);
00266 }
00267 }
00269
00284 template<typename E>
00285 details::trace_manip trace(E const &e)
00286 {
00287 backtrace const *tr = dynamic_cast<backtrace const *>(&e);
00288 return details::trace_manip(tr);
00289 }
00290
00291
00292 }
00293
00294 #endif
00295
00296