Compare commits
11 Commits
7c4b9218f2
...
50ab391133
Author | SHA1 | Date |
---|---|---|
Bananymous | 50ab391133 | |
Bananymous | 991647bc8f | |
Bananymous | 57300687ff | |
Bananymous | d559339f5f | |
Bananymous | 2bf65ef512 | |
Bananymous | d20752c318 | |
Bananymous | 5f66ef34dd | |
Bananymous | da0b4cd40e | |
Bananymous | 68f9dc1f8a | |
Bananymous | 5121d0d934 | |
Bananymous | 2c520391eb |
|
@ -55,14 +55,15 @@ start_userspace_thread:
|
||||||
movw %bx, %gs
|
movw %bx, %gs
|
||||||
xorw %bx, %bx
|
xorw %bx, %bx
|
||||||
|
|
||||||
popl %edx
|
|
||||||
popl %esi
|
|
||||||
popl %edi
|
popl %edi
|
||||||
|
popl %esi
|
||||||
|
popl %edx
|
||||||
popl %ecx
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
|
||||||
pushl $(0x20 | 3)
|
pushl $(0x20 | 3)
|
||||||
pushl %eax
|
pushl %eax
|
||||||
pushl $0x202
|
pushl $0x202
|
||||||
pushl $(0x18 | 3)
|
pushl $(0x18 | 3)
|
||||||
pushl %ecx
|
pushl %ebx
|
||||||
iret
|
iret
|
||||||
|
|
|
@ -216,6 +216,14 @@ higher_half:
|
||||||
# call global constuctors
|
# call global constuctors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
|
movl $__init_array_start, %ebx
|
||||||
|
jmp 2f
|
||||||
|
1: movl (%ebx), %eax
|
||||||
|
call *%eax
|
||||||
|
addl $4, %ebx
|
||||||
|
2: cmpl $__init_array_end, %ebx
|
||||||
|
jne 1b
|
||||||
|
|
||||||
# call to the kernel itself (clear ebp for stacktrace)
|
# call to the kernel itself (clear ebp for stacktrace)
|
||||||
xorl %ebp, %ebp
|
xorl %ebp, %ebp
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
.section .text
|
|
||||||
|
|
||||||
.global _start
|
|
||||||
_start:
|
|
||||||
# Set up end of the stack frame linked list.
|
|
||||||
movl $0, %ebp
|
|
||||||
pushl %ebp # rip=0
|
|
||||||
pushl %ebp # rbp=0
|
|
||||||
movl %esp, %ebp
|
|
||||||
|
|
||||||
# Prepare signals, memory allocation, stdio and such.
|
|
||||||
#call initialize_standard_library
|
|
||||||
|
|
||||||
# Run the global constructors.
|
|
||||||
call _init
|
|
||||||
|
|
||||||
# Run main
|
|
||||||
call main
|
|
||||||
|
|
||||||
# Terminate the process with the exit code.
|
|
||||||
movl %eax, %edi
|
|
||||||
call exit
|
|
||||||
.size _start, . - _start
|
|
|
@ -1,9 +1,9 @@
|
||||||
/* x86 crti.s */
|
/* i686 crti.s */
|
||||||
.section .init
|
.section .init
|
||||||
.global _init
|
.global _init
|
||||||
.type _init, @function
|
.type _init, @function
|
||||||
_init:
|
_init:
|
||||||
push %ebp
|
pushl %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
|
||||||
|
|
||||||
|
@ -11,6 +11,14 @@ _init:
|
||||||
.global _fini
|
.global _fini
|
||||||
.type _fini, @function
|
.type _fini, @function
|
||||||
_fini:
|
_fini:
|
||||||
push %ebp
|
pushl %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_start
|
||||||
|
__init_array_start:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_start
|
||||||
|
__fini_array_start:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* x86 crtn.s */
|
/* i686 crtn.s */
|
||||||
.section .init
|
.section .init
|
||||||
/* gcc will nicely put the contents of crtend.o's .init section here. */
|
/* gcc will nicely put the contents of crtend.o's .init section here. */
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
@ -8,3 +8,11 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_end
|
||||||
|
__init_array_end:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_end
|
||||||
|
__fini_array_end:
|
||||||
|
|
|
@ -39,14 +39,15 @@ start_userspace_thread:
|
||||||
|
|
||||||
call get_userspace_thread_stack_top
|
call get_userspace_thread_stack_top
|
||||||
|
|
||||||
popq %rdx
|
|
||||||
popq %rsi
|
|
||||||
popq %rdi
|
popq %rdi
|
||||||
|
popq %rsi
|
||||||
|
popq %rdx
|
||||||
popq %rcx
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
|
||||||
pushq $(0x20 | 3)
|
pushq $(0x20 | 3)
|
||||||
pushq %rax
|
pushq %rax
|
||||||
pushq $0x202
|
pushq $0x202
|
||||||
pushq $(0x18 | 3)
|
pushq $(0x18 | 3)
|
||||||
pushq %rcx
|
pushq %rbx
|
||||||
iretq
|
iretq
|
||||||
|
|
|
@ -216,6 +216,14 @@ higher_half:
|
||||||
# call global constuctors
|
# call global constuctors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
|
movq $__init_array_start, %rbx
|
||||||
|
jmp 2f
|
||||||
|
1: movq (%rbx), %rax
|
||||||
|
call *%rax
|
||||||
|
addq $8, %rbx
|
||||||
|
2: cmpq $__init_array_end, %rbx
|
||||||
|
jne 1b
|
||||||
|
|
||||||
# call to the kernel itself (clear rbp for stacktrace)
|
# call to the kernel itself (clear rbp for stacktrace)
|
||||||
xorq %rbp, %rbp
|
xorq %rbp, %rbp
|
||||||
|
|
||||||
|
|
|
@ -14,3 +14,11 @@ _fini:
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_start
|
||||||
|
__init_array_start:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_start
|
||||||
|
__fini_array_start:
|
||||||
|
|
|
@ -8,3 +8,11 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_end
|
||||||
|
__init_array_end:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_end
|
||||||
|
__fini_array_end:
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> clone_from(const OpenFileDescriptorSet&);
|
BAN::ErrorOr<void> clone_from(const OpenFileDescriptorSet&);
|
||||||
|
|
||||||
BAN::ErrorOr<int> open(VirtualFileSystem::File, int flags);
|
BAN::ErrorOr<int> open(VirtualFileSystem::File&&, int flags);
|
||||||
BAN::ErrorOr<int> open(BAN::StringView absolute_path, int flags);
|
BAN::ErrorOr<int> open(BAN::StringView absolute_path, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<int> socket(int domain, int type, int protocol);
|
BAN::ErrorOr<int> socket(int domain, int type, int protocol);
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace Kernel
|
||||||
int argc { 0 };
|
int argc { 0 };
|
||||||
char** argv { nullptr };
|
char** argv { nullptr };
|
||||||
char** envp { nullptr };
|
char** envp { nullptr };
|
||||||
|
int file_fd { -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<int> OpenFileDescriptorSet::open(VirtualFileSystem::File file, int flags)
|
BAN::ErrorOr<int> OpenFileDescriptorSet::open(VirtualFileSystem::File&& file, int flags)
|
||||||
{
|
{
|
||||||
ASSERT(file.inode);
|
ASSERT(file.inode);
|
||||||
|
|
||||||
|
|
|
@ -411,7 +411,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, absolute_path, O_EXEC));
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, absolute_path, O_EXEC));
|
||||||
return TRY(LibELF::LoadableELF::load_from_inode(page_table, file.inode));
|
return TRY(LibELF::LoadableELF::load_from_inode(page_table, credentials, file.inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_fork(uintptr_t sp, uintptr_t ip)
|
BAN::ErrorOr<long> Process::sys_fork(uintptr_t sp, uintptr_t ip)
|
||||||
|
@ -515,6 +515,13 @@ namespace Kernel
|
||||||
m_loadable_elf->reserve_address_space();
|
m_loadable_elf->reserve_address_space();
|
||||||
m_loadable_elf->update_suid_sgid(m_credentials);
|
m_loadable_elf->update_suid_sgid(m_credentials);
|
||||||
m_userspace_info.entry = m_loadable_elf->entry_point();
|
m_userspace_info.entry = m_loadable_elf->entry_point();
|
||||||
|
if (m_loadable_elf->has_interpreter())
|
||||||
|
{
|
||||||
|
VirtualFileSystem::File file;
|
||||||
|
TRY(file.canonical_path.append("<self>"));
|
||||||
|
file.inode = m_loadable_elf->inode();
|
||||||
|
m_userspace_info.file_fd = TRY(m_open_file_descriptors.open(BAN::move(file), O_EXEC));
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
|
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
|
||||||
{
|
{
|
||||||
|
@ -539,7 +546,7 @@ namespace Kernel
|
||||||
auto region = TRY(MemoryBackedRegion::create(
|
auto region = TRY(MemoryBackedRegion::create(
|
||||||
page_table(),
|
page_table(),
|
||||||
bytes,
|
bytes,
|
||||||
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
{ .start = m_userspace_info.entry, .end = KERNEL_OFFSET },
|
||||||
MemoryRegion::Type::PRIVATE,
|
MemoryRegion::Type::PRIVATE,
|
||||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
||||||
));
|
));
|
||||||
|
@ -910,13 +917,14 @@ namespace Kernel
|
||||||
file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(file.inode);
|
auto inode = file.inode;
|
||||||
|
ASSERT(inode);
|
||||||
|
|
||||||
int fd = TRY(m_open_file_descriptors.open(file, flags));
|
int fd = TRY(m_open_file_descriptors.open(BAN::move(file), flags));
|
||||||
|
|
||||||
// Open controlling terminal
|
// Open controlling terminal
|
||||||
if (!(flags & O_NOCTTY) && file.inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
if (!(flags & O_NOCTTY) && inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
||||||
m_controlling_terminal = static_cast<TTY*>(file.inode.ptr());
|
m_controlling_terminal = static_cast<TTY*>(inode.ptr());
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -1575,9 +1583,6 @@ namespace Kernel
|
||||||
if (args->prot != PROT_NONE && (args->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)))
|
if (args->prot != PROT_NONE && (args->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
if (args->flags & MAP_FIXED)
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
|
|
||||||
if (!(args->flags & MAP_PRIVATE) == !(args->flags & MAP_SHARED))
|
if (!(args->flags & MAP_PRIVATE) == !(args->flags & MAP_SHARED))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
auto region_type = (args->flags & MAP_PRIVATE) ? MemoryRegion::Type::PRIVATE : MemoryRegion::Type::SHARED;
|
auto region_type = (args->flags & MAP_PRIVATE) ? MemoryRegion::Type::PRIVATE : MemoryRegion::Type::SHARED;
|
||||||
|
@ -1595,17 +1600,23 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
page_flags |= PageTable::Flags::UserSupervisor;
|
page_flags |= PageTable::Flags::UserSupervisor;
|
||||||
|
|
||||||
|
AddressRange address_range { .start = 0x400000, .end = KERNEL_OFFSET };
|
||||||
|
if (args->flags & MAP_FIXED)
|
||||||
|
{
|
||||||
|
vaddr_t base_addr = reinterpret_cast<vaddr_t>(args->addr);
|
||||||
|
address_range.start = BAN::Math::div_round_up<vaddr_t>(base_addr, PAGE_SIZE) * PAGE_SIZE;
|
||||||
|
address_range.end = BAN::Math::div_round_up<vaddr_t>(base_addr + args->len, PAGE_SIZE) * PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
if (args->flags & MAP_ANONYMOUS)
|
if (args->flags & MAP_ANONYMOUS)
|
||||||
{
|
{
|
||||||
if (args->addr != nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
if (args->off != 0)
|
if (args->off != 0)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
auto region = TRY(MemoryBackedRegion::create(
|
auto region = TRY(MemoryBackedRegion::create(
|
||||||
page_table(),
|
page_table(),
|
||||||
args->len,
|
args->len,
|
||||||
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -1614,9 +1625,6 @@ namespace Kernel
|
||||||
return m_mapped_regions.back()->vaddr();
|
return m_mapped_regions.back()->vaddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->addr != nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes));
|
auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes));
|
||||||
|
@ -1635,7 +1643,7 @@ namespace Kernel
|
||||||
inode,
|
inode,
|
||||||
page_table(),
|
page_table(),
|
||||||
args->off, args->len,
|
args->off, args->len,
|
||||||
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1644,7 +1652,7 @@ namespace Kernel
|
||||||
memory_region = TRY(static_cast<Device&>(*inode).mmap_region(
|
memory_region = TRY(static_cast<Device&>(*inode).mmap_region(
|
||||||
page_table(),
|
page_table(),
|
||||||
args->off, args->len,
|
args->off, args->len,
|
||||||
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1775,7 +1783,7 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
int pts_master_fd = TRY(m_open_file_descriptors.open(file, flags));
|
int pts_master_fd = TRY(m_open_file_descriptors.open(BAN::move(file), flags));
|
||||||
|
|
||||||
if (!(flags & O_NOCTTY) && is_session_leader() && !m_controlling_terminal)
|
if (!(flags & O_NOCTTY) && is_session_leader() && !m_controlling_terminal)
|
||||||
m_controlling_terminal = (TTY*)pts_slave.ptr();
|
m_controlling_terminal = (TTY*)pts_slave.ptr();
|
||||||
|
|
|
@ -190,22 +190,23 @@ namespace Kernel
|
||||||
|
|
||||||
// Signal mask is inherited
|
// Signal mask is inherited
|
||||||
|
|
||||||
auto& userspace_info = process().userspace_info();
|
const auto& userspace_info = process().userspace_info();
|
||||||
ASSERT(userspace_info.entry);
|
ASSERT(userspace_info.entry);
|
||||||
|
|
||||||
// Initialize stack for returning
|
// Initialize stack for returning
|
||||||
PageTable::with_fast_page(process().page_table().physical_address_of(kernel_stack_top() - PAGE_SIZE), [&] {
|
PageTable::with_fast_page(process().page_table().physical_address_of(kernel_stack_top() - PAGE_SIZE), [&] {
|
||||||
uintptr_t sp = PageTable::fast_page() + PAGE_SIZE;
|
uintptr_t sp = PageTable::fast_page() + PAGE_SIZE;
|
||||||
write_to_stack(sp, userspace_info.entry);
|
write_to_stack(sp, userspace_info.entry);
|
||||||
write_to_stack(sp, userspace_info.argc);
|
write_to_stack(sp, userspace_info.file_fd);
|
||||||
write_to_stack(sp, userspace_info.argv);
|
|
||||||
write_to_stack(sp, userspace_info.envp);
|
write_to_stack(sp, userspace_info.envp);
|
||||||
|
write_to_stack(sp, userspace_info.argv);
|
||||||
|
write_to_stack(sp, userspace_info.argc);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_userspace_thread);;
|
m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_userspace_thread);
|
||||||
m_interrupt_stack.cs = 0x08;
|
m_interrupt_stack.cs = 0x08;
|
||||||
m_interrupt_stack.flags = 0x002;
|
m_interrupt_stack.flags = 0x002;
|
||||||
m_interrupt_stack.sp = kernel_stack_top() - 4 * sizeof(uintptr_t);
|
m_interrupt_stack.sp = kernel_stack_top() - 5 * sizeof(uintptr_t);
|
||||||
m_interrupt_stack.ss = 0x10;
|
m_interrupt_stack.ss = 0x10;
|
||||||
|
|
||||||
memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters));
|
memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters));
|
||||||
|
|
|
@ -104,7 +104,7 @@ case $1 in
|
||||||
run_qemu -nographic $QEMU_ACCEL
|
run_qemu -nographic $QEMU_ACCEL
|
||||||
;;
|
;;
|
||||||
qemu-debug)
|
qemu-debug)
|
||||||
run_qemu -serial stdio -d int -no-reboot
|
run_qemu -serial stdio -d int -action reboot=shutdown,shutdown=pause
|
||||||
;;
|
;;
|
||||||
bochs)
|
bochs)
|
||||||
run_bochs
|
run_bochs
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
From 0c0f7c2421aa650b11ae3914200c4be153718ca8 Mon Sep 17 00:00:00 2001
|
diff -ruN binutils-2.39/bfd/config.bfd binutils-2.39-banan_os/bfd/config.bfd
|
||||||
From: Bananymous <bananymousosq@gmail.com>
|
--- binutils-2.39/bfd/config.bfd 2022-07-08 12:46:47.000000000 +0300
|
||||||
Date: Sun, 29 Oct 2023 17:39:44 +0200
|
+++ binutils-2.39-banan_os/bfd/config.bfd 2024-08-26 15:25:08.612615228 +0300
|
||||||
Subject: [PATCH] Add target banan_os for i386 and x86_64
|
@@ -602,6 +602,11 @@
|
||||||
|
|
||||||
---
|
|
||||||
bfd/config.bfd | 10 ++++++++++
|
|
||||||
config.sub | 2 +-
|
|
||||||
gas/configure.tgt | 1 +
|
|
||||||
ld/configure.tgt | 6 ++++++
|
|
||||||
4 files changed, 18 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/bfd/config.bfd b/bfd/config.bfd
|
|
||||||
index a4c6c8e885..1f083e596f 100644
|
|
||||||
--- a/bfd/config.bfd
|
|
||||||
+++ b/bfd/config.bfd
|
|
||||||
@@ -602,6 +602,11 @@ case "${targ}" in
|
|
||||||
targ_defvec=i386_elf32_vec
|
targ_defvec=i386_elf32_vec
|
||||||
targ_selvecs=iamcu_elf32_vec
|
targ_selvecs=iamcu_elf32_vec
|
||||||
;;
|
;;
|
||||||
|
@ -26,7 +13,7 @@ index a4c6c8e885..1f083e596f 100644
|
||||||
i[3-7]86-*-dicos*)
|
i[3-7]86-*-dicos*)
|
||||||
targ_defvec=i386_elf32_vec
|
targ_defvec=i386_elf32_vec
|
||||||
targ_selvecs=iamcu_elf32_vec
|
targ_selvecs=iamcu_elf32_vec
|
||||||
@@ -656,6 +661,11 @@ case "${targ}" in
|
@@ -656,6 +661,11 @@
|
||||||
targ64_selvecs=x86_64_elf64_vec
|
targ64_selvecs=x86_64_elf64_vec
|
||||||
;;
|
;;
|
||||||
#ifdef BFD64
|
#ifdef BFD64
|
||||||
|
@ -38,11 +25,10 @@ index a4c6c8e885..1f083e596f 100644
|
||||||
x86_64-*-cloudabi*)
|
x86_64-*-cloudabi*)
|
||||||
targ_defvec=x86_64_elf64_cloudabi_vec
|
targ_defvec=x86_64_elf64_cloudabi_vec
|
||||||
want64=true
|
want64=true
|
||||||
diff --git a/config.sub b/config.sub
|
diff -ruN binutils-2.39/config.sub binutils-2.39-banan_os/config.sub
|
||||||
index dba16e84c7..9a37bb30fd 100755
|
--- binutils-2.39/config.sub 2022-07-08 12:46:47.000000000 +0300
|
||||||
--- a/config.sub
|
+++ binutils-2.39-banan_os/config.sub 2024-08-26 16:01:54.868646232 +0300
|
||||||
+++ b/config.sub
|
@@ -1754,7 +1754,7 @@
|
||||||
@@ -1754,7 +1754,7 @@ case $os in
|
|
||||||
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
|
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
|
||||||
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
|
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
|
||||||
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
|
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
|
||||||
|
@ -51,11 +37,10 @@ index dba16e84c7..9a37bb30fd 100755
|
||||||
;;
|
;;
|
||||||
# This one is extra strict with allowed versions
|
# This one is extra strict with allowed versions
|
||||||
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
|
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
|
||||||
diff --git a/gas/configure.tgt b/gas/configure.tgt
|
diff -ruN binutils-2.39/gas/configure.tgt binutils-2.39-banan_os/gas/configure.tgt
|
||||||
index 62f806bdfe..e05db38382 100644
|
--- binutils-2.39/gas/configure.tgt 2022-07-08 12:46:47.000000000 +0300
|
||||||
--- a/gas/configure.tgt
|
+++ binutils-2.39-banan_os/gas/configure.tgt 2024-08-26 15:29:24.317178187 +0300
|
||||||
+++ b/gas/configure.tgt
|
@@ -221,6 +221,7 @@
|
||||||
@@ -221,6 +221,7 @@ case ${generic_target} in
|
|
||||||
h8300-*-elf) fmt=elf ;;
|
h8300-*-elf) fmt=elf ;;
|
||||||
h8300-*-linux*) fmt=elf em=linux ;;
|
h8300-*-linux*) fmt=elf em=linux ;;
|
||||||
|
|
||||||
|
@ -63,30 +48,98 @@ index 62f806bdfe..e05db38382 100644
|
||||||
i386-*-beospe*) fmt=coff em=pe ;;
|
i386-*-beospe*) fmt=coff em=pe ;;
|
||||||
i386-*-beos*) fmt=elf ;;
|
i386-*-beos*) fmt=elf ;;
|
||||||
i386-*-elfiamcu) fmt=elf arch=iamcu ;;
|
i386-*-elfiamcu) fmt=elf arch=iamcu ;;
|
||||||
diff --git a/ld/configure.tgt b/ld/configure.tgt
|
diff -ruN binutils-2.39/ld/configure.tgt binutils-2.39-banan_os/ld/configure.tgt
|
||||||
index 2bae9099b6..640426e81f 100644
|
--- binutils-2.39/ld/configure.tgt 2022-07-29 10:37:48.000000000 +0300
|
||||||
--- a/ld/configure.tgt
|
+++ binutils-2.39-banan_os/ld/configure.tgt 2024-08-26 15:43:54.040175458 +0300
|
||||||
+++ b/ld/configure.tgt
|
@@ -352,6 +352,10 @@
|
||||||
@@ -352,6 +352,9 @@ i[3-7]86-*-aros*) targ_emul=elf_i386
|
|
||||||
i[3-7]86-*-rdos*) targ_emul=elf_i386
|
i[3-7]86-*-rdos*) targ_emul=elf_i386
|
||||||
targ_extra_emuls=elf_iamcu
|
targ_extra_emuls=elf_iamcu
|
||||||
;;
|
;;
|
||||||
+i[3-7]86-*-banan_os*) targ_emul=elf_i386
|
+i[3-7]86-*-banan_os*) targ_emul=elf_i386_banan_os
|
||||||
+ targ64_extra_emuls=elf_x86_64
|
+ targ_extra_emuls=elf_i386
|
||||||
|
+ targ64_extra_emuls="elf_x86_64_banan_os elf_x86_64"
|
||||||
+ ;;
|
+ ;;
|
||||||
i[3-7]86-*-bsd) targ_emul=i386bsd
|
i[3-7]86-*-bsd) targ_emul=i386bsd
|
||||||
targ_extra_ofiles=
|
targ_extra_ofiles=
|
||||||
;;
|
;;
|
||||||
@@ -988,6 +991,9 @@ visium-*-elf) targ_emul=elf32visium
|
@@ -988,6 +992,9 @@
|
||||||
;;
|
;;
|
||||||
x86_64-*-rdos*) targ_emul=elf64rdos
|
x86_64-*-rdos*) targ_emul=elf64rdos
|
||||||
;;
|
;;
|
||||||
+x86_64-*-banan_os*) targ_emul=elf_x86_64
|
+x86_64-*-banan_os*) targ_emul=elf_x86_64_banan_os
|
||||||
+ targ_extra_emuls=elf_i386
|
+ targ_extra_emuls="elf_i386_banan_os elf_x86_64 elf_i386"
|
||||||
+ ;;
|
+ ;;
|
||||||
x86_64-*-cloudabi*) targ_emul=elf_x86_64_cloudabi
|
x86_64-*-cloudabi*) targ_emul=elf_x86_64_cloudabi
|
||||||
;;
|
;;
|
||||||
x86_64-*-haiku*) targ_emul=elf_x86_64_haiku
|
x86_64-*-haiku*) targ_emul=elf_x86_64_haiku
|
||||||
--
|
diff -ruN binutils-2.39/ld/emulparams/elf_banan_os.sh binutils-2.39-banan_os/ld/emulparams/elf_banan_os.sh
|
||||||
2.42.0
|
--- binutils-2.39/ld/emulparams/elf_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
|
||||||
|
+++ binutils-2.39-banan_os/ld/emulparams/elf_banan_os.sh 2024-08-26 15:51:32.242246455 +0300
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+ELF_INTERPRETER_NAME=\"/usr/lib/DynamicLoader.so\"
|
||||||
|
diff -ruN binutils-2.39/ld/emulparams/elf_i386_banan_os.sh binutils-2.39-banan_os/ld/emulparams/elf_i386_banan_os.sh
|
||||||
|
--- binutils-2.39/ld/emulparams/elf_i386_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
|
||||||
|
+++ binutils-2.39-banan_os/ld/emulparams/elf_i386_banan_os.sh 2024-08-26 15:51:26.431570961 +0300
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+source_sh ${srcdir}/emulparams/elf_i386.sh
|
||||||
|
+source_sh ${srcdir}/emulparams/elf_banan_os.sh
|
||||||
|
diff -ruN binutils-2.39/ld/emulparams/elf_x86_64_banan_os.sh binutils-2.39-banan_os/ld/emulparams/elf_x86_64_banan_os.sh
|
||||||
|
--- binutils-2.39/ld/emulparams/elf_x86_64_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
|
||||||
|
+++ binutils-2.39-banan_os/ld/emulparams/elf_x86_64_banan_os.sh 2024-08-26 15:51:21.591003274 +0300
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+source_sh ${srcdir}/emulparams/elf_x86_64.sh
|
||||||
|
+source_sh ${srcdir}/emulparams/elf_banan_os.sh
|
||||||
|
diff -ruN binutils-2.39/ld/Makefile.am binutils-2.39-banan_os/ld/Makefile.am
|
||||||
|
--- binutils-2.39/ld/Makefile.am 2022-07-08 12:46:48.000000000 +0300
|
||||||
|
+++ binutils-2.39-banan_os/ld/Makefile.am 2024-08-26 15:46:27.818947949 +0300
|
||||||
|
@@ -275,6 +275,7 @@
|
||||||
|
eelf32xtensa.c \
|
||||||
|
eelf32z80.c \
|
||||||
|
eelf_i386.c \
|
||||||
|
+ eelf_i386_banan_os.c \
|
||||||
|
eelf_i386_be.c \
|
||||||
|
eelf_i386_fbsd.c \
|
||||||
|
eelf_i386_haiku.c \
|
||||||
|
@@ -453,6 +454,7 @@
|
||||||
|
eelf64tilegx_be.c \
|
||||||
|
eelf_mipsel_haiku.c \
|
||||||
|
eelf_x86_64.c \
|
||||||
|
+ eelf_x86_64_banan_os.c \
|
||||||
|
eelf_x86_64_cloudabi.c \
|
||||||
|
eelf_x86_64_fbsd.c \
|
||||||
|
eelf_x86_64_haiku.c \
|
||||||
|
diff -ruN binutils-2.39/ld/Makefile.in binutils-2.39-banan_os/ld/Makefile.in
|
||||||
|
--- binutils-2.39/ld/Makefile.in 2022-08-05 12:56:53.000000000 +0300
|
||||||
|
+++ binutils-2.39-banan_os/ld/Makefile.in 2024-08-26 15:52:12.046704200 +0300
|
||||||
|
@@ -772,6 +772,7 @@
|
||||||
|
eelf32xtensa.c \
|
||||||
|
eelf32z80.c \
|
||||||
|
eelf_i386.c \
|
||||||
|
+ eelf_i386_banan_os.c \
|
||||||
|
eelf_i386_be.c \
|
||||||
|
eelf_i386_fbsd.c \
|
||||||
|
eelf_i386_haiku.c \
|
||||||
|
@@ -949,6 +950,7 @@
|
||||||
|
eelf64tilegx_be.c \
|
||||||
|
eelf_mipsel_haiku.c \
|
||||||
|
eelf_x86_64.c \
|
||||||
|
+ eelf_x86_64_banan_os.c \
|
||||||
|
eelf_x86_64_cloudabi.c \
|
||||||
|
eelf_x86_64_fbsd.c \
|
||||||
|
eelf_x86_64_haiku.c \
|
||||||
|
@@ -1441,6 +1443,7 @@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx_be.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Po@am__quote@
|
||||||
|
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_banan_os.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Po@am__quote@
|
||||||
|
@@ -1451,6 +1454,7 @@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_mipsel_haiku.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_s390.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Po@am__quote@
|
||||||
|
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_banan_os.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_cloudabi.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Po@am__quote@
|
||||||
|
|
|
@ -79,10 +79,11 @@ build_binutils () {
|
||||||
cd $BANAN_BUILD_DIR/toolchain
|
cd $BANAN_BUILD_DIR/toolchain
|
||||||
|
|
||||||
if [ ! -d $BINUTILS_VERSION ]; then
|
if [ ! -d $BINUTILS_VERSION ]; then
|
||||||
wget $BINUTILS_URL
|
if [ ! -f $BINUTILS_TAR ]; then
|
||||||
|
wget $BINUTILS_URL
|
||||||
|
fi
|
||||||
tar xf $BINUTILS_TAR
|
tar xf $BINUTILS_TAR
|
||||||
cd $BINUTILS_VERSION
|
patch -ruN -p1 -d "$BINUTILS_VERSION" < "$BANAN_TOOLCHAIN_DIR/$BINUTILS_VERSION.patch"
|
||||||
patch -s -p1 < $BANAN_TOOLCHAIN_DIR/$BINUTILS_VERSION.patch
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $BANAN_BUILD_DIR/toolchain/$BINUTILS_VERSION
|
cd $BANAN_BUILD_DIR/toolchain/$BINUTILS_VERSION
|
||||||
|
@ -92,7 +93,9 @@ build_binutils () {
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$BANAN_SYSROOT" \
|
||||||
--disable-initfini-array \
|
--enable-initfini-array \
|
||||||
|
--enable-shared \
|
||||||
|
--enable-lto \
|
||||||
--disable-nls \
|
--disable-nls \
|
||||||
--disable-werror
|
--disable-werror
|
||||||
|
|
||||||
|
@ -106,10 +109,11 @@ build_gcc () {
|
||||||
cd $BANAN_BUILD_DIR/toolchain
|
cd $BANAN_BUILD_DIR/toolchain
|
||||||
|
|
||||||
if [ ! -d $GCC_VERSION ]; then
|
if [ ! -d $GCC_VERSION ]; then
|
||||||
wget $GCC_URL
|
if [ ! -f $GCC_TAR ]; then
|
||||||
|
wget $GCC_URL
|
||||||
|
fi
|
||||||
tar xf $GCC_TAR
|
tar xf $GCC_TAR
|
||||||
cd $GCC_VERSION
|
patch -ruN -p1 -d "$GCC_VERSION" < "$BANAN_TOOLCHAIN_DIR/$GCC_VERSION.patch"
|
||||||
patch -s -p1 < $BANAN_TOOLCHAIN_DIR/$GCC_VERSION.patch
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $BANAN_BUILD_DIR/toolchain/$GCC_VERSION
|
cd $BANAN_BUILD_DIR/toolchain/$GCC_VERSION
|
||||||
|
@ -119,7 +123,9 @@ build_gcc () {
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$BANAN_SYSROOT" \
|
||||||
--disable-initfini-array \
|
--enable-initfini-array \
|
||||||
|
--enable-shared \
|
||||||
|
--enable-lto \
|
||||||
--disable-nls \
|
--disable-nls \
|
||||||
--enable-languages=c,c++
|
--enable-languages=c,c++
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,32 +45,43 @@ set(LIBC_SOURCES
|
||||||
../../../BAN/BAN/Assert.cpp
|
../../../BAN/BAN/Assert.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(libc ${LIBC_SOURCES})
|
add_library(objlibc OBJECT ${LIBC_SOURCES})
|
||||||
target_compile_definitions(libc PRIVATE __arch=${BANAN_ARCH})
|
target_compile_definitions(objlibc PRIVATE __arch=${BANAN_ARCH})
|
||||||
target_compile_definitions(libc PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
|
target_compile_definitions(objlibc PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
|
||||||
if (NOT BANAN_ENABLE_SSE)
|
if (NOT BANAN_ENABLE_SSE)
|
||||||
target_compile_options(libc PRIVATE -mno-sse -mno-sse2)
|
target_compile_options(objlibc PRIVATE -mno-sse -mno-sse2)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_compile_options(libc PRIVATE -O2 -g -Wstack-usage=512 -fno-tree-loop-distribute-patterns -fno-exceptions -nostdlib)
|
target_compile_options(objlibc PRIVATE -O2 -g -Wstack-usage=512 -fno-tree-loop-distribute-patterns -fno-exceptions -fpic -nolibc)
|
||||||
target_compile_options(libc PUBLIC -Wall -Wextra -Werror -Wno-error=stack-usage=)
|
target_compile_options(objlibc PUBLIC -Wall -Wextra -Werror -Wno-error=stack-usage=)
|
||||||
|
|
||||||
function(add_crtx crtx)
|
function(add_crtx crtx)
|
||||||
add_custom_target(${crtx}
|
add_custom_target(${crtx}
|
||||||
COMMAND ${CMAKE_CXX_COMPILER} -c -o ${CMAKE_INSTALL_LIBDIR}/${crtx}.o ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/${crtx}.S
|
COMMAND ${CMAKE_CXX_COMPILER} -c -o ${CMAKE_INSTALL_LIBDIR}/${crtx}.o ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/${crtx}.S
|
||||||
DEPENDS sysroot
|
DEPENDS sysroot
|
||||||
)
|
)
|
||||||
add_dependencies(libc ${crtx})
|
add_dependencies(objlibc ${crtx})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_crtx(crt0)
|
add_crtx(crt0)
|
||||||
add_crtx(crti)
|
add_crtx(crti)
|
||||||
add_crtx(crtn)
|
add_crtx(crtn)
|
||||||
|
|
||||||
banan_include_headers(libc ban)
|
banan_include_headers(objlibc ban)
|
||||||
banan_include_headers(libc kernel)
|
banan_include_headers(objlibc kernel)
|
||||||
|
|
||||||
|
banan_install_headers(objlibc)
|
||||||
|
|
||||||
|
add_library(libc STATIC $<TARGET_OBJECTS:objlibc>)
|
||||||
|
add_library(libc-shared SHARED $<TARGET_OBJECTS:objlibc>)
|
||||||
|
|
||||||
|
target_link_options(libc PRIVATE -nolibc)
|
||||||
|
target_link_options(libc-shared PRIVATE -nolibc)
|
||||||
|
|
||||||
banan_install_headers(libc)
|
|
||||||
install(TARGETS libc OPTIONAL)
|
install(TARGETS libc OPTIONAL)
|
||||||
|
install(TARGETS libc-shared OPTIONAL)
|
||||||
|
|
||||||
|
set_target_properties(libc-shared PROPERTIES OUTPUT_NAME libc)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||||
|
|
|
@ -21,6 +21,14 @@ _start:
|
||||||
# call global constructors
|
# call global constructors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
|
movl $__init_array_start, %ebx
|
||||||
|
jmp 2f
|
||||||
|
1: movl (%ebx), %eax
|
||||||
|
call *%eax
|
||||||
|
addl $4, %ebx
|
||||||
|
2: cmpl $__init_array_end, %ebx
|
||||||
|
jne 1b
|
||||||
|
|
||||||
# call main
|
# call main
|
||||||
movl 0(%esp), %eax
|
movl 0(%esp), %eax
|
||||||
xchgl %eax, 8(%esp)
|
xchgl %eax, 8(%esp)
|
||||||
|
|
|
@ -14,3 +14,11 @@ _fini:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_start
|
||||||
|
__init_array_start:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_start
|
||||||
|
__fini_array_start:
|
||||||
|
|
|
@ -8,3 +8,11 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_end
|
||||||
|
__init_array_end:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_end
|
||||||
|
__fini_array_end:
|
||||||
|
|
|
@ -22,6 +22,14 @@ _start:
|
||||||
# call global constructors
|
# call global constructors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
|
movq $__init_array_start, %rbx
|
||||||
|
jmp 2f
|
||||||
|
1: movq (%rbx), %rax
|
||||||
|
call *%rax
|
||||||
|
addq $8, %rbx
|
||||||
|
2: cmpq $__init_array_end, %rbx
|
||||||
|
jne 1b
|
||||||
|
|
||||||
# call main
|
# call main
|
||||||
movq 16(%rsp), %rdi
|
movq 16(%rsp), %rdi
|
||||||
movq 8(%rsp), %rsi
|
movq 8(%rsp), %rsi
|
||||||
|
|
|
@ -14,3 +14,11 @@ _fini:
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_start
|
||||||
|
__init_array_start:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_start
|
||||||
|
__fini_array_start:
|
||||||
|
|
|
@ -8,3 +8,11 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .init_array
|
||||||
|
.global __init_array_end
|
||||||
|
__init_array_end:
|
||||||
|
|
||||||
|
.section .fini_array
|
||||||
|
.global __fini_array_end
|
||||||
|
__fini_array_end:
|
||||||
|
|
|
@ -12,6 +12,9 @@ __BEGIN_DECLS
|
||||||
#define RTLD_GLOBAL 3
|
#define RTLD_GLOBAL 3
|
||||||
#define RTLD_LOCAL 4
|
#define RTLD_LOCAL 4
|
||||||
|
|
||||||
|
#define RTLD_NEXT ((void*)-1)
|
||||||
|
#define RTLD_DEFAULT ((void*) 0)
|
||||||
|
|
||||||
int dlclose(void* handle);
|
int dlclose(void* handle);
|
||||||
char* dlerror(void);
|
char* dlerror(void);
|
||||||
void* dlopen(const char* file, int mode);
|
void* dlopen(const char* file, int mode);
|
||||||
|
|
|
@ -52,11 +52,9 @@ __BEGIN_DECLS
|
||||||
#define PTHREAD_SCOPE_PROCESS 23
|
#define PTHREAD_SCOPE_PROCESS 23
|
||||||
#define PTHREAD_SCOPE_SYSTEM 24
|
#define PTHREAD_SCOPE_SYSTEM 24
|
||||||
|
|
||||||
#if 0
|
#define PTHREAD_COND_INITIALIZER (pthread_cond_t)0
|
||||||
#define PTHREAD_COND_INITIALIZER
|
#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t)0
|
||||||
#define PTHREAD_MUTEX_INITIALIZER
|
#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)0
|
||||||
#define PTHREAD_RWLOCK_INITIALIZER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
|
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
|
||||||
int pthread_attr_destroy(pthread_attr_t* attr);
|
int pthread_attr_destroy(pthread_attr_t* attr);
|
||||||
|
|
|
@ -26,117 +26,190 @@ typedef unsigned long long sigset_t;
|
||||||
|
|
||||||
union sigval
|
union sigval
|
||||||
{
|
{
|
||||||
int sival_int; /* Integer signal value. */
|
int sival_int; /* Integer signal value. */
|
||||||
void* sival_ptr; /* Pointer signal value. */
|
void* sival_ptr; /* Pointer signal value. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sigevent
|
struct sigevent
|
||||||
{
|
{
|
||||||
int sigev_notify; /* Notification type. */
|
int sigev_notify; /* Notification type. */
|
||||||
int sigev_signo; /* Signal number. */
|
int sigev_signo; /* Signal number. */
|
||||||
union sigval sigev_value; /* Signal value. */
|
union sigval sigev_value; /* Signal value. */
|
||||||
void (*sigev_notify_function)(union sigval); /* Notification function. */
|
void (*sigev_notify_function)(union sigval); /* Notification function. */
|
||||||
pthread_attr_t* sigev_notify_attributes; /* Notification attributes. */
|
pthread_attr_t* sigev_notify_attributes; /* Notification attributes. */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIGEV_NONE 1
|
#define SIGEV_NONE 1
|
||||||
#define SIGEV_SIGNAL 2
|
#define SIGEV_SIGNAL 2
|
||||||
#define SIGEV_THREAD 3
|
#define SIGEV_THREAD 3
|
||||||
|
|
||||||
#define SIGABRT 1
|
#define SIGABRT 1
|
||||||
#define SIGALRM 2
|
#define SIGALRM 2
|
||||||
#define SIGBUS 3
|
#define SIGBUS 3
|
||||||
#define SIGCHLD 4
|
#define BUS_ADRALN 1
|
||||||
#define SIGCONT 5
|
#define BUS_ADRERR 2
|
||||||
#define SIGFPE 6
|
#define BUS_OBJERR 3
|
||||||
#define SIGHUP 7
|
#define SIGCHLD 4
|
||||||
#define SIGILL 8
|
#define CLD_EXITED 1
|
||||||
#define SIGINT 9
|
#define CLD_KILLED 2
|
||||||
#define SIGKILL 10
|
#define CLD_DUMPED 3
|
||||||
#define SIGPIPE 11
|
#define CLD_TRAPPED 4
|
||||||
#define SIGQUIT 12
|
#define CLD_STOPPED 5
|
||||||
#define SIGSEGV 13
|
#define CLD_CONTINUED 6
|
||||||
#define SIGSTOP 14
|
#define SIGCONT 5
|
||||||
#define SIGTERM 15
|
#define SIGFPE 6
|
||||||
#define SIGTSTP 16
|
#define FPE_INTDIV 1
|
||||||
#define SIGTTIN 17
|
#define FPE_INTOVF 2
|
||||||
#define SIGTTOU 18
|
#define FPE_FLTDIV 3
|
||||||
#define SIGUSR1 19
|
#define FPE_FLTOVF 4
|
||||||
#define SIGUSR2 20
|
#define FPE_FLTUND 5
|
||||||
#define SIGPOLL 21
|
#define FPE_FLTRES 6
|
||||||
#define SIGPROF 22
|
#define FPE_FLTINV 7
|
||||||
#define SIGSYS 23
|
#define FPE_FLTSUB 8
|
||||||
#define SIGTRAP 24
|
#define SIGHUP 7
|
||||||
#define SIGURG 25
|
#define SIGILL 8
|
||||||
#define SIGVTALRM 26
|
#define ILL_ILLOPC 1
|
||||||
#define SIGXCPU 27
|
#define ILL_ILLOPN 2
|
||||||
#define SIGXFSZ 28
|
#define ILL_ILLADR 3
|
||||||
#define SIGWINCH 29
|
#define ILL_ILLTRP 4
|
||||||
#define SIGRTMIN 30
|
#define ILL_PRVOPC 5
|
||||||
#define SIGRTMAX (SIGRTMIN+32)
|
#define ILL_PRVREG 6
|
||||||
|
#define ILL_COPROC 7
|
||||||
|
#define ILL_BADSTK 8
|
||||||
|
#define SIGINT 9
|
||||||
|
#define SIGKILL 10
|
||||||
|
#define SIGPIPE 11
|
||||||
|
#define SIGQUIT 12
|
||||||
|
#define SIGSEGV 13
|
||||||
|
#define SEGV_MAPERR 1
|
||||||
|
#define SEGV_ACCERR 2
|
||||||
|
#define SIGSTOP 14
|
||||||
|
#define SIGTERM 15
|
||||||
|
#define SIGTSTP 16
|
||||||
|
#define SIGTTIN 17
|
||||||
|
#define SIGTTOU 18
|
||||||
|
#define SIGUSR1 19
|
||||||
|
#define SIGUSR2 20
|
||||||
|
#define SIGPOLL 21
|
||||||
|
#define POLL_IN 1
|
||||||
|
#define POLL_OUT 2
|
||||||
|
#define POLL_MSG 3
|
||||||
|
#define POLL_ERR 4
|
||||||
|
#define POLL_PRI 5
|
||||||
|
#define POLL_HUP 6
|
||||||
|
#define SIGPROF 22
|
||||||
|
#define SIGSYS 23
|
||||||
|
#define SIGTRAP 24
|
||||||
|
#define SIGURG 25
|
||||||
|
#define SIGVTALRM 26
|
||||||
|
#define SIGXCPU 27
|
||||||
|
#define SIGXFSZ 28
|
||||||
|
#define SIGWINCH 29
|
||||||
|
#define SIGRTMIN 30
|
||||||
|
#define SIGRTMAX (SIGRTMIN+32)
|
||||||
|
|
||||||
|
#define SI_USER 10
|
||||||
|
#define SI_QUEUE 11
|
||||||
|
#define SI_TIMER 12
|
||||||
|
#define SI_ASYNCIO 13
|
||||||
|
#define SI_MESGQ 14
|
||||||
|
|
||||||
#define _SIGMIN SIGABRT
|
#define _SIGMIN SIGABRT
|
||||||
#define _SIGMAX SIGRTMAX
|
#define _SIGMAX SIGRTMAX
|
||||||
|
|
||||||
#define SIG_BLOCK 1
|
#define SIG_BLOCK 1
|
||||||
#define SIG_UNBLOCK 2
|
#define SIG_UNBLOCK 2
|
||||||
#define SIG_SETMASK 3
|
#define SIG_SETMASK 3
|
||||||
|
|
||||||
#define SA_NOCLDSTOP 0x001
|
#define SA_NOCLDSTOP 0x001
|
||||||
#define SA_ONSTACK 0x002
|
#define SA_ONSTACK 0x002
|
||||||
#define SA_RESETHAND 0x004
|
#define SA_RESETHAND 0x004
|
||||||
#define SA_RESTART 0x008
|
#define SA_RESTART 0x008
|
||||||
#define SA_SIGINFO 0x010
|
#define SA_SIGINFO 0x010
|
||||||
#define SA_NOCLDWAIT 0x020
|
#define SA_NOCLDWAIT 0x020
|
||||||
#define SA_NODEFER 0x040
|
#define SA_NODEFER 0x040
|
||||||
#define SS_ONSTACK 0x080
|
#define SS_ONSTACK 0x080
|
||||||
#define SS_DISABLE 0x100
|
#define SS_DISABLE 0x100
|
||||||
#define MINSIGSTKSZ 0x200
|
#define MINSIGSTKSZ 0x200
|
||||||
#define SIGSTKSZ 0x400
|
#define SIGSTKSZ 0x400
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void** ss_sp; /* Stack base or pointer. */
|
void** ss_sp; /* Stack base or pointer. */
|
||||||
size_t ss_size; /* Stack size. */
|
size_t ss_size; /* Stack size. */
|
||||||
int ss_flags; /* Flags. */
|
int ss_flags; /* Flags. */
|
||||||
} stack_t;
|
} stack_t;
|
||||||
|
|
||||||
typedef struct {} mcontext_t;
|
enum
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
REG_RAX,
|
||||||
|
REG_RBX,
|
||||||
|
REG_RCX,
|
||||||
|
REG_RDX,
|
||||||
|
REG_RDI,
|
||||||
|
REG_RSI,
|
||||||
|
REG_RSP,
|
||||||
|
REG_RBP,
|
||||||
|
REG_RIP,
|
||||||
|
REG_R8,
|
||||||
|
REG_R9,
|
||||||
|
REG_R10,
|
||||||
|
REG_R11,
|
||||||
|
REG_R12,
|
||||||
|
REG_R13,
|
||||||
|
REG_R14,
|
||||||
|
REG_R15,
|
||||||
|
#elif defined(__i686__)
|
||||||
|
REG_EAX,
|
||||||
|
REG_EBX,
|
||||||
|
REG_ECX,
|
||||||
|
REG_EDX,
|
||||||
|
REG_EDI,
|
||||||
|
REG_ESI,
|
||||||
|
REG_ESP,
|
||||||
|
REG_EBP,
|
||||||
|
REG_EIP,
|
||||||
|
#else
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
__REG_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
long gregs[__REG_COUNT];
|
||||||
|
} mcontext_t;
|
||||||
|
|
||||||
typedef struct __ucontext_t
|
typedef struct __ucontext_t
|
||||||
{
|
{
|
||||||
struct __ucontext_t* uc_link; /* Pointer to the context that is resumed when this context returns. */
|
struct __ucontext_t* uc_link; /* Pointer to the context that is resumed when this context returns. */
|
||||||
sigset_t uc_sigmask; /* The set of signals that are blocked when this context is active. */
|
sigset_t uc_sigmask; /* The set of signals that are blocked when this context is active. */
|
||||||
stack_t uc_stack; /* The stack used by this context. */
|
stack_t uc_stack; /* The stack used by this context. */
|
||||||
mcontext_t uc_mcontext; /* A machine-specific representation of the saved context. */
|
mcontext_t uc_mcontext; /* A machine-specific representation of the saved context. */
|
||||||
} ucontext_t;
|
} ucontext_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int si_signo; /* Signal number. */
|
int si_signo; /* Signal number. */
|
||||||
int si_code; /* Signal code. */
|
int si_code; /* Signal code. */
|
||||||
int si_errno; /* If non-zero, an errno value associated with this signal, as described in <errno.h>. */
|
int si_errno; /* If non-zero, an errno value associated with this signal, as described in <errno.h>. */
|
||||||
pid_t si_pid; /* Sending process ID. */
|
pid_t si_pid; /* Sending process ID. */
|
||||||
uid_t si_uid; /* Real user ID of sending process. */
|
uid_t si_uid; /* Real user ID of sending process. */
|
||||||
void* si_addr; /* Address of faulting instruction. */
|
void* si_addr; /* Address of faulting instruction. */
|
||||||
int si_status; /* Exit value or signal. */
|
int si_status; /* Exit value or signal. */
|
||||||
long si_band; /* Band event for SIGPOLL. */
|
long si_band; /* Band event for SIGPOLL. */
|
||||||
union sigval si_value; /* Signal value. */
|
union sigval si_value; /* Signal value. */
|
||||||
} siginfo_t;
|
} siginfo_t;
|
||||||
|
|
||||||
struct sigaction
|
struct sigaction
|
||||||
{
|
{
|
||||||
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */
|
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */
|
||||||
sigset_t sa_mask; /* Set of signals to be blocked during execution of the signal handling function. */
|
sigset_t sa_mask; /* Set of signals to be blocked during execution of the signal handling function. */
|
||||||
int sa_flags; /* Special flags. */
|
int sa_flags; /* Special flags. */
|
||||||
void (*sa_sigaction)(int, siginfo_t*, void*); /* Pointer to a signal-catching function. */
|
void (*sa_sigaction)(int, siginfo_t*, void*); /* Pointer to a signal-catching function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: The <signal.h> header shall define the symbolic constants in the
|
|
||||||
// Code column of the following table for use as values of si_code
|
|
||||||
// that are signal-specific or non-signal-specific reasons why the
|
|
||||||
// signal was generated.
|
|
||||||
|
|
||||||
int kill(pid_t pid, int sig);
|
int kill(pid_t pid, int sig);
|
||||||
int killpg(pid_t pgpr, int sig);
|
int killpg(pid_t pgpr, int sig);
|
||||||
void psiginfo(const siginfo_t* pinfo, const char* message);
|
void psiginfo(const siginfo_t* pinfo, const char* message);
|
||||||
|
|
|
@ -149,15 +149,7 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#if !defined(__ssize_t_defined) && (defined(__need_all_types) || defined(__need_ssize_t))
|
#if !defined(__ssize_t_defined) && (defined(__need_all_types) || defined(__need_ssize_t))
|
||||||
#define __ssize_t_defined 1
|
#define __ssize_t_defined 1
|
||||||
#if __SIZEOF_SIZE_T__ == __SIZEOF_INT__
|
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||||
typedef int ssize_t;
|
|
||||||
#elif __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
|
|
||||||
typedef long ssize_t;
|
|
||||||
#elif __SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__
|
|
||||||
typedef long long ssize_t;
|
|
||||||
#else
|
|
||||||
#error "unsupported sizeof(size_t)"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#undef __need_ssize_t
|
#undef __need_ssize_t
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct malloc_pool_t
|
||||||
|
|
||||||
static malloc_pool_t s_malloc_pools[s_malloc_pool_count];
|
static malloc_pool_t s_malloc_pools[s_malloc_pool_count];
|
||||||
|
|
||||||
void init_malloc()
|
void _init_malloc()
|
||||||
{
|
{
|
||||||
size_t pool_size = s_malloc_pool_size_initial;
|
size_t pool_size = s_malloc_pool_size_initial;
|
||||||
for (size_t i = 0; i < s_malloc_pool_count; i++)
|
for (size_t i = 0; i < s_malloc_pool_count; i++)
|
||||||
|
|
|
@ -15,20 +15,20 @@
|
||||||
|
|
||||||
struct FILE
|
struct FILE
|
||||||
{
|
{
|
||||||
int fd { -1 };
|
int fd;
|
||||||
mode_t mode { 0 };
|
mode_t mode;
|
||||||
int buffer_type { _IOLBF };
|
int buffer_type;
|
||||||
bool eof { false };
|
bool eof;
|
||||||
bool error { false };
|
bool error;
|
||||||
|
|
||||||
int pid { -1 };
|
int pid;
|
||||||
|
|
||||||
int unget_char { EOF };
|
int unget_char;
|
||||||
|
|
||||||
unsigned char inline_buffer_storage[BUFSIZ] {};
|
unsigned char inline_buffer_storage[BUFSIZ];
|
||||||
unsigned char* buffer = inline_buffer_storage;
|
unsigned char* buffer;
|
||||||
uint32_t buffer_size = BUFSIZ;
|
uint32_t buffer_size;
|
||||||
uint32_t buffer_index { 0 };
|
uint32_t buffer_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScopeLock
|
struct ScopeLock
|
||||||
|
@ -47,18 +47,46 @@ struct ScopeLock
|
||||||
FILE* m_file;
|
FILE* m_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static FILE s_files[FOPEN_MAX] {
|
static FILE s_files[FOPEN_MAX];
|
||||||
{ .fd = STDIN_FILENO, .mode = O_RDONLY },
|
|
||||||
{ .fd = STDOUT_FILENO, .mode = O_WRONLY },
|
|
||||||
{ .fd = STDERR_FILENO, .mode = O_WRONLY, .buffer_type = _IONBF },
|
|
||||||
{ .fd = STDDBG_FILENO, .mode = O_WRONLY },
|
|
||||||
};
|
|
||||||
|
|
||||||
FILE* stdin = &s_files[0];
|
FILE* stdin = &s_files[0];
|
||||||
FILE* stdout = &s_files[1];
|
FILE* stdout = &s_files[1];
|
||||||
FILE* stderr = &s_files[2];
|
FILE* stderr = &s_files[2];
|
||||||
FILE* stddbg = &s_files[3];
|
FILE* stddbg = &s_files[3];
|
||||||
|
|
||||||
|
static void init_closed_file(FILE* file)
|
||||||
|
{
|
||||||
|
file->fd = -1;
|
||||||
|
file->mode = 0;
|
||||||
|
file->buffer_type = _IOLBF;
|
||||||
|
file->eof = false;
|
||||||
|
file->error = false;
|
||||||
|
file->pid = -1;
|
||||||
|
file->unget_char = EOF;
|
||||||
|
file->buffer = file->inline_buffer_storage;
|
||||||
|
file->buffer_size = BUFSIZ;
|
||||||
|
file->buffer_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _init_stdio()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < FOPEN_MAX; i++)
|
||||||
|
init_closed_file(&s_files[i]);
|
||||||
|
|
||||||
|
s_files[STDIN_FILENO].fd = STDIN_FILENO;
|
||||||
|
s_files[STDIN_FILENO].mode = O_RDONLY;
|
||||||
|
|
||||||
|
s_files[STDOUT_FILENO].fd = STDOUT_FILENO;
|
||||||
|
s_files[STDOUT_FILENO].mode = O_WRONLY;
|
||||||
|
|
||||||
|
s_files[STDERR_FILENO].fd = STDERR_FILENO;
|
||||||
|
s_files[STDERR_FILENO].mode = O_WRONLY;
|
||||||
|
s_files[STDERR_FILENO].buffer_type = _IONBF;
|
||||||
|
|
||||||
|
s_files[STDDBG_FILENO].fd = STDDBG_FILENO;
|
||||||
|
s_files[STDDBG_FILENO].mode = O_WRONLY;
|
||||||
|
}
|
||||||
|
|
||||||
void clearerr(FILE* file)
|
void clearerr(FILE* file)
|
||||||
{
|
{
|
||||||
ScopeLock _(file);
|
ScopeLock _(file);
|
||||||
|
@ -79,7 +107,7 @@ int fclose(FILE* file)
|
||||||
ScopeLock _(file);
|
ScopeLock _(file);
|
||||||
(void)fflush(file);
|
(void)fflush(file);
|
||||||
int ret = (close(file->fd) == -1) ? EOF : 0;
|
int ret = (close(file->fd) == -1) ? EOF : 0;
|
||||||
file = {};
|
init_closed_file(file);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
|
|
||||||
char** environ;
|
char** environ;
|
||||||
|
|
||||||
extern void init_malloc();
|
extern void _init_malloc();
|
||||||
|
extern void _init_stdio();
|
||||||
extern "C" void _init_libc(char** _environ)
|
extern "C" void _init_libc(char** _environ)
|
||||||
{
|
{
|
||||||
init_malloc();
|
_init_malloc();
|
||||||
|
_init_stdio();
|
||||||
|
|
||||||
if (!_environ)
|
if (!_environ)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,133 +1,254 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
#include <kernel/Memory/Heap.h>
|
||||||
|
#include <kernel/Random.h>
|
||||||
#include <LibELF/LoadableELF.h>
|
#include <LibELF/LoadableELF.h>
|
||||||
#include <LibELF/Values.h>
|
#include <LibELF/Values.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
namespace LibELF
|
namespace LibELF
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::load_from_inode(PageTable& page_table, BAN::RefPtr<Inode> inode)
|
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::load_from_inode(PageTable& page_table, const Credentials& credentials, BAN::RefPtr<Inode> inode)
|
||||||
{
|
{
|
||||||
auto* elf_ptr = new LoadableELF(page_table, inode);
|
auto elf = TRY(BAN::UniqPtr<LoadableELF>::create(page_table));
|
||||||
if (elf_ptr == nullptr)
|
TRY(elf->initialize(credentials, inode));
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return elf;
|
||||||
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
|
|
||||||
TRY(elf->initialize());
|
|
||||||
return BAN::move(elf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadableELF::LoadableELF(PageTable& page_table, BAN::RefPtr<Inode> inode)
|
LoadableELF::LoadableELF(PageTable& page_table)
|
||||||
: m_inode(inode)
|
: m_page_table(page_table)
|
||||||
, m_page_table(page_table)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadableELF::~LoadableELF()
|
LoadableELF::~LoadableELF()
|
||||||
{
|
{
|
||||||
if (!m_loaded)
|
const auto cleanup_program_headers =
|
||||||
return;
|
[&](BAN::Span<const ElfNativeProgramHeader> headers)
|
||||||
for (const auto& program_header : m_program_headers)
|
|
||||||
{
|
|
||||||
switch (program_header.p_type)
|
|
||||||
{
|
{
|
||||||
case PT_NULL:
|
for (const auto& header : headers)
|
||||||
continue;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
{
|
||||||
vaddr_t start = program_header.p_vaddr & PAGE_ADDR_MASK;
|
ASSERT(header.p_type == PT_LOAD);
|
||||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
|
||||||
|
const vaddr_t vaddr = header.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const size_t pages = range_page_count(header.p_vaddr, header.p_memsz);
|
||||||
for (size_t i = 0; i < pages; i++)
|
for (size_t i = 0; i < pages; i++)
|
||||||
{
|
if (paddr_t paddr = m_page_table.physical_address_of(vaddr + i * PAGE_SIZE))
|
||||||
paddr_t paddr = m_page_table.physical_address_of(start + i * PAGE_SIZE);
|
|
||||||
if (paddr != 0)
|
|
||||||
Heap::get().release_page(paddr);
|
Heap::get().release_page(paddr);
|
||||||
}
|
m_page_table.unmap_range(vaddr, pages * PAGE_SIZE);
|
||||||
m_page_table.unmap_range(start, pages * PAGE_SIZE);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
};
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
if (!m_is_loaded)
|
||||||
}
|
return;
|
||||||
|
cleanup_program_headers(m_executable.program_headers.span());
|
||||||
|
cleanup_program_headers(m_interpreter.program_headers.span());
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> LoadableELF::initialize()
|
static BAN::ErrorOr<ElfNativeFileHeader> read_and_validate_file_header(BAN::RefPtr<Inode> inode)
|
||||||
{
|
{
|
||||||
if ((size_t)m_inode->size() < sizeof(ElfNativeFileHeader))
|
if ((size_t)inode->size() < sizeof(ElfNativeFileHeader))
|
||||||
{
|
{
|
||||||
dprintln("Too small file");
|
dprintln("File is too small to be ELF");
|
||||||
return BAN::Error::from_errno(ENOEXEC);
|
return BAN::Error::from_errno(ENOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nread = TRY(m_inode->read(0, BAN::ByteSpan::from(m_file_header)));
|
ElfNativeFileHeader file_header;
|
||||||
ASSERT(nread == sizeof(m_file_header));
|
|
||||||
|
|
||||||
if (m_file_header.e_ident[EI_MAG0] != ELFMAG0 ||
|
size_t nread = TRY(inode->read(0, BAN::ByteSpan::from(file_header)));
|
||||||
m_file_header.e_ident[EI_MAG1] != ELFMAG1 ||
|
ASSERT(nread == sizeof(file_header));
|
||||||
m_file_header.e_ident[EI_MAG2] != ELFMAG2 ||
|
|
||||||
m_file_header.e_ident[EI_MAG3] != ELFMAG3)
|
if (file_header.e_ident[EI_MAG0] != ELFMAG0 ||
|
||||||
|
file_header.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||||
|
file_header.e_ident[EI_MAG2] != ELFMAG2 ||
|
||||||
|
file_header.e_ident[EI_MAG3] != ELFMAG3)
|
||||||
{
|
{
|
||||||
dprintln("Invalid magic in header");
|
dprintln("Not an ELF file");
|
||||||
return BAN::Error::from_errno(ENOEXEC);
|
return BAN::Error::from_errno(ENOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_file_header.e_ident[EI_DATA] != ELFDATA2LSB)
|
if (file_header.e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
{
|
{
|
||||||
dprintln("Only little-endian is supported");
|
dprintln("Not in little-endian");
|
||||||
return BAN::Error::from_errno(ENOEXEC);
|
return BAN::Error::from_errno(ENOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_file_header.e_ident[EI_VERSION] != EV_CURRENT)
|
if (file_header.e_ident[EI_VERSION] != EV_CURRENT)
|
||||||
{
|
{
|
||||||
dprintln("Invalid version");
|
dprintln("Unsupported version {}", file_header.e_ident[EI_VERSION]);
|
||||||
return BAN::Error::from_errno(ENOEXEC);
|
return BAN::Error::from_errno(ENOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARCH(i686)
|
#if ARCH(i686)
|
||||||
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS32)
|
if (file_header.e_ident[EI_CLASS] != ELFCLASS32)
|
||||||
#elif ARCH(x86_64)
|
#elif ARCH(x86_64)
|
||||||
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS64)
|
if (file_header.e_ident[EI_CLASS] != ELFCLASS64)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dprintln("Not in native format");
|
dprintln("Not in native format");
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_file_header.e_type != ET_EXEC)
|
if (file_header.e_type != ET_EXEC && file_header.e_type != ET_DYN)
|
||||||
{
|
{
|
||||||
dprintln("Only executable files are supported");
|
dprintln("Unsupported file header type {}", file_header.e_type);
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_header.e_version != EV_CURRENT)
|
||||||
|
{
|
||||||
|
dprintln("Unsupported version {}", file_header.e_version);
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_file_header.e_version != EV_CURRENT)
|
if (file_header.e_phentsize < sizeof(ElfNativeProgramHeader))
|
||||||
{
|
{
|
||||||
dprintln("Unsupported version");
|
dprintln("Too small program header size ({} bytes)", file_header.e_phentsize);
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(m_file_header.e_phentsize <= sizeof(ElfNativeProgramHeader));
|
return file_header;
|
||||||
|
}
|
||||||
|
|
||||||
TRY(m_program_headers.resize(m_file_header.e_phnum));
|
BAN::ErrorOr<LoadableELF::LoadResult> LoadableELF::load_elf_file(const Credentials& credentials, BAN::RefPtr<Inode> inode) const
|
||||||
for (size_t i = 0; i < m_file_header.e_phnum; i++)
|
{
|
||||||
|
auto file_header = TRY(read_and_validate_file_header(inode));
|
||||||
|
|
||||||
|
BAN::Vector<uint8_t> pheader_buffer;
|
||||||
|
TRY(pheader_buffer.resize(file_header.e_phnum * file_header.e_phentsize));
|
||||||
|
TRY(inode->read(file_header.e_phoff, BAN::ByteSpan(pheader_buffer.span())));
|
||||||
|
|
||||||
|
BAN::Vector<ElfNativeProgramHeader> program_headers;
|
||||||
|
BAN::RefPtr<Inode> interp;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < file_header.e_phnum; i++)
|
||||||
{
|
{
|
||||||
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, BAN::ByteSpan::from(m_program_headers[i])));
|
const auto& pheader = *reinterpret_cast<ElfNativeProgramHeader*>(pheader_buffer.data() + i * file_header.e_phentsize);
|
||||||
|
|
||||||
const auto& pheader = m_program_headers[i];
|
|
||||||
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
|
|
||||||
{
|
|
||||||
dprintln("Unsupported program header type {}", pheader.p_type);
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
}
|
|
||||||
if (pheader.p_memsz < pheader.p_filesz)
|
if (pheader.p_memsz < pheader.p_filesz)
|
||||||
{
|
{
|
||||||
dprintln("Invalid program header");
|
dprintln("Invalid program header, memsz less than filesz");
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
|
switch (pheader.p_type)
|
||||||
|
{
|
||||||
|
case PT_LOAD:
|
||||||
|
for (const auto& program_header : program_headers)
|
||||||
|
{
|
||||||
|
const vaddr_t a1 = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t b1 = pheader.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t a2 = (program_header.p_vaddr + program_header.p_memsz + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t b2 = (pheader.p_vaddr + pheader.p_memsz + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
|
if (a1 < b2 && b1 < a2)
|
||||||
|
{
|
||||||
|
dwarnln("Overlapping LOAD segments");
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRY(program_headers.push_back(pheader));
|
||||||
|
break;
|
||||||
|
case PT_INTERP:
|
||||||
|
{
|
||||||
|
BAN::Vector<uint8_t> buffer;
|
||||||
|
TRY(buffer.resize(pheader.p_memsz, 0));
|
||||||
|
TRY(inode->read(pheader.p_offset, BAN::ByteSpan(buffer.data(), pheader.p_filesz)));
|
||||||
|
|
||||||
|
BAN::StringView path(reinterpret_cast<const char*>(buffer.data()));
|
||||||
|
interp = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, path, O_EXEC)).inode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadResult {
|
||||||
|
.elf_file = {
|
||||||
|
.inode = inode,
|
||||||
|
.file_header = file_header,
|
||||||
|
.program_headers = BAN::move(program_headers),
|
||||||
|
.dynamic_base = 0
|
||||||
|
},
|
||||||
|
.interp = interp
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadableELF::does_executable_and_interpreter_overlap() const
|
||||||
|
{
|
||||||
|
ASSERT(m_executable.inode);
|
||||||
|
ASSERT(m_interpreter.inode);
|
||||||
|
|
||||||
|
for (const auto& epheader : m_executable.program_headers)
|
||||||
|
{
|
||||||
|
for (const auto& ipheader : m_interpreter.program_headers)
|
||||||
|
{
|
||||||
|
const vaddr_t e1 = epheader.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t i1 = ipheader.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t e2 = (epheader.p_vaddr + epheader.p_memsz + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
|
const vaddr_t i2 = (ipheader.p_vaddr + ipheader.p_memsz + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
|
if (e1 < i2 && i1 < e2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> LoadableELF::initialize(const Credentials& credentials, BAN::RefPtr<Inode> inode)
|
||||||
|
{
|
||||||
|
auto executable_load_result = TRY(load_elf_file(credentials, inode));
|
||||||
|
m_executable = executable_load_result.elf_file;
|
||||||
|
|
||||||
|
if (m_executable.file_header.e_type == ET_DYN)
|
||||||
|
{
|
||||||
|
m_executable.dynamic_base = (Random::get_u32() & 0x7FFFF000) + 0x100000;
|
||||||
|
m_executable.file_header.e_entry += m_executable.dynamic_base;
|
||||||
|
for (auto& program_header : m_executable.program_headers)
|
||||||
|
program_header.p_vaddr += m_executable.dynamic_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (executable_load_result.interp)
|
||||||
|
{
|
||||||
|
auto interp_load_result = TRY(load_elf_file(credentials, executable_load_result.interp));
|
||||||
|
m_interpreter = interp_load_result.elf_file;
|
||||||
|
|
||||||
|
if (interp_load_result.interp)
|
||||||
|
{
|
||||||
|
dwarnln("Executable has specified interpreter for its interpreter");
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_interpreter.file_header.e_type == ET_DYN)
|
||||||
|
{
|
||||||
|
for (int attempt = 0; attempt < 100; attempt++)
|
||||||
|
{
|
||||||
|
const vaddr_t dynamic_base = (Random::get_u32() & 0x3FFFF000) + 0x40000000;
|
||||||
|
for (auto& program_header : m_interpreter.program_headers)
|
||||||
|
program_header.p_vaddr += dynamic_base;
|
||||||
|
if (does_executable_and_interpreter_overlap())
|
||||||
|
{
|
||||||
|
for (auto& program_header : m_interpreter.program_headers)
|
||||||
|
program_header.p_vaddr -= dynamic_base;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_interpreter.dynamic_base = dynamic_base;
|
||||||
|
m_interpreter.file_header.e_entry += dynamic_base;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool can_load_interpreter = (m_interpreter.file_header.e_type == ET_DYN)
|
||||||
|
? (m_interpreter.dynamic_base != 0)
|
||||||
|
: !does_executable_and_interpreter_overlap();
|
||||||
|
|
||||||
|
if (!can_load_interpreter)
|
||||||
|
{
|
||||||
|
dwarnln("Could not find space to load interpreter");
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -135,91 +256,83 @@ namespace LibELF
|
||||||
|
|
||||||
vaddr_t LoadableELF::entry_point() const
|
vaddr_t LoadableELF::entry_point() const
|
||||||
{
|
{
|
||||||
return m_file_header.e_entry;
|
if (m_interpreter.inode)
|
||||||
|
return m_interpreter.file_header.e_entry;
|
||||||
|
return m_executable.file_header.e_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadableELF::contains(vaddr_t address) const
|
bool LoadableELF::contains(vaddr_t address) const
|
||||||
{
|
{
|
||||||
for (const auto& program_header : m_program_headers)
|
for (const auto& program_header : m_executable.program_headers)
|
||||||
{
|
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
|
||||||
switch (program_header.p_type)
|
return true;
|
||||||
{
|
for (const auto& program_header : m_interpreter.program_headers)
|
||||||
case PT_NULL:
|
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
|
||||||
continue;
|
return true;
|
||||||
case PT_LOAD:
|
|
||||||
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadableELF::is_address_space_free() const
|
bool LoadableELF::is_address_space_free() const
|
||||||
{
|
{
|
||||||
for (const auto& program_header : m_program_headers)
|
const auto are_program_headers_free =
|
||||||
{
|
[&](BAN::Span<const ElfNativeProgramHeader> program_headers) -> bool
|
||||||
switch (program_header.p_type)
|
|
||||||
{
|
{
|
||||||
case PT_NULL:
|
for (const auto& program_header : program_headers)
|
||||||
break;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
{
|
||||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
ASSERT(program_header.p_type == PT_LOAD);
|
||||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
const vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
const size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||||
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
|
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
return true;
|
||||||
ASSERT_NOT_REACHED();
|
};
|
||||||
}
|
if (!are_program_headers_free(m_executable.program_headers.span()))
|
||||||
}
|
return false;
|
||||||
|
if (!are_program_headers_free(m_interpreter.program_headers.span()))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadableELF::reserve_address_space()
|
void LoadableELF::reserve_address_space()
|
||||||
{
|
{
|
||||||
for (const auto& program_header : m_program_headers)
|
const auto reserve_program_headers =
|
||||||
{
|
[&](BAN::Span<const ElfNativeProgramHeader> program_headers)
|
||||||
switch (program_header.p_type)
|
|
||||||
{
|
{
|
||||||
case PT_NULL:
|
for (const auto& program_header : program_headers)
|
||||||
break;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
{
|
||||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
ASSERT(program_header.p_type == PT_LOAD);
|
||||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
const vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||||
ASSERT(m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE));
|
const size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||||
break;
|
if (!m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE))
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
m_virtual_page_count += pages;
|
||||||
}
|
}
|
||||||
default:
|
};
|
||||||
ASSERT_NOT_REACHED();
|
reserve_program_headers(m_executable.program_headers.span());
|
||||||
}
|
reserve_program_headers(m_interpreter.program_headers.span());
|
||||||
}
|
m_is_loaded = true;
|
||||||
m_loaded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadableELF::update_suid_sgid(Kernel::Credentials& credentials)
|
void LoadableELF::update_suid_sgid(Kernel::Credentials& credentials)
|
||||||
{
|
{
|
||||||
if (m_inode->mode().mode & +Inode::Mode::ISUID)
|
auto inode = m_executable.inode;
|
||||||
credentials.set_euid(m_inode->uid());
|
ASSERT(inode);
|
||||||
if (m_inode->mode().mode & +Inode::Mode::ISGID)
|
|
||||||
credentials.set_egid(m_inode->gid());
|
if (inode->mode().mode & +Inode::Mode::ISUID)
|
||||||
|
credentials.set_euid(inode->uid());
|
||||||
|
if (inode->mode().mode & +Inode::Mode::ISGID)
|
||||||
|
credentials.set_egid(inode->gid());
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
||||||
{
|
{
|
||||||
for (const auto& program_header : m_program_headers)
|
const auto load_page_from_program_header =
|
||||||
{
|
[&](BAN::RefPtr<Inode> inode, BAN::Span<const ElfNativeProgramHeader> program_headers) -> BAN::ErrorOr<bool>
|
||||||
switch (program_header.p_type)
|
|
||||||
{
|
{
|
||||||
case PT_NULL:
|
for (const auto& program_header : program_headers)
|
||||||
break;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
{
|
||||||
|
ASSERT(program_header.p_type == PT_LOAD);
|
||||||
if (!(program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz))
|
if (!(program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -229,8 +342,8 @@ namespace LibELF
|
||||||
if (program_header.p_flags & LibELF::PF_X)
|
if (program_header.p_flags & LibELF::PF_X)
|
||||||
flags |= PageTable::Flags::Execute;
|
flags |= PageTable::Flags::Execute;
|
||||||
|
|
||||||
vaddr_t vaddr = address & PAGE_ADDR_MASK;
|
const vaddr_t vaddr = address & PAGE_ADDR_MASK;
|
||||||
paddr_t paddr = Heap::get().take_free_page();
|
const paddr_t paddr = Heap::get().take_free_page();
|
||||||
if (paddr == 0)
|
if (paddr == 0)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
|
@ -251,44 +364,52 @@ namespace LibELF
|
||||||
file_offset = vaddr - program_header.p_vaddr;
|
file_offset = vaddr - program_header.p_vaddr;
|
||||||
|
|
||||||
size_t bytes = BAN::Math::min<size_t>(PAGE_SIZE - vaddr_offset, program_header.p_filesz - file_offset);
|
size_t bytes = BAN::Math::min<size_t>(PAGE_SIZE - vaddr_offset, program_header.p_filesz - file_offset);
|
||||||
TRY(m_inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
|
TRY(inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map page with the correct flags
|
// Map page with the correct flags
|
||||||
m_page_table.map_page_at(paddr, vaddr, flags);
|
m_page_table.map_page_at(paddr, vaddr, flags);
|
||||||
|
|
||||||
return {};
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
ASSERT_NOT_REACHED();
|
return false;
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
if (TRY(load_page_from_program_header(m_executable.inode, m_executable.program_headers.span())))
|
||||||
|
return {};
|
||||||
|
if (TRY(load_page_from_program_header(m_interpreter.inode, m_interpreter.program_headers.span())))
|
||||||
|
return {};
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::clone(Kernel::PageTable& new_page_table)
|
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::clone(Kernel::PageTable& new_page_table)
|
||||||
{
|
{
|
||||||
auto* elf_ptr = new LoadableELF(new_page_table, m_inode);
|
auto elf = TRY(BAN::UniqPtr<LoadableELF>::create(new_page_table));
|
||||||
if (elf_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
|
|
||||||
|
|
||||||
memcpy(&elf->m_file_header, &m_file_header, sizeof(ElfNativeFileHeader));
|
const auto clone_loadable_file =
|
||||||
|
[](const LoadableElfFile& source, LoadableElfFile& destination) -> BAN::ErrorOr<void>
|
||||||
TRY(elf->m_program_headers.resize(m_program_headers.size()));
|
|
||||||
memcpy(elf->m_program_headers.data(), m_program_headers.data(), m_program_headers.size() * sizeof(ElfNativeProgramHeader));
|
|
||||||
|
|
||||||
elf->reserve_address_space();
|
|
||||||
|
|
||||||
for (const auto& program_header : m_program_headers)
|
|
||||||
{
|
|
||||||
switch (program_header.p_type)
|
|
||||||
{
|
{
|
||||||
case PT_NULL:
|
if (!source.inode)
|
||||||
break;
|
return {};
|
||||||
case PT_LOAD:
|
|
||||||
|
destination.inode = source.inode;
|
||||||
|
destination.file_header = source.file_header;
|
||||||
|
destination.dynamic_base = source.dynamic_base;
|
||||||
|
|
||||||
|
TRY(destination.program_headers.reserve(source.program_headers.size()));
|
||||||
|
for (const auto& program_header : source.program_headers)
|
||||||
|
MUST(destination.program_headers.emplace_back(program_header));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto map_loadable_file =
|
||||||
|
[&](BAN::Span<const ElfNativeProgramHeader> program_headers) -> BAN::ErrorOr<void>
|
||||||
|
{
|
||||||
|
for (const auto& program_header : program_headers)
|
||||||
{
|
{
|
||||||
|
ASSERT(program_header.p_type == PT_LOAD);
|
||||||
if (!(program_header.p_flags & LibELF::PF_W))
|
if (!(program_header.p_flags & LibELF::PF_W))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -317,13 +438,17 @@ namespace LibELF
|
||||||
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
|
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
|
||||||
elf->m_physical_page_count++;
|
elf->m_physical_page_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
return {};
|
||||||
ASSERT_NOT_REACHED();
|
};
|
||||||
}
|
|
||||||
}
|
TRY(clone_loadable_file(m_executable, elf->m_executable));
|
||||||
|
TRY(clone_loadable_file(m_interpreter, elf->m_interpreter));
|
||||||
|
|
||||||
|
elf->reserve_address_space();
|
||||||
|
|
||||||
|
TRY(map_loadable_file(elf->m_executable.program_headers.span()));
|
||||||
|
TRY(map_loadable_file(elf->m_interpreter.program_headers.span()));
|
||||||
|
|
||||||
return elf;
|
return elf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,14 @@ namespace LibELF
|
||||||
BAN_NON_MOVABLE(LoadableELF);
|
BAN_NON_MOVABLE(LoadableELF);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> load_from_inode(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
static BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> load_from_inode(Kernel::PageTable&, const Kernel::Credentials&, BAN::RefPtr<Kernel::Inode>);
|
||||||
~LoadableELF();
|
~LoadableELF();
|
||||||
|
|
||||||
Kernel::vaddr_t entry_point() const;
|
Kernel::vaddr_t entry_point() const;
|
||||||
|
|
||||||
|
bool has_interpreter() const { return !!m_interpreter.inode; }
|
||||||
|
BAN::RefPtr<Kernel::Inode> inode() { return m_executable.inode; }
|
||||||
|
|
||||||
bool contains(Kernel::vaddr_t address) const;
|
bool contains(Kernel::vaddr_t address) const;
|
||||||
bool is_address_space_free() const;
|
bool is_address_space_free() const;
|
||||||
void reserve_address_space();
|
void reserve_address_space();
|
||||||
|
@ -41,17 +44,36 @@ namespace LibELF
|
||||||
size_t physical_page_count() const { return m_physical_page_count; }
|
size_t physical_page_count() const { return m_physical_page_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
struct LoadableElfFile
|
||||||
BAN::ErrorOr<void> initialize();
|
{
|
||||||
|
BAN::RefPtr<Kernel::Inode> inode;
|
||||||
|
ElfNativeFileHeader file_header;
|
||||||
|
BAN::Vector<ElfNativeProgramHeader> program_headers;
|
||||||
|
Kernel::vaddr_t dynamic_base;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoadResult
|
||||||
|
{
|
||||||
|
LoadableElfFile elf_file;
|
||||||
|
BAN::RefPtr<Kernel::Inode> interp;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<Kernel::Inode> m_inode;
|
LoadableELF(Kernel::PageTable&);
|
||||||
Kernel::PageTable& m_page_table;
|
BAN::ErrorOr<void> initialize(const Kernel::Credentials&, BAN::RefPtr<Kernel::Inode>);
|
||||||
ElfNativeFileHeader m_file_header;
|
|
||||||
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
bool does_executable_and_interpreter_overlap() const;
|
||||||
size_t m_virtual_page_count = 0;
|
BAN::ErrorOr<LoadResult> load_elf_file(const Kernel::Credentials&, BAN::RefPtr<Kernel::Inode>) const;
|
||||||
size_t m_physical_page_count = 0;
|
|
||||||
bool m_loaded { false };
|
private:
|
||||||
|
LoadableElfFile m_executable;
|
||||||
|
LoadableElfFile m_interpreter;
|
||||||
|
Kernel::PageTable& m_page_table;
|
||||||
|
size_t m_virtual_page_count { 0 };
|
||||||
|
size_t m_physical_page_count { 0 };
|
||||||
|
bool m_is_loaded { false };
|
||||||
|
|
||||||
|
friend class BAN::UniqPtr<LoadableELF>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,16 @@ namespace LibELF
|
||||||
Elf32Word p_align;
|
Elf32Word p_align;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Elf32Dynamic
|
||||||
|
{
|
||||||
|
Elf32Sword d_tag;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Elf32Word d_val;
|
||||||
|
Elf32Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
using Elf64Addr = uint64_t;
|
using Elf64Addr = uint64_t;
|
||||||
using Elf64Off = uint64_t;
|
using Elf64Off = uint64_t;
|
||||||
using Elf64Half = uint16_t;
|
using Elf64Half = uint16_t;
|
||||||
|
@ -155,6 +165,16 @@ namespace LibELF
|
||||||
Elf64Xword p_align;
|
Elf64Xword p_align;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Elf64Dynamic
|
||||||
|
{
|
||||||
|
Elf64Sxword d_tag;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Elf64Xword d_val;
|
||||||
|
Elf64Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
#if ARCH(i686)
|
#if ARCH(i686)
|
||||||
using ElfNativeAddr = Elf32Addr;
|
using ElfNativeAddr = Elf32Addr;
|
||||||
using ElfNativeOff = Elf32Off;
|
using ElfNativeOff = Elf32Off;
|
||||||
|
@ -167,6 +187,7 @@ namespace LibELF
|
||||||
using ElfNativeRelocation = Elf32Relocation;
|
using ElfNativeRelocation = Elf32Relocation;
|
||||||
using ElfNativeRelocationA = Elf32RelocationA;
|
using ElfNativeRelocationA = Elf32RelocationA;
|
||||||
using ElfNativeProgramHeader = Elf32ProgramHeader;
|
using ElfNativeProgramHeader = Elf32ProgramHeader;
|
||||||
|
using ElfNativeDynamic = Elf32Dynamic;
|
||||||
#elif ARCH(x86_64)
|
#elif ARCH(x86_64)
|
||||||
using ElfNativeAddr = Elf64Addr;
|
using ElfNativeAddr = Elf64Addr;
|
||||||
using ElfNativeOff = Elf64Off;
|
using ElfNativeOff = Elf64Off;
|
||||||
|
@ -181,6 +202,7 @@ namespace LibELF
|
||||||
using ElfNativeRelocation = Elf64Relocation;
|
using ElfNativeRelocation = Elf64Relocation;
|
||||||
using ElfNativeRelocationA = Elf64RelocationA;
|
using ElfNativeRelocationA = Elf64RelocationA;
|
||||||
using ElfNativeProgramHeader = Elf64ProgramHeader;
|
using ElfNativeProgramHeader = Elf64ProgramHeader;
|
||||||
|
using ElfNativeDynamic = Elf64Dynamic;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ set(USERSPACE_TESTS
|
||||||
test-mouse
|
test-mouse
|
||||||
test-popen
|
test-popen
|
||||||
test-setjmp
|
test-setjmp
|
||||||
|
test-shared
|
||||||
test-sort
|
test-sort
|
||||||
test-tcp
|
test-tcp
|
||||||
test-udp
|
test-udp
|
||||||
|
|
|
@ -10,5 +10,5 @@ foo_t foo;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
printf("main\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(test-shared ${SOURCES})
|
||||||
|
banan_link_library(test-shared libc-shared)
|
||||||
|
|
||||||
|
install(TARGETS test-shared OPTIONAL)
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("printf works!\n");
|
||||||
|
}
|
Loading…
Reference in New Issue