linux stacktraces wip

This commit is contained in:
Mikulas Florek 2021-04-14 19:29:53 +02:00
parent 809257e28a
commit e2e261574d
3 changed files with 136 additions and 129 deletions

View file

@ -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;

View file

@ -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

View file

@ -362,7 +362,6 @@ namespace LuaWrapper {
}
struct GlobalState
{
struct SMSlice {