1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-15 04:04:59 +00:00
Commit graph

41 commits

Author SHA1 Message Date
Andreas Kling
60c2fba9b9 UserspaceEmulator+LibX86: Clean up some obnoxious template spam
Don't require clients to templatize modrm().read{8,16,32,64}() with
the ValueWithShadow type when we can figure it out automatically.
The main complication here is that ValueWithShadow is a UE concept
while the MemoryOrRegisterReference inlines exist at the lower LibX86
layer and so doesn't have direct access to those types. But that's
nothing we can't solve with some simple template trickery. :^)
2020-09-23 21:15:01 +02:00
Nico Weber
993ceb66fd UserspaceEmulator: Fix off-by-one in code cache access
m_cached_code_end points at the first invalid byte, so we need to
update the cache if the last byte we want to read points at the
end or past it.  Previously we updated the cache 1 byte prematurely in
read16, read32, read64 (but not in read8).

Noticed by reading the code (the code looked different from read8() and
the other 3).  I didn't find anything that actually hit this case.
2020-09-23 21:00:28 +02:00
Nico Weber
f1c0f661f4
UserspaceEmulator+LibX86: Add support for 64-bit memory reads and writes (#3584)
This is useful for reading and writing doubles for #3329.
It is also useful for emulating 64-bit binaries.

MemoryOrRegisterReference assumes that 64-bit values are always
memory references since that's enough for fpu support. If we
ever want to emulate 64-bit binaries, that part will need minor
updating.
2020-09-23 20:45:43 +02:00
Nico Weber
4b5cfce6b1 UserspaceEmulator: Emulate two FPU instructions! 2020-08-30 19:48:59 +02:00
Andreas Kling
5ba2022b8e UserspaceEmulator: Result is initialized after OR with all-1 immediate
When compiling with "-Os", GCC produces the following pattern for
atomic decrement (which is used by our RefCounted template):

    or eax, -1
    lock xadd [destination], eax

Since or-ing with -1 will always produce the same output (-1), we can
mark the result of these operations as initialized. This stops us from
complaining about false positives when running the shell in UE. :^)
2020-08-07 15:41:53 +02:00
Andreas Kling
8dea25d974 UserspaceEmulator: Add support for UNIX signals :^)
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!
2020-08-05 22:34:50 +02:00
Nico Weber
8593bdb711 LibX86: Disassemble most remaining FPU instructions
Some of the remaining instructions have different behavior for
register and non-register ops.  Since we already have the
two-level flags tables, model this by setting all handlers in
the two-level table to the register op handler, while the
first-level flags table stores the action for the non-reg handler.
2020-07-30 16:53:33 +02:00
Nico Weber
c99a3efc5b LibX86: Disassemble most FPU instructions starting with D9
Some of these don't just use the REG bits of the mod/rm byte
as slashes, but also the R/M bits to have up to 9 different
instructions per opcode/slash combination (1 opcode requires
that MOD is != 11, the other 8 have MODE == 11).

This is done by making the slashes table two levels deep for
these cases.

Some of this is cosmetic (e.g "FST st0" has no effect already,
but its bit pattern gets disassembled as "FNOP"), but for
most uses it isn't.

FSTENV and FSTCW have an extraordinary 0x9b prefix. This is
not yet handled in this patch.
2020-07-28 18:55:29 +02:00
Andreas Kling
31b94114c0 UserspaceEmulator: Recognize xor/sub zeroing idioms and don't taint
"xor reg,reg" or "sub reg,reg" both zero out the register, which means
we know for sure the result is 0. So mark the value as initialized,
and make sure we don't taint the CPU flags.

This removes some false positives from the uninitialized memory use
detection mechanism.

