|
@@ -0,0 +1,199 @@
|
|
|
+#include "core/utils/Utility.h"
|
|
|
+
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+#include "ErrorSimulator.h"
|
|
|
+#include "core/utils/Error.h"
|
|
|
+#include "core/utils/Logger.h"
|
|
|
+
|
|
|
+static CoreExitHandler exitHandler = nullptr;
|
|
|
+static void* exitData = nullptr;
|
|
|
+static CoreOutOfMemoryHandler outOfMemoryHandler = nullptr;
|
|
|
+static void* outOfMemoryData = nullptr;
|
|
|
+
|
|
|
+size_t corePopCount(u64 u) {
|
|
|
+ static const u64 map[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
|
|
|
+ size_t sum = 0;
|
|
|
+ for(size_t i = 0; i < sizeof(u64) * 8; i += 4) {
|
|
|
+ sum += map[(u >> i) & 0xF];
|
|
|
+ }
|
|
|
+ return sum;
|
|
|
+}
|
|
|
+
|
|
|
+void coreExitWithHandler(const char* file, int line, int value) {
|
|
|
+ if(value != 0) {
|
|
|
+ file = coreGetShortFileName(file);
|
|
|
+ CORE_LOG_ERROR("Exit from %s:%d with value %d", file, line, value);
|
|
|
+ }
|
|
|
+ if(exitHandler != nullptr) {
|
|
|
+ exitHandler(value, exitData);
|
|
|
+ }
|
|
|
+ exit(value);
|
|
|
+}
|
|
|
+
|
|
|
+void coreSetExitHandler(CoreExitHandler eh, void* data) {
|
|
|
+ exitHandler = eh;
|
|
|
+ exitData = data;
|
|
|
+}
|
|
|
+
|
|
|
+void coreSetOutOfMemoryHandler(CoreOutOfMemoryHandler h, void* data) {
|
|
|
+ outOfMemoryHandler = h;
|
|
|
+ outOfMemoryData = data;
|
|
|
+}
|
|
|
+
|
|
|
+static void* exitOnNull(void* p, size_t n) {
|
|
|
+ if(p == nullptr) {
|
|
|
+ CORE_LOG_ERROR("Out of memory, requested '%zd' bytes", n)
|
|
|
+ CORE_EXIT(1);
|
|
|
+ }
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+static void* coreRealAllocate(size_t n) {
|
|
|
+ void* p = malloc(n);
|
|
|
+ while(p == nullptr && outOfMemoryHandler != nullptr) {
|
|
|
+ outOfMemoryHandler(outOfMemoryData);
|
|
|
+ p = malloc(n);
|
|
|
+ }
|
|
|
+ return exitOnNull(p, n);
|
|
|
+}
|
|
|
+
|
|
|
+static void* coreRealReallocate(void* oldP, size_t n) {
|
|
|
+ if(n <= 0) {
|
|
|
+ free(oldP);
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ void* p = realloc(oldP, n);
|
|
|
+ while(p == nullptr && outOfMemoryHandler != nullptr) {
|
|
|
+ outOfMemoryHandler(outOfMemoryData);
|
|
|
+ p = realloc(oldP, n);
|
|
|
+ }
|
|
|
+ return exitOnNull(p, n);
|
|
|
+}
|
|
|
+
|
|
|
+static void coreRealFree(void* p) {
|
|
|
+ free(p);
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CORE_CHECK_MEMORY
|
|
|
+static const u8 CANARY[16] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
|
|
|
+ 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
|
|
|
+
|
|
|
+struct CoreMemoryInfo;
|
|
|
+typedef struct CoreMemoryInfo CoreMemoryInfo;
|
|
|
+struct CoreMemoryInfo {
|
|
|
+ CoreMemoryInfo* next;
|
|
|
+ CoreMemoryInfo* previous;
|
|
|
+ size_t size;
|
|
|
+ int line;
|
|
|
+ char buffer[64 - 2 * sizeof(void*) - sizeof(size_t) - sizeof(int)];
|
|
|
+ char canary[sizeof(CANARY)];
|
|
|
+};
|
|
|
+static_assert(sizeof(CoreMemoryInfo) == 80, "memory info has invalid size");
|
|
|
+static CoreMemoryInfo* headMemoryInfo = nullptr;
|
|
|
+
|
|
|
+static void addMemoryInfo(CoreMemoryInfo* info, const char* file, int line,
|
|
|
+ size_t n) {
|
|
|
+ info->next = nullptr;
|
|
|
+ info->previous = nullptr;
|
|
|
+ info->size = n;
|
|
|
+ info->line = line;
|
|
|
+ strncpy(info->buffer, coreGetShortFileName(file), sizeof(info->buffer));
|
|
|
+ memcpy(info->canary, CANARY, sizeof(CANARY));
|
|
|
+ memcpy((char*)info + n - sizeof(CANARY), CANARY, sizeof(CANARY));
|
|
|
+ if(headMemoryInfo == nullptr) {
|
|
|
+ headMemoryInfo = info;
|
|
|
+ } else {
|
|
|
+ headMemoryInfo->previous = info;
|
|
|
+ info->next = headMemoryInfo;
|
|
|
+ headMemoryInfo = info;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void removeMemoryInfo(CoreMemoryInfo* info) {
|
|
|
+ if(info->previous == nullptr) {
|
|
|
+ if(info->next == nullptr) {
|
|
|
+ headMemoryInfo = nullptr;
|
|
|
+ } else {
|
|
|
+ headMemoryInfo = info->next;
|
|
|
+ info->next->previous = nullptr;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(info->next == nullptr) {
|
|
|
+ info->previous->next = nullptr;
|
|
|
+ } else {
|
|
|
+ info->previous->next = info->next;
|
|
|
+ info->next->previous = info->previous;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void* coreDebugAllocate(const char* file, int line, size_t n) {
|
|
|
+ n += sizeof(CoreMemoryInfo) + sizeof(CANARY);
|
|
|
+ void* p = coreRealAllocate(n + sizeof(CANARY));
|
|
|
+ addMemoryInfo(p, file, line, n);
|
|
|
+ return (char*)p + sizeof(CoreMemoryInfo);
|
|
|
+}
|
|
|
+
|
|
|
+void* coreDebugReallocate(const char* file, int line, void* p, size_t n) {
|
|
|
+ if(n > 0) {
|
|
|
+ n += sizeof(CoreMemoryInfo) + sizeof(CANARY);
|
|
|
+ }
|
|
|
+ void* rp = (void*)p;
|
|
|
+ if(rp != nullptr) {
|
|
|
+ rp = (char*)rp - sizeof(CoreMemoryInfo);
|
|
|
+ removeMemoryInfo(rp);
|
|
|
+ }
|
|
|
+ void* np = coreRealReallocate(rp, n);
|
|
|
+ if(np == nullptr) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ addMemoryInfo(np, file, line, n);
|
|
|
+ return (char*)np + sizeof(CoreMemoryInfo);
|
|
|
+}
|
|
|
+
|
|
|
+static bool checkCanary(void* p) {
|
|
|
+ return memcmp(p, CANARY, sizeof(CANARY)) != 0;
|
|
|
+}
|
|
|
+
|
|
|
+void coreFreeDebug(const char* file, int line, void* p) {
|
|
|
+ if(p == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ CoreMemoryInfo* rp = (CoreMemoryInfo*)((char*)p - sizeof(CoreMemoryInfo));
|
|
|
+ if(checkCanary(rp->canary)) {
|
|
|
+ file = coreGetShortFileName(file);
|
|
|
+ CORE_LOG_ERROR("Free at %s:%d violated pre canary", file, line);
|
|
|
+ CORE_EXIT(1);
|
|
|
+ } else if(checkCanary((char*)rp + rp->size - sizeof(CANARY))) {
|
|
|
+ file = coreGetShortFileName(file);
|
|
|
+ CORE_LOG_ERROR("Free at %s:%d violated post canary", file, line);
|
|
|
+ CORE_EXIT(1);
|
|
|
+ }
|
|
|
+ removeMemoryInfo(rp);
|
|
|
+ coreRealFree(rp);
|
|
|
+}
|
|
|
+
|
|
|
+void corePrintMemoryReport() {
|
|
|
+ for(CoreMemoryInfo* i = headMemoryInfo; i != nullptr; i = i->next) {
|
|
|
+ CORE_LOG_ERROR("%s:%d was not freed", i->buffer, i->line);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+void* coreAllocate(size_t n) {
|
|
|
+ return coreRealAllocate(n);
|
|
|
+}
|
|
|
+
|
|
|
+void* coreReallocate(void* p, size_t n) {
|
|
|
+ return coreRealReallocate(p, n);
|
|
|
+}
|
|
|
+
|
|
|
+void coreFree(void* p) {
|
|
|
+ coreRealFree(p);
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|