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)
|
||||
|
||||
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")
|
||||
elseif (IS_OS_WINDOWS)
|
||||
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;
|
||||
}
|
||||
|
||||
extern void (*__start_init_array[])();
|
||||
extern void (*__stop_init_array[])();
|
||||
extern void (*__start_fini_array[])();
|
||||
extern void (*__stop_fini_array[])();
|
||||
|
||||
#ifdef EHS_DEBUG
|
||||
unsigned long __stack_chk_guard = 0x0000DEAD;
|
||||
#else
|
||||
unsigned long __stack_chk_guard = ehs::HRNG::GenerateSeed_u64();
|
||||
#endif
|
||||
|
||||
void* __dso_handle = (void*)&__dso_handle;
|
||||
|
||||
void __stack_chk_fail(void)
|
||||
{
|
||||
EHS_LOG("Error", 0, "Found corrupted stack.");
|
||||
@ -67,6 +74,22 @@ extern "C"
|
||||
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 count = 0;
|
||||
@ -77,20 +100,176 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
void* operator new[](unsigned long size) noexcept(false)
|
||||
struct Block
|
||||
{
|
||||
syscall(SYS_brk,)
|
||||
void* ptr = (void*)syscall(SYS_mmap, nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
EHS_LOG("Error", 0, "Failed to allocate memory on the heap.");
|
||||
size_t size;
|
||||
Block* prev;
|
||||
Block* next;
|
||||
int free;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
syscall(SYS_munmap, ptr, GetStackSize())
|
||||
free(ptr);
|
||||
}
|
@ -635,7 +635,7 @@ void LogRaised(const ehs::Log& log)
|
||||
ehs::BaseConsole::Write_8(result);
|
||||
}
|
||||
|
||||
int main()
|
||||
void start()
|
||||
{
|
||||
ehs::Console::Attach();
|
||||
|
||||
@ -682,6 +682,4 @@ int main()
|
||||
ehs::GarbageCollector::Stop();
|
||||
|
||||
ehs::Console::Free();
|
||||
|
||||
return code;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#include <ehs/EHS.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)
|
||||
{
|
||||
@ -8,23 +8,23 @@ ehs::Int_32 Main(ehs::Str_8* appName, ehs::Str_8* appVerId, ehs::Version* appVer
|
||||
*appVerId = "Release";
|
||||
*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)
|
||||
{
|
||||
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
|
||||
{
|
||||
ehs::BaseConsole::Write_8("String: ", false);
|
||||
ehs::Str_8 in = ehs::BaseConsole::Read_8();
|
||||
ehs::BaseConsole::Write_8("Result: " + ehs::Str_8::FromNum(in.Hash_64()));
|
||||
ehs::Console::Write_8("String: ", false);
|
||||
ehs::Str_8 in = ehs::Console::Read_8();
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user