Fixes #2850.
2020-07-27 13:20:23 +02:00
Nico Weber
f6db97b8a9 LibX86: Support disassembling a few FPU opcodes better 2020-07-26 11:29:03 +02:00
Andreas Kling
abebec0e04 UserspaceEmulator: Use the base address of instructions in backtraces
Instead of using SoftCPU::eip() which points at the *next* instruction
most of the time, stash away a "base EIP" so we can use it when making
backtraces. This makes the correct line number show up! :^)
2020-07-21 19:08:01 +02:00
Andreas Kling
e634fe6072 UserspaceEmulator: Warn on conditional op with uninitialized dependency
We now track whether the flags register is tainted by the use of one or
more uninitialized values in a computation.

For now, the state is binary; the flags are either tainted or not.
We could be more precise about this and only taint the specific flags
that get updated by each instruction, but I think this will already get
us 99% of the results we want. :^)
2020-07-21 16:40:09 +02:00
Andreas Kling
be5f42adea UserspaceEmulator+LibX86: Start tracking uninitialized memory :^)
This patch introduces the concept of shadow bits. For every byte of
memory there is a corresponding shadow byte that contains metadata
about that memory.

Initially, the only metadata is whether the byte has been initialized
or not. That's represented by the least significant shadow bit.

Shadow bits travel together with regular values throughout the entire
CPU and MMU emulation. There are two main helper classes to facilitate
this: ValueWithShadow and ValueAndShadowReference.

ValueWithShadow<T> is basically a struct { T value; T shadow; } whereas
ValueAndShadowReference<T> is struct { T& value; T& shadow; }.

The latter is used as a wrapper around general-purpose registers, since
they can't use the plain ValueWithShadow memory as we need to be able
to address individual 8-bit and 16-bit subregisters (EAX, AX, AL, AH.)

Whenever a computation is made using uninitialized inputs, the result
is tainted and becomes uninitialized as well. This allows us to track
this state as it propagates throughout memory and registers.

This patch doesn't yet keep track of tainted flags, that will be an
important upcoming improvement to this.

I'm sure I've messed up some things here and there, but it seems to
basically work, so we have a place to start! :^)
2020-07-21 02:37:29 +02:00
Andreas Kling
485d1faf09 UserspaceEmulator: Add helpers for making loop instructions generic
Use them to implement CMPSB/CMPSW/CMPSD.
2020-07-18 00:25:02 +02:00
Andreas Kling
86a7820ad7 UserspaceEmulator: Add 16-bit PUSH/POP instructions 2020-07-18 00:25:02 +02:00
Andreas Kling
9f1221c785 UserspaceEmulator: Implement the ROL/ROR/RCL/RCR instructions 2020-07-16 19:21:45 +02:00
Andreas Kling
db1929e3ff UserspaceEmulator: Make the shift/rotate instructions more generic 2020-07-16 19:21:45 +02:00
Andreas Kling
c314292319 UserspaceEmulator: Catch use-after-frees by tracking malloc/free :^)
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.)
2020-07-15 23:25:20 +02:00
Andreas Kling
ef84865c8c LibX86+UserspaceEmulator: Devirtualize and inline more instruction code
Use some template hacks to force GCC to inline more of the instruction
decoding stuff into the UserspaceEmulator main execution loop.

This is my last optimization for today, and we've gone from ~60 seconds
when running "UserspaceEmulator UserspaceEmulator id" to ~8 seconds :^)
2020-07-13 21:00:51 +02:00
Andreas Kling
2f81c20002 UserspaceEmulator: Move the SoftCPU stream virtuals to the header
They don't actually get inlined yet, but at least this devirtualizes
them which is nice.
2020-07-13 20:41:48 +02:00
Andreas Kling
8656835935 UserspaceEmulator: Add a very simple instruction fetch cache
To avoid MMU region lookup on every single instruction fetch, we now
cache a raw pointer to the current instruction. This gets automatically
invalidated when we jump somewhere, but as long as we're executing
sequentially, instruction fetches will hit the cache and bypass all
the region lookup stuff.

