By jD91mZM2 on
Hallo Welt! Have you ever written a project and when it’s done you just think “Now what”? The project you’ve been working on for days, weeks, maybe months I don’t know, is just suddenly… without direction?
I’m not trying to say my work here is done, but I do feel like we’re close… and that’s frightening. In fact, this week has been all about finishing things off (whenever I had time - life kept getting in the way an annoying lot)
Features of the week
The PR of both last week and this one was merged, so as I’m writing this the features are actually available on Redox OS. All you have to do is update your version!
In kernel commit
I made it possible to ignore signals and therefore stop signal
handlers from being invoked in the tracee, and handle it yourself
instead. A typical use for this could be a debugger that wants
SIGINT to just stop the tracee instead of quitting it.
I was about to add another flag,
PTRACE_FLAG_SIGIGNORE, which would
when set just ignore any started signal. But when I thought about it
long and hard, I realized we already have something similar: sysemu!
Recent changes have already made sysemu work so you can activate it
after a pre-syscall event and it will just return with your own set
registers instead of handling the system call in the kernel. So it’s
an awful lot like ignoring the system call… Aha. The flags were
merged, and RFC commit
now has the flag
PTRACE_FLAG_IGNORE which will handle both signals
and system calls, and is scalable.
Turns out, however, that signal handlers can not actually handle
int3. The internal kernel function doesn’t signal the process but
exit directly. Whether this behavior is desired or not
is something I should first ask you guys and then the project leader
Jeremy Soller. Would a process really benefit from being able to
register a signal handler to catch their own
Until then, I made kernel commit
use a new flag as specified by RFC commit
PTRACE_STOP_BREAKPOINT. Similar to
PTRACE_STOP_SIGNAL, this will
let the tracer inspect the stopped tracee, and choose whether or not
PTRACE_FLAG_IGNORE for the next call and therefore not
perform the default behavior - exiting with
SIGTRAP. Told you the
PTRACE_FLAG_IGNORE designs were scalable!
One big thing I thought I’d have to do is make memory maps readable,
/proc/<pid>/maps. Turns out, unless I’m mistaken, that
most programs that wish to inject code into a tracee doesn’t actually
use this but rather just writes directly to
rip before running it,
reversing it, and resetting
rip back again. This means I don’t have
to let the user read memory maps, which is good because I don’t know
if all the needed information is even available in Redox yet. And if a
user wants to inject a looot of code, they can just inject a syscall
that allocates a huge region and then write their code and jump to
I still have some things on my to-do list, but most are just testing things or thinking through some implementation details. For example, yesterday I resolved an old concern about catching the rsp of same-ring interrupts. This is unlikely to ever be needed, but as I can’t prove it will never happen I should probably make sure it behaves correctly. A few other things I did was researching if modifying the CS register could be bad as well as remove a TODO comment about the safety of the memory implementation (which Jeremy had already gave a thumbs up on).
Then I suppose I should go back to investigating if GDB can be ported. I’m also debating whether it’d be worth it to “just” write a debugger from scratch in rust that keeps both Linux and Redox’s vastly different systems in mind from the start. Pros would be using Rust and that it’d be easier for me to make something basic than investigate something as huge as GDB. Cons are that GDB is huge and I’d hardly be able to re-implement the entirety of it. Input from anybody working on GDB or a competitor would be absolutely great!