PT_SETTREGS sets the regsiters of the traced thread. It can only be
used when the tracee is stopped.
Also, refactor ptrace.
The implementation was getting long and cluttered the alraedy large
Process.cpp file.
This commit moves the bulk of the implementation to Kernel/Ptrace.cpp,
and factors out peek & poke to separate methods of the Process class.
This was a missing feature in the PT_TRACEME command.
This feature allows the tracer to interact with the tracee before the
tracee has started executing its program.
It will be useful for automatically inserting a breakpoint at a
debugged program's entry point.
Before this commit, m_blocker was only set to null in Thread::block,
after the thread has been unblocked.
Starting with this commit, m_blocker is also set to null in
Thread::unblock.
This change will allow us to implement a missing feature of the PT_TRACE
command of the ptrace syscall - stopping the traced thread when it
exits the execve syscall.
That feature will be implemented by sending a blocking SIGSTOP to the
traced thread after it has executed the execve logic and before it
starts executing the new program in userspace.
However, since Process::exec arranges the tss to return to userspace
(the so-called "yield-teleport"), the code in Thread::block that should
be run after the thread unblocks, and sets m_blocker to null, never
actually runs.
Setting m_blocker to null in Thread::unblock allows us to avoid an
incorrect state where the thread is in a Running state but conatins a
pointer to a Blocker.
PT_POKE writes a single word to the tracee's address space.
Some caveats:
- If the user requests to write to an address in a read-only region, we
temporarily change the page's protections to allow it.
- If the user requests to write to a region that's backed by a
SharedInodeVMObject, we replace the vmobject with a PrivateIndoeVMObject.
We were hitting strcmp() in every variable lookup to see if the lookup
was for "this". Caching a FlyString("this") turns that check into one
pointer comparison instead. :^)
This turns into much less code in the most common cases, here's why:
The normal Optional usage pattern is something like:
auto foo = get_me_an_optional();
if (foo.has_value())
do_stuff_with(foo.value());
In this typical scenario, we check has_value() before calling value().
Without inlining, value() will double-check has_value() itself and
assert if it fails. Inlining allows the compiler to optimize all of
this away.
We now use minherit(MAP_INHERIT_ZERO) to create a gettid() cache that
is automatically invalidated on fork(). This is needed since the TID
will be different in a forked child, and so we can't have a stale
cached TID lying around.
This is a gigantic speedup for LibJS (and everyone else too) :^)
This patch adds the minherit() syscall originally invented by OpenBSD.
Only the MAP_INHERIT_ZERO mode is supported for now. If set on an mmap
region, that region will be zeroed out on fork().
This patch adds a pure virtual X86::SymbolProvider that can be passed
to Instruction::to_string(). If the instruction contains what appears
to be a program address, stringification will try to symbolicate that
address via the SymbolProvider.
This makes it possible (and very flexible) to add symbolication to
clients of the disassembler. :^)
This is really just a workaround to keep SystemMonitor's process table
working right wrt selection retention during resorts (while also doing
full index invalidation on things like ProfileViewer inversion.)
It's starting to feel like the model abstraction is not super great
and we'll need a better approach if we want to actually build some more
dynamic functionality into our views.
`ResourceLoader::load` now rejects URLs which specify a `port`
associated with network services known to be vulnerable to
inter-protocol exploitation.
Fixes#1735
We now store the previous thread state in m_stop_state for all
transitions to the Stopped state via Thread::set_state.
Fixes#1752 whereupon resuming a thread that was stopped with SIGTSTP,
the previous state of the thread is not remembered correctly, resulting
in m_stop_state == State::Invalid and the associated assertion fails.