summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-12 20:25:41 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-12 21:37:54 +0200
commit1b196df4c465ed3a94ec52a5e43802d1df2ed797 (patch)
tree4168aebe86eb4c8f6f31570e0da68e372f217981
parent56d3a949e69a5217298bba71189fec22571b9d24 (diff)
downloadserenity-1b196df4c465ed3a94ec52a5e43802d1df2ed797.zip
UserspaceEmulator: Implement/stub out various syscalls
Moving forward on getting /bin/id to run inside the emulator. :^)
-rw-r--r--DevTools/UserspaceEmulator/Emulator.cpp78
-rw-r--r--DevTools/UserspaceEmulator/Emulator.h6
2 files changed, 83 insertions, 1 deletions
diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp
index 545a949030..84e2852e11 100644
--- a/DevTools/UserspaceEmulator/Emulator.cpp
+++ b/DevTools/UserspaceEmulator/Emulator.cpp
@@ -31,6 +31,7 @@
#include <Kernel/API/Syscall.h>
#include <stdio.h>
#include <string.h>
+#include <sys/mman.h>
#include <unistd.h>
namespace UserspaceEmulator {
@@ -216,8 +217,10 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
(void)arg2;
(void)arg3;
- printf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
+ dbgprintf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
switch (function) {
+ case SC_mmap:
+ return virt$mmap(arg1);
case SC_gettid:
return virt$gettid();
case SC_pledge:
@@ -226,6 +229,16 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
return virt$unveil(arg1);
case SC_getuid:
return virt$getuid();
+ case SC_getgid:
+ return virt$getgid();
+ case SC_write:
+ return virt$write(arg1, arg2, arg3);
+ case SC_read:
+ return virt$read(arg1, arg2, arg3);
+ case SC_mprotect:
+ return virt$mprotect(arg1, arg2, arg3);
+ case SC_madvise:
+ return virt$madvise(arg1, arg2, arg3);
case SC_exit:
virt$exit((int)arg1);
return 0;
@@ -236,6 +249,34 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
}
}
+u32 Emulator::virt$mmap(u32 params_addr)
+{
+ Syscall::SC_mmap_params params;
+ mmu().copy_from_vm(&params, params_addr, sizeof(params));
+
+ ASSERT(params.addr == 0);
+ ASSERT(params.flags & MAP_ANONYMOUS);
+
+ // FIXME: Write a proper VM allocator
+ static u32 next_address = 0x30000000;
+
+ u32 final_address = 0;
+ u32 final_size = round_up_to_power_of_two(params.size, PAGE_SIZE);
+
+ if (params.alignment) {
+ // FIXME: What if alignment is not a power of 2?
+ final_address = round_up_to_power_of_two(next_address, params.alignment);
+ } else {
+ final_address = next_address;
+ }
+
+ next_address = final_address + final_size;
+
+ mmu().add_region(make<SimpleRegion>(final_address, final_size));
+
+ return final_address;
+}
+
u32 Emulator::virt$gettid()
{
return gettid();
@@ -251,11 +292,46 @@ u32 Emulator::virt$unveil(u32)
return 0;
}
+u32 Emulator::virt$mprotect(FlatPtr, size_t, int)
+{
+ return 0;
+}
+
+u32 Emulator::virt$madvise(FlatPtr, size_t, int)
+{
+ return 0;
+}
+
uid_t Emulator::virt$getuid()
{
return getuid();
}
+uid_t Emulator::virt$getgid()
+{
+ return getgid();
+}
+
+u32 Emulator::virt$write(int fd, FlatPtr data, ssize_t size)
+{
+ if (size < 0)
+ return -EINVAL;
+ auto buffer = mmu().copy_buffer_from_vm(data, size);
+ return syscall(SC_write, fd, buffer.data(), buffer.size());
+}
+
+u32 Emulator::virt$read(int fd, FlatPtr buffer, ssize_t size)
+{
+ if (size < 0)
+ return -EINVAL;
+ auto local_buffer = ByteBuffer::create_uninitialized(size);
+ int nread = syscall(SC_read, fd, local_buffer.data(), local_buffer.size());
+ if (nread < 0)
+ return nread;
+ mmu().copy_to_vm(buffer, local_buffer.data(), local_buffer.size());
+ return nread;
+}
+
void Emulator::virt$exit(int status)
{
out() << "exit(" << status << "), shutting down!";
diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h
index cfc461164d..dd09f934fb 100644
--- a/DevTools/UserspaceEmulator/Emulator.h
+++ b/DevTools/UserspaceEmulator/Emulator.h
@@ -55,10 +55,16 @@ private:
void setup_stack();
+ u32 virt$mmap(u32);
u32 virt$gettid();
u32 virt$unveil(u32);
u32 virt$pledge(u32);
uid_t virt$getuid();
+ gid_t virt$getgid();
+ u32 virt$read(int, FlatPtr, ssize_t);
+ u32 virt$write(int, FlatPtr, ssize_t);
+ u32 virt$mprotect(FlatPtr, size_t, int);
+ u32 virt$madvise(FlatPtr, size_t, int);
void virt$exit(int);
bool m_shutdown { false };