mirror of https://github.com/flysand7/ciabatta.git
Assert stack trace
This commit is contained in:
parent
e79c192472
commit
c024b3b241
2
bake.cmd
2
bake.cmd
|
@ -44,5 +44,5 @@ llvm-ar rc ciabatta.lib bin\*.obj bin\%PLATFORM%\*.obj
|
||||||
if "%TEST%"=="" set TEST=assert
|
if "%TEST%"=="" set TEST=assert
|
||||||
|
|
||||||
echo Compiling test_%TEST%.c
|
echo Compiling test_%TEST%.c
|
||||||
clang -fno-builtin test\test_%TEST%.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS%
|
clang -fno-builtin test\test_%TEST%.c ciabatta.lib -std=c11 -lDbghelp -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS%
|
||||||
::cl test\test_math.c /Iinc -D_CRT_SECURE_NO_WARNINGS /Z7 /link ciabatta.lib kernel32.lib user32.lib shell32.lib -nostdlib -nodefaultlibs
|
::cl test\test_math.c /Iinc -D_CRT_SECURE_NO_WARNINGS /Z7 /link ciabatta.lib kernel32.lib user32.lib shell32.lib -nostdlib -nodefaultlibs
|
||||||
|
|
|
@ -27,6 +27,9 @@ typedef struct _OS_ModeFlags {
|
||||||
} _OS_ModeFlags;
|
} _OS_ModeFlags;
|
||||||
|
|
||||||
typedef struct FILE FILE;
|
typedef struct FILE FILE;
|
||||||
|
|
||||||
|
void _os_print_stack_trace();
|
||||||
|
|
||||||
int _os_del_file(char const *filename);
|
int _os_del_file(char const *filename);
|
||||||
int _os_mov_file(char const *old, char const *new);
|
int _os_mov_file(char const *old, char const *new);
|
||||||
char *_os_tmpname(char *buffer);
|
char *_os_tmpname(char *buffer);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <stdio.h> // printf
|
#include <stdio.h> // printf
|
||||||
#include <stdlib.h> // abort
|
#include <stdlib.h> // abort
|
||||||
|
#include <_os.h> // stack trace
|
||||||
|
|
||||||
void _Noreturn _assert(
|
void _Noreturn _assert(
|
||||||
char const *cond,
|
char const *cond,
|
||||||
|
@ -14,5 +15,7 @@ void _Noreturn _assert(
|
||||||
printf(" Function: %s\n", func);
|
printf(" Function: %s\n", func);
|
||||||
printf(" File: %s\n", file);
|
printf(" File: %s\n", file);
|
||||||
printf(" Line: %d\n", line);
|
printf(" Line: %d\n", line);
|
||||||
|
printf("Trace:\n");
|
||||||
|
_os_print_stack_trace();
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,11 @@
|
||||||
ArgConv arg_conv;
|
ArgConv arg_conv;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static uint64_t get_int_arg(Format *fmt, va_list args, bool *signp) {
|
inline static uint64_t get_int_arg(
|
||||||
|
Format *fmt,
|
||||||
|
va_list *args,
|
||||||
|
bool *signp
|
||||||
|
) {
|
||||||
bool sign = 0;
|
bool sign = 0;
|
||||||
uint64_t num = 0;
|
uint64_t num = 0;
|
||||||
|
|
||||||
|
@ -66,7 +70,7 @@
|
||||||
// If we've got HH or H we need to parse as int, and do the necessary conv
|
// If we've got HH or H we need to parse as int, and do the necessary conv
|
||||||
// to unsigned if needed.
|
// to unsigned if needed.
|
||||||
if(fmt->arg_len < LEN_I) {
|
if(fmt->arg_len < LEN_I) {
|
||||||
int ch = va_arg(args, int);
|
int ch = va_arg(*args, int);
|
||||||
if(ch < 0) {
|
if(ch < 0) {
|
||||||
if(fmt->flag_unsigned) {
|
if(fmt->flag_unsigned) {
|
||||||
num = ch + (fmt->arg_len == LEN_HH? UCHAR_MAX : USHRT_MAX);
|
num = ch + (fmt->arg_len == LEN_HH? UCHAR_MAX : USHRT_MAX);
|
||||||
|
@ -82,12 +86,12 @@
|
||||||
// plus handle the sign
|
// plus handle the sign
|
||||||
else if(fmt->flag_unsigned) {
|
else if(fmt->flag_unsigned) {
|
||||||
switch(fmt->arg_len) {
|
switch(fmt->arg_len) {
|
||||||
case LEN_I: num = va_arg(args, unsigned int); break;
|
case LEN_I: num = va_arg(*args, unsigned int); break;
|
||||||
case LEN_L: num = va_arg(args, unsigned long); break;
|
case LEN_L: num = va_arg(*args, unsigned long); break;
|
||||||
case LEN_LL: num = va_arg(args, unsigned long long); break;
|
case LEN_LL: num = va_arg(*args, unsigned long long); break;
|
||||||
case LEN_J: num = va_arg(args, uintmax_t); break;
|
case LEN_J: num = va_arg(*args, uintmax_t); break;
|
||||||
case LEN_Z: num = va_arg(args, size_t); break;
|
case LEN_Z: num = va_arg(*args, size_t); break;
|
||||||
case LEN_T: num = va_arg(args, size_t); break;
|
case LEN_T: num = va_arg(*args, size_t); break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,12 +99,12 @@
|
||||||
// TODO: signed size_t
|
// TODO: signed size_t
|
||||||
int64_t i = 0;
|
int64_t i = 0;
|
||||||
switch(fmt->arg_len) {
|
switch(fmt->arg_len) {
|
||||||
case LEN_I: i = va_arg(args, int); break;
|
case LEN_I: i = va_arg(*args, int); break;
|
||||||
case LEN_L: i = va_arg(args, long); break;
|
case LEN_L: i = va_arg(*args, long); break;
|
||||||
case LEN_LL: i = va_arg(args, long long); break;
|
case LEN_LL: i = va_arg(*args, long long); break;
|
||||||
case LEN_J: i = va_arg(args, uintmax_t); break;
|
case LEN_J: i = va_arg(*args, uintmax_t); break;
|
||||||
case LEN_Z: i = va_arg(args, int64_t); break;
|
case LEN_Z: i = va_arg(*args, int64_t); break;
|
||||||
case LEN_T: i = va_arg(args, ptrdiff_t); break;
|
case LEN_T: i = va_arg(*args, ptrdiff_t); break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
|
@ -143,7 +147,7 @@ inline static int suffix(fmt_atoi)(fchar const *str, int *value) {
|
||||||
inline static int suffix(fmt_parse)(
|
inline static int suffix(fmt_parse)(
|
||||||
Format *format,
|
Format *format,
|
||||||
fchar const *str,
|
fchar const *str,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
*format = (Format){0};
|
*format = (Format){0};
|
||||||
// Parse flags
|
// Parse flags
|
||||||
|
@ -161,7 +165,7 @@ inline static int suffix(fmt_parse)(
|
||||||
int width = 0;
|
int width = 0;
|
||||||
if(str[i] == '*') {
|
if(str[i] == '*') {
|
||||||
++i;
|
++i;
|
||||||
width = va_arg(args, int);
|
width = va_arg(*args, int);
|
||||||
if(width < 0) {
|
if(width < 0) {
|
||||||
width = -width;
|
width = -width;
|
||||||
format->flag_zero = true;
|
format->flag_zero = true;
|
||||||
|
@ -178,7 +182,7 @@ inline static int suffix(fmt_parse)(
|
||||||
++i;
|
++i;
|
||||||
if(str[i] == '*') {
|
if(str[i] == '*') {
|
||||||
++i;
|
++i;
|
||||||
prec = va_arg(args, int);
|
prec = va_arg(*args, int);
|
||||||
if(prec < 0) {
|
if(prec < 0) {
|
||||||
prec = 0;
|
prec = 0;
|
||||||
}
|
}
|
||||||
|
@ -333,7 +337,7 @@ inline static int suffix(fmt_fprint_int)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
suffix(out_func_t) *out,
|
suffix(out_func_t) *out,
|
||||||
Format *fmt,
|
Format *fmt,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
|
|
||||||
|
@ -448,10 +452,10 @@ inline static int suffix(fmt_fprint_ptr)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
suffix(out_func_t) *out,
|
suffix(out_func_t) *out,
|
||||||
Format *fmt,
|
Format *fmt,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
uintptr_t num = va_arg(args, uintptr_t);
|
uintptr_t num = va_arg(*args, uintptr_t);
|
||||||
|
|
||||||
int s_len = 2 + 16; // length of significant chars
|
int s_len = 2 + 16; // length of significant chars
|
||||||
int d_len = s_len; // length of all displayed chars
|
int d_len = s_len; // length of all displayed chars
|
||||||
|
@ -530,7 +534,7 @@ inline static int suffix(fmt_fprint_char)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
suffix(out_func_t) *out,
|
suffix(out_func_t) *out,
|
||||||
Format *fmt,
|
Format *fmt,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
bool sign;
|
bool sign;
|
||||||
|
@ -570,10 +574,10 @@ inline static int suffix(fmt_just_fucking_print_float_someone_improve_this_later
|
||||||
void *ctx,
|
void *ctx,
|
||||||
suffix(out_func_t) *out,
|
suffix(out_func_t) *out,
|
||||||
Format *fmt,
|
Format *fmt,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
double f = va_arg(args, double);
|
double f = va_arg(*args, double);
|
||||||
uint64_t i = (uint64_t)f;
|
uint64_t i = (uint64_t)f;
|
||||||
|
|
||||||
char digits_arr[33] = {0};
|
char digits_arr[33] = {0};
|
||||||
|
@ -616,10 +620,10 @@ inline static int suffix(fmt_fprint_str)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
suffix(out_func_t) *out,
|
suffix(out_func_t) *out,
|
||||||
Format *fmt,
|
Format *fmt,
|
||||||
va_list args
|
va_list *args
|
||||||
) {
|
) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
char *str = va_arg(args, char *);
|
char *str = va_arg(*args, char *);
|
||||||
uint64_t len = strlen(str);
|
uint64_t len = strlen(str);
|
||||||
|
|
||||||
// Calculate padding
|
// Calculate padding
|
||||||
|
@ -666,31 +670,31 @@ inline static int suffix(fmt_print)(
|
||||||
if(fmt[i] == '%') {
|
if(fmt[i] == '%') {
|
||||||
++i;
|
++i;
|
||||||
Format format;
|
Format format;
|
||||||
int fmt_len = suffix(fmt_parse)(&format, fmt+i, args);
|
int fmt_len = suffix(fmt_parse)(&format, fmt+i, &args);
|
||||||
if(fmt_len < 0) return -1;
|
if(fmt_len < 0) return -1;
|
||||||
i += fmt_len;
|
i += fmt_len;
|
||||||
int written;
|
int written;
|
||||||
switch(format.arg_conv) {
|
switch(format.arg_conv) {
|
||||||
case CONV_INT: {
|
case CONV_INT: {
|
||||||
written = suffix(fmt_fprint_int)(ctx, out, &format, args);
|
written = suffix(fmt_fprint_int)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_FLT: {
|
case CONV_FLT: {
|
||||||
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, args);
|
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_EXP: {
|
case CONV_EXP: {
|
||||||
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, args);
|
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_SCI: {
|
case CONV_SCI: {
|
||||||
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, args);
|
written = suffix(fmt_just_fucking_print_float_someone_improve_this_later)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_CHAR: {
|
case CONV_CHAR: {
|
||||||
written = suffix(fmt_fprint_char)(ctx, out, &format, args);
|
written = suffix(fmt_fprint_char)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_STR: {
|
case CONV_STR: {
|
||||||
written = suffix(fmt_fprint_str)(ctx, out, &format, args);
|
written = suffix(fmt_fprint_str)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_PTR: {
|
case CONV_PTR: {
|
||||||
written = suffix(fmt_fprint_ptr)(ctx, out, &format, args);
|
written = suffix(fmt_fprint_ptr)(ctx, out, &format, &args);
|
||||||
} break;
|
} break;
|
||||||
case CONV_N: {
|
case CONV_N: {
|
||||||
int *n = va_arg(args, int *);
|
int *n = va_arg(args, int *);
|
||||||
|
|
|
@ -88,7 +88,7 @@ int strcmp(const char *s1, const char *s2) {
|
||||||
int diff;
|
int diff;
|
||||||
do {
|
do {
|
||||||
diff = *s1 - *s2;
|
diff = *s1 - *s2;
|
||||||
} while(diff != 0 && *s1 != 0 && *s2 != 0);
|
} while(diff == 0 && *s1++ != 0 && *s2++ != 0);
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include<Windows.h>
|
#include<Windows.h>
|
||||||
|
#include<DbgHelp.h>
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
||||||
|
|
||||||
|
@ -49,6 +54,29 @@ static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) {
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _os_print_stack_trace() {
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
SymInitialize(process, NULL, TRUE);
|
||||||
|
|
||||||
|
void *stack[128];
|
||||||
|
USHORT frames = CaptureStackBackTrace(2, 128, stack, NULL);
|
||||||
|
|
||||||
|
SYMBOL_INFO* symbol = calloc(sizeof(SYMBOL_INFO)+256, 1);
|
||||||
|
symbol->MaxNameLen = 255;
|
||||||
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
for(size_t i = 0; i < frames; i++) {
|
||||||
|
SymFromAddr(process, (DWORD64)stack[i], 0, symbol);
|
||||||
|
if(strcmp(symbol->Name, "BaseThreadInitThunk") == 0) break;
|
||||||
|
if(strcmp(symbol->Name, "mainCRTStartup") == 0) break;
|
||||||
|
printf(" %u: 0x%"PRIx64" (%s)\n",
|
||||||
|
(int)(frames-i-1),
|
||||||
|
symbol->Address,
|
||||||
|
symbol->Name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
free(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
void _os_init_eh() {
|
void _os_init_eh() {
|
||||||
void *res = AddVectoredExceptionHandler(1, &_win32_handler);
|
void *res = AddVectoredExceptionHandler(1, &_win32_handler);
|
||||||
if(res == NULL) {
|
if(res == NULL) {
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void do_more_stuff(char *ptr) {
|
||||||
|
assert(ptr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_stuff() {
|
||||||
|
do_more_stuff(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
assert(2+2 == 4);
|
assert(2+2 == 4);
|
||||||
assert(0 != 0); // Bad case of assert
|
do_stuff();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue