Assert stack trace

This commit is contained in:
bumbread 2022-06-19 16:24:36 +11:00
parent e79c192472
commit c024b3b241
7 changed files with 83 additions and 36 deletions

View File

@ -44,5 +44,5 @@ llvm-ar rc ciabatta.lib bin\*.obj bin\%PLATFORM%\*.obj
if "%TEST%"=="" set TEST=assert
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

View File

@ -27,6 +27,9 @@ typedef struct _OS_ModeFlags {
} _OS_ModeFlags;
typedef struct FILE FILE;
void _os_print_stack_trace();
int _os_del_file(char const *filename);
int _os_mov_file(char const *old, char const *new);
char *_os_tmpname(char *buffer);

View File

@ -3,6 +3,7 @@
#include <stdio.h> // printf
#include <stdlib.h> // abort
#include <_os.h> // stack trace
void _Noreturn _assert(
char const *cond,
@ -14,5 +15,7 @@ void _Noreturn _assert(
printf(" Function: %s\n", func);
printf(" File: %s\n", file);
printf(" Line: %d\n", line);
printf("Trace:\n");
_os_print_stack_trace();
abort();
}

View File

@ -58,7 +58,11 @@
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;
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
// to unsigned if needed.
if(fmt->arg_len < LEN_I) {
int ch = va_arg(args, int);
int ch = va_arg(*args, int);
if(ch < 0) {
if(fmt->flag_unsigned) {
num = ch + (fmt->arg_len == LEN_HH? UCHAR_MAX : USHRT_MAX);
@ -82,12 +86,12 @@
// plus handle the sign
else if(fmt->flag_unsigned) {
switch(fmt->arg_len) {
case LEN_I: num = va_arg(args, unsigned int); break;
case LEN_L: num = va_arg(args, unsigned 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_Z: num = va_arg(args, size_t); break;
case LEN_T: num = va_arg(args, size_t); break;
case LEN_I: num = va_arg(*args, unsigned int); break;
case LEN_L: num = va_arg(*args, unsigned 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_Z: num = va_arg(*args, size_t); break;
case LEN_T: num = va_arg(*args, size_t); break;
default:;
}
}
@ -95,12 +99,12 @@
// TODO: signed size_t
int64_t i = 0;
switch(fmt->arg_len) {
case LEN_I: i = va_arg(args, int); break;
case LEN_L: i = va_arg(args, long); break;
case LEN_LL: i = va_arg(args, long long); break;
case LEN_J: i = va_arg(args, uintmax_t); break;
case LEN_Z: i = va_arg(args, int64_t); break;
case LEN_T: i = va_arg(args, ptrdiff_t); break;
case LEN_I: i = va_arg(*args, int); break;
case LEN_L: i = va_arg(*args, long); break;
case LEN_LL: i = va_arg(*args, long long); break;
case LEN_J: i = va_arg(*args, uintmax_t); break;
case LEN_Z: i = va_arg(*args, int64_t); break;
case LEN_T: i = va_arg(*args, ptrdiff_t); break;
default:;
}
if(i < 0) {
@ -143,7 +147,7 @@ inline static int suffix(fmt_atoi)(fchar const *str, int *value) {
inline static int suffix(fmt_parse)(
Format *format,
fchar const *str,
va_list args
va_list *args
) {
*format = (Format){0};
// Parse flags
@ -161,7 +165,7 @@ inline static int suffix(fmt_parse)(
int width = 0;
if(str[i] == '*') {
++i;
width = va_arg(args, int);
width = va_arg(*args, int);
if(width < 0) {
width = -width;
format->flag_zero = true;
@ -178,7 +182,7 @@ inline static int suffix(fmt_parse)(
++i;
if(str[i] == '*') {
++i;
prec = va_arg(args, int);
prec = va_arg(*args, int);
if(prec < 0) {
prec = 0;
}
@ -333,7 +337,7 @@ inline static int suffix(fmt_fprint_int)(
void *ctx,
suffix(out_func_t) *out,
Format *fmt,
va_list args
va_list *args
) {
int w = 0;
@ -448,10 +452,10 @@ inline static int suffix(fmt_fprint_ptr)(
void *ctx,
suffix(out_func_t) *out,
Format *fmt,
va_list args
va_list *args
) {
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 d_len = s_len; // length of all displayed chars
@ -530,7 +534,7 @@ inline static int suffix(fmt_fprint_char)(
void *ctx,
suffix(out_func_t) *out,
Format *fmt,
va_list args
va_list *args
) {
int w = 0;
bool sign;
@ -570,10 +574,10 @@ inline static int suffix(fmt_just_fucking_print_float_someone_improve_this_later
void *ctx,
suffix(out_func_t) *out,
Format *fmt,
va_list args
va_list *args
) {
int w = 0;
double f = va_arg(args, double);
double f = va_arg(*args, double);
uint64_t i = (uint64_t)f;
char digits_arr[33] = {0};
@ -616,10 +620,10 @@ inline static int suffix(fmt_fprint_str)(
void *ctx,
suffix(out_func_t) *out,
Format *fmt,
va_list args
va_list *args
) {
int w = 0;
char *str = va_arg(args, char *);
char *str = va_arg(*args, char *);
uint64_t len = strlen(str);
// Calculate padding
@ -666,31 +670,31 @@ inline static int suffix(fmt_print)(
if(fmt[i] == '%') {
++i;
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;
i += fmt_len;
int written;
switch(format.arg_conv) {
case CONV_INT: {
written = suffix(fmt_fprint_int)(ctx, out, &format, args);
written = suffix(fmt_fprint_int)(ctx, out, &format, &args);
} break;
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;
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;
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;
case CONV_CHAR: {
written = suffix(fmt_fprint_char)(ctx, out, &format, args);
written = suffix(fmt_fprint_char)(ctx, out, &format, &args);
} break;
case CONV_STR: {
written = suffix(fmt_fprint_str)(ctx, out, &format, args);
written = suffix(fmt_fprint_str)(ctx, out, &format, &args);
} break;
case CONV_PTR: {
written = suffix(fmt_fprint_ptr)(ctx, out, &format, args);
written = suffix(fmt_fprint_ptr)(ctx, out, &format, &args);
} break;
case CONV_N: {
int *n = va_arg(args, int *);

View File

@ -88,7 +88,7 @@ int strcmp(const char *s1, const char *s2) {
int diff;
do {
diff = *s1 - *s2;
} while(diff != 0 && *s1 != 0 && *s2 != 0);
} while(diff == 0 && *s1++ != 0 && *s2++ != 0);
return diff;
}

View File

@ -3,9 +3,14 @@
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<DbgHelp.h>
#include <signal.h>
#include <stddef.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0]))
@ -49,6 +54,29 @@ static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) {
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 *res = AddVectoredExceptionHandler(1, &_win32_handler);
if(res == NULL) {

View File

@ -1,7 +1,16 @@
#include <assert.h>
#include <stddef.h>
void do_more_stuff(char *ptr) {
assert(ptr != NULL);
}
void do_stuff() {
do_more_stuff(NULL);
}
int main() {
assert(2+2 == 4);
assert(0 != 0); // Bad case of assert
do_stuff();
}