23 #ifndef RC_NO_STACKTRACE
35 #include <mach/mach_init.h>
36 #include <sys/sysctl.h>
37 #include <mach/mach_vm.h>
46 const size_t ErrorMsg_text_bufsize = 4096;
47 const size_t ErrorMsg_what_bufsize = 4096+1024;
66 class ErrorMsg :
virtual public std::exception {
69 static size_t TaskPid(
size_t pid=0) {
70 static size_t task_pid = 0;
79 size_t GetLoadAddress() {
81 vm_map_offset_t vmoffset;
83 uint32_t nesting_depth = 0;
84 struct vm_region_submap_info_64 vbr;
85 mach_msg_type_number_t vbrcount = 16;
88 if ((kr = mach_vm_region_recurse(TaskPid(), &vmoffset, &vmsize,
90 (vm_region_recurse_info_t)&vbr,
91 &vbrcount)) != KERN_SUCCESS)
108 size_t AmountWritten(
size_t size,
size_t written) {
109 return (size <= written) ? size-1 : written;
113 #define R_Safe_snprintf(str, size, ...) \
114 AmountWritten(size, size_t(snprintf(str, size, __VA_ARGS__)));
128 ErrorMsg(
const char* new_err_msg=NULL,
const char* filename=NULL,
131 char stacktrace_txt[ErrorMsg_text_bufsize] = {0};
134 if (new_err_msg == NULL) {
139 err_msg[ErrorMsg_text_bufsize-1] =
'\0';
142 #ifndef RC_NO_STACKTRACE
144 int backtrace_cnt = 0;
145 const int backtrace_size = 128;
146 void *bt_buffer[backtrace_size];
148 char **backtrace_symb;
149 backtrace_cnt = backtrace(bt_buffer, backtrace_size);
150 backtrace_symb = backtrace_symbols(bt_buffer, backtrace_cnt);
152 if (backtrace_symb != NULL) {
153 for (
int i=0; i<backtrace_cnt; i++) {
154 offset += R_Safe_snprintf(stacktrace_txt+offset,
156 backtrace_symb[backtrace_cnt-i-1]);
158 offset += R_Safe_snprintf(stacktrace_txt+offset,
161 SafeFree(backtrace_symb);
170 if (SymInitialize && SymFromAddr && SymCleanup) {
171 HANDLE process = GetCurrentProcess();
172 SymInitialize(process, NULL,
true);
175 const size_t symbolnamelen = 255;
176 char symboldata[
sizeof(SYMBOL_INFO)+(symbolnamelen+1)];
177 SYMBOL_INFO *symbol =
reinterpret_cast<SYMBOL_INFO*
>(symboldata);
178 symbol->MaxNameLen = symbolnamelen;
179 symbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
181 backtrace_cnt = CaptureStackBackTrace(0, backtrace_size,
184 for(
int i=0; i<backtrace_cnt; i++) {
185 offset += R_Safe_snprintf(stacktrace_txt+offset,
187 static_cast<long unsigned int>(
size_t(bt_buffer[i])));
188 if (SymFromAddr(process, DWORD64(bt_buffer[i]), 0, symbol)) {
189 offset += R_Safe_snprintf(stacktrace_txt+offset,
191 static_cast<long unsigned int>(
size_t(symbol->Address)));
194 offset += R_Safe_snprintf(stacktrace_txt+offset,
198 offset += R_Safe_snprintf(stacktrace_txt+offset,
207 if (filename != NULL && filename[0] !=
'\0') {
209 written = snprintf(what_msg, ErrorMsg_what_bufsize,
210 "%s, %s, line %d, load address %p%s", err_msg, filename,
211 line_number, (
void *)GetLoadAddress(), stacktrace_txt);
213 written = snprintf(what_msg, ErrorMsg_what_bufsize,
214 "%s, %s, line %d%s", err_msg, filename, line_number,
219 written = snprintf(what_msg, ErrorMsg_what_bufsize,
"%s%s", err_msg,
222 if (written >=
int(ErrorMsg_what_bufsize)) {
223 for (
size_t i=ErrorMsg_what_bufsize-4; i<ErrorMsg_what_bufsize-1;
227 what_msg[ErrorMsg_what_bufsize-1] =
'\0';
231 #undef R_Safe_snprintf
257 return (0 == strncmp(err_msg, test_err, ErrorMsg_text_bufsize));
279 char err_msg[ErrorMsg_text_bufsize];
280 char what_msg[ErrorMsg_what_bufsize];
292 #define RC_MAKE_ERROR_TYPE(Type) \
293 class ErrorMsg##Type : virtual public RC::ErrorMsg {\
297 ErrorMsg##Type(const char* new_err_msg, const char* filename = "",\
298 int line_number = 0)\
299 : RC::ErrorMsg(new_err_msg, filename, line_number) {\
300 snprintf(type_msg, ErrorMsg_type_bufsize, #Type);\
327 #define Throw_RC_Error(err) throw RC::ErrorMsg(err, __FILE__, __LINE__)
335 #define Throw_RC_Type(Type, err) throw RC::ErrorMsg##Type(err, __FILE__, __LINE__)
339 #define Catch_RC_Error() catch (RC::ErrorMsgFatal& err) { fprintf(stderr, "Fatal Error: %s\n", err.what()); exit(-1); } catch (RC::ErrorMsg& err) { fprintf(stderr, "Error: %s\n", err.what()); }
342 #define Catch_RC_Error_Exit() catch (RC::ErrorMsg& err) { fprintf(stderr, "Error: %s\n", err.what()); exit(-1); }
368 memset (&sa, 0,
sizeof(sa));
370 sigaction(SIGSEGV, &sa, NULL);
#define Throw_RC_Type(Type, err)
Use this to throw an RC:ErrorMsg subtype exception.
Definition: Errors.h:335
#define RC_MAKE_ERROR_TYPE(Type)
Creates new RC::ErrorMsg subtypes.
Definition: Errors.h:292
#define RC_DYNAMIC_LOAD_FUNC_RAW(FuncName, Library)
Use as RC_DYNAMIC_LOAD_FUNC_RAW(FuncName,Library) to load FuncName from the dynamic library file Libr...
Definition: Macros.h:197
Ptr< Type > Cast()
Dynamically casts to an RC::Ptr of the type used as a template parameter on this function.
Definition: PtrCommon.h:57
The version information and configuration settings for RC Lib.
Provides typedefs and routines for working with primitives.
#define RC_NOEXCEPT
Provides noexcept if available.
Definition: Types.h:64
An exception class that records where the exception was thrown and provides a stack trace.
Definition: Errors.h:66
virtual const char * GetType() const noexcept
Provides the type of the exception if this is a subclass.
Definition: Errors.h:246
virtual const char * GetError() const noexcept
Provides the reason given for the error.
Definition: Errors.h:237
virtual bool IsError(const char *test_err) const noexcept
Return true if the the reason for the exception matches test_err.
Definition: Errors.h:256
ErrorMsg(const char *new_err_msg=NULL, const char *filename=NULL, int line_number=0) noexcept
The default constructor.
Definition: Errors.h:128
virtual const char * what() const noexcept
Returns a full descriptive error message with reason, source location, and stack trace.
Definition: Errors.h:266
A class with static methods for file and directory info and manipulation.
Definition: File.h:1214
Provides both client and server sides of blocking TCP connections.
Definition: Net.h:429
A static class for catching and throwing segfaults.
Definition: Errors.h:353
static void Handler(int)
The default handler for a segfault. It throws ErrorMsgFatal.
Definition: Errors.h:357
static void SetHandler()
Call this to set the segfault handler to Segfault::Handler.
Definition: Errors.h:363
const size_t ErrorMsg_text_size
The maximum size of the char array returned by ErrorMsg::what() and ErrorMsg::GetError(),...
Definition: Errors.h:44
const size_t ErrorMsg_type_bufsize
The maximum size of the char array returned by ErrorMsg::GetType(), including the null.
Definition: Errors.h:51