Verified Commit acf9a01c authored by jD91mZM2's avatar jD91mZM2

Fix signal handling on Redox

parent ce8e8b58
......@@ -100,7 +100,7 @@ dependencies = [
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)",
"strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)",
"strace 0.1.0",
"structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -278,7 +278,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strace"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#a05ecc3eb8620ffe115236756411bb9f5f416675"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)",
......@@ -512,7 +511,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)" = "<none>"
"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "<none>"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
"checksum structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
......
......@@ -14,13 +14,13 @@ log = "0.4.8"
byteorder = "1.3.4"
num-traits = "0.2.12"
# f80 = { git = "https://gitlab.redox-os.org/redox-os/f80.git", rev = "d8de286" }
libc = "0.2.71"
[[bin]]
path = "./bin/gdb-redox.rs"
name = "gdb-redox"
[target.'cfg(target_os = "linux")'.dependencies]
libc = "0.2.71"
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" }
# strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" }
strace = { path = "../../strace/source" }
all: minimal-asm redox-asm minimal-c signal-c
all: minimal-asm redox-asm minimal-c signal-c sighandler-c
clean:
rm minimal-asm redox-asm minimal-c
rm minimal-asm redox-asm minimal-c signal-c sighandler-c
%-asm.o: %.asm
nix-shell -p nasm --run "nasm -f elf64 $< -g -o $@"
......
#include <stdio.h>
#include <string.h>
#include <signal.h>
volatile char *msg;
volatile int signal_num;
void sighandler(int sig) {
msg = "Signal received";
signal_num = sig;
}
int main() {
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = sighandler;
sigaction(SIGUSR1, &sa, NULL);
puts("Raising signal...");
raise(SIGUSR1);
puts("Raised signal");
printf("%s: %d\n", msg, signal_num);
}
......@@ -70,7 +70,7 @@ impl Handler for App {
Ok(buf)
}
fn write_memory(&self, address: u64, bytes: &[u8]) -> Result<()> {
self.tracee.setmem(bytes, address as usize)?;
self.tracee.setmem(address as usize, bytes)?;
Ok(())
}
fn query_supported_features(&self) -> Vec<String> {
......
......@@ -332,18 +332,18 @@ impl super::Target for Os {
Ok(())
}
fn getmem(&self, src: usize, dest: &mut [u8]) -> Result<usize> {
fn getmem(&self, address: usize, memory: &mut [u8]) -> Result<usize> {
// TODO: Don't report errors when able to read part of requested?
// Also implement this in the Redox kernel perhaps
getmem(src, dest, |addr| unsafe {
getmem(address, memory, |addr| unsafe {
Ok(e!(libc::ptrace(libc::PTRACE_PEEKDATA, self.pid, addr)) as usize)
})
}
fn setmem(&self, src: &[u8], dest: usize) -> Result<()> {
fn setmem(&self, address: usize, memory: &[u8]) -> Result<()> {
setmem(
src,
dest,
memory,
address,
|addr| unsafe { Ok(e!(libc::ptrace(libc::PTRACE_PEEKDATA, self.pid, addr)) as usize) },
|addr, word| unsafe {
e!(libc::ptrace(libc::PTRACE_POKEDATA, self.pid, addr, word));
......
......@@ -47,10 +47,10 @@ pub trait Target: Sized {
fn setregs(&self, regs: &Registers) -> Result<()>;
/// Read a region of memory from tracee
fn getmem(&self, src: usize, dest: &mut [u8]) -> Result<usize>;
fn getmem(&self, address: usize, memory: &mut [u8]) -> Result<usize>;
/// Read a region of memory from tracee
fn setmem(&self, src: &[u8], dest: usize) -> Result<()>;
fn setmem(&self, address: usize, memory: &[u8]) -> Result<()>;
/// Single-step one instruction, return instruction pointer
fn step(&self, signal: Option<u8>) -> Result<Option<u64>>;
......
......@@ -11,7 +11,7 @@ use std::{
use gdb_remote_protocol::{Error, StopReason};
use log::error;
use strace::{Flags, Tracer};
use strace::{EventData, Flags, Tracer};
use syscall::flag::*;
pub struct Os {
......@@ -69,17 +69,34 @@ impl Os {
/// Continues the tracer with the specified flags, and the breakpoint
/// flag. If the process exits, we waitpid the child and set the status. We
/// also return `Exited` to signal that the process is no longer
/// alive. Returns `Running` and sets status to SIGSTOP if the process does
/// alive. Returns `Running` and sets status to SIGTRAP if the process does
/// not exit.
fn next(&self, flags: Flags) -> Result<ProcessState> {
let mut tracer = self.tracer.borrow_mut();
match tracer.next(flags | Flags::STOP_BREAKPOINT) {
Ok(_event) => {
// Just pretend ptrace SIGSTOP:ped this
let status = (SIGSTOP << 8) | 0x7f;
match tracer.next(flags | Flags::STOP_BREAKPOINT | Flags::STOP_SIGNAL) {
Ok(event) => {
let signal = if event.cause == Flags::STOP_SIGNAL {
let (signal, handler) = match event.data {
EventData::StopSignal(sig, handler) => (sig, handler),
_ => unreachable!(),
};
// If breakpoint is signal, step into the signal handler
if handler != syscall::SIG_DFL && handler != syscall::SIG_IGN {
e!(tracer.next(Flags::STOP_SINGLESTEP));
}
signal
} else {
// Just pretend ptrace SIGTRAP:ped this
SIGTRAP
};
let status = (signal << 8) | 0x7f;
assert!(syscall::wifstopped(status));
assert_eq!(syscall::wstopsig(status), SIGSTOP);
assert_eq!(syscall::wstopsig(status), signal);
self.last_status.set(status);
Ok(ProcessState::Running)
},
......@@ -154,8 +171,7 @@ impl super::Target for Os {
// TODO: Don't stop only on syscall, stop on first instruction.
// Single-stepping doesn't work across fexec yet for some reason.
// e!(tracer.next(Flags::STOP_SINGLESTEP));
e!(tracer.next(Flags::STOP_EXEC));
e!(tracer.next(Flags::STOP_SINGLESTEP));
Ok(Os {
pid,
......@@ -335,17 +351,17 @@ impl super::Target for Os {
Ok(())
}
fn getmem(&self, src: usize, dest: &mut [u8]) -> Result<usize> {
fn getmem(&self, address: usize, memory: &mut [u8]) -> Result<usize> {
// TODO: Don't report errors when able to read part of requested?
// Also implement this in the Redox kernel perhaps
let mut tracer = self.tracer.borrow_mut();
e!(tracer.mem.read(src as *const u8, dest));
Ok(dest.len())
e!(tracer.mem.read(address as *const u8, memory));
Ok(memory.len())
}
fn setmem(&self, src: &[u8], dest: usize) -> Result<()> {
fn setmem(&self, address: usize, memory: &[u8]) -> Result<()> {
let mut tracer = self.tracer.borrow_mut();
e!(tracer.mem.write(src, dest as *mut u8));
e!(tracer.mem.write(address as *mut u8, memory));
Ok(())
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment