Compare commits

...

8 Commits

Author SHA1 Message Date
Bananymous 2a16a67aed Kernel: Ignore SA_RESTART flag on sigaction
This is a big hack but a lot of ports set this flag. This seems really
annoying to implement properly
2025-01-24 19:34:22 +02:00
Bananymous c6cd185cb5 DynamicLoader: Fix copy relocations
Weak symbols are now actually resolved to the same strong symbol between
shared objects and copy relocations now work!
2025-01-24 19:23:33 +02:00
Bananymous 58cdcf754c ports: Update curl port
This patch updates curl to version 8.11.1 and adds support for dynamic
libraries
2025-01-24 19:23:33 +02:00
Bananymous d969f5df7b ports: Add zstd port 2025-01-24 19:23:33 +02:00
Bananymous b6455e0661 LibC: Implement stub for clock 2025-01-24 19:23:33 +02:00
Bananymous 15021b442c LibC: Fix memchr and memcmp assembly implementations
These functions did not work with size 0 :D
2025-01-23 21:55:26 +02:00
Bananymous ee078fc638 Kernel: Fix fd status/descriptor flag handling
I was not sharing status and offset on fork and I was sharing descriptor
flags on dup/dup2
2025-01-17 20:12:04 +02:00
Bananymous 9893c90e74 Kernel: Remove SYS_DUP and implement it using fcntl F_DUPFD 2025-01-17 19:29:47 +02:00
14 changed files with 310 additions and 217 deletions

View File

@ -29,7 +29,6 @@ namespace Kernel
BAN::ErrorOr<void> pipe(int fds[2]);
BAN::ErrorOr<int> dup(int);
BAN::ErrorOr<int> dup2(int, int);
BAN::ErrorOr<int> fcntl(int fd, int cmd, int extra);
@ -51,27 +50,45 @@ namespace Kernel
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
BAN::ErrorOr<BAN::StringView> path_of(int) const;
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
BAN::ErrorOr<int> flags_of(int) const;
BAN::ErrorOr<int> status_flags_of(int) const;
private:
struct OpenFileDescription : public BAN::RefCounted<OpenFileDescription>
{
OpenFileDescription(VirtualFileSystem::File file, off_t offset, int flags)
OpenFileDescription(VirtualFileSystem::File file, off_t offset, int status_flags)
: file(BAN::move(file))
, offset(offset)
, flags(flags)
, status_flags(status_flags)
{ }
BAN::RefPtr<Inode> inode() const { return file.inode; }
BAN::StringView path() const { return file.canonical_path.sv(); }
VirtualFileSystem::File file;
off_t offset { 0 };
int flags { 0 };
int status_flags;
friend class BAN::RefPtr<OpenFileDescription>;
};
struct OpenFile
{
OpenFile() = default;
OpenFile(BAN::RefPtr<OpenFileDescription> description, int descriptor_flags)
: description(BAN::move(description))
, descriptor_flags(descriptor_flags)
{ }
BAN::RefPtr<Inode> inode() const { ASSERT(description); return description->file.inode; }
BAN::StringView path() const { ASSERT(description); return description->file.canonical_path.sv(); }
int& status_flags() { ASSERT(description); return description->status_flags; }
const int& status_flags() const { ASSERT(description); return description->status_flags; }
off_t& offset() { ASSERT(description); return description->offset; }
const off_t& offset() const { ASSERT(description); return description->offset; }
BAN::RefPtr<OpenFileDescription> description;
int descriptor_flags { 0 };
};
BAN::ErrorOr<void> validate_fd(int) const;
BAN::ErrorOr<int> get_free_fd() const;
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]) const;
@ -79,7 +96,7 @@ namespace Kernel
private:
const Credentials& m_credentials;
BAN::Array<BAN::RefPtr<OpenFileDescription>, OPEN_MAX> m_open_files;
BAN::Array<OpenFile, OPEN_MAX> m_open_files;
};
}

View File

@ -138,7 +138,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_pselect(sys_pselect_t* arguments);
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
BAN::ErrorOr<long> sys_dup(int fildes);
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
BAN::ErrorOr<long> sys_fcntl(int fildes, int cmd, int extra);

View File

@ -36,26 +36,14 @@ namespace Kernel
if (other.validate_fd(fd).is_error())
continue;
auto& open_file = other.m_open_files[fd];
auto& open_file = m_open_files[fd];
open_file.description = other.m_open_files[fd].description;
open_file.descriptor_flags = other.m_open_files[fd].descriptor_flags;
VirtualFileSystem::File temp_file;
temp_file.inode = open_file->inode();
TRY(temp_file.canonical_path.append(open_file->path()));
auto result = BAN::RefPtr<OpenFileDescription>::create(BAN::move(temp_file), open_file->offset, open_file->flags);
if (result.is_error())
if (open_file.path() == "<pipe wr>"_sv)
{
close_all();
return result.error();
}
m_open_files[fd] = result.release_value();
if (m_open_files[fd]->path() == "<pipe wr>"_sv)
{
ASSERT(m_open_files[fd]->inode()->is_pipe());
static_cast<Pipe*>(m_open_files[fd]->inode().ptr())->clone_writing();
ASSERT(open_file.inode()->is_pipe());
static_cast<Pipe*>(open_file.inode().ptr())->clone_writing();
}
}
@ -78,8 +66,10 @@ namespace Kernel
if ((flags & O_TRUNC) && (flags & O_WRONLY) && file.inode->mode().ifreg())
TRY(file.inode->truncate(0));
constexpr int status_mask = O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE;
int fd = TRY(get_free_fd());
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(BAN::move(file), 0, flags));
m_open_files[fd].description = TRY(BAN::RefPtr<OpenFileDescription>::create(BAN::move(file), 0, flags & status_mask));
m_open_files[fd].descriptor_flags = flags & O_CLOEXEC;
return fd;
}
@ -110,11 +100,12 @@ namespace Kernel
return BAN::Error::from_errno(EPROTOTYPE);
}
int extra_flags = 0;
int status_flags = 0;
int descriptor_flags = 0;
if (type & SOCK_NONBLOCK)
extra_flags |= O_NONBLOCK;
status_flags |= O_NONBLOCK;
if (type & SOCK_CLOEXEC)
extra_flags |= O_CLOEXEC;
descriptor_flags |= O_CLOEXEC;
type &= ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
Socket::Type sock_type;
@ -144,7 +135,8 @@ namespace Kernel
auto socket = TRY(NetworkManager::get().create_socket(sock_domain, sock_type, 0777, m_credentials.euid(), m_credentials.egid()));
int fd = TRY(get_free_fd());
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(socket, "<socket>"_sv), 0, O_RDWR | extra_flags));
m_open_files[fd].description = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(socket, "<socket>"_sv), 0, O_RDWR | status_flags));
m_open_files[fd].descriptor_flags = descriptor_flags;
return fd;
}
@ -153,28 +145,14 @@ namespace Kernel
TRY(get_free_fd_pair(fds));
auto pipe = TRY(Pipe::create(m_credentials));
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe rd>"_sv), 0, O_RDONLY));
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe wr>"_sv), 0, O_WRONLY));
m_open_files[fds[0]].description = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe rd>"_sv), 0, O_RDONLY));
m_open_files[fds[0]].descriptor_flags = 0;
m_open_files[fds[1]].description = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe wr>"_sv), 0, O_WRONLY));
m_open_files[fds[1]].descriptor_flags = 0;
return {};
}
BAN::ErrorOr<int> OpenFileDescriptorSet::dup(int fildes)
{
TRY(validate_fd(fildes));
int result = TRY(get_free_fd());
m_open_files[result] = m_open_files[fildes];
if (m_open_files[result]->path() == "<pipe wr>"_sv)
{
ASSERT(m_open_files[result]->inode()->is_pipe());
static_cast<Pipe*>(m_open_files[result]->inode().ptr())->clone_writing();
}
return result;
}
BAN::ErrorOr<int> OpenFileDescriptorSet::dup2(int fildes, int fildes2)
{
if (fildes2 < 0 || fildes2 >= (int)m_open_files.size())
@ -186,13 +164,13 @@ namespace Kernel
(void)close(fildes2);
m_open_files[fildes2] = m_open_files[fildes];
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
m_open_files[fildes2].description = m_open_files[fildes].description;
m_open_files[fildes2].descriptor_flags = 0;
if (m_open_files[fildes2]->path() == "<pipe wr>"_sv)
if (m_open_files[fildes2].path() == "<pipe wr>"_sv)
{
ASSERT(m_open_files[fildes2]->inode()->is_pipe());
static_cast<Pipe*>(m_open_files[fildes2]->inode().ptr())->clone_writing();
ASSERT(m_open_files[fildes2].inode()->is_pipe());
static_cast<Pipe*>(m_open_files[fildes2].inode().ptr())->clone_writing();
}
return fildes;
@ -204,22 +182,41 @@ namespace Kernel
switch (cmd)
{
case F_DUPFD:
case F_DUPFD_CLOEXEC:
{
const int new_fd = TRY(get_free_fd());
m_open_files[new_fd].description = m_open_files[fd].description;
m_open_files[new_fd].descriptor_flags = (cmd == F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
if (m_open_files[new_fd].path() == "<pipe wr>"_sv)
{
ASSERT(m_open_files[new_fd].inode()->is_pipe());
static_cast<Pipe*>(m_open_files[new_fd].inode().ptr())->clone_writing();
}
return new_fd;
}
case F_GETFD:
return m_open_files[fd]->flags & FD_CLOEXEC;
return m_open_files[fd].descriptor_flags;
case F_SETFD:
m_open_files[fd]->flags &= ~FD_CLOEXEC;
m_open_files[fd]->flags |= extra & FD_CLOEXEC;
if (extra & FD_CLOEXEC)
m_open_files[fd].descriptor_flags |= O_CLOEXEC;
else
m_open_files[fd].descriptor_flags &= ~O_CLOEXEC;
return 0;
case F_GETFL:
return m_open_files[fd]->flags & ~(O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE);
return m_open_files[fd].status_flags();
case F_SETFL:
m_open_files[fd]->flags &= ~O_NONBLOCK;
m_open_files[fd]->flags |= extra & O_NONBLOCK;
extra &= O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC;
m_open_files[fd].status_flags() &= ~O_ACCMODE;
m_open_files[fd].status_flags() |= extra;
return 0;
default:
break;
}
dwarnln("TODO: fcntl command {}", cmd);
return BAN::Error::from_errno(ENOTSUP);
}
@ -234,10 +231,10 @@ namespace Kernel
base_offset = 0;
break;
case SEEK_CUR:
base_offset = m_open_files[fd]->offset;
base_offset = m_open_files[fd].offset();
break;
case SEEK_END:
base_offset = m_open_files[fd]->inode()->size();
base_offset = m_open_files[fd].inode()->size();
break;
default:
return BAN::Error::from_errno(EINVAL);
@ -247,7 +244,7 @@ namespace Kernel
if (new_offset < 0)
return BAN::Error::from_errno(EINVAL);
m_open_files[fd]->offset = new_offset;
m_open_files[fd].offset() = new_offset;
return new_offset;
}
@ -255,26 +252,27 @@ namespace Kernel
BAN::ErrorOr<off_t> OpenFileDescriptorSet::tell(int fd) const
{
TRY(validate_fd(fd));
return m_open_files[fd]->offset;
return m_open_files[fd].offset();
}
BAN::ErrorOr<void> OpenFileDescriptorSet::truncate(int fd, off_t length)
{
TRY(validate_fd(fd));
return m_open_files[fd]->inode()->truncate(length);
return m_open_files[fd].inode()->truncate(length);
}
BAN::ErrorOr<void> OpenFileDescriptorSet::close(int fd)
{
TRY(validate_fd(fd));
if (m_open_files[fd]->path() == "<pipe wr>"_sv)
if (m_open_files[fd].path() == "<pipe wr>"_sv)
{
ASSERT(m_open_files[fd]->inode()->is_pipe());
static_cast<Pipe*>(m_open_files[fd]->inode().ptr())->close_writing();
ASSERT(m_open_files[fd].inode()->is_pipe());
static_cast<Pipe*>(m_open_files[fd].inode().ptr())->close_writing();
}
m_open_files[fd].clear();
m_open_files[fd].description.clear();
m_open_files[fd].descriptor_flags = 0;
return {};
}
@ -291,7 +289,7 @@ namespace Kernel
{
if (validate_fd(fd).is_error())
continue;
if (m_open_files[fd]->flags & O_CLOEXEC)
if (m_open_files[fd].descriptor_flags & O_CLOEXEC)
(void)close(fd);
}
}
@ -300,12 +298,12 @@ namespace Kernel
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if (!(open_file->flags & O_RDONLY))
if (!(open_file.status_flags() & O_RDONLY))
return BAN::Error::from_errno(EBADF);
if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_read())
if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_read())
return 0;
size_t nread = TRY(open_file->inode()->read(open_file->offset, buffer));
open_file->offset += nread;
size_t nread = TRY(open_file.inode()->read(open_file.offset(), buffer));
open_file.offset() += nread;
return nread;
}
@ -313,14 +311,14 @@ namespace Kernel
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if (!(open_file->flags & O_WRONLY))
if (!(open_file.status_flags() & O_WRONLY))
return BAN::Error::from_errno(EBADF);
if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_write())
if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_write())
return 0;
if (open_file->flags & O_APPEND)
open_file->offset = open_file->inode()->size();
size_t nwrite = TRY(open_file->inode()->write(open_file->offset, buffer));
open_file->offset += nwrite;
if (open_file.status_flags() & O_APPEND)
open_file.offset() = open_file.inode()->size();
size_t nwrite = TRY(open_file.inode()->write(open_file.offset(), buffer));
open_file.offset() += nwrite;
return nwrite;
}
@ -328,11 +326,11 @@ namespace Kernel
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if (!(open_file->flags & O_RDONLY))
if (!(open_file.status_flags() & O_RDONLY))
return BAN::Error::from_errno(EACCES);
for (;;)
{
auto ret = open_file->inode()->list_next_inodes(open_file->offset++, list, list_len);
auto ret = open_file.inode()->list_next_inodes(open_file.offset()++, list, list_len);
if (ret.is_error() && ret.error().get_error_code() == ENODATA)
continue;
return ret;
@ -342,32 +340,32 @@ namespace Kernel
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
{
TRY(validate_fd(fd));
return TRY(m_open_files[fd]->file.clone());
return TRY(m_open_files[fd].description->file.clone());
}
BAN::ErrorOr<BAN::StringView> OpenFileDescriptorSet::path_of(int fd) const
{
TRY(validate_fd(fd));
return m_open_files[fd]->path();
return m_open_files[fd].path();
}
BAN::ErrorOr<BAN::RefPtr<Inode>> OpenFileDescriptorSet::inode_of(int fd)
{
TRY(validate_fd(fd));
return m_open_files[fd]->inode();
return m_open_files[fd].inode();
}
BAN::ErrorOr<int> OpenFileDescriptorSet::flags_of(int fd) const
BAN::ErrorOr<int> OpenFileDescriptorSet::status_flags_of(int fd) const
{
TRY(validate_fd(fd));
return m_open_files[fd]->flags;
return m_open_files[fd].status_flags();
}
BAN::ErrorOr<void> OpenFileDescriptorSet::validate_fd(int fd) const
{
if (fd < 0 || fd >= (int)m_open_files.size())
return BAN::Error::from_errno(EBADF);
if (!m_open_files[fd])
if (!m_open_files[fd].description)
return BAN::Error::from_errno(EBADF);
return {};
}
@ -375,7 +373,7 @@ namespace Kernel
BAN::ErrorOr<int> OpenFileDescriptorSet::get_free_fd() const
{
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
if (!m_open_files[fd])
if (!m_open_files[fd].description)
return fd;
return BAN::Error::from_errno(EMFILE);
}
@ -385,7 +383,7 @@ namespace Kernel
size_t found = 0;
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
{
if (!m_open_files[fd])
if (!m_open_files[fd].description)
fds[found++] = fd;
if (found == 2)
return {};

View File

@ -441,8 +441,8 @@ namespace Kernel
if (fd == AT_FDCWD)
return TRY(m_working_directory.clone());
int flags = TRY(m_open_file_descriptors.flags_of(fd));
if (!(flags & O_RDONLY) && !(flags & O_SEARCH))
const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(fd));
if (!(status_flags & O_RDONLY) && !(status_flags & O_SEARCH))
return BAN::Error::from_errno(EBADF);
return TRY(m_open_file_descriptors.file_of(fd));
@ -514,8 +514,8 @@ namespace Kernel
auto working_directory = TRY(m_working_directory.clone());
OpenFileDescriptorSet open_file_descriptors(m_credentials);
TRY(open_file_descriptors.clone_from(m_open_file_descriptors));
auto open_file_descriptors = TRY(BAN::UniqPtr<OpenFileDescriptorSet>::create(m_credentials));
TRY(open_file_descriptors->clone_from(m_open_file_descriptors));
BAN::Vector<BAN::UniqPtr<MemoryRegion>> mapped_regions;
TRY(mapped_regions.reserve(m_mapped_regions.size()));
@ -526,7 +526,7 @@ namespace Kernel
forked->m_controlling_terminal = m_controlling_terminal;
forked->m_working_directory = BAN::move(working_directory);
forked->m_page_table = BAN::move(page_table);
forked->m_open_file_descriptors = BAN::move(open_file_descriptors);
forked->m_open_file_descriptors = BAN::move(*open_file_descriptors);
forked->m_mapped_regions = BAN::move(mapped_regions);
forked->m_is_userspace = m_is_userspace;
forked->m_userspace_info = m_userspace_info;
@ -1320,8 +1320,8 @@ namespace Kernel
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
auto flags = TRY(m_open_file_descriptors.flags_of(arguments->socket));
if ((flags & O_NONBLOCK) && !inode->can_write())
const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket));
if ((status_flags & O_NONBLOCK) && !inode->can_write())
return BAN::Error::from_errno(EAGAIN);
BAN::ConstByteSpan message { reinterpret_cast<const uint8_t*>(arguments->message), arguments->length };
@ -1348,8 +1348,8 @@ namespace Kernel
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
auto flags = TRY(m_open_file_descriptors.flags_of(arguments->socket));
if ((flags & O_NONBLOCK) && !inode->can_read())
const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket));
if ((status_flags & O_NONBLOCK) && !inode->can_read())
return BAN::Error::from_errno(EAGAIN);
BAN::ByteSpan buffer { reinterpret_cast<uint8_t*>(arguments->buffer), arguments->length };
@ -1462,12 +1462,6 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_dup(int fildes)
{
LockGuard _(m_process_lock);
return TRY(m_open_file_descriptors.dup(fildes));
}
BAN::ErrorOr<long> Process::sys_dup2(int fildes, int fildes2)
{
LockGuard _(m_process_lock);
@ -1703,11 +1697,11 @@ namespace Kernel
auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes));
auto inode_flags = TRY(m_open_file_descriptors.flags_of(args->fildes));
if (!(inode_flags & O_RDONLY))
const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(args->fildes));
if (!(status_flags & O_RDONLY))
return BAN::Error::from_errno(EACCES);
if (region_type == MemoryRegion::Type::SHARED)
if ((args->prot & PROT_WRITE) && !(inode_flags & O_WRONLY))
if ((args->prot & PROT_WRITE) && !(status_flags & O_WRONLY))
return BAN::Error::from_errno(EACCES);
BAN::UniqPtr<MemoryRegion> memory_region;
@ -2019,8 +2013,13 @@ namespace Kernel
if (act)
{
if (act->sa_flags)
if (act->sa_flags == SA_RESTART)
dwarnln("FIXME: sigaction ignoring SA_RESTART", signal, act->sa_flags);
else if (act->sa_flags)
{
dwarnln("TODO: sigaction({}, {H})", signal, act->sa_flags);
return BAN::Error::from_errno(ENOTSUP);
}
m_signal_handlers[signal] = *act;
}

View File

@ -1,21 +1,26 @@
#!/bin/bash ../install.sh
NAME='curl'
VERSION='8.8.0'
DOWNLOAD_URL="https://curl.se/download/curl-$VERSION.tar.gz#77c0e1cd35ab5b45b659645a93b46d660224d0024f1185e8a95cdb27ae3d787d"
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib')
VERSION='8.11.1'
DOWNLOAD_URL="https://curl.se/download/curl-$VERSION.tar.gz#a889ac9dbba3644271bd9d1302b5c22a088893719b72be3487bc3d401e5c4e80"
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIGURE_OPTIONS=(
'--disable-threaded-resolver'
'--disable-ipv6'
'--disable-docs'
'--disable-ntlm'
'--enable-optimize'
'--with-openssl'
'--with-zlib'
'--with-zstd'
'--without-libpsl'
'--with-ca-bundle=/etc/ssl/certs/ca-certificates.crt'
'--without-ca-path'
)
install() {
make install DESTDIR="$BANAN_SYSROOT" || exit 1
# remove libtool file
rm -f $BANAN_SYSROOT/usr/lib/libcurl.la
}

View File

@ -0,0 +1,20 @@
diff -ruN curl-8.11.1/configure curl-8.11.1-banan_os/configure
--- curl-8.11.1/configure 2024-12-11 09:08:12.000000000 +0200
+++ curl-8.11.1-banan_os/configure 2025-01-22 18:29:34.167111729 +0200
@@ -15537,6 +15537,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

17
ports/zstd/build.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash ../install.sh
NAME='zstd'
VERSION='1.5.6'
DOWNLOAD_URL="https://github.com/facebook/zstd/releases/download/v$VERSION/zstd-$VERSION.tar.gz#8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1"
configure() {
:
}
build() {
make -C lib -j$(nproc) lib-nomt || exit 1
}
install() {
make -C lib install "DESTDIR=$BANAN_SYSROOT" PREFIX=/usr || exit 1
}

View File

@ -3,10 +3,11 @@ memchr:
xchgl 4(%esp), %edi
movl 8(%esp), %eax
movl 12(%esp), %ecx
movl $1, %edx
cmpl $1, %ecx # clear ZF if count is zero
repne scasb
xorl %eax, %eax
testl %ecx, %ecx
cmovnzl %edi, %eax
cmovel %edi, %edx
leal -1(%edx), %eax
movl 4(%esp), %edi
ret
@ -15,6 +16,7 @@ memcmp:
xchgl 4(%esp), %edi
xchgl 8(%esp), %esi
movl 12(%esp), %ecx
testl %ecx, %ecx # set ZF if count is zero
repe cmpsb
jne .memcmp_not_equal
xorl %eax, %eax

View File

@ -2,15 +2,17 @@
memchr:
movb %sil, %al
movq %rdx, %rcx
movq $1, %rdx
cmpq $1, %rcx # clear ZF if count is zero
repne scasb
xorq %rax, %rax
testq %rcx, %rcx
cmovnzq %rdi, %rax
cmoveq %rdi, %rdx
leaq -1(%rdx), %rax
ret
.global memcmp
memcmp:
movq %rdx, %rcx
testq %rcx, %rcx # set ZF if count is zero
repe cmpsb
jne .memcmp_not_equal
xorq %rax, %rax

