123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- * Copyright (C)2005-2016 Haxe Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #include <hl.h>
- #include "hlsystem.h"
- #include <stdarg.h>
- #include <string.h>
- #ifdef HL_CONSOLE
- #include <posix/posix.h>
- #endif
- HL_PRIM void *hl_fatal_error( const char *msg, const char *file, int line ) {
- hl_blocking(true);
- # ifdef HL_WIN_DESKTOP
- HWND consoleWnd = GetConsoleWindow();
- DWORD pid;
- GetWindowThreadProcessId(consoleWnd, &pid);
- if( consoleWnd == NULL || GetActiveWindow() != NULL || GetCurrentProcessId() == pid ) {
- char buf[256];
- sprintf(buf,"%s\n\n%s(%d)",msg,file,line);
- MessageBoxA(NULL,buf,"Fatal Error", MB_OK | MB_ICONERROR);
- }
- # endif
- printf("%s(%d) : FATAL ERROR : %s\n",file,line,msg);
- hl_blocking(false);
- hl_debug_break();
- exit(1);
- return NULL;
- }
- typedef uchar *(*resolve_symbol_type)( void *addr, uchar *out, int *outSize );
- typedef int (*capture_stack_type)( void **stack, int size );
- static resolve_symbol_type resolve_symbol_func = NULL;
- static capture_stack_type capture_stack_func = NULL;
- int hl_internal_capture_stack( void **stack, int size ) {
- return capture_stack_func(stack,size);
- }
- HL_PRIM uchar *hl_resolve_symbol( void *addr, uchar *out, int *outSize ) {
- return resolve_symbol_func(addr, out, outSize);
- }
- static void (*throw_jump)( jmp_buf, int ) = NULL;
- HL_PRIM void hl_setup_longjump( void *j ) {
- throw_jump = j;
- }
- HL_PRIM void hl_setup_exception( void *resolve_symbol, void *capture_stack ) {
- resolve_symbol_func = resolve_symbol;
- capture_stack_func = capture_stack;
- }
- HL_PRIM void hl_set_error_handler( vclosure *d ) {
- hl_thread_info *t = hl_get_thread();
- t->trap_uncaught = t->trap_current;
- t->exc_handler = d;
- }
- static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) {
- while( true ) {
- if( trap == NULL || trap == t->trap_uncaught || t->trap_current == NULL || trap->prev == NULL ) return true;
- if( !trap->tcheck || !v ) return false;
- hl_type *ot = ((hl_type**)trap->tcheck)[1]; // it's an obj with first field is a hl_type
- if( !ot || hl_safe_cast(v->t,ot) ) return false;
- trap = trap->prev;
- }
- return false;
- }
- HL_PRIM void hl_throw( vdynamic *v ) {
- hl_thread_info *t = hl_get_thread();
- hl_trap_ctx *trap = t->trap_current;
- bool call_handler = false;
- if( t->flags & HL_EXC_KILL )
- hl_fatal("Exception Occured");
- if( !(t->flags & HL_EXC_RETHROW) )
- t->exc_stack_count = capture_stack_func(t->exc_stack_trace, HL_EXC_MAX_STACK);
- t->exc_value = v;
- t->trap_current = trap->prev;
- call_handler = trap == t->trap_uncaught || t->trap_current == NULL;
- if( (t->flags&HL_EXC_CATCH_ALL) || break_on_trap(t,trap,v) ) {
- if( trap == t->trap_uncaught ) t->trap_uncaught = NULL;
- t->flags |= HL_EXC_IS_THROW;
- hl_debug_break();
- t->flags &= ~HL_EXC_IS_THROW;
- }
- t->flags &= ~HL_EXC_RETHROW;
- if( t->exc_handler && call_handler ) hl_dyn_call_safe(t->exc_handler,&v,1,&call_handler);
- if( throw_jump == NULL ) throw_jump = longjmp;
- throw_jump(trap->buf,1);
- HL_UNREACHABLE;
- }
- HL_PRIM void hl_null_access() {
- hl_error("Null access");
- HL_UNREACHABLE;
- }
- HL_PRIM void hl_throw_buffer( hl_buffer *b ) {
- vdynamic *d = hl_alloc_dynamic(&hlt_bytes);
- d->v.ptr = hl_buffer_content(b,NULL);
- hl_throw(d);
- }
- HL_PRIM void hl_dump_stack() {
- void *stack[0x1000];
- int count = capture_stack_func(stack, 0x1000);
- int i;
- for(i=0;i<count;i++) {
- void *addr = stack[i];
- uchar sym[512];
- int size = 512;
- uchar *str = resolve_symbol_func(addr, sym, &size);
- if( str == NULL ) {
- int iaddr = (int)(int_val)addr;
- usprintf(sym,512,USTR("@0x%X"),iaddr);
- str = sym;
- }
- uprintf(USTR("%s\n"),str);
- }
- fflush(stdout);
- }
- HL_PRIM bool hl_maybe_print_custom_stack( vdynamic *exc ) {
- hl_type *ot = exc->t;
- while( ot->kind == HOBJ ) {
- if( ot->obj->super == NULL ) {
- if( ucmp(ot->obj->name, USTR("haxe.Exception")) == 0 ) {
- hl_field_lookup *f = hl_lookup_find(ot->obj->rt->lookup, ot->obj->rt->nlookup, hl_hash_gen(USTR("__customStack"), true));
- if( f == NULL || f->field_index < 0 ) break;
- vdynamic *customStack = *(vdynamic**)((char*)(exc) + f->field_index);
- if( customStack != NULL ) {
- uprintf(USTR("%s\n"), hl_to_string(customStack));
- return true;
- }
- }
- break;
- }
- ot = ot->obj->super;
- }
- return false;
- }
- HL_PRIM void hl_print_uncaught_exception(vdynamic *exc) {
- uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(exc));
- if (!hl_maybe_print_custom_stack(exc)) {
- varray *a = hl_exception_stack();
- for (int i = 0; i < a->size; i++)
- uprintf(USTR("Called from %s\n"), hl_aptr(a, uchar *)[i]);
- }
- fflush(stdout);
- }
- HL_PRIM varray *hl_exception_stack() {
- hl_thread_info *t = hl_get_thread();
- varray *a = hl_alloc_array(&hlt_bytes, t->exc_stack_count);
- int i, pos = 0;
- for(i=0;i<t->exc_stack_count;i++) {
- void *addr = t->exc_stack_trace[i];
- uchar sym[512];
- int size = 512;
- uchar *str = resolve_symbol_func(addr, sym, &size);
- if( str == NULL ) continue;
- hl_aptr(a,vbyte*)[pos++] = hl_copy_bytes((vbyte*)str,sizeof(uchar)*(size+1));
- }
- a->size = pos;
- return a;
- }
- HL_PRIM int hl_exception_stack_raw( varray *arr ) {
- hl_thread_info *t = hl_get_thread();
- if( arr ) memcpy(hl_aptr(arr,void*), t->exc_stack_trace, t->exc_stack_count*sizeof(void*));
- return t->exc_stack_count;
- }
- HL_PRIM int hl_call_stack_raw( varray *arr ) {
- if( !arr )
- return capture_stack_func(NULL,0);
- return capture_stack_func(hl_aptr(arr,void*), arr->size);
- }
- HL_PRIM void hl_rethrow( vdynamic *v ) {
- hl_get_thread()->flags |= HL_EXC_RETHROW;
- hl_throw(v);
- }
- HL_PRIM vdynamic *hl_alloc_strbytes( const uchar *fmt, ... ) {
- uchar _buf[256];
- vdynamic *d;
- int len;
- uchar *buf = _buf;
- int bsize = sizeof(_buf) / sizeof(uchar);
- va_list args;
- while( true ) {
- va_start(args, fmt);
- len = uvszprintf(buf,bsize,fmt,args);
- va_end(args);
- if( (len + 2) << 1 < bsize ) break;
- if( buf != _buf ) free(buf);
- bsize <<= 1;
- buf = (uchar*)malloc(bsize * sizeof(uchar));
- }
- d = hl_alloc_dynamic(&hlt_bytes);
- d->v.ptr = hl_copy_bytes((vbyte*)buf,(len + 1) << 1);
- if( buf != _buf ) free(buf);
- return d;
- }
- HL_PRIM void hl_fatal_fmt( const char *file, int line, const char *fmt, ...) {
- char buf[256];
- va_list args;
- va_start(args, fmt);
- vsprintf(buf,fmt, args);
- va_end(args);
- hl_fatal_error(buf,file,line);
- }
- #ifdef HL_VCC
- # pragma optimize( "", off )
- #endif
- HL_PRIM HL_NO_OPT void hl_breakpoint() {
- hl_debug_break();
- }
- #ifdef HL_VCC
- # pragma optimize( "", on )
- #endif
- #ifdef HL_LINUX
- #include <unistd.h>
- #include <fcntl.h>
- #endif
- #if defined(HL_MAC) && defined(__x86_64__)
- extern bool is_debugger_attached(void);
- # define MAC_DEBUG
- #endif
- HL_PRIM bool hl_detect_debugger() {
- # if defined(HL_WIN)
- return (bool)IsDebuggerPresent();
- # elif defined(HL_LINUX)
- static int debugger_present = -1;
- if(debugger_present < 0) {
- char buf[2048];
- char *tracer_pid;
- ssize_t num_read;
- debugger_present = 0;
- int status_fd = open("/proc/self/status", O_RDONLY);
- if (status_fd == -1)
- return 0;
- num_read = read(status_fd, buf, sizeof(buf));
- close(status_fd);
- if (num_read > 0) {
- buf[num_read] = 0;
- tracer_pid = strstr(buf, "TracerPid:");
- if (tracer_pid && atoi(tracer_pid + sizeof("TracerPid:") - 1) > 0)
- debugger_present = 1;
- }
- }
- return debugger_present == 1;
- # elif defined(MAC_DEBUG)
- return is_debugger_attached();
- # else
- return false;
- # endif
- }
- #ifdef HL_VCC
- # pragma optimize( "", off )
- #endif
- HL_PRIM HL_NO_OPT void hl_assert() {
- hl_debug_break();
- hl_error("assert");
- }
- #ifdef HL_VCC
- # pragma optimize( "", on )
- #endif
- #define _SYMBOL _ABSTRACT(hl_symbol)
- DEFINE_PRIM(_ARR,exception_stack,_NO_ARG);
- DEFINE_PRIM(_I32,exception_stack_raw,_ARR);
- DEFINE_PRIM(_I32,call_stack_raw,_ARR);
- DEFINE_PRIM(_VOID,set_error_handler,_FUN(_VOID,_DYN));
- DEFINE_PRIM(_VOID,breakpoint,_NO_ARG);
- DEFINE_PRIM(_BYTES,resolve_symbol, _SYMBOL _BYTES _REF(_I32));
|