linux stacktraces wip
This commit is contained in:
parent
809257e28a
commit
e2e261574d
|
@ -33,7 +33,7 @@ uniform("Stiffness", "float", 10)
|
|||
|
||||
common [[
|
||||
#ifdef SKINNED
|
||||
layout(std140, binding = 4) uniform ModelState {
|
||||
layout(std140, binding = 4) uniform ModelState {
|
||||
float layer;
|
||||
float fur_scale;
|
||||
float fur_gravity;
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
#include "engine/allocators.h"
|
||||
#include "engine/debug.h"
|
||||
#include "engine/atomic.h"
|
||||
#include "engine/string.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
static bool g_is_crash_reporting_enabled = false;
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
namespace Lumix {
|
||||
|
||||
|
||||
namespace debug
|
||||
{
|
||||
namespace debug {
|
||||
|
||||
|
||||
void debugOutput(const char* message)
|
||||
{
|
||||
static Lumix::DefaultAllocator stack_node_allocator;
|
||||
|
||||
|
||||
void debugOutput(const char* message) {
|
||||
printf("%s", message);
|
||||
}
|
||||
|
||||
|
||||
void debugBreak()
|
||||
{
|
||||
void debugBreak() {
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,8 @@ void debugBreak()
|
|||
int StackTree::s_instances = 0;
|
||||
|
||||
|
||||
struct StackNode
|
||||
{
|
||||
~StackNode()
|
||||
{
|
||||
struct StackNode {
|
||||
~StackNode() {
|
||||
delete m_next;
|
||||
delete m_first_child;
|
||||
}
|
||||
|
@ -47,69 +45,118 @@ struct StackNode
|
|||
};
|
||||
|
||||
|
||||
StackTree::StackTree()
|
||||
{
|
||||
StackTree::StackTree() {}
|
||||
StackTree::~StackTree() {}
|
||||
void StackTree::refreshModuleList() {}
|
||||
|
||||
|
||||
int StackTree::getPath(StackNode* node, Span<StackNode*> output) {
|
||||
u32 i = 0;
|
||||
while (i < output.length() && node) {
|
||||
output[i] = node;
|
||||
i++;
|
||||
node = node->m_parent;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
StackTree::~StackTree()
|
||||
{
|
||||
StackNode* StackTree::getParent(StackNode* node) {
|
||||
return node ? node->m_parent : nullptr;
|
||||
}
|
||||
|
||||
|
||||
void StackTree::refreshModuleList()
|
||||
{
|
||||
bool StackTree::getFunction(StackNode* node, Span<char> out, int& line) {
|
||||
char** str = backtrace_symbols(&node->m_instruction, 1);
|
||||
if (!str) return false;
|
||||
|
||||
copyString(out, *str);
|
||||
free(str);
|
||||
line = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int StackTree::getPath(StackNode* node, Span<StackNode*> output)
|
||||
{
|
||||
return 0;
|
||||
void StackTree::printCallstack(StackNode* node) {
|
||||
char** str = backtrace_symbols(&node->m_instruction, 1);
|
||||
if (str) {
|
||||
printf("%s", *str);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StackNode* StackTree::getParent(StackNode* node)
|
||||
{
|
||||
return nullptr;
|
||||
StackNode* StackTree::insertChildren(StackNode* root_node, void** instruction, void** stack) {
|
||||
StackNode* node = root_node;
|
||||
while (instruction >= stack) {
|
||||
StackNode* new_node = LUMIX_NEW(stack_node_allocator, StackNode)();
|
||||
node->m_first_child = new_node;
|
||||
new_node->m_parent = node;
|
||||
new_node->m_next = nullptr;
|
||||
new_node->m_first_child = nullptr;
|
||||
new_node->m_instruction = *instruction;
|
||||
node = new_node;
|
||||
--instruction;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
StackNode* StackTree::record() {
|
||||
static const int frames_to_capture = 256;
|
||||
void* stack[frames_to_capture];
|
||||
const int captured_frames_count = backtrace(stack, frames_to_capture);
|
||||
|
||||
bool StackTree::getFunction(StackNode* node, Span<char> out, int& line)
|
||||
{
|
||||
return false;
|
||||
void** ptr = stack + captured_frames_count - 1;
|
||||
if (!m_root) {
|
||||
m_root = LUMIX_NEW(stack_node_allocator, StackNode)();
|
||||
m_root->m_instruction = *ptr;
|
||||
m_root->m_first_child = nullptr;
|
||||
m_root->m_next = nullptr;
|
||||
m_root->m_parent = nullptr;
|
||||
--ptr;
|
||||
return insertChildren(m_root, ptr, stack);
|
||||
}
|
||||
|
||||
StackNode* node = m_root;
|
||||
while (ptr >= stack) {
|
||||
while (node->m_instruction != *ptr && node->m_next) {
|
||||
node = node->m_next;
|
||||
}
|
||||
if (node->m_instruction != *ptr) {
|
||||
node->m_next = LUMIX_NEW(stack_node_allocator, StackNode);
|
||||
node->m_next->m_parent = node->m_parent;
|
||||
node->m_next->m_instruction = *ptr;
|
||||
node->m_next->m_next = nullptr;
|
||||
node->m_next->m_first_child = nullptr;
|
||||
--ptr;
|
||||
return insertChildren(node->m_next, ptr, stack);
|
||||
}
|
||||
|
||||
if (node->m_first_child) {
|
||||
--ptr;
|
||||
node = node->m_first_child;
|
||||
} else if (ptr != stack) {
|
||||
--ptr;
|
||||
return insertChildren(node, ptr, stack);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
void StackTree::printCallstack(StackNode* node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StackNode* StackTree::insertChildren(StackNode* root_node, void** instruction, void** stack)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
StackNode* StackTree::record()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static const u32 UNINITIALIZED_MEMORY_PATTERN = 0xCD;
|
||||
static const u32 FREED_MEMORY_PATTERN = 0xDD;
|
||||
static const u32 ALLOCATION_GUARD = 0xFDFDFDFD;
|
||||
|
||||
|
||||
|
||||
Allocator::Allocator(IAllocator& source)
|
||||
: m_source(source)
|
||||
, m_root(nullptr)
|
||||
, m_total_size(0)
|
||||
, m_is_fill_enabled(true)
|
||||
, m_are_guards_enabled(true)
|
||||
{
|
||||
, m_are_guards_enabled(true) {
|
||||
m_sentinels[0].next = &m_sentinels[1];
|
||||
m_sentinels[0].previous = nullptr;
|
||||
m_sentinels[0].stack_leaf = nullptr;
|
||||
|
@ -126,15 +173,12 @@ Allocator::Allocator(IAllocator& source)
|
|||
}
|
||||
|
||||
|
||||
Allocator::~Allocator()
|
||||
{
|
||||
Allocator::~Allocator() {
|
||||
AllocationInfo* last_sentinel = &m_sentinels[1];
|
||||
if (m_root != last_sentinel)
|
||||
{
|
||||
if (m_root != last_sentinel) {
|
||||
debugOutput("Memory leaks detected!\n");
|
||||
AllocationInfo* info = m_root;
|
||||
while (info != last_sentinel)
|
||||
{
|
||||
while (info != last_sentinel) {
|
||||
char tmp[2048];
|
||||
sprintf(tmp, "\nAllocation size : %zu, memory %p\n", info->size, info + sizeof(info)); //-V568
|
||||
debugOutput(tmp);
|
||||
|
@ -146,25 +190,21 @@ Allocator::~Allocator()
|
|||
}
|
||||
|
||||
|
||||
void Allocator::lock()
|
||||
{
|
||||
void Allocator::lock() {
|
||||
m_mutex.enter();
|
||||
}
|
||||
|
||||
|
||||
void Allocator::unlock()
|
||||
{
|
||||
void Allocator::unlock() {
|
||||
m_mutex.exit();
|
||||
}
|
||||
|
||||
|
||||
void Allocator::checkGuards()
|
||||
{
|
||||
void Allocator::checkGuards() {
|
||||
if (m_are_guards_enabled) return;
|
||||
|
||||
auto* info = m_root;
|
||||
while (info)
|
||||
{
|
||||
while (info) {
|
||||
auto user_ptr = getUserPtrFromAllocationInfo(info);
|
||||
void* system_ptr = getSystemFromUser(user_ptr);
|
||||
ASSERT(*(u32*)system_ptr == ALLOCATION_GUARD);
|
||||
|
@ -175,46 +215,37 @@ void Allocator::checkGuards()
|
|||
}
|
||||
|
||||
|
||||
size_t Allocator::getAllocationOffset()
|
||||
{
|
||||
size_t Allocator::getAllocationOffset() {
|
||||
return sizeof(AllocationInfo) + (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) : 0);
|
||||
}
|
||||
|
||||
|
||||
size_t Allocator::getNeededMemory(size_t size)
|
||||
{
|
||||
size_t Allocator::getNeededMemory(size_t size) {
|
||||
return size + sizeof(AllocationInfo) + (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) << 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
size_t Allocator::getNeededMemory(size_t size, size_t align)
|
||||
{
|
||||
return size + sizeof(AllocationInfo) + (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) << 1 : 0) +
|
||||
align;
|
||||
size_t Allocator::getNeededMemory(size_t size, size_t align) {
|
||||
return size + sizeof(AllocationInfo) + (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) << 1 : 0) + align;
|
||||
}
|
||||
|
||||
|
||||
Allocator::AllocationInfo* Allocator::getAllocationInfoFromSystem(void* system_ptr)
|
||||
{
|
||||
return (AllocationInfo*)(m_are_guards_enabled ? (u8*)system_ptr + sizeof(ALLOCATION_GUARD)
|
||||
: system_ptr);
|
||||
Allocator::AllocationInfo* Allocator::getAllocationInfoFromSystem(void* system_ptr) {
|
||||
return (AllocationInfo*)(m_are_guards_enabled ? (u8*)system_ptr + sizeof(ALLOCATION_GUARD) : system_ptr);
|
||||
}
|
||||
|
||||
|
||||
void* Allocator::getUserPtrFromAllocationInfo(AllocationInfo* info)
|
||||
{
|
||||
void* Allocator::getUserPtrFromAllocationInfo(AllocationInfo* info) {
|
||||
return ((u8*)info + sizeof(AllocationInfo));
|
||||
}
|
||||
|
||||
|
||||
Allocator::AllocationInfo* Allocator::getAllocationInfoFromUser(void* user_ptr)
|
||||
{
|
||||
Allocator::AllocationInfo* Allocator::getAllocationInfoFromUser(void* user_ptr) {
|
||||
return (AllocationInfo*)((u8*)user_ptr - sizeof(AllocationInfo));
|
||||
}
|
||||
|
||||
|
||||
u8* Allocator::getUserFromSystem(void* system_ptr, size_t align)
|
||||
{
|
||||
u8* Allocator::getUserFromSystem(void* system_ptr, size_t align) {
|
||||
size_t diff = (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) : 0) + sizeof(AllocationInfo);
|
||||
|
||||
if (align) diff += (align - diff % align) % align;
|
||||
|
@ -222,8 +253,7 @@ u8* Allocator::getUserFromSystem(void* system_ptr, size_t align)
|
|||
}
|
||||
|
||||
|
||||
u8* Allocator::getSystemFromUser(void* user_ptr)
|
||||
{
|
||||
u8* Allocator::getSystemFromUser(void* user_ptr) {
|
||||
AllocationInfo* info = getAllocationInfoFromUser(user_ptr);
|
||||
size_t diff = (m_are_guards_enabled ? sizeof(ALLOCATION_GUARD) : 0) + sizeof(AllocationInfo);
|
||||
if (info->align) diff += (info->align - diff % info->align) % info->align;
|
||||
|
@ -231,8 +261,7 @@ u8* Allocator::getSystemFromUser(void* user_ptr)
|
|||
}
|
||||
|
||||
|
||||
void* Allocator::reallocate(void* user_ptr, size_t size)
|
||||
{
|
||||
void* Allocator::reallocate(void* user_ptr, size_t size) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
return m_source.reallocate(user_ptr, size);
|
||||
#else
|
||||
|
@ -252,8 +281,7 @@ void* Allocator::reallocate(void* user_ptr, size_t size)
|
|||
}
|
||||
|
||||
|
||||
void* Allocator::allocate_aligned(size_t size, size_t align)
|
||||
{
|
||||
void* Allocator::allocate_aligned(size_t size, size_t align) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
return m_source.allocate_aligned(size, align);
|
||||
#else
|
||||
|
@ -282,13 +310,11 @@ void* Allocator::allocate_aligned(size_t size, size_t align)
|
|||
info->align = u16(align);
|
||||
info->stack_leaf = m_stack_tree.record();
|
||||
info->size = size;
|
||||
if (m_is_fill_enabled)
|
||||
{
|
||||
if (m_is_fill_enabled) {
|
||||
memset(user_ptr, UNINITIALIZED_MEMORY_PATTERN, size);
|
||||
}
|
||||
|
||||
if (m_are_guards_enabled)
|
||||
{
|
||||
if (m_are_guards_enabled) {
|
||||
*(u32*)system_ptr = ALLOCATION_GUARD;
|
||||
*(u32*)((u8*)system_ptr + system_size - sizeof(ALLOCATION_GUARD)) = ALLOCATION_GUARD;
|
||||
}
|
||||
|
@ -298,22 +324,18 @@ void* Allocator::allocate_aligned(size_t size, size_t align)
|
|||
}
|
||||
|
||||
|
||||
void Allocator::deallocate_aligned(void* user_ptr)
|
||||
{
|
||||
void Allocator::deallocate_aligned(void* user_ptr) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
m_source.deallocate_aligned(user_ptr);
|
||||
#else
|
||||
if (user_ptr)
|
||||
{
|
||||
if (user_ptr) {
|
||||
AllocationInfo* info = getAllocationInfoFromUser(user_ptr);
|
||||
void* system_ptr = getSystemFromUser(user_ptr);
|
||||
if (m_is_fill_enabled)
|
||||
{
|
||||
if (m_is_fill_enabled) {
|
||||
memset(user_ptr, FREED_MEMORY_PATTERN, info->size);
|
||||
}
|
||||
|
||||
if (m_are_guards_enabled)
|
||||
{
|
||||
if (m_are_guards_enabled) {
|
||||
ASSERT(*(u32*)system_ptr == ALLOCATION_GUARD);
|
||||
size_t system_size = getNeededMemory(info->size, info->align);
|
||||
ASSERT(*(u32*)((u8*)system_ptr + system_size - sizeof(ALLOCATION_GUARD)) == ALLOCATION_GUARD);
|
||||
|
@ -321,8 +343,7 @@ void Allocator::deallocate_aligned(void* user_ptr)
|
|||
|
||||
{
|
||||
MutexGuard lock(m_mutex);
|
||||
if (info == m_root)
|
||||
{
|
||||
if (info == m_root) {
|
||||
m_root = info->next;
|
||||
}
|
||||
info->previous->next = info->next;
|
||||
|
@ -339,8 +360,7 @@ void Allocator::deallocate_aligned(void* user_ptr)
|
|||
}
|
||||
|
||||
|
||||
void* Allocator::reallocate_aligned(void* user_ptr, size_t size, size_t align)
|
||||
{
|
||||
void* Allocator::reallocate_aligned(void* user_ptr, size_t size, size_t align) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
return m_source.reallocate_aligned(user_ptr, size, align);
|
||||
#else
|
||||
|
@ -360,8 +380,7 @@ void* Allocator::reallocate_aligned(void* user_ptr, size_t size, size_t align)
|
|||
}
|
||||
|
||||
|
||||
void* Allocator::allocate(size_t size)
|
||||
{
|
||||
void* Allocator::allocate(size_t size) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
return m_source.allocate(size);
|
||||
#else
|
||||
|
@ -388,13 +407,11 @@ void* Allocator::allocate(size_t size)
|
|||
info->stack_leaf = m_stack_tree.record();
|
||||
info->size = size;
|
||||
info->align = 0;
|
||||
if (m_is_fill_enabled)
|
||||
{
|
||||
if (m_is_fill_enabled) {
|
||||
memset(user_ptr, UNINITIALIZED_MEMORY_PATTERN, size);
|
||||
}
|
||||
|
||||
if (m_are_guards_enabled)
|
||||
{
|
||||
if (m_are_guards_enabled) {
|
||||
*(u32*)system_ptr = ALLOCATION_GUARD;
|
||||
*(u32*)((u8*)system_ptr + system_size - sizeof(ALLOCATION_GUARD)) = ALLOCATION_GUARD;
|
||||
}
|
||||
|
@ -403,22 +420,18 @@ void* Allocator::allocate(size_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
void Allocator::deallocate(void* user_ptr)
|
||||
{
|
||||
void Allocator::deallocate(void* user_ptr) {
|
||||
#ifndef LUMIX_DEBUG
|
||||
m_source.deallocate(user_ptr);
|
||||
#else
|
||||
if (user_ptr)
|
||||
{
|
||||
if (user_ptr) {
|
||||
AllocationInfo* info = getAllocationInfoFromUser(user_ptr);
|
||||
void* system_ptr = getSystemFromUser(user_ptr);
|
||||
if (m_is_fill_enabled)
|
||||
{
|
||||
if (m_is_fill_enabled) {
|
||||
memset(user_ptr, FREED_MEMORY_PATTERN, info->size);
|
||||
}
|
||||
|
||||
if (m_are_guards_enabled)
|
||||
{
|
||||
if (m_are_guards_enabled) {
|
||||
ASSERT(*(u32*)system_ptr == ALLOCATION_GUARD);
|
||||
size_t system_size = getNeededMemory(info->size);
|
||||
ASSERT(*(u32*)((u8*)system_ptr + system_size - sizeof(ALLOCATION_GUARD)) == ALLOCATION_GUARD);
|
||||
|
@ -426,8 +439,7 @@ void Allocator::deallocate(void* user_ptr)
|
|||
|
||||
{
|
||||
MutexGuard lock(m_mutex);
|
||||
if (info == m_root)
|
||||
{
|
||||
if (info == m_root) {
|
||||
m_root = info->next;
|
||||
}
|
||||
info->previous->next = info->next;
|
||||
|
@ -444,19 +456,15 @@ void Allocator::deallocate(void* user_ptr)
|
|||
}
|
||||
|
||||
|
||||
} // namespace Debug
|
||||
} // namespace debug
|
||||
|
||||
|
||||
|
||||
void enableCrashReporting(bool enable)
|
||||
{
|
||||
void enableCrashReporting(bool enable) {
|
||||
g_is_crash_reporting_enabled = false;
|
||||
}
|
||||
|
||||
|
||||
void installUnhandledExceptionHandler()
|
||||
{
|
||||
}
|
||||
void installUnhandledExceptionHandler() {}
|
||||
|
||||
|
||||
} // namespace Lumix
|
||||
|
|
|
@ -362,7 +362,6 @@ namespace LuaWrapper {
|
|||
}
|
||||
|
||||
|
||||
|
||||
struct GlobalState
|
||||
{
|
||||
struct SMSlice {
|
||||
|
|
Loading…
Reference in a new issue