Let's adapt this class a bit better to how it's actually being used.
Instead of having valid/invalid states and storing an error in case
it's invalid, a MappedFile is now always valid, and the factory
function that creates it will return an OSError if mapping fails.
This was a goofy kernel API where you could assign an icon_id (int) to
a process which referred to a global shbuf with a 16x16 icon bitmap
inside it.
Instead of this, programs that want to display a process icon now
retrieve it from the process executable instead.
This commit gets rid of ELF::Loader entirely since its very ambiguous
purpose was actually to load executables for the kernel, and that is
now handled by the kernel itself.
This patch includes some drive-by cleanup in LibDebug and CrashDaemon
enabled by the fact that we no longer need to keep the ref-counted
ELF::Loader around.
Keep the debug symbols for shared libraries in memory after we opened
them the first time. This dramatically speeds up symbolication of
backtraces when running dynamically linked programs in UE.
When loading dynamic objects, the emulator loads the interpreter,
generates an auxiliary vector and starts executing the loader.
Additionally, this commits also makes the MallocTracer and backtrace
symbolication work for dynamically loaded programs.
The implementation only supports a single iovec for now.
Some might say having more than one iovec is the main point of
recvmsg() and sendmsg(), but I'm interested in the control message
bits.
With this, `ue /bin/ntpquery` can be used to test sendto() and
recvfrom() in ue. (It eventually hits an unimplemented FILD_RM64,
but not before doing emulated network i/o and printing response
details.)
This is racy in userspace and non-racy in kernelspace so let's keep
it in kernelspace.
The behavior change where CLOEXEC is preserved when dup2() is called
with (old_fd == new_fd) was good though, let's keep that.
The emulator will now register signal handlers for all possible signals
and act as a translation layer between the kernel and the emulated
process.
To get an accurate simulation of signal handling, we duplicate the same
trampoline mechanism used by the kernel's signal delivery system, and
also use the "sigreturn" syscall to return from a signal handler.
Signal masking is not fully implemented yet, but this is pretty cool!
This virtual syscall works by exec'ing the UserspaceEmulator itself,
with the emulated program's provided arguments as the arguments to the
new UserspaceEmulator instance.
This means that we "follow" exec'ed programs and emulate them as well.
In the future we might want to make this an opt-in (or opt-out, idk)
behavior, but for now it's what we do.
This is really quite cool, I think! :^)
Note that running a setuid program (e.g /bin/ping) in UE does not
actually run uid=0. You'll have to run UE itself as uid=0 if you want
to test programs that do setuid/setgid.