Compare commits
8 Commits
82978da5e3
...
2a16a67aed
Author | SHA1 | Date |
---|---|---|
|
2a16a67aed | |
|
c6cd185cb5 | |
|
58cdcf754c | |
|
d969f5df7b | |
|
b6455e0661 | |
|
15021b442c | |
|
ee078fc638 | |
|
9893c90e74 |
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue