Fixed heap manager and added custom linker script for calling global/static ctors and dtors.
This commit is contained in:
parent
2aecad825b
commit
18ab086b3d
@ -230,7 +230,8 @@ add_executable(StrToHash src/StrToHash.cpp)
|
|||||||
target_include_directories(EHS PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(EHS PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
if (IS_OS_LINUX)
|
if (IS_OS_LINUX)
|
||||||
target_link_options(EHS PUBLIC -nostdlib -nostartfiles -e _start)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
|
||||||
|
target_link_options(EHS PUBLIC -nostdlib -nostartfiles -e start -T ${PROJECT_SOURCE_DIR}/custom.ld)
|
||||||
set(CMAKE_INSTALL_PREFIX "${USER_HOME_DIRECTORY}/.local")
|
set(CMAKE_INSTALL_PREFIX "${USER_HOME_DIRECTORY}/.local")
|
||||||
elseif (IS_OS_WINDOWS)
|
elseif (IS_OS_WINDOWS)
|
||||||
set(CMAKE_INSTALL_PREFIX "${USER_HOME_DIRECTORY}/EHS")
|
set(CMAKE_INSTALL_PREFIX "${USER_HOME_DIRECTORY}/EHS")
|
||||||
|
48
custom.ld
Normal file
48
custom.ld
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* Define memory regions */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
RAM (wxa) : ORIGIN = 0x20000000, LENGTH = 1M /* Adjust these values for your target */
|
||||||
|
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* Adjust these values for your target */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define the entry point of the program */
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Place the program code at the beginning of ROM */
|
||||||
|
.text : {
|
||||||
|
*(.text)
|
||||||
|
*(.text*)
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* Initialize data section in ROM, copy to RAM at startup */
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
*(.data*)
|
||||||
|
} > RAM AT > ROM
|
||||||
|
|
||||||
|
/* Uninitialized data section in RAM */
|
||||||
|
.bss : {
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* Constructor array section */
|
||||||
|
.init_array : {
|
||||||
|
__start_init_array = .; /* Define the start symbol */
|
||||||
|
KEEP(*(SORT(.init_array.*)))
|
||||||
|
KEEP(*(.init_array))
|
||||||
|
__stop_init_array = .; /* Define the end symbol */
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
.fini_array : {
|
||||||
|
__start_fini_array = .; /* Define the start symbol for destructors */
|
||||||
|
KEEP(*(SORT(.fini_array.*)))
|
||||||
|
KEEP(*(.fini_array))
|
||||||
|
__stop_fini_array = .; /* Define the end symbol for destructors */
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* Add other sections as needed */
|
||||||
|
}
|
195
src/CRT_LNX.cpp
195
src/CRT_LNX.cpp
@ -49,12 +49,19 @@ extern "C"
|
|||||||
return &tls_errno;
|
return &tls_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void (*__start_init_array[])();
|
||||||
|
extern void (*__stop_init_array[])();
|
||||||
|
extern void (*__start_fini_array[])();
|
||||||
|
extern void (*__stop_fini_array[])();
|
||||||
|
|
||||||
#ifdef EHS_DEBUG
|
#ifdef EHS_DEBUG
|
||||||
unsigned long __stack_chk_guard = 0x0000DEAD;
|
unsigned long __stack_chk_guard = 0x0000DEAD;
|
||||||
#else
|
#else
|
||||||
unsigned long __stack_chk_guard = ehs::HRNG::GenerateSeed_u64();
|
unsigned long __stack_chk_guard = ehs::HRNG::GenerateSeed_u64();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void* __dso_handle = (void*)&__dso_handle;
|
||||||
|
|
||||||
void __stack_chk_fail(void)
|
void __stack_chk_fail(void)
|
||||||
{
|
{
|
||||||
EHS_LOG("Error", 0, "Found corrupted stack.");
|
EHS_LOG("Error", 0, "Found corrupted stack.");
|
||||||
@ -67,6 +74,22 @@ extern "C"
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void construct() __attribute__((constructor));
|
||||||
|
|
||||||
|
void construct()
|
||||||
|
{
|
||||||
|
for (void (**p)() = __start_init_array; p < __stop_init_array; ++p)
|
||||||
|
(*p)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void destruct() __attribute__((destructor));
|
||||||
|
|
||||||
|
void destruct()
|
||||||
|
{
|
||||||
|
for (void (**p)() = __start_fini_array; p < __stop_fini_array; ++p)
|
||||||
|
(*p)();
|
||||||
|
}
|
||||||
|
|
||||||
size_t strlen(const char *s)
|
size_t strlen(const char *s)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@ -77,20 +100,176 @@ extern "C"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new[](unsigned long size) noexcept(false)
|
struct Block
|
||||||
{
|
{
|
||||||
syscall(SYS_brk,)
|
size_t size;
|
||||||
void* ptr = (void*)syscall(SYS_mmap, nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
Block* prev;
|
||||||
if (ptr == MAP_FAILED)
|
Block* next;
|
||||||
{
|
int free;
|
||||||
EHS_LOG("Error", 0, "Failed to allocate memory on the heap.");
|
};
|
||||||
|
|
||||||
|
Block* first = nullptr;
|
||||||
|
Block* last = nullptr;
|
||||||
|
|
||||||
|
/// Extends heap memory upwards, towards zero.
|
||||||
|
/// @param [in] s The size of the memory needed aligned by 4 bytes.
|
||||||
|
/// @returns The new memory block.
|
||||||
|
Block* extend_heap(ehs::UInt_64 s)
|
||||||
|
{
|
||||||
|
Block* b = (Block*)syscall(SYS_brk, nullptr);
|
||||||
|
|
||||||
|
if ((void*)syscall(SYS_brk, (char*)(b + 1) + s) == (void*)-1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
b->size = s;
|
||||||
|
b->prev = last;
|
||||||
|
b->next = nullptr;
|
||||||
|
b->free = 0;
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->next = b;
|
||||||
|
|
||||||
|
last = b;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds the first block that will fit the given size.
|
||||||
|
/// @param [in] s The 4 byte aligned size to look for.
|
||||||
|
/// @returns The matching available memory block.
|
||||||
|
Block* find_first(ehs::UInt_64 s)
|
||||||
|
{
|
||||||
|
Block* current = first;
|
||||||
|
while (current && (!current->free || current->size < s))
|
||||||
|
current = current->next;
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fragments an existing free memory block into the given size.
|
||||||
|
/// @param [in] in The memory block to fragment.
|
||||||
|
/// @param [in] s The size of the new memory block.
|
||||||
|
/// @returns The new memory block.
|
||||||
|
Block* fragment_block(Block* in, ehs::UInt_64 s)
|
||||||
|
{
|
||||||
|
ehs::UInt_64 totalSize = sizeof(Block) + s;
|
||||||
|
Block* b = (Block*)((char*)(in + 1) + (in->size - totalSize));
|
||||||
|
b->size = s;
|
||||||
|
b->prev = in;
|
||||||
|
b->next = in->next;
|
||||||
|
b->free = 0;
|
||||||
|
|
||||||
|
in->size -= totalSize;
|
||||||
|
in->next = b;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Will find or allocate a memory block.
|
||||||
|
/// @param [in] size The size of the memory block to request.
|
||||||
|
/// @returns The requested memory on the heap.
|
||||||
|
void* malloc(ehs::UInt_64 size)
|
||||||
|
{
|
||||||
|
Block* b;
|
||||||
|
|
||||||
|
size = ((size - 1) >> 2 << 2) + 4;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
b = find_first(size);
|
||||||
|
if (!b)
|
||||||
|
b = extend_heap(size);
|
||||||
|
else if (b->size > sizeof(Block) + size)
|
||||||
|
b = fragment_block(b, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b = extend_heap(size);
|
||||||
|
if (!b)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
first = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return b + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* realloc(void* ptr, ehs::UInt_64 new_size)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return malloc(new_size);
|
||||||
|
|
||||||
|
if (!new_size)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
Block* b = (Block*)ptr - 1;
|
||||||
|
if (b->free)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (b->size == new_size)
|
||||||
|
return ptr;
|
||||||
|
else if (b->size > sizeof(Block) + new_size)
|
||||||
|
return fragment_block(b, new_size) + 1;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Will flag the provided memory as free and will defragment other blocks adjacent to it.
|
||||||
|
/// @param [in] ptr The memory to flag as free.
|
||||||
|
/// @note If all data after the provided memory is free, it will reduce the heap size.
|
||||||
|
void free(void* ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block* b = (Block*)ptr - 1;
|
||||||
|
if (b->free)
|
||||||
|
return;
|
||||||
|
|
||||||
|
b->free = 1;
|
||||||
|
|
||||||
|
while (b->prev && b->prev->free)
|
||||||
|
b = b->prev;
|
||||||
|
|
||||||
|
while (b->next && b->next->free)
|
||||||
|
{
|
||||||
|
b->size += sizeof(Block) + b->next->size;
|
||||||
|
b->next = b->next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!b->next)
|
||||||
|
syscall(SYS_brk, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
ehs::UInt_64 get_heap_size()
|
||||||
|
{
|
||||||
|
if (!first || !last)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ((char*)last + last->size) - (char*)first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new(unsigned long size) noexcept
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* ptr, unsigned long size) noexcept
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new[](unsigned long size) noexcept(false)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* ptr, unsigned long size) noexcept
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void* ptr) noexcept
|
void operator delete[](void* ptr) noexcept
|
||||||
{
|
{
|
||||||
syscall(SYS_munmap, ptr, GetStackSize())
|
free(ptr);
|
||||||
}
|
}
|
@ -635,7 +635,7 @@ void LogRaised(const ehs::Log& log)
|
|||||||
ehs::BaseConsole::Write_8(result);
|
ehs::BaseConsole::Write_8(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
void start()
|
||||||
{
|
{
|
||||||
ehs::Console::Attach();
|
ehs::Console::Attach();
|
||||||
|
|
||||||
@ -682,6 +682,4 @@ int main()
|
|||||||
ehs::GarbageCollector::Stop();
|
ehs::GarbageCollector::Stop();
|
||||||
|
|
||||||
ehs::Console::Free();
|
ehs::Console::Free();
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#include <ehs/EHS.h>
|
#include <ehs/EHS.h>
|
||||||
#include <ehs/Str.h>
|
#include <ehs/Str.h>
|
||||||
#include <ehs/io/BaseConsole.h>
|
#include <ehs/io/Console.h>
|
||||||
|
|
||||||
ehs::Int_32 Main(ehs::Str_8* appName, ehs::Str_8* appVerId, ehs::Version* appVer)
|
ehs::Int_32 Main(ehs::Str_8* appName, ehs::Str_8* appVerId, ehs::Version* appVer)
|
||||||
{
|
{
|
||||||
@ -8,23 +8,23 @@ ehs::Int_32 Main(ehs::Str_8* appName, ehs::Str_8* appVerId, ehs::Version* appVer
|
|||||||
*appVerId = "Release";
|
*appVerId = "Release";
|
||||||
*appVer = {1, 0, 0};
|
*appVer = {1, 0, 0};
|
||||||
|
|
||||||
ehs::Vector<ehs::Str_8> args = ehs::BaseConsole::GetArgs_8();
|
ehs::Vector<ehs::Str_8> args = ehs::Console::GetArgs_8();
|
||||||
|
|
||||||
if (args.Size() > 1)
|
if (args.Size() > 1)
|
||||||
{
|
{
|
||||||
for (ehs::UInt_64 i = 1; i < args.Size(); ++i)
|
for (ehs::UInt_64 i = 1; i < args.Size(); ++i)
|
||||||
ehs::BaseConsole::Write_8("Result " + ehs::Str_8::FromNum(i) + ": " + ehs::Str_8::FromNum(args[i].Hash_64()));
|
ehs::Console::Write_8("Result " + ehs::Str_8::FromNum(i) + ": " + ehs::Str_8::FromNum(args[i].Hash_64()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ehs::BaseConsole::Write_8("String: ", false);
|
ehs::Console::Write_8("String: ", false);
|
||||||
ehs::Str_8 in = ehs::BaseConsole::Read_8();
|
ehs::Str_8 in = ehs::Console::Read_8();
|
||||||
ehs::BaseConsole::Write_8("Result: " + ehs::Str_8::FromNum(in.Hash_64()));
|
ehs::Console::Write_8("Result: " + ehs::Str_8::FromNum(in.Hash_64()));
|
||||||
|
|
||||||
ehs::BaseConsole::Read_8();
|
ehs::Console::Read_8();
|
||||||
}
|
}
|
||||||
|
|
||||||
ehs::BaseConsole::Free();
|
ehs::Console::Free();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user