This patch introduces a "MallocTracer" to the UserspaceEmulator.
If this object is present on the Emulator, it can be notified whenever
the emulated program does a malloc() or free().
The notifications come in via a magic instruction sequence that we
embed in the LibC malloc() and free() functions. The sequence is:
"salc x2, push reg32 x2, pop reg32 x3"
The data about the malloc/free operation is in the three pushes.
We make sure the sequence is harmless when running natively.
Memory accesses on MmapRegion are then audited to see if they fall
inside a known-to-be-freed malloc chunk. If so, we complain loud
and red in the debugger output. :^)
This is very, very cool! :^)
It's also a whole lot slower than before, since now we're auditing
memory accesses against a new set of metadata. This will need to be
optimized (and running in this mode should be opt-in, perhaps even
a separate program, etc.)
Here goes mkdir(), unlink(), socket(), getsockopt(), fchmod()
bind(), connect(), listen(), select() and recvfrom().
They're not perfect but they seem to work. :^)
Since this code is performance-sensitive, let's have the compiler do
whatever it can to help us with the most important files.
This yields a ~8% speedup.
Here's the first time we get a taste of better information than the
real hardware can give us: unlike x86 CPUs, we can actually support
write-only memory, so now we do!
While this isn't immediately useful, it's still pretty cool. :^)
Ultimately we'll want to support passing some options to the emulator
as well, but for now just pass all arguments (except argv[0] of course)
through to the emulated process.
This is still not perfect, but slightly better than what we had before.
The SoftMMU now receives full X86::LogicalAddress values from SoftCPU.
This allows the MMU to reroute TLS accesses to a special memory region.
The ELF executable's PT_TLS header tells us how to allocate the TLS.
Basically, the GS register points to a magical 4-byte area which has
a pointer to the TCB (thread control block). The TCB lives in normal
flat memory space and is accessed through the DS register.
(And all other memory, too.) This will mutate later when we add shadow
memory etc, but for now just zero-initialize it since that's expected
by the emulated program.
Instead of starting with argv=nullptr, envp=nullptr, programs now
start with both pointing to a null terminated array (that immediately
terminates.) :^)
This patch adds a basic ELF program loader to the UserspaceEmulator and
creates MMU regions for each PT_LOAD header. (Note that we don't yet
respect the R/W/X flags etc.)
We also turn the SoftCPU into an X86::InstructionStream and give it an
EIP register so we can actually execute code by fetching memory through
our MMU abstraction.
This introduces a new X86 CPU emulator for running SerenityOS userspace
programs in a virtualized interpreter environment.
The main goal is to be able to instrument memory accesses and catch
interesting bugs that are very hard to find otherwise. But before we
can do fancy things like that, we have to build a competent emulator
able to actually run programs.
This initial version is able to run a very small program that makes
some tiny syscalls, but nothing more.