This is about a ~2x speedup. :^)
2020-07-13 20:14:14 +02:00
Andreas Kling
079021a607 UserspaceEmulator: Put the executable name in argv[0] :^)
The emulated program can now find its own name in argv[0]. Very cool!
2020-07-12 21:37:54 +02:00
Andreas Kling
0af485dfff UserspaceEmulator: Implement STOSB/STOSW/STOSD
...and add a template to handle REP* instruction prefixes. This can be
further generalized, but let's go one step at a time.
2020-07-11 23:57:14 +02:00
Andreas Kling
ae1d14bc7a UserspaceEmulator: Load the target executable ELF semi-properly :^)
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.
2020-07-11 16:45:48 +02:00
Andreas Kling
76b9fb258d UserspaceEmulator: Convert the XOR instruction to inline assembly 2020-07-11 16:02:25 +02:00
Andreas Kling
7d41b95071 UserspaceEmulator: Tweak INC and SAR helpers to not be SoftCPU members
It's quite nice having these as compartmentalized free functions.
2020-07-11 15:47:53 +02:00
Andreas Kling
e852768ba6 UserspaceEmulator: Add the INC and ADD instructions
More inline assembly. I'm still figuring out how to combine templates
and inline assembly, but it's turning out pretty cool. :^)
2020-07-11 14:20:08 +02:00
Andreas Kling
12ab46def9 UserspaceEmulator: Give SoftCPU an API for evaluating jump conditions
There are 16 conditions and they're all based on a combination of the
CPU flags.
2020-07-11 13:45:39 +02:00
Andreas Kling
e5afe6a579 UserspaceEmulator: Implement the CMP family of instructions
These are identical to SUB, except they don't store the result (they
only upate the arithmetic flags.)
2020-07-11 13:27:40 +02:00
Andreas Kling
04d58f54b3 UserspaceEmulator: Implement the SAR instruction
Let's try doing this with some inline assembly. We know we're running
on an x86 target anyway. :^)
2020-07-10 20:20:27 +02:00
Andreas Kling
0cf7fd5268 UserspaceEmulator+LibX86: Implement all the forms of XOR
And they're all generic, which will make it easy to support more ops.
2020-07-10 20:20:27 +02:00
Andreas Kling
9955819d92 UserspaceEmulator: Better 8/16 bit GPR accessors 2020-07-10 20:20:27 +02:00
Andreas Kling
6f27770cea UserspaceEmulator: Add 8/16 bit memory read/write operations 2020-07-10 20:20:27 +02:00
Andreas Kling
f8b38eabeb UserspaceEmulator: First cut of generic instruction implementations
Let's use C++ templates to implement the generic parts of instructions.
There are tons of them with the same set of inputs, just different
behavior. Templates are perfect for this.
2020-07-10 20:20:27 +02:00
Andreas Kling
30ef30ca09 UserspaceEmulator: Add proper segment registers
Some things will flow better if we're able to index into a table of our
segment registers.
2020-07-10 20:20:27 +02:00
Andreas Kling
4f41fada39 UserspaceEmulator: Add accessors for the 16-bit GPRs 2020-07-10 20:20:27 +02:00
Andreas Kling
f1801cfb28 UserspaceEmulator: Fix a Clang warning
Clang didn't like default construction of PartAddressableRegister,
so let's just use memset() then.
2020-07-10 20:20:27 +02:00
Andreas Kling
4d8683b632 UserspaceEmulator: Tidy up SoftCPU's general purpose registers
This patch adds a PartAddressableRegister type, which divides a 32-bit
value into separate parts needed for the EAX/AX/AL/AH register splits.

Clean up the code around register access to make it a little less
cumbersome to use.
2020-07-09 23:27:50 +02:00
Andreas Kling
d10765bec3 UserspaceEmulator: Add an initial stack and implement PUSH/POP reg32
Programs now start out with a 64 KB stack at 0x10000000. :^)
2020-07-09 16:20:08 +02:00
Andreas Kling
934f0b999e UserspaceEmulator: Add arithmetic CPU flags 2020-07-07 22:44:58 +02:00
Andreas Kling
8d8bb07476 UserspaceEmulator: Start building a userspace X86 emulator :^)
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.
2020-07-07 22:44:58 +02:00