View File

@ -36,7 +36,6 @@ __BEGIN_DECLS
O(SYS_SET_PWD, setpwd) \
O(SYS_CLOCK_GETTIME, clock_gettime) \
O(SYS_PIPE, pipe) \
O(SYS_DUP, dup) \
O(SYS_DUP2, dup2) \
O(SYS_KILL, kill) \
O(SYS_TCGETPGRP, tcgetpgrp) \

View File

@ -18,6 +18,12 @@ int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
return syscall(SYS_NANOSLEEP, rqtp, rmtp);
}
clock_t clock(void)
{
dwarnln("TODO: clock");
return -1;
}
time_t time(time_t* tloc)
{
timespec tp;

View File

@ -125,7 +125,7 @@ int fsync(int fildes)
int dup(int fildes)
{
return syscall(SYS_DUP, fildes);
return fcntl(fildes, F_DUPFD, 0);
}
int dup2(int fildes, int fildes2)

View File

@ -125,6 +125,9 @@ namespace LibELF
PT_SHLIB = 5,
PT_PHDR = 6,
PT_LOOS = 0x60000000,
PT_GNU_EH_FRAME = 0x6474E550,
PT_GNU_STACK = 0x6474E551,
PT_GNU_RELRO = 0x6474E552,
PT_HIOS = 0x6FFFFFFF,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7FFFFFFF,

View File

@ -169,6 +169,9 @@ struct LoadedElf
char path[PATH_MAX];
};
static LoadedElf s_loaded_files[128];
static size_t s_loaded_file_count = 0;
constexpr uintptr_t SYM_NOT_FOUND = -1;
static uint32_t elf_hash(const char* name)
@ -203,65 +206,99 @@ static ElfNativeSymbol* find_symbol(const LoadedElf& elf, const char* name)
return nullptr;
}
static uintptr_t get_symbol_address(const LoadedElf& elf, const char* name)
{
auto* symbol = find_symbol(elf, name);
if (symbol == nullptr)
return SYM_NOT_FOUND;
return elf.base + symbol->st_value;
}
static LoadedElf* get_libc_elf();
static LoadedElf* get_libgcc_elf();
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
static void handle_copy_relocation(const LoadedElf& elf, const RelocT& reloc)
{
uintptr_t symbol_address = 0;
size_t symbol_size = 0;
#if defined(__x86_64__)
const bool is_copy = (ELF64_R_TYPE(reloc.r_info) == R_X86_64_COPY);
if (const uint32_t symbol_index = ELF64_R_SYM(reloc.r_info))
if (ELF64_R_TYPE(reloc.r_info) != R_X86_64_COPY)
return;
const uint32_t symbol_index = ELF64_R_SYM(reloc.r_info);
#elif defined(__i686__)
const bool is_copy = (ELF32_R_TYPE(reloc.r_info) == R_386_COPY);
if (const uint32_t symbol_index = ELF32_R_SYM(reloc.r_info))
if (ELF32_R_TYPE(reloc.r_info) != R_386_COPY)
return;
const uint32_t symbol_index = ELF32_R_SYM(reloc.r_info);
#else
#error "unsupported architecture"
#endif
if (symbol_index == 0)
print_error_and_exit("copy relocation without a symbol", 0);
const auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + symbol_index * elf.syment);
const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name);
ElfNativeSymbol* src_sym = nullptr;
const LoadedElf* src_elf = nullptr;
for (size_t i = 0; i < s_loaded_file_count; i++)
{
if (&elf == &s_loaded_files[i])
continue;
auto* match = find_symbol(s_loaded_files[i], symbol_name);
if (match == nullptr)
continue;
if (src_sym == nullptr || ELF_ST_BIND(match->st_info) != STB_WEAK)
{
src_sym = match;
src_elf = &s_loaded_files[i];
}
if (ELF_ST_BIND(match->st_info) != STB_WEAK)
break;
}
if (src_sym == nullptr)
print_error_and_exit("copy relocation source not found", 0);
memcpy(
reinterpret_cast<void*>(elf.base + reloc.r_offset),
reinterpret_cast<void*>(src_elf->base + src_sym->st_value),
symbol.st_size
);
src_sym->st_value = (elf.base + reloc.r_offset) - src_elf->base;
}
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc, bool resolve_symbols)
{
uintptr_t symbol_address = 0;
#if defined(__x86_64__)
if (ELF64_R_TYPE(reloc.r_info) == R_X86_64_COPY)
return 0;
const uint32_t symbol_index = ELF64_R_SYM(reloc.r_info);
#elif defined(__i686__)
if (ELF32_R_TYPE(reloc.r_info) == R_386_COPY)
return 0;
const uint32_t symbol_index = ELF32_R_SYM(reloc.r_info);
#else
#error "unsupported architecture"
#endif
if (resolve_symbols == !symbol_index)
return 0;
if (symbol_index)
{
const auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + symbol_index * elf.syment);
const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name);
symbol_size = symbol.st_size;
if (!is_copy && symbol.st_shndx)
if (symbol.st_shndx && ELF_ST_BIND(symbol.st_info) != STB_WEAK)
symbol_address = elf.base + symbol.st_value;
else
{
// external symbol
symbol_address = SYM_NOT_FOUND;
for (size_t i = 0; symbol_address == SYM_NOT_FOUND; i++)
for (size_t i = 0; i < s_loaded_file_count; i++)
{
auto& dynamic = elf.dynamics[i];
if (dynamic.d_tag == DT_NULL)
break;
if (dynamic.d_tag != DT_NEEDED)
const auto* match = find_symbol(s_loaded_files[i], symbol_name);
if (match == nullptr)
continue;
const auto& lib_elf = *reinterpret_cast<LoadedElf*>(dynamic.d_un.d_ptr);
symbol_address = get_symbol_address(lib_elf, symbol_name);
if (symbol_address == SYM_NOT_FOUND || ELF_ST_BIND(match->st_info) != STB_WEAK)
symbol_address = s_loaded_files[i].base + match->st_value;
if (ELF_ST_BIND(match->st_info) != STB_WEAK)
break;
}
// libgcc_s.so needs symbols from libc, but we can't link it as toolchain
// has to be built before libc. This hack allows resolving symbols from
// libc even if its not specified as dependency, but is loaded
if (symbol_address == SYM_NOT_FOUND)
if (const auto* libc_elf = get_libc_elf())
symbol_address = get_symbol_address(*libc_elf, symbol_name);
if (symbol_address == SYM_NOT_FOUND)
if (const auto* libgcc_elf = get_libgcc_elf())
symbol_address = get_symbol_address(*libgcc_elf, symbol_name);
if (symbol_address == SYM_NOT_FOUND)
{
if (ELF_ST_BIND(symbol.st_info) != STB_WEAK)
@ -290,15 +327,6 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
value = symbol_address;
add_addend = true;
break;
case R_X86_64_COPY:
if (symbol_address == 0)
print_error_and_exit("copy undefined weak symbol?", 0);
memcpy(
reinterpret_cast<void*>(elf.base + reloc.r_offset),
reinterpret_cast<void*>(symbol_address),
symbol_size
);
break;
case R_X86_64_GLOB_DAT:
size = 8;
value = symbol_address;
@ -334,13 +362,6 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
value = symbol_address - reloc.r_offset;
add_addend = true;
break;
case R_386_COPY:
memcpy(
reinterpret_cast<void*>(elf.base + reloc.r_offset),
reinterpret_cast<void*>(symbol_address),
symbol_size
);
break;
case R_386_GLOB_DAT:
size = 4;
value = symbol_address;
@ -357,6 +378,8 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
default:
print(STDERR_FILENO, "unsupported reloc type ");
print_uint(STDERR_FILENO, ELF32_R_TYPE(reloc.r_info));
print(STDERR_FILENO, " in ");
print(STDERR_FILENO, elf.path);
print_error_and_exit("", 0);
}
#else
@ -394,9 +417,19 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
static void relocate_elf(LoadedElf& elf, bool lazy_load)
{
// FIXME: handle circular dependencies
if (elf.is_relocated)
return;
// do copy relocations
if (elf.rel && elf.relent)
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent));
if (elf.rela && elf.relaent)
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent));
// relocate libraries
for (size_t i = 0;; i++)
{
@ -408,16 +441,13 @@ static void relocate_elf(LoadedElf& elf, bool lazy_load)
relocate_elf(*reinterpret_cast<LoadedElf*>(dynamic.d_un.d_ptr), lazy_load);
}
if (elf.is_relocated)
return;
// do "normal" relocations
if (elf.rel && elf.relent)
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent));
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent), true);
if (elf.rela && elf.relaent)
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent));
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent), true);
// do jumprel relocations
if (elf.jmprel && elf.pltrelsz)
@ -431,11 +461,11 @@ static void relocate_elf(LoadedElf& elf, bool lazy_load)
{
case DT_REL:
for (size_t i = 0; i < elf.pltrelsz / sizeof(ElfNativeRelocation); i++)
handle_relocation(elf, reinterpret_cast<ElfNativeRelocation*>(elf.jmprel)[i]);
handle_relocation(elf, reinterpret_cast<ElfNativeRelocation*>(elf.jmprel)[i], true);
break;
case DT_RELA:
for (size_t i = 0; i < elf.pltrelsz / sizeof(ElfNativeRelocationA); i++)
handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[i]);
handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[i], true);
break;
}
}
@ -477,9 +507,9 @@ __attribute__((used))
uintptr_t resolve_symbol(const LoadedElf& elf, uintptr_t plt_entry)
{
if (elf.pltrel == DT_REL)
return handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.jmprel + plt_entry));
return handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.jmprel + plt_entry), true);
if (elf.pltrel == DT_RELA)
return handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[plt_entry]);
return handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[plt_entry], true);
print_error_and_exit("invalid value for DT_PLTREL", 0);
}
@ -567,6 +597,14 @@ static void handle_dynamic(LoadedElf& elf)
syscall(SYS_CLOSE, library_fd);
}
// do relocations without symbols
if (elf.rel && elf.relent)
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent), false);
if (elf.rela && elf.relaent)
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent), false);
if (pltgot == 0)
return;
@ -689,25 +727,6 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
}
}
static LoadedElf s_loaded_files[128];
static size_t s_loaded_file_count = 0;
static LoadedElf* get_libc_elf()
{
for (size_t i = 0; i < s_loaded_file_count; i++)
if (strcmp(s_loaded_files[i].path, "/usr/lib/libc.so") == 0)
return &s_loaded_files[i];
return nullptr;
}
static LoadedElf* get_libgcc_elf()
{
for (size_t i = 0; i < s_loaded_file_count; i++)
if (strcmp(s_loaded_files[i].path, "/usr/lib/libgcc_s.so") == 0)
return &s_loaded_files[i];
return nullptr;
}
static LoadedElf& load_elf(const char* path, int fd)
{
for (size_t i = 0; i < s_loaded_file_count; i++)
@ -732,9 +751,9 @@ static LoadedElf& load_elf(const char* path, int fd)
#endif
// FIXME: This is very hacky :D
do {
do
base = (get_random_uptr() & base_mask) + 0x100000;
} while (!can_load_elf(fd, file_header, base));
while (!can_load_elf(fd, file_header, base));
}
bool needs_writable = false;
@ -793,6 +812,11 @@ static LoadedElf& load_elf(const char* path, int fd)
case PT_NOTE:
case PT_PHDR:
break;
case PT_GNU_EH_FRAME:
case PT_GNU_STACK:
case PT_GNU_RELRO:
print(STDDBG_FILENO, "TODO: PT_GNU_*\n");
break;
case PT_LOAD:
program_header.p_vaddr += base;
load_program_header(program_header, fd, needs_writable);
@ -833,6 +857,15 @@ static LoadedElf& load_elf(const char* path, int fd)
return elf;
}
static void call_init_libc(LoadedElf& elf, char** envp)
{
const auto* _init_libc = find_symbol(elf, "_init_libc");
if (_init_libc == nullptr)
return;
using _init_libc_t = void(*)(char**);
reinterpret_cast<_init_libc_t>(elf.base + _init_libc->st_value)(envp);
}
static void call_init_funcs(LoadedElf& elf, char** envp, bool skip)
{
if (elf.has_called_init)
@ -860,14 +893,7 @@ static void call_init_funcs(LoadedElf& elf, char** envp, bool skip)
reinterpret_cast<init_t*>(elf.init_array)[i]();
if (strcmp(elf.path, "/usr/lib/libc.so") == 0)
{
const uintptr_t init_libc = get_symbol_address(elf, "_init_libc");
if (init_libc != SYM_NOT_FOUND)
{
using init_libc_t = void(*)(char**);
reinterpret_cast<init_libc_t>(init_libc)(envp);
}
}
call_init_libc(elf, envp);
elf.has_called_init = true;
}
@ -891,7 +917,7 @@ int _entry(int argc, char** argv, char** envp, int fd)
}
init_random();
auto elf = load_elf(argv[0], fd);
auto& elf = load_elf(argv[0], fd);
syscall(SYS_CLOSE, fd);
fini_random();