diff --git a/alloc.h b/alloc.h index 59d928f..2130903 100644 --- a/alloc.h +++ b/alloc.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_ALLOC_H #define ULE_ALLOC_H diff --git a/array.hpp b/array.hpp index 68ef720..e00feaa 100644 --- a/array.hpp +++ b/array.hpp @@ -85,7 +85,7 @@ struct Array { void removeAndShrink(u32 index) { ULE_TYPES_H_FTAG; for (u32 i = index + 1; i < this->length; i++) { - String::memcpy(this->data[i - 1], this->data[i], sizeof(T)); + String::memcpy(&this->data[i - 1], &this->data[i], sizeof(T)); } this->length--; } diff --git a/file.h b/file.h index c0843c6..190a757 100644 --- a/file.h +++ b/file.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_FILE_H #define ULE_FILE_H diff --git a/print.cpp b/print.cpp index 444b0c8..568d802 100644 --- a/print.cpp +++ b/print.cpp @@ -63,16 +63,22 @@ void trace(String* string) { #define BACKTRACE_MAX_FUNCTION_NAME_LENGTH 1024 HANDLE processHandle = GetCurrentProcess(); SymInitialize(processHandle, null, true); + SymSetOptions(SYMOPT_LOAD_LINES); void* stack[BACKTRACE_MAX_FRAMES]; unsigned short numFrames = CaptureStackBackTrace(0, BACKTRACE_MAX_FRAMES, stack, null); - char buffer[sizeof(SYMBOL_INFO) + (BACKTRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)]; + char buffer[sizeof(SYMBOL_INFO) + BACKTRACE_MAX_FUNCTION_NAME_LENGTH*sizeof(TCHAR)]; SYMBOL_INFO* symbol = (SYMBOL_INFO*) buffer; symbol->MaxNameLen = BACKTRACE_MAX_FUNCTION_NAME_LENGTH; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - DWORD displacement; + // @TODO I believe that 'displacement' and line.LineNumber are supposed to be source code column numbers + // and line numbers respectively, but displacement doesn't work at all (seems like) and line.LineNumber + // is consistently off by a few lines. Perhaps it's post-processed source? I don't know. For now, + // filename + line.LineNUmber are printed and we hope that's enough, and understand the line #s are only + // approximate. + DWORD displacement; IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); for (u32 i = 0; i < numFrames; i++) { @@ -81,25 +87,53 @@ void trace(String* string) { if (SymGetLineFromAddr64(processHandle, address, &displacement, &line)) { if (string == null) { - print("\tat %s in %s: line: %lu: address %0x%0X\n", symbol->Name, line.FileName, line.LineNumber, symbol->Address); + print(" %-30s %s:%u\n", symbol->Name, line.FileName, line.LineNumber); } else { - string->appendf("\tat %s in %s: line: %lu: address %0x%0X\n", symbol->Name, line.FileName, line.LineNumber, symbol->Address); + string->appendf(" %-30s %s:%u\n", symbol->Name, line.FileName, line.LineNumber); } } else { if (string == null) { - print("\tSymGetLineFromAddr64 returned error code %lu.\n", GetLastError()); - print("\tat %s, address 0x%0X.\n", symbol->Name, symbol->Address); + warn("SymGetLineFromAddr64 returned error code %lu.\n", GetLastError()); + print(" %-30s unknown file\n", symbol->Name); } else { - string->appendf("\tSymGetLineFromAddr64 returned error code %lu.\n", GetLastError()); - string->appendf("\tat %s, address 0x%0X.\n", symbol->Name, symbol->Address); + warn("SymGetLineFromAddr64 returned error code %lu.\n", GetLastError()); + string->appendf(" %-30s unknown file\n", symbol->Name); } } } #undef BACKTRACE_MAX_FUNCTION_NAME_LENGTH } +#include +#include +void writeMinidump(void* exceptionPointers) { // 'EXCEPTION_POINTERS*' actually + // create a file + EXCEPTION_POINTERS* ep = (EXCEPTION_POINTERS*) exceptionPointers; + HANDLE hFile = CreateFile(_T("MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, null); + + if ((hFile != null) && (hFile != INVALID_HANDLE_VALUE)) { + // carry on with creating the minidump + MINIDUMP_EXCEPTION_INFORMATION mdei; + mdei.ThreadId = GetCurrentThreadId(); + mdei.ExceptionPointers = ep; + mdei.ClientPointers = FALSE; + + MINIDUMP_TYPE mdt = MiniDumpNormal; + BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, mdt, (ep != 0) ? &mdei : 0, 0, 0); + if (!rv) { + println(_T("MiniDumpWriteDump failed. Error: %u"), GetLastError()); + } else { + println(_T("MiniDump created.")); + } + + CloseHandle(hFile); + } else { + println(_T("Failed to CreateFile for MiniDump. Error: %u"), GetLastError()); + } +} #else +void writeMinidump(void* exceptionPointers) {} // stub... does nothing on Unix // OSX and Linux stacktrace stuff. #include // backtrace, backtrace_symbols #include // abi::__cxa_demangle @@ -169,17 +203,17 @@ void trace(String* string) { continue; } else { - println("warning: failed to demangle name: %s, exit status of attempt: %d", traces[i], status); + warn("warning: failed to demangle name: %s, exit status of attempt: %d", traces[i], status); // just write back the original trace, un-demangled. trace = traces[i]; } } if (string == null) { - print("%s\n", trace); + print(" %s\n", trace); } else { - string->appendf("%s\n", trace); + string->appendf(" %s\n", trace); } } @@ -227,35 +261,6 @@ void setCustomDieBehavior(void (*dieBehavior)(const char* string)) { customDie = dieBehavior; } -#ifdef _WIN32 -#include -#include -static void writeMinidump(EXCEPTION_POINTERS* pep) { - // create a file - HANDLE hFile = CreateFile(_T("MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, null); - - if ((hFile != null) && (hFile != INVALID_HANDLE_VALUE)) { - // carry on with creating the minidump - MINIDUMP_EXCEPTION_INFORMATION mdei; - mdei.ThreadId = GetCurrentThreadId(); - mdei.ExceptionPointers = pep; - mdei.ClientPointers = FALSE; - - MINIDUMP_TYPE mdt = MiniDumpNormal; - BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, mdt, (pep != 0) ? &mdei : 0, 0, 0); - if (!rv) { - println(_T("MiniDumpWriteDump failed. Error: %u"), GetLastError()); - } else { - println(_T("MiniDump created.")); - } - - CloseHandle(hFile); - } else { - println(_T("Failed to CreateFile for MiniDump. Error: %u"), GetLastError()); - } -} -#endif - // for fatal errors which may occur at runtime, even on a release binary. // if a fatal error should not occur at runtime on a release binary, consider preferring 'massert' // it's unclear when you should use asserts vs. die actually. idk man, they kinda do the same thing right now diff --git a/print.h b/print.h index 956b935..685051d 100644 --- a/print.h +++ b/print.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_PRINT_H #define ULE_PRINT_H @@ -82,6 +83,7 @@ extern void println(const char* format, ...); // Prints a stack trace, or concatenates the stack trace to |string| if it is not null. extern void trace(String* string = null); +extern void writeMinidump(void* exceptionPointers); // This ends the program and calls trace(). generally you should use 'massert' instead extern void die(const char* format, ...); diff --git a/serialize.h b/serialize.h index b0d5b94..be59500 100644 --- a/serialize.h +++ b/serialize.h @@ -1,4 +1,5 @@ +#pragma once #ifdef ULE_CONFIG_OPTION_SERIALIZATION #ifndef ULE_SERIALIZE_H #define ULE_SERIALIZE_H diff --git a/string.h b/string.h index 6ec3177..976f48d 100644 --- a/string.h +++ b/string.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_STRING_H #define ULE_STRING_H @@ -259,7 +260,7 @@ public: static inline const char* firstCharOccurence(const char* string, u32 length, char c) { ULE_TYPES_H_FTAG; - for (s32 i = 0; i < length; i++) { + for (u32 i = 0; i < length; i++) { const char* s = string + i; if (*s == c) { return s; @@ -852,7 +853,7 @@ public: Capacity = LocalBufSize; \ } else { \ while (Capacity < new_capacity) { \ - Capacity *= 1.5; \ + Capacity = (s32)(Capacity * 1.5f); \ Data = (char*) STR_MEMALLOC((size_t) Capacity * sizeof(char)); \ } \ } \ diff --git a/types.h b/types.h index cbe0ec3..720c69a 100644 --- a/types.h +++ b/types.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_TYPES_H #define ULE_TYPES_H diff --git a/util.h b/util.h index 34a9e6d..6d84a85 100644 --- a/util.h +++ b/util.h @@ -1,4 +1,5 @@ +#pragma once #ifndef ULE_UTIL_H #define ULE_UTIL_H