From 4230fc17bdb0b209458c43cccdce03057e0e1102 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Mon, 21 Oct 2019 12:13:06 +0100 Subject: [PATCH 01/23] Initial checkin --- padre/Cargo.lock | 400 +++++++++++++++++++--------- padre/Cargo.toml | 12 +- padre/src/debugger.rs | 125 ++++----- padre/src/debugger/lldb/debugger.rs | 76 +++--- padre/src/debugger/lldb/process.rs | 38 +-- padre/src/main.rs | 157 +++++------ padre/src/notifier.rs | 17 +- padre/src/server.rs | 214 +++++++-------- padre/src/util.rs | 186 ++++++------- 9 files changed, 674 insertions(+), 551 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index ee9f9ab..753d4d0 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -18,7 +18,7 @@ dependencies = [ [[package]] name = "arc-swap" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -34,7 +34,7 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -126,7 +126,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -134,6 +134,14 @@ name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.7.1" @@ -215,13 +223,43 @@ name = "futures" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-channel-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-sink-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getrandom" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -263,7 +301,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -290,10 +328,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.62" +version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -305,6 +346,14 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" @@ -356,7 +405,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -381,7 +430,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -411,7 +460,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -428,7 +477,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -442,7 +491,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -454,7 +503,7 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -470,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -490,13 +539,13 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-process 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -509,23 +558,70 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pin-project" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pkg-config" version = "0.3.15" @@ -558,7 +654,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -576,7 +672,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -650,7 +746,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -662,7 +758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -766,7 +862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -821,22 +917,13 @@ name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "signal-hook" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "signal-hook-registry" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -855,11 +942,16 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -886,7 +978,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -914,32 +1006,30 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.22" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -953,12 +1043,15 @@ dependencies = [ ] [[package]] -name = "tokio-current-thread" -version = "0.1.6" +name = "tokio-codec" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -970,14 +1063,35 @@ dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-executor" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-fs" -version = "0.1.6" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -991,20 +1105,52 @@ dependencies = [ ] [[package]] -name = "tokio-process" -version = "0.2.4" +name = "tokio-io" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-macros" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-net" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1027,28 +1173,23 @@ dependencies = [ ] [[package]] -name = "tokio-signal" -version = "0.2.7" +name = "tokio-sync" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.6" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1064,31 +1205,17 @@ dependencies = [ "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio-threadpool" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tokio-timer" -version = "0.2.11" +version = "0.3.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1102,34 +1229,33 @@ dependencies = [ ] [[package]] -name = "tokio-udp" -version = "0.1.3" +name = "tracing" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-attributes 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-uds" -version = "0.2.5" +name = "tracing-attributes" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tracing-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1270,7 +1396,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arc-swap 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "854ede29f7a0ce90519fb2439d030320c6201119b87dab0ee96044603e1130b9" +"checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" @@ -1286,6 +1412,7 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" @@ -1297,6 +1424,10 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" +"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" +"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" +"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" "checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" @@ -1306,8 +1437,9 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" @@ -1328,8 +1460,13 @@ dependencies = [ "checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "562cc58f3e865231cf1fa1760097159a642018f5953ffbfe4f2df2ef72bf0d90" +"checksum pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "21a5bc357e14eb5cc61f4e24867b3aec66b850d83ea830beffa2244ad7a97f1e" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" @@ -1367,11 +1504,11 @@ dependencies = [ "checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68" "checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c65d951ab12d976b61a41cf9ed4531fc19735c6e6d84a4bb1453711e762ec731" @@ -1379,22 +1516,25 @@ dependencies = [ "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f17f5d6ab0f35c1506678b28fb1798bdf74fcb737e9843c7b17b73e426eba38" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +"checksum tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9f5d22fd1e84bd4045d28813491cb7d7caae34d45c80517c2213f09a85e8787a" "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" -"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" +"checksum tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf85e16971e06e680c622e0c1b455be94b086275c5ddcd6d4a83a2bfbb83cda" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-process 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afbd6ef1b8cc2bd2c2b580d882774d443ebb1c6ceefe35ba9ea4ab586c89dbe8" +"checksum tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "112784d5543df30660b04a72ca423bfbd90e8bb32f94dcf610f15401218b22c5" +"checksum tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "86b616374bcdadd95974e1f0dfca07dc913f1163c53840c0d664aca35114964e" +"checksum tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a441682cd32f3559383112c4a7f372f5c9fa1950c5cf8c8dd05274a2ce8c2654" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" "checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" +"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" -"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b97c1587fe71018eb245a4a9daa13a5a3b681bbc1f7fdadfe24720e141472c13" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c21ff9457accc293386c20e8f754d0b059e67e325edf2284f04230d125d7e5ff" +"checksum tracing-attributes 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff978fd9c9afe2cc9c671e247713421c6406b3422305cbdce5de695d3ab4c3c" +"checksum tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "528c8ebaaa16cdac34795180b046c031775b0d56402704d98c096788f33d646a" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" diff --git a/padre/Cargo.toml b/padre/Cargo.toml index 52a2049..839a4f2 100644 --- a/padre/Cargo.toml +++ b/padre/Cargo.toml @@ -8,11 +8,17 @@ edition = "2018" bytes = "0.4.12" clap = "2.32.0" lazy_static = "1.3.0" +libc = "0.2.65" regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = "0.1.22" -tokio-signal = "0.2" -tokio-process = "0.2.4" websocket = "0.22.4" + +[dependencies.tokio] +version = "^0.2.0-alpha.6" +features = ["process"] + +[dependencies.tokio-net] +version = "^0.2.0-alpha.6" +features = ["signal"] diff --git a/padre/src/debugger.rs b/padre/src/debugger.rs index 7380082..60e88ec 100644 --- a/padre/src/debugger.rs +++ b/padre/src/debugger.rs @@ -12,9 +12,9 @@ use crate::util::{file_is_binary_executable, file_is_text}; use tokio::prelude::*; -mod lldb; -mod node; -mod python; +//mod lldb; +//mod node; +//mod python; /// Debuggers #[derive(Debug)] @@ -68,62 +68,67 @@ pub enum DebuggerCmdV1 { #[derive(Debug)] pub struct Debugger { - debugger: Box, + //debugger: lldb::ImplDebugger, } impl Debugger { - pub fn new(debugger: Box) -> Debugger { - Debugger { debugger } + pub fn new() -> Debugger { + Debugger {} } + //pub fn new(debugger: lldb::ImplDebugger) -> Debugger { + // Debugger { debugger } + //} + pub fn stop(&mut self) { - self.debugger.teardown(); + //self.debugger.teardown(); } - pub fn handle_v1_cmd( + pub async fn handle_v1_cmd( &mut self, cmd: &DebuggerCmdV1, - config: Arc>, - ) -> Box + Send> { - match cmd { - DebuggerCmdV1::Run => self.debugger.run(config), - DebuggerCmdV1::Breakpoint(fl) => self.debugger.breakpoint(fl, config), - DebuggerCmdV1::StepIn => self.debugger.step_in(), - DebuggerCmdV1::StepOver => self.debugger.step_over(), - DebuggerCmdV1::Continue => self.debugger.continue_(), - DebuggerCmdV1::Print(v) => self.debugger.print(v, config), - } + //config: Arc>, + ) -> Result { + Ok(serde_json::json!({"status":"OK"})) +// match cmd { +// DebuggerCmdV1::Run => self.debugger.run(), //config), +// DebuggerCmdV1::Breakpoint(fl) => self.debugger.breakpoint(fl), //, config), +// DebuggerCmdV1::StepIn => self.debugger.step_in(), +// DebuggerCmdV1::StepOver => self.debugger.step_over(), +// DebuggerCmdV1::Continue => self.debugger.continue_(), +// DebuggerCmdV1::Print(v) => self.debugger.print(v), //, config), +// } } } -/// Debugger trait that implements the basics -pub trait DebuggerV1: Debug { - fn setup(&mut self); - fn teardown(&mut self); - fn run( - &mut self, - config: Arc>, - ) -> Box + Send>; - fn breakpoint( - &mut self, - file_location: &FileLocation, - config: Arc>, - ) -> Box + Send>; - fn step_in(&mut self) -> Box + Send>; - fn step_over(&mut self) -> Box + Send>; - fn continue_(&mut self) -> Box + Send>; - fn print( - &mut self, - variable: &Variable, - config: Arc>, - ) -> Box + Send>; -} +// /// Debugger trait that implements the basics +// pub trait DebuggerV1: Debug { +// fn setup(&mut self); +// fn teardown(&mut self); +// fn run( +// &mut self, +// //config: Arc>, +// ) -> Box + Send>; +// fn breakpoint( +// &mut self, +// file_location: &FileLocation, +// //config: Arc>, +// ) -> Box + Send>; +// fn step_in(&mut self) -> Box + Send>; +// fn step_over(&mut self) -> Box + Send>; +// fn continue_(&mut self) -> Box + Send>; +// fn print( +// &mut self, +// variable: &Variable, +// //config: Arc>, +// ) -> Box + Send>; +// } /// Get the debugger implementation /// /// If the debugger type is not specified it will try it's best to guess what kind of debugger to /// return. -pub fn get_debugger( +pub async fn get_debugger( debugger_cmd: Option<&str>, debugger_type: Option<&str>, run_cmd: Vec, @@ -135,7 +140,7 @@ pub fn get_debugger( "node" => DebuggerType::Node, _ => panic!("Couldn't understand debugger type {}", s), }, - None => match get_debugger_type(&run_cmd[0]) { + None => match get_debugger_type(&run_cmd[0]).await { Some(s) => s, None => match debugger_cmd { Some(s) => match s { @@ -161,24 +166,24 @@ pub fn get_debugger( }, }; - let mut debugger: Box = match debugger_type { - DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), - DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), - DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), - }; +// let mut debugger: lldb::ImplDebugger = match debugger_type { +// DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), +// DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), +// DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), +// }; - debugger.setup(); +// debugger.setup(); - Debugger::new(debugger) + Debugger::new() } /// Guesses the debugger type -fn get_debugger_type(run_cmd: &str) -> Option { - if is_node(&run_cmd) { +async fn get_debugger_type(run_cmd: &str) -> Option { + if is_node(&run_cmd).await { Some(DebuggerType::Node) - } else if is_python(&run_cmd) { + } else if is_python(&run_cmd).await { Some(DebuggerType::Python) - } else if is_lldb(&run_cmd) { + } else if is_lldb(&run_cmd).await { Some(DebuggerType::LLDB) } else { None @@ -186,8 +191,8 @@ fn get_debugger_type(run_cmd: &str) -> Option { } /// Checks if the file is a binary executable -fn is_lldb(cmd: &str) -> bool { - if file_is_binary_executable(cmd) { +async fn is_lldb(cmd: &str) -> bool { + if file_is_binary_executable(cmd).await { return true; } @@ -195,8 +200,8 @@ fn is_lldb(cmd: &str) -> bool { } /// Checks if the file is a NodeJS script -fn is_node(cmd: &str) -> bool { - if file_is_text(cmd) && cmd.ends_with(".js") { +async fn is_node(cmd: &str) -> bool { + if file_is_text(cmd).await && cmd.ends_with(".js") { return true; } @@ -207,9 +212,9 @@ fn is_node(cmd: &str) -> bool { false } -/// Checks if the file is a NodeJS script -fn is_python(cmd: &str) -> bool { - if file_is_text(cmd) && cmd.ends_with(".py") { +/// Checks if the file is a Python script +async fn is_python(cmd: &str) -> bool { + if file_is_text(cmd).await && cmd.ends_with(".py") { return true; } diff --git a/padre/src/debugger/lldb/debugger.rs b/padre/src/debugger/lldb/debugger.rs index a642c87..a0f5dbc 100644 --- a/padre/src/debugger/lldb/debugger.rs +++ b/padre/src/debugger/lldb/debugger.rs @@ -10,7 +10,7 @@ use std::time::Duration; use super::process::{Event, LLDBProcess, Listener}; use crate::config::Config; -use crate::debugger::{DebuggerV1, FileLocation, Variable}; +use crate::debugger::{FileLocation, Variable}; use crate::notifier::{log_msg, LogLevel}; use bytes::Bytes; @@ -28,9 +28,7 @@ impl ImplDebugger { process: Arc::new(Mutex::new(LLDBProcess::new(debugger_cmd, run_cmd))), } } -} -impl DebuggerV1 for ImplDebugger { /// Perform any initial setup including starting LLDB and setting up the stdio analyser stuff /// - startup lldb and setup the stdio analyser /// - perform initial setup so we can analyse LLDB properly @@ -70,10 +68,10 @@ impl DebuggerV1 for ImplDebugger { exit(0); } - fn run( + async fn run( &mut self, config: Arc>, - ) -> Box + Send> { + ) -> Result { log_msg(LogLevel::INFO, "Launching process"); let (tx, rx) = mpsc::channel(1); @@ -141,11 +139,11 @@ impl DebuggerV1 for ImplDebugger { Box::new(f) } - fn breakpoint( + async fn breakpoint( &mut self, file_location: &FileLocation, config: Arc>, - ) -> Box + Send> { + ) -> Result { log_msg( LogLevel::INFO, &format!( @@ -192,27 +190,27 @@ impl DebuggerV1 for ImplDebugger { Box::new(f) } - fn step_in(&mut self) -> Box + Send> { + async fn step_in(&mut self) -> Result { self.step("step-in") } - fn step_over(&mut self) -> Box + Send> { + async fn step_over(&mut self) -> Result { self.step("step-over") } - fn continue_(&mut self) -> Box + Send> { + async fn continue_(&mut self) -> Result { self.step("continue") } - fn print( + async fn print( &mut self, variable: &Variable, config: Arc>, - ) -> Box + Send> { - match self.check_process() { - Some(f) => return f, - _ => {} - } + ) -> Result { + //match self.check_process() { + // Some(f) => return f, + // _ => {} + //} let (tx, rx) = mpsc::channel(1); @@ -259,17 +257,15 @@ impl DebuggerV1 for ImplDebugger { Box::new(f) } -} -impl ImplDebugger { - fn step( + async fn step( &mut self, kind: &str, - ) -> Box + Send> { - match self.check_process() { - Some(f) => return f, - _ => {} - } + ) -> Result { + //match self.check_process() { + // Some(f) => return f, + // _ => {} + //} let stmt = format!("thread {}\n", kind); @@ -283,20 +279,20 @@ impl ImplDebugger { Box::new(f) } - fn check_process( - &mut self, - ) -> Option + Send>> { - match self.process.lock().unwrap().is_process_running() { - false => { - log_msg(LogLevel::WARN, "No process running"); - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"ERROR"}); - Ok(resp) - }); - - Some(Box::new(f)) - } - true => None, - } - } + //fn check_process( + // &mut self, + //) -> Option> { + // match self.process.lock().unwrap().is_process_running() { + // false => { + // log_msg(LogLevel::WARN, "No process running"); + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"ERROR"}); + // Ok(resp) + // }); + + // Some(Box::new(f)) + // } + // true => None, + // } + //} } diff --git a/padre/src/debugger/lldb/process.rs b/padre/src/debugger/lldb/process.rs index 3235273..e6ded9b 100644 --- a/padre/src/debugger/lldb/process.rs +++ b/padre/src/debugger/lldb/process.rs @@ -9,13 +9,13 @@ use std::sync::{Arc, Mutex}; use crate::debugger::{FileLocation, Variable}; use crate::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; -use crate::util::{check_and_spawn_process, read_output, setup_stdin}; +use crate::util::{check_and_spawn_process, read_output}; //, setup_stdin}; use bytes::Bytes; use regex::Regex; +use tokio::net::process::{Child, ChildStderr, ChildStdout}; use tokio::prelude::*; use tokio::sync::mpsc::Sender; -use tokio_process::{Child, ChildStderr, ChildStdout}; /// You can register to listen for one of the following events: /// - LLDBLaunched: LLDB has started up initially @@ -114,15 +114,15 @@ impl LLDBProcess { .take() .expect("LLDB process did not have a handle to stderr"), ); - let stdin_tx = setup_stdin( - lldb_process - .stdin() - .take() - .expect("LLDB process did not have a handle to stdin"), - false, - ); - - self.lldb_stdin_tx = Some(stdin_tx); + //let stdin_tx = setup_stdin( + // lldb_process + // .stdin() + // .take() + // .expect("LLDB process did not have a handle to stdin"), + // false, + //); + + //self.lldb_stdin_tx = Some(stdin_tx); self.lldb_process = Some(lldb_process); } @@ -132,14 +132,14 @@ impl LLDBProcess { /// Send a message to write to stdin pub fn write_stdin(&mut self, bytes: Bytes) { - let tx = self.lldb_stdin_tx.clone(); - tokio::spawn( - tx.clone() - .unwrap() - .send(bytes) - .map(move |_| {}) - .map_err(|e| eprintln!("Error sending to LLDB: {}", e)), - ); + //let tx = self.lldb_stdin_tx.clone(); + //tokio::spawn( + // tx.clone() + // .unwrap() + // .send(bytes) + // .map(move |_| {}) + // .map_err(|e| eprintln!("Error sending to LLDB: {}", e)), + //); } pub fn add_listener(&mut self, kind: Listener, sender: Sender) { diff --git a/padre/src/main.rs b/padre/src/main.rs index 3721a4c..74049ac 100644 --- a/padre/src/main.rs +++ b/padre/src/main.rs @@ -30,11 +30,12 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use clap::{App, Arg, ArgMatches}; +use libc::{SIGINT, SIGQUIT, SIGTERM}; use tokio::net::TcpListener; use tokio::prelude::*; use tokio::runtime::current_thread::Runtime; use tokio::timer::Delay; -use tokio_signal::unix::{Signal, SIGINT, SIGQUIT, SIGTERM}; +use tokio_net::signal::unix::{signal, SignalKind}; mod config; mod debugger; @@ -94,110 +95,82 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -fn exit_padre(debugger: Arc>) { +fn exit_padre() { //debugger: Arc>) { + println!("QUITTING"); let when = Instant::now() + Duration::new(5, 0); - tokio::spawn({ - Delay::new(when) - .map_err(|e| panic!("timer failed; err={:?}", e)) - .and_then(|_| { - println!("Timed out exiting!"); - exit(-1); - #[allow(unreachable_code)] - Ok(()) - }) - }); - - debugger.lock().unwrap().stop(); + //tokio::spawn({ + // Delay::new(when) + // .map_err(|e| panic!("timer failed; err={:?}", e)) + // .and_then(|_| { + // println!("Timed out exiting!"); + // exit(-1); + // #[allow(unreachable_code)] + // Ok(()) + // }) + //}); + + //debugger.lock().unwrap().stop(); + // + + exit(0); } -struct Runner {} - -impl Future for Runner { - type Item = (); - type Error = (); - - fn poll(&mut self) -> Poll { - let args = get_app_args(); - - let debug_cmd: Vec = args - .values_of("debug_cmd") - .expect("Can't find program to debug, please rerun with correct parameters") - .map(|x| x.to_string()) - .collect::>(); - - let debugger = Arc::new(Mutex::new(debugger::get_debugger( - args.value_of("debugger"), - args.value_of("type"), - debug_cmd, - ))); - - let connection_addr = get_connection(&args); - let listener = TcpListener::bind(&connection_addr) - .map(|listener| { - println!("Listening on {}", &connection_addr); - listener - }) - .expect(&format!("Can't open TCP listener on {}", &connection_addr)); - - let debugger_signal = debugger.clone(); - let signals = Signal::new(SIGINT) - .flatten_stream() - .for_each(move |_| { - exit_padre(debugger_signal.clone()); - Ok(()) - }) - .map_err(|e| { - println!("Caught SIGINT Error: {:?}", e); - }); - - let debugger_signal = debugger.clone(); - let signals = Signal::new(SIGQUIT) - .flatten_stream() - .for_each(move |_| { - exit_padre(debugger_signal.clone()); - Ok(()) - }) - .map_err(|e| { - println!("Caught SIGQUIT Error: {:?}", e); - }) - .join(signals) - .map(|_| {}); - - let debugger_signal = debugger.clone(); - let signals = Signal::new(SIGTERM) - .flatten_stream() - .for_each(move |_| { - exit_padre(debugger_signal.clone()); - Ok(()) - }) - .map_err(|e| { - println!("Caught SIGTERM Error: {:?}", e); - }) - .join(signals) - .map(|_| {}); - - tokio::spawn(signals); - - tokio::spawn( +async fn run_padre() -> () { + let args = get_app_args(); + + let debug_cmd: Vec = args + .values_of("debug_cmd") + .expect("Can't find program to debug, please rerun with correct parameters") + .map(|x| x.to_string()) + .collect::>(); + + // let debugger = Arc::new(Mutex::new(debugger::get_debugger( + // args.value_of("debugger"), + // args.value_of("type"), + // debug_cmd, + // ))); + + let connection_addr = get_connection(&args); + let mut incoming = TcpListener::bind(&connection_addr) + .map(|listener| { + println!("Listening on {}", &connection_addr); listener - .incoming() - .map_err(|e| eprintln!("failed to accept socket; error = {:?}", e)) - .for_each(move |socket| { - server::process_connection(socket, debugger.clone()); + }) + .await + .expect(&format!("Can't open TCP listener on {}", &connection_addr)) + .incoming(); - Ok(()) - }), - ); + // let debugger_signal = debugger.clone(); + let mut signals = signal(SignalKind::interrupt()).unwrap(); - Ok(Async::Ready(())) + while let Some(_) = signals.next().await { + exit_padre(); //debugger_signal.clone()); + } + + let mut signals = signal(SignalKind::quit()).unwrap(); + + while let Some(_) = signals.next().await { + exit_padre(); //debugger_signal.clone()); + } + + let mut signals = signal(SignalKind::terminate()).unwrap(); + + while let Some(_) = signals.next().await { + exit_padre(); //debugger_signal.clone()); + } + + while let Some(Ok(stream)) = incoming.next().await { + tokio::spawn(async move { + server::process_connection(stream); //, debugger.clone()); + }); } } fn main() -> io::Result<()> { let mut runtime = Runtime::new().unwrap(); - runtime.spawn(Runner {}); + runtime.block_on(run_padre()); runtime.run().unwrap(); diff --git a/padre/src/notifier.rs b/padre/src/notifier.rs index 27e3c60..fbb20e4 100644 --- a/padre/src/notifier.rs +++ b/padre/src/notifier.rs @@ -28,7 +28,8 @@ pub enum LogLevel { DEBUG, } -/// A `Listener` is a wrapper around the ... +/// A `Listener` is a wrapper around the socket that we can use to send +/// messages to #[derive(Debug)] struct Listener { sender: Sender, @@ -70,13 +71,13 @@ impl Notifier { /// Send the message to all clients fn send_msg(&mut self, msg: Notification) { for listener in self.listeners.iter_mut() { - let sender = listener.sender.clone(); - tokio::spawn( - sender - .send(PadreSend::Notification(msg.clone())) - .map(|_| ()) - .map_err(|e| eprintln!("Notifier can't send to socket: {}", e)), - ); + let msg_copy = msg.clone(); + let mut sender = listener.sender.clone(); + tokio::spawn(async move { + if let Err(e) = sender.send(PadreSend::Notification(msg_copy)).await { + eprintln!("Notifier can't send to socket: {}", e); + } + }); } } } diff --git a/padre/src/server.rs b/padre/src/server.rs index 2b1ef44..00232aa 100644 --- a/padre/src/server.rs +++ b/padre/src/server.rs @@ -147,109 +147,109 @@ pub enum PadreSend { /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. -pub fn process_connection(socket: TcpStream, debugger: Arc>) { - let addr = socket.peer_addr().unwrap(); +pub fn process_connection(stream: TcpStream) { + //, debugger: Arc>) { + let addr = stream.peer_addr().unwrap(); let config = Arc::new(Mutex::new(Config::new())); - let (request_tx, request_rx) = VimCodec::new().framed(socket).split(); + let (request_tx, request_rx) = VimCodec::new().framed(stream).split(); let (connection_tx, connection_rx) = mpsc::channel(1); add_listener(connection_tx.clone(), addr.clone()); - tokio::spawn( - request_tx - .send_all(connection_rx.map_err(|e| { - eprintln!("failed to retrieve message to send: {}", e); - io::Error::new(io::ErrorKind::Other, e) - })) - .then(|res| { - if let Err(e) = res { - eprintln!("failed to send data to socket; error = {:?}", e); - } - - Ok(()) - }), - ); - - let connection_tx_2 = connection_tx.clone(); + //tokio::spawn( + // request_tx + // .send_all(connection_rx.map_err(|e| { + // eprintln!("failed to retrieve message to send: {}", e); + // io::Error::new(io::ErrorKind::Other, e) + // })) + // .then(|res| { + // if let Err(e) = res { + // eprintln!("failed to send data to socket; error = {:?}", e); + // } + + // Ok(()) + // }), + //); + + //let connection_tx_2 = connection_tx.clone(); + + //tokio::spawn( + // request_rx + // //.and_then(move |req| respond(req, debugger.clone(), config.clone())) + // .for_each(move |resp| { + // tokio::spawn( + // connection_tx_2 + // .clone() + // .send(PadreSend::Response(resp)) + // .map(|_| {}) + // .map_err(|e| println!("Error responding: {}", e)), + // ); + // Ok(()) + // }) + // .map_err(move |e| { + // match e.kind() { + // // Remove socket from notifier if pipe broken, otherwise report error + // std::io::ErrorKind::ConnectionReset => { + // remove_listener(&addr.clone()); + // } + // _ => unreachable!(), + // } + // }), + //); tokio::spawn( - request_rx - .and_then(move |req| respond(req, debugger.clone(), config.clone())) - .for_each(move |resp| { - tokio::spawn( - connection_tx_2 - .clone() - .send(PadreSend::Response(resp)) - .map(|_| {}) - .map_err(|e| println!("Error responding: {}", e)), - ); - Ok(()) - }) - .map_err(move |e| { - match e.kind() { - // Remove socket from notifier if pipe broken, otherwise report error - std::io::ErrorKind::ConnectionReset => { - remove_listener(&addr.clone()); - } - _ => unreachable!(), - } - }), + check_for_and_report_padre_updates() ); - - tokio::spawn(future::lazy(|| { - check_for_and_report_padre_updates(); - Ok(()) - })); } /// Process a PadreRequest. /// /// Forwards the request to the appropriate place to handle it and responds appropriately. -fn respond( - request: PadreRequest, - debugger: Arc>, - config: Arc>, -) -> Box + Send> { - match request.cmd() { - RequestCmd::PadreCmd(cmd) => { - let json_response = match cmd { - PadreCmd::Ping => ping(), - PadreCmd::Pings => pings(), - PadreCmd::GetConfig(key) => get_config(config, key), - PadreCmd::SetConfig(key, value) => set_config(config, key, *value), - }; - - Box::new(future::lazy(move || match json_response { - Ok(args) => Ok(Response::new(request.id(), args)), - Err(e) => { - log_msg(LogLevel::ERROR, &format!("{}", e)); - let resp = serde_json::json!({"status":"ERROR"}); - Ok(Response::new(request.id(), resp)) - } - })) - } - RequestCmd::DebuggerCmd(cmd) => { - let f = match cmd { - DebuggerCmd::V1(v1cmd) => debugger.lock().unwrap().handle_v1_cmd(v1cmd, config), - }; - - Box::new( - f.timeout(Duration::new(30, 0)) - .then(move |resp| match resp { - Ok(s) => Ok(Response::new(request.id(), s)), - Err(e) => { - log_msg(LogLevel::ERROR, &format!("{}", e)); - let resp = serde_json::json!({"status":"ERROR"}); - Ok(Response::new(request.id(), resp)) - } - }), - ) - } - } -} +//fn respond( +// request: PadreRequest, +// debugger: Arc>, +// //config: Arc>, +//) -> Box + Send> { +// match request.cmd() { +// RequestCmd::PadreCmd(cmd) => { +// let json_response = match cmd { +// PadreCmd::Ping => ping(), +// PadreCmd::Pings => pings(), +// PadreCmd::GetConfig(key) => get_config(config, key), +// PadreCmd::SetConfig(key, value) => set_config(config, key, *value), +// }; +// +// Box::new(future::lazy(move || match json_response { +// Ok(args) => Ok(Response::new(request.id(), args)), +// Err(e) => { +// log_msg(LogLevel::ERROR, &format!("{}", e)); +// let resp = serde_json::json!({"status":"ERROR"}); +// Ok(Response::new(request.id(), resp)) +// } +// })) +// } +// RequestCmd::DebuggerCmd(cmd) => { +// let f = match cmd { +// DebuggerCmd::V1(v1cmd) => debugger.lock().unwrap().handle_v1_cmd(v1cmd, config), +// }; +// +// Box::new( +// f.timeout(Duration::new(30, 0)) +// .then(move |resp| match resp { +// Ok(s) => Ok(Response::new(request.id(), s)), +// Err(e) => { +// log_msg(LogLevel::ERROR, &format!("{}", e)); +// let resp = serde_json::json!({"status":"ERROR"}); +// Ok(Response::new(request.id(), resp)) +// } +// }), +// ) +// } +// } +//} fn ping() -> Result { Ok(serde_json::json!({"status":"OK","ping":"pong"})) @@ -261,28 +261,28 @@ fn pings() -> Result { Ok(serde_json::json!({"status":"OK"})) } -fn get_config(config: Arc>, key: &str) -> Result { - let value = config.lock().unwrap().get_config(key); - match value { - Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), - None => Ok(serde_json::json!({"status":"ERROR"})), - } -} - -fn set_config( - config: Arc>, - key: &str, - value: i64, -) -> Result { - let config_set = config.lock().unwrap().set_config(key, value); - match config_set { - true => Ok(serde_json::json!({"status":"OK"})), - false => Ok(serde_json::json!({"status":"ERROR"})), - } -} +//fn get_config(config: Arc>, key: &str) -> Result { +// let value = config.lock().unwrap().get_config(key); +// match value { +// Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), +// None => Ok(serde_json::json!({"status":"ERROR"})), +// } +//} +// +//fn set_config( +// config: Arc>, +// key: &str, +// value: i64, +//) -> Result { +// let config_set = config.lock().unwrap().set_config(key, value); +// match config_set { +// true => Ok(serde_json::json!({"status":"OK"})), +// false => Ok(serde_json::json!({"status":"ERROR"})), +// } +//} /// Checks whether we're on the latest version with git and if not gives a warning -fn check_for_and_report_padre_updates() { +async fn check_for_and_report_padre_updates() { let padre_exe = current_exe().unwrap(); let padre_dir = padre_exe.parent().unwrap(); diff --git a/padre/src/util.rs b/padre/src/util.rs index bf45b1b..ae0a2f4 100644 --- a/padre/src/util.rs +++ b/padre/src/util.rs @@ -7,16 +7,16 @@ use std::io::{self, BufRead}; use std::mem; use std::net::TcpListener; use std::path::{Path, PathBuf}; -use std::process::{exit, Command, Stdio}; +use std::process::{exit, Stdio}; use std::thread; use crate::notifier::{log_msg, LogLevel}; use bytes::Bytes; use tokio::io::AsyncRead; +use tokio::net::process::{Child, ChildStdin, Command}; use tokio::prelude::*; use tokio::sync::mpsc::{self, Sender}; -use tokio_process::{Child, ChildStdin, CommandExt}; const BUFSIZE: usize = 4096; @@ -78,65 +78,65 @@ pub fn check_and_spawn_process(mut debugger_cmd: Vec, run_cmd: Vec Sender { - let (stdin_tx, stdin_rx) = mpsc::channel(1); - let mut tx = stdin_tx.clone(); - - thread::spawn(move || { - let mut stdin = io::stdin(); - loop { - let mut buf = vec![0; 1024]; - let n = match stdin.read(&mut buf) { - Err(_) | Ok(0) => break, - Ok(n) => n, - }; - buf.truncate(n); - tx = match tx.send(Bytes::from(buf)).wait() { - Ok(tx) => tx, - Err(_) => break, - }; - } - }); - - // Current implementation needs a kick, this is all liable to change with - // upcoming versions of tokio anyway so living with it for now. - match stdin.write(&[13]) { - Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {} - _ => unreachable!(), - } - - tokio::spawn( - stdin_rx - .for_each(move |text| { - if output_stdin { - io::stdout().write_all(&text).unwrap(); - } - match stdin.write(&text) { - Ok(_) => {} - Err(e) => { - eprintln!("Writing stdin err e: {}", e); - } - }; - Ok(()) - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - }), - ); - - stdin_tx -} +//pub fn setup_stdin(mut stdin: ChildStdin, output_stdin: bool) -> Sender { +// let (stdin_tx, stdin_rx) = mpsc::channel(1); +// let mut tx = stdin_tx.clone(); +// +// thread::spawn(move || { +// let mut stdin = io::stdin(); +// loop { +// let mut buf = vec![0; 1024]; +// let n = match stdin.read(&mut buf) { +// Err(_) | Ok(0) => break, +// Ok(n) => n, +// }; +// buf.truncate(n); +// tx = match tx.send(Bytes::from(buf)).wait() { +// Ok(tx) => tx, +// Err(_) => break, +// }; +// } +// }); +// +// // Current implementation needs a kick, this is all liable to change with +// // upcoming versions of tokio anyway so living with it for now. +// match stdin.write(&[13]) { +// Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {} +// _ => unreachable!(), +// } +// +// tokio::spawn( +// stdin_rx +// .for_each(move |text| { +// if output_stdin { +// io::stdout().write_all(&text).unwrap(); +// } +// match stdin.write(&text) { +// Ok(_) => {} +// Err(e) => { +// eprintln!("Writing stdin err e: {}", e); +// } +// }; +// Ok(()) +// }) +// .map_err(|e| { +// eprintln!("Reading stdin error {:?}", e); +// }), +// ); +// +// stdin_tx +//} /// Find out if a file is a binary executable (either ELF or Mach-O /// executable). -pub fn file_is_binary_executable(cmd: &str) -> bool { - let output = get_file_type(cmd); +pub async fn file_is_binary_executable(cmd: &str) -> bool { + let output = get_file_type(cmd).await; if output.contains("ELF") || (output.contains("Mach-O") && output.to_ascii_lowercase().contains("executable")) @@ -148,8 +148,8 @@ pub fn file_is_binary_executable(cmd: &str) -> bool { } /// Find out if a file is a text file (either ASCII or UTF-8). -pub fn file_is_text(cmd: &str) -> bool { - let output = get_file_type(cmd); +pub async fn file_is_text(cmd: &str) -> bool { + let output = get_file_type(cmd).await; if output.contains("ASCII") || output.contains("UTF-8") { true @@ -187,11 +187,13 @@ pub fn file_exists(path: &str) -> bool { } /// Get the file type as output by the UNIX `file` command. -fn get_file_type(cmd: &str) -> String { +async fn get_file_type(cmd: &str) -> String { let output = Command::new("file") .arg("-L") // Follow symlinks .arg(cmd) - .output() + .output(); + let output = output + .await .expect(&format!("Can't run file on {} to find file type", cmd)); String::from_utf8_lossy(&output.stdout).to_string() @@ -220,41 +222,41 @@ where } } -impl Stream for ReadOutput -where - A: AsyncRead + BufRead, -{ - type Item = String; - type Error = io::Error; - - fn poll(&mut self) -> Poll, io::Error> { - let mut buf = [0; BUFSIZE]; - loop { - let n = match self.io.read(&mut buf) { - Ok(t) => t, - Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { - return Ok(Async::NotReady); - } - Err(e) => return Err(e.into()), - }; - - if n == 0 && self.text.len() == 0 { - return Ok(None.into()); - } - - if n == BUFSIZE { - let bufstr = String::from_utf8_lossy(&buf[0..n]); - self.text.push_str(&bufstr); - continue; - } - - let bufstr = String::from_utf8_lossy(&buf[0..n]); - self.text.push_str(&bufstr); - break; - } - Ok(Some(mem::replace(&mut self.text, String::new())).into()) - } -} +//impl Stream for ReadOutput +//where +// A: AsyncRead + BufRead, +//{ +// type Item = String; +// type Error = io::Error; +// +// fn poll(&mut self) -> Poll, io::Error> { +// let mut buf = [0; BUFSIZE]; +// loop { +// let n = match self.io.read(&mut buf) { +// Ok(t) => t, +// Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { +// return Ok(Async::NotReady); +// } +// Err(e) => return Err(e.into()), +// }; +// +// if n == 0 && self.text.len() == 0 { +// return Ok(None.into()); +// } +// +// if n == BUFSIZE { +// let bufstr = String::from_utf8_lossy(&buf[0..n]); +// self.text.push_str(&bufstr); +// continue; +// } +// +// let bufstr = String::from_utf8_lossy(&buf[0..n]); +// self.text.push_str(&bufstr); +// break; +// } +// Ok(Some(mem::replace(&mut self.text, String::new())).into()) +// } +//} #[cfg(test)] mod tests { From 96382761a710d2c2238f85bd7d9ca7ecc51e0ad9 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Mon, 21 Oct 2019 13:36:51 +0100 Subject: [PATCH 02/23] Basics --- padre/src/debugger.rs | 29 ++++--- padre/src/main.rs | 77 +++++++++-------- padre/src/server.rs | 192 ++++++++++++++++++------------------------ 3 files changed, 138 insertions(+), 160 deletions(-) diff --git a/padre/src/debugger.rs b/padre/src/debugger.rs index 60e88ec..cc143e1 100644 --- a/padre/src/debugger.rs +++ b/padre/src/debugger.rs @@ -82,6 +82,7 @@ impl Debugger { pub fn stop(&mut self) { //self.debugger.teardown(); + std::process::exit(-1); } pub async fn handle_v1_cmd( @@ -90,14 +91,14 @@ impl Debugger { //config: Arc>, ) -> Result { Ok(serde_json::json!({"status":"OK"})) -// match cmd { -// DebuggerCmdV1::Run => self.debugger.run(), //config), -// DebuggerCmdV1::Breakpoint(fl) => self.debugger.breakpoint(fl), //, config), -// DebuggerCmdV1::StepIn => self.debugger.step_in(), -// DebuggerCmdV1::StepOver => self.debugger.step_over(), -// DebuggerCmdV1::Continue => self.debugger.continue_(), -// DebuggerCmdV1::Print(v) => self.debugger.print(v), //, config), -// } + // match cmd { + // DebuggerCmdV1::Run => self.debugger.run(), //config), + // DebuggerCmdV1::Breakpoint(fl) => self.debugger.breakpoint(fl), //, config), + // DebuggerCmdV1::StepIn => self.debugger.step_in(), + // DebuggerCmdV1::StepOver => self.debugger.step_over(), + // DebuggerCmdV1::Continue => self.debugger.continue_(), + // DebuggerCmdV1::Print(v) => self.debugger.print(v), //, config), + // } } } @@ -166,13 +167,13 @@ pub async fn get_debugger( }, }; -// let mut debugger: lldb::ImplDebugger = match debugger_type { -// DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), -// DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), -// DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), -// }; + // let mut debugger: lldb::ImplDebugger = match debugger_type { + // DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), + // DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), + // DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), + // }; -// debugger.setup(); + // debugger.setup(); Debugger::new() } diff --git a/padre/src/main.rs b/padre/src/main.rs index 74049ac..9d921b0 100644 --- a/padre/src/main.rs +++ b/padre/src/main.rs @@ -34,7 +34,7 @@ use libc::{SIGINT, SIGQUIT, SIGTERM}; use tokio::net::TcpListener; use tokio::prelude::*; use tokio::runtime::current_thread::Runtime; -use tokio::timer::Delay; +use tokio::timer::delay; use tokio_net::signal::unix::{signal, SignalKind}; mod config; @@ -95,25 +95,16 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -fn exit_padre() { //debugger: Arc>) { - println!("QUITTING"); +fn exit_padre(debugger: Arc>) { let when = Instant::now() + Duration::new(5, 0); - //tokio::spawn({ - // Delay::new(when) - // .map_err(|e| panic!("timer failed; err={:?}", e)) - // .and_then(|_| { - // println!("Timed out exiting!"); - // exit(-1); - // #[allow(unreachable_code)] - // Ok(()) - // }) - //}); - - //debugger.lock().unwrap().stop(); - // - - exit(0); + tokio::spawn(async move { + delay(when).await; + println!("Timed out exiting!"); + exit(-1); + }); + + debugger.lock().unwrap().stop(); } async fn run_padre() -> () { @@ -125,11 +116,11 @@ async fn run_padre() -> () { .map(|x| x.to_string()) .collect::>(); - // let debugger = Arc::new(Mutex::new(debugger::get_debugger( - // args.value_of("debugger"), - // args.value_of("type"), - // debug_cmd, - // ))); + // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in + // the case of multiple connections but is there a way around it? + let debugger = Arc::new(Mutex::new( + debugger::get_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd).await, + )); let connection_addr = get_connection(&args); let mut incoming = TcpListener::bind(&connection_addr) @@ -141,28 +132,40 @@ async fn run_padre() -> () { .expect(&format!("Can't open TCP listener on {}", &connection_addr)) .incoming(); - // let debugger_signal = debugger.clone(); - let mut signals = signal(SignalKind::interrupt()).unwrap(); + // TODO: Merge the following into one lot of signals when we know how to - while let Some(_) = signals.next().await { - exit_padre(); //debugger_signal.clone()); - } + let debugger_signals = debugger.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::interrupt()).unwrap(); - let mut signals = signal(SignalKind::quit()).unwrap(); + while let Some(_) = signals.next().await { + exit_padre(debugger_signals.clone()); + } + }); - while let Some(_) = signals.next().await { - exit_padre(); //debugger_signal.clone()); - } + let debugger_signals = debugger.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::quit()).unwrap(); - let mut signals = signal(SignalKind::terminate()).unwrap(); + while let Some(_) = signals.next().await { + exit_padre(debugger_signals.clone()); + } + }); - while let Some(_) = signals.next().await { - exit_padre(); //debugger_signal.clone()); - } + let debugger_signals = debugger.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::terminate()).unwrap(); + + while let Some(_) = signals.next().await { + exit_padre(debugger_signals.clone()); + } + }); while let Some(Ok(stream)) = incoming.next().await { + let debugger_stream = debugger.clone(); + tokio::spawn(async move { - server::process_connection(stream); //, debugger.clone()); + server::process_connection(stream, debugger_stream.clone()); }); } } diff --git a/padre/src/server.rs b/padre/src/server.rs index 00232aa..1c18d73 100644 --- a/padre/src/server.rs +++ b/padre/src/server.rs @@ -147,109 +147,83 @@ pub enum PadreSend { /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. -pub fn process_connection(stream: TcpStream) { - //, debugger: Arc>) { +pub fn process_connection(stream: TcpStream, debugger: Arc>) { let addr = stream.peer_addr().unwrap(); let config = Arc::new(Mutex::new(Config::new())); - let (request_tx, request_rx) = VimCodec::new().framed(stream).split(); + let (mut request_tx, mut request_rx) = VimCodec::new().framed(stream).split(); - let (connection_tx, connection_rx) = mpsc::channel(1); + let (mut connection_tx, mut connection_rx) = mpsc::channel(1); add_listener(connection_tx.clone(), addr.clone()); - //tokio::spawn( - // request_tx - // .send_all(connection_rx.map_err(|e| { - // eprintln!("failed to retrieve message to send: {}", e); - // io::Error::new(io::ErrorKind::Other, e) - // })) - // .then(|res| { - // if let Err(e) = res { - // eprintln!("failed to send data to socket; error = {:?}", e); - // } - - // Ok(()) - // }), - //); - - //let connection_tx_2 = connection_tx.clone(); - - //tokio::spawn( - // request_rx - // //.and_then(move |req| respond(req, debugger.clone(), config.clone())) - // .for_each(move |resp| { - // tokio::spawn( - // connection_tx_2 - // .clone() - // .send(PadreSend::Response(resp)) - // .map(|_| {}) - // .map_err(|e| println!("Error responding: {}", e)), - // ); - // Ok(()) - // }) - // .map_err(move |e| { - // match e.kind() { - // // Remove socket from notifier if pipe broken, otherwise report error - // std::io::ErrorKind::ConnectionReset => { - // remove_listener(&addr.clone()); - // } - // _ => unreachable!(), - // } - // }), - //); - - tokio::spawn( - check_for_and_report_padre_updates() - ); + tokio::spawn(async move { + while let Some(msg) = connection_rx.next().await { + request_tx.send(msg).await.unwrap(); + } + }); + + tokio::spawn(async move { + while let Some(req) = request_rx.next().await { + let resp = respond(req.unwrap(), debugger.clone(), config.clone()).unwrap(); + connection_tx + .clone() + .send(PadreSend::Response(resp)) + .await + .unwrap(); + } + }); + + tokio::spawn(check_for_and_report_padre_updates()); } /// Process a PadreRequest. /// /// Forwards the request to the appropriate place to handle it and responds appropriately. -//fn respond( -// request: PadreRequest, -// debugger: Arc>, -// //config: Arc>, -//) -> Box + Send> { -// match request.cmd() { -// RequestCmd::PadreCmd(cmd) => { -// let json_response = match cmd { -// PadreCmd::Ping => ping(), -// PadreCmd::Pings => pings(), -// PadreCmd::GetConfig(key) => get_config(config, key), -// PadreCmd::SetConfig(key, value) => set_config(config, key, *value), -// }; -// -// Box::new(future::lazy(move || match json_response { -// Ok(args) => Ok(Response::new(request.id(), args)), -// Err(e) => { -// log_msg(LogLevel::ERROR, &format!("{}", e)); -// let resp = serde_json::json!({"status":"ERROR"}); -// Ok(Response::new(request.id(), resp)) -// } -// })) -// } -// RequestCmd::DebuggerCmd(cmd) => { -// let f = match cmd { -// DebuggerCmd::V1(v1cmd) => debugger.lock().unwrap().handle_v1_cmd(v1cmd, config), -// }; -// -// Box::new( -// f.timeout(Duration::new(30, 0)) -// .then(move |resp| match resp { -// Ok(s) => Ok(Response::new(request.id(), s)), -// Err(e) => { -// log_msg(LogLevel::ERROR, &format!("{}", e)); -// let resp = serde_json::json!({"status":"ERROR"}); -// Ok(Response::new(request.id(), resp)) -// } -// }), -// ) -// } -// } -//} +fn respond( + request: PadreRequest, + debugger: Arc>, + config: Arc>, +) -> Result { + match request.cmd() { + RequestCmd::PadreCmd(cmd) => { + let json_response = match cmd { + PadreCmd::Ping => ping(), + PadreCmd::Pings => pings(), + PadreCmd::GetConfig(key) => get_config(config, key), + PadreCmd::SetConfig(key, value) => set_config(config, key, *value), + }; + + match json_response { + Ok(args) => Ok(Response::new(request.id(), args)), + Err(e) => { + log_msg(LogLevel::ERROR, &format!("{}", e)); + let resp = serde_json::json!({"status":"ERROR"}); + Ok(Response::new(request.id(), resp)) + } + } + } + RequestCmd::DebuggerCmd(cmd) => { + //let f = match cmd { + // DebuggerCmd::V1(v1cmd) => debugger.lock().unwrap().handle_v1_cmd(v1cmd, config), + //}; + // + //Box::new( + // f.timeout(Duration::new(30, 0)) + // .then(move |resp| match resp { + // Ok(s) => Ok(Response::new(request.id(), s)), + // Err(e) => { + // log_msg(LogLevel::ERROR, &format!("{}", e)); + // let resp = serde_json::json!({"status":"ERROR"}); + // Ok(Response::new(request.id(), resp)) + // } + // }), + //) + panic!("BALLS"); + } + } +} fn ping() -> Result { Ok(serde_json::json!({"status":"OK","ping":"pong"})) @@ -261,25 +235,25 @@ fn pings() -> Result { Ok(serde_json::json!({"status":"OK"})) } -//fn get_config(config: Arc>, key: &str) -> Result { -// let value = config.lock().unwrap().get_config(key); -// match value { -// Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), -// None => Ok(serde_json::json!({"status":"ERROR"})), -// } -//} -// -//fn set_config( -// config: Arc>, -// key: &str, -// value: i64, -//) -> Result { -// let config_set = config.lock().unwrap().set_config(key, value); -// match config_set { -// true => Ok(serde_json::json!({"status":"OK"})), -// false => Ok(serde_json::json!({"status":"ERROR"})), -// } -//} +fn get_config(config: Arc>, key: &str) -> Result { + let value = config.lock().unwrap().get_config(key); + match value { + Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), + None => Ok(serde_json::json!({"status":"ERROR"})), + } +} + +fn set_config( + config: Arc>, + key: &str, + value: i64, +) -> Result { + let config_set = config.lock().unwrap().set_config(key, value); + match config_set { + true => Ok(serde_json::json!({"status":"OK"})), + false => Ok(serde_json::json!({"status":"ERROR"})), + } +} /// Checks whether we're on the latest version with git and if not gives a warning async fn check_for_and_report_padre_updates() { From ba22d1c3db6c160b822526ffc892d47be6abc1c7 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 24 Oct 2019 07:28:29 +0100 Subject: [PATCH 03/23] Spawns python and can interact with it now, needs finishing --- autoload/padre/debugger.vim | 65 +--- padre/Cargo.lock | 13 +- padre/Cargo.toml | 1 + padre/integration/features/python.feature | 3 +- padre/src/config.rs | 1 + padre/src/debugger.rs | 89 ++--- padre/src/debugger/python/debugger.rs | 426 ++++++++++------------ padre/src/debugger/python/process.rs | 78 ++-- padre/src/main.rs | 10 +- padre/src/server.rs | 41 +-- padre/src/util.rs | 189 +++++----- padre/src/vimcodec.rs | 31 +- 12 files changed, 400 insertions(+), 547 deletions(-) diff --git a/autoload/padre/debugger.vim b/autoload/padre/debugger.vim index e9a189f..6c56e4f 100644 --- a/autoload/padre/debugger.vim +++ b/autoload/padre/debugger.vim @@ -135,7 +135,7 @@ function! padre#debugger#Debug(...) endfunction function! padre#debugger#Run() - call padre#socket#Send({"cmd": "run"}, function('padre#debugger#RunCallback')) + call padre#socket#Send({"cmd": "run"}, function('padre#debugger#GenericCallback')) endfunction function! padre#debugger#Stop() @@ -161,7 +161,7 @@ function! padre#debugger#Stop() endfunction function! s:SetBreakpointInDebugger(line, file) - call padre#socket#Send({"cmd": "breakpoint", "file": a:file, "line": str2nr(a:line)}, function('padre#debugger#BreakpointCallback')) + call padre#socket#Send({"cmd": "breakpoint", "file": a:file, "line": str2nr(a:line)}, function('padre#debugger#GenericCallback')) endfunction function! padre#debugger#Breakpoint() @@ -173,19 +173,19 @@ function! padre#debugger#Breakpoint() endfunction function! padre#debugger#StepIn() - call padre#socket#Send({"cmd": "stepIn"}, function('padre#debugger#StepInCallback')) + call padre#socket#Send({"cmd": "stepIn"}, function('padre#debugger#GenericCallback')) endfunction function! padre#debugger#StepOver() - call padre#socket#Send({"cmd": "stepOver"}, function('padre#debugger#StepOverCallback')) + call padre#socket#Send({"cmd": "stepOver"}, function('padre#debugger#GenericCallback')) endfunction function! padre#debugger#PrintVariable(variable) - call padre#socket#Send({"cmd": "print", "variable": a:variable}, function('padre#debugger#PrintVariableCallback')) + call padre#socket#Send({"cmd": "print", "variable": a:variable}, function('padre#debugger#GenericCallback')) endfunction function! padre#debugger#Continue() - call padre#socket#Send({"cmd": "continue"}, function('padre#debugger#ContinueCallback')) + call padre#socket#Send({"cmd": "continue"}, function('padre#debugger#GenericCallback')) endfunction """""""""""""""" @@ -198,63 +198,12 @@ function! padre#debugger#SignalPADREStarted() endfor endfunction -function! padre#debugger#RunCallback(channel_id, data) +function! padre#debugger#GenericCallback(channel_id, data) if a:data['status'] != 'OK' call padre#debugger#Log(2, 'Error: ' . string(a:data)) - return - endif - - if has_key(a:data, 'pid') - call padre#debugger#Log(4, 'Process ' . a:data['pid'] . ' Running') endif endfunction -function! padre#debugger#BreakpointCallback(channel_id, data) - if a:data['status'] == 'OK' - elseif a:data['status'] == 'PENDING' - call padre#debugger#Log(4, 'Breakpoint pending') - else - call padre#debugger#Log(2, 'Error: ' . string(a:data)) - endif -endfunction - -function! padre#debugger#BreakpointSet(fileName, lineNum) - let l:msg = 'Breakpoint set file=' . a:fileName . ', line=' . a:lineNum - call padre#debugger#Log(4, l:msg) -endfunction - -function! padre#debugger#StepInCallback(channel_id, data) - if a:data['status'] != 'OK' - call padre#debugger#Log(2, 'Error: ' . string(a:data)) - endif -endfunction - -function! padre#debugger#StepOverCallback(channel_id, data) - if a:data['status'] != 'OK' - call padre#debugger#Log(2, 'Error: ' . string(a:data)) - endif -endfunction - -function! padre#debugger#ContinueCallback(channel_id, data) - if a:data['status'] != 'OK' - call padre#debugger#Log(2, 'Error: ' . string(a:data)) - endif -endfunction - -function! padre#debugger#PrintVariableCallback(channel_id, data) - let l:status = remove(a:data, 'status') - if l:status != 'OK' - call padre#debugger#Log(2, 'Error printing variable: ' . string(a:data)) - return - endif - - let l:variable_name = remove(a:data, 'variable') - - execute "let l:json = system('python -m json.tool', '" . substitute(json_encode(a:data), "'", "''", "g") . "')" - let l:msg = 'Variable ' . l:variable_name . "=\n" . l:json - call padre#debugger#Log(4, l:msg) -endfunction - function! padre#debugger#JumpToPosition(file, line) let l:msg = 'Stopped file=' . a:file . ' line=' . a:line call padre#debugger#Log(4, l:msg) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 753d4d0..26b153a 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -540,6 +540,7 @@ dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", @@ -614,7 +615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -899,7 +900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -964,7 +965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1122,7 +1123,7 @@ version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1246,7 +1247,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1511,7 +1512,7 @@ dependencies = [ "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c65d951ab12d976b61a41cf9ed4531fc19735c6e6d84a4bb1453711e762ec731" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" diff --git a/padre/Cargo.toml b/padre/Cargo.toml index 839a4f2..ddda4fc 100644 --- a/padre/Cargo.toml +++ b/padre/Cargo.toml @@ -9,6 +9,7 @@ bytes = "0.4.12" clap = "2.32.0" lazy_static = "1.3.0" libc = "0.2.65" +pin-project = "0.4" regex = "1.1.2" serde = "1.0" serde_derive = "1.0" diff --git a/padre/integration/features/python.feature b/padre/integration/features/python.feature index 5f07e53..8e00266 100644 --- a/padre/integration/features/python.feature +++ b/padre/integration/features/python.feature @@ -5,9 +5,10 @@ Feature: Python Given that we have a test program './test_files/test_prog.py' that runs with 'python3' debugger of type 'python' When I debug the program with PADRE When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#Log | [4,"Launching process"] | + | padre#debugger#Log | [4,"Process launched with pid: \\d+"] | | padre#debugger#JumpToPosition | [".*test_prog.py",3] | When I send a command 'b a' using the terminal Then I expect to be called with diff --git a/padre/src/config.rs b/padre/src/config.rs index 5f7661f..15a1ae6 100644 --- a/padre/src/config.rs +++ b/padre/src/config.rs @@ -25,6 +25,7 @@ use std::collections::HashMap; /// /// Only config items that are meaningful and have defaults can be set and /// retreived. +#[derive(Clone, Debug)] pub struct Config<'a> { config: HashMap<&'a str, i64>, } diff --git a/padre/src/debugger.rs b/padre/src/debugger.rs index cc143e1..70a50f4 100644 --- a/padre/src/debugger.rs +++ b/padre/src/debugger.rs @@ -11,10 +11,11 @@ use crate::config::Config; use crate::util::{file_is_binary_executable, file_is_text}; use tokio::prelude::*; +use tokio::sync::mpsc::Receiver; //mod lldb; //mod node; -//mod python; +mod python; /// Debuggers #[derive(Debug)] @@ -52,12 +53,6 @@ impl Variable { /// All debugger commands #[derive(Clone, Deserialize, Debug, PartialEq)] pub enum DebuggerCmd { - V1(DebuggerCmdV1), -} - -/// All V1 debugger commands -#[derive(Clone, Deserialize, Debug, PartialEq)] -pub enum DebuggerCmdV1 { Run, Breakpoint(FileLocation), StepIn, @@ -68,71 +63,49 @@ pub enum DebuggerCmdV1 { #[derive(Debug)] pub struct Debugger { - //debugger: lldb::ImplDebugger, + debugger: Arc>, } impl Debugger { - pub fn new() -> Debugger { - Debugger {} + pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver) -> Debugger { + let debugger = Debugger { + debugger: impl_debugger.clone(), + }; + + let queue_processing_debugger = impl_debugger.clone(); + + tokio::spawn(async move { + while let Some(cmd) = queue_rx.next().await { + let mut debugger = queue_processing_debugger.lock().unwrap(); + match cmd { + DebuggerCmd::Run => debugger.run(), + DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl), + DebuggerCmd::StepIn => debugger.step_in(), + DebuggerCmd::StepOver => debugger.step_over(), + DebuggerCmd::Continue => debugger.continue_(), + DebuggerCmd::Print(v) => debugger.print(&v), + }; + }; + }); + + debugger } - //pub fn new(debugger: lldb::ImplDebugger) -> Debugger { - // Debugger { debugger } - //} - pub fn stop(&mut self) { - //self.debugger.teardown(); + //self.debugger.lock().unwrap().teardown(); std::process::exit(-1); } - - pub async fn handle_v1_cmd( - &mut self, - cmd: &DebuggerCmdV1, - //config: Arc>, - ) -> Result { - Ok(serde_json::json!({"status":"OK"})) - // match cmd { - // DebuggerCmdV1::Run => self.debugger.run(), //config), - // DebuggerCmdV1::Breakpoint(fl) => self.debugger.breakpoint(fl), //, config), - // DebuggerCmdV1::StepIn => self.debugger.step_in(), - // DebuggerCmdV1::StepOver => self.debugger.step_over(), - // DebuggerCmdV1::Continue => self.debugger.continue_(), - // DebuggerCmdV1::Print(v) => self.debugger.print(v), //, config), - // } - } } -// /// Debugger trait that implements the basics -// pub trait DebuggerV1: Debug { -// fn setup(&mut self); -// fn teardown(&mut self); -// fn run( -// &mut self, -// //config: Arc>, -// ) -> Box + Send>; -// fn breakpoint( -// &mut self, -// file_location: &FileLocation, -// //config: Arc>, -// ) -> Box + Send>; -// fn step_in(&mut self) -> Box + Send>; -// fn step_over(&mut self) -> Box + Send>; -// fn continue_(&mut self) -> Box + Send>; -// fn print( -// &mut self, -// variable: &Variable, -// //config: Arc>, -// ) -> Box + Send>; -// } - /// Get the debugger implementation /// /// If the debugger type is not specified it will try it's best to guess what kind of debugger to /// return. -pub async fn get_debugger( +pub async fn create_debugger( debugger_cmd: Option<&str>, debugger_type: Option<&str>, run_cmd: Vec, + queue_rx: Receiver, ) -> Debugger { let debugger_type = match debugger_type { Some(s) => match s.to_ascii_lowercase().as_str() { @@ -167,15 +140,13 @@ pub async fn get_debugger( }, }; - // let mut debugger: lldb::ImplDebugger = match debugger_type { + let mut debugger: python::ImplDebugger = python::ImplDebugger::new(debugger_cmd, run_cmd); // DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), // DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), // DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), // }; - // debugger.setup(); - - Debugger::new() + Debugger::new(Arc::new(Mutex::new(debugger)), queue_rx) } /// Guesses the debugger type diff --git a/padre/src/debugger/python/debugger.rs b/padre/src/debugger/python/debugger.rs index 368f683..4edf7a9 100644 --- a/padre/src/debugger/python/debugger.rs +++ b/padre/src/debugger/python/debugger.rs @@ -11,7 +11,7 @@ use std::time::Duration; use super::process::{Event, Listener, PDBStatus, Process}; use crate::config::Config; -use crate::debugger::{DebuggerV1, FileLocation, Variable}; +use crate::debugger::{FileLocation, Variable}; use crate::notifier::{log_msg, LogLevel}; use bytes::Bytes; @@ -32,105 +32,55 @@ impl ImplDebugger { } } - fn check_process_running( - &self, - ) -> Option + Send>> { - match self.process.lock().unwrap().get_status() { - PDBStatus::None => { - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"ERROR"}); - Ok(resp) - }); - return Some(Box::new(f)); - } - _ => None, - } - } -} + //fn check_process_running( + // &self, + //) -> Option + Send>> { + // match self.process.lock().unwrap().get_status() { + // PDBStatus::None => { + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"ERROR"}); + // Ok(resp) + // }); + // return Some(Box::new(f)); + // } + // _ => None, + // } + //} -impl DebuggerV1 for ImplDebugger { fn setup(&mut self) {} fn teardown(&mut self) { exit(0); } - fn run( - &mut self, - config: Arc>, - ) -> Box + Send> { - let pending_breakpoints = match self.pending_breakpoints.take() { - Some(pb) => pb, - None => { - let msg = "Process already running, not launching"; - eprintln!("{}", msg); - log_msg(LogLevel::WARN, msg); - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"ERROR"}); - Ok(resp) - }); - return Box::new(f); - } - }; + /// Run python and perform any setup necessary + pub fn run<'a>(&mut self) { + // // TODO: Find a better way of doing this, this madness + // let pending_breakpoints = match self.pending_breakpoints.take() { + // Some(pb) => pb, + // None => { + // let msg = "Process already running, not launching"; + // eprintln!("{}", msg); + // log_msg(LogLevel::WARN, msg); + // return Ok(serde_json::json!({"status":"ERROR"})); + // } + // }; log_msg(LogLevel::INFO, "Launching process"); - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::Launch, tx); - let process = self.process.clone(); - let process2 = self.process.clone(); - - let f = rx - .take(1) - .into_future() - .and_then(move |event| { - match event.0.unwrap() { - Event::Launched => { - for bkpt in &pending_breakpoints { - let stmt = format!("break {}:{}\n", bkpt.name, bkpt.line_num); - process - .clone() - .lock() - .unwrap() - .write_stdin(Bytes::from(stmt)); - } - } - _ => unreachable!(), - } - Ok(()) - }) - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("ProcessSpawnTimeout") - .unwrap() as u64, - 0, - )) - .map(move |_| { - let pid = process2.lock().unwrap().get_pid(); - serde_json::json!({"status":"OK","pid":pid}) - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") - }); - self.process.lock().unwrap().run(); - - Box::new(f) + // TODO: Timeouts + tokio::spawn(async move { + process.lock().unwrap().run(); + }); } - fn breakpoint( + pub fn breakpoint( &mut self, file_location: &FileLocation, - config: Arc>, - ) -> Box + Send> { + //config: Arc>, + ) { log_msg( LogLevel::INFO, &format!( @@ -139,169 +89,169 @@ impl DebuggerV1 for ImplDebugger { ), ); - // If not started yet add as a pending breakpoint that will get set during run period. - match self.process.lock().unwrap().get_status() { - PDBStatus::None => { - match self.pending_breakpoints { - Some(ref mut x) => x.push(file_location.clone()), - None => {} - }; - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"PENDING"}); - Ok(resp) - }); - return Box::new(f); - } - _ => {} - } - - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::Breakpoint, tx); - - let f = rx - .take(1) - .into_future() - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("BreakpointTimeout") - .unwrap() as u64, - 0, - )) - .map(move |event| match event.0.unwrap() { - Event::BreakpointSet(_) => serde_json::json!({"status":"OK"}), - _ => unreachable!(), - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") - }); - - let full_file_path = PathBuf::from(format!("{}", file_location.name)); - let full_file_name = full_file_path.canonicalize().unwrap(); - let stmt = format!( - "break {}:{}\n", - full_file_name.to_str().unwrap(), - file_location.line_num - ); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - Box::new(f) + // // If not started yet add as a pending breakpoint that will get set during run period. + // match self.process.lock().unwrap().get_status() { + // PDBStatus::None => { + // match self.pending_breakpoints { + // Some(ref mut x) => x.push(file_location.clone()), + // None => {} + // }; + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"PENDING"}); + // Ok(resp) + // }); + // return Box::new(f); + // } + // _ => {} + // } + // + // let (tx, rx) = mpsc::channel(1); + // + // self.process + // .lock() + // .unwrap() + // .add_listener(Listener::Breakpoint, tx); + // + // let f = rx + // .take(1) + // .into_future() + // .timeout(Duration::new( + // config + // .lock() + // .unwrap() + // .get_config("BreakpointTimeout") + // .unwrap() as u64, + // 0, + // )) + // .map(move |event| match event.0.unwrap() { + // Event::BreakpointSet(_) => serde_json::json!({"status":"OK"}), + // _ => unreachable!(), + // }) + // .map_err(|e| { + // eprintln!("Reading stdin error {:?}", e); + // io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") + // }); + // + // let full_file_path = PathBuf::from(format!("{}", file_location.name)); + // let full_file_name = full_file_path.canonicalize().unwrap(); + // let stmt = format!( + // "break {}:{}\n", + // full_file_name.to_str().unwrap(), + // file_location.line_num + // ); + // + // self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + // + // Box::new(f) } - fn step_in(&mut self) -> Box + Send> { - match self.check_process_running() { - Some(f) => return f, - None => {} - }; - - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("step\n")); - - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"OK"}); - Ok(resp) - }); - - Box::new(f) + pub fn step_in(&mut self) { + // //match self.check_process_running() { + // // Some(f) => return f, + // // None => {} + // //}; + // + // self.process + // .lock() + // .unwrap() + // .write_stdin(Bytes::from("step\n")); + // + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"OK"}); + // Ok(resp) + // }); + // + // Box::new(f) } - fn step_over(&mut self) -> Box + Send> { - match self.check_process_running() { - Some(f) => return f, - None => {} - }; - - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("next\n")); - - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"OK"}); - Ok(resp) - }); - - Box::new(f) + pub fn step_over(&mut self) { + // //match self.check_process_running() { + // // Some(f) => return f, + // // None => {} + // //}; + // + // self.process + // .lock() + // .unwrap() + // .write_stdin(Bytes::from("next\n")); + // + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"OK"}); + // Ok(resp) + // }); + // + // Box::new(f) } - fn continue_(&mut self) -> Box + Send> { - match self.check_process_running() { - Some(f) => return f, - None => {} - }; - - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("continue\n")); - - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"OK"}); - Ok(resp) - }); - - Box::new(f) + pub fn continue_(&mut self) { + // //match self.check_process_running() { + // // Some(f) => return f, + // // None => {} + // //}; + // + // self.process + // .lock() + // .unwrap() + // .write_stdin(Bytes::from("continue\n")); + // + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"OK"}); + // Ok(resp) + // }); + // + // Box::new(f) } - fn print( + pub fn print( &mut self, variable: &Variable, - config: Arc>, - ) -> Box + Send> { - match self.check_process_running() { - Some(f) => return f, - None => {} - }; - - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .set_status(PDBStatus::Printing(variable.clone())); - - self.process - .lock() - .unwrap() - .add_listener(Listener::PrintVariable, tx); - - let f = rx - .take(1) - .into_future() - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("PrintVariableTimeout") - .unwrap() as u64, - 0, - )) - .map(move |event| match event.0.unwrap() { - Event::PrintVariable(variable, value) => serde_json::json!({ - "status": "OK", - "variable": variable.name, - "value": value, - }), - _ => unreachable!(), - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out printing variable") - }); - - let stmt = format!("print({})\n", variable.name); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - Box::new(f) + //config: Arc>, + ) { + // //match self.check_process_running() { + // // Some(f) => return f, + // // None => {} + // //}; + // + // let (tx, rx) = mpsc::channel(1); + // + // self.process + // .lock() + // .unwrap() + // .set_status(PDBStatus::Printing(variable.clone())); + // + // self.process + // .lock() + // .unwrap() + // .add_listener(Listener::PrintVariable, tx); + // + // let f = rx + // .take(1) + // .into_future() + // .timeout(Duration::new( + // config + // .lock() + // .unwrap() + // .get_config("PrintVariableTimeout") + // .unwrap() as u64, + // 0, + // )) + // .map(move |event| match event.0.unwrap() { + // Event::PrintVariable(variable, value) => serde_json::json!({ + // "status": "OK", + // "variable": variable.name, + // "value": value, + // }), + // _ => unreachable!(), + // }) + // .map_err(|e| { + // eprintln!("Reading stdin error {:?}", e); + // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") + // }); + // + // let stmt = format!("print({})\n", variable.name); + // + // self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + // + // Box::new(f) } } diff --git a/padre/src/debugger/python/process.rs b/padre/src/debugger/python/process.rs index 8599816..8f47cec 100644 --- a/padre/src/debugger/python/process.rs +++ b/padre/src/debugger/python/process.rs @@ -5,11 +5,11 @@ //! happening then. use std::collections::HashMap; -use std::io::BufReader; +use std::io; use std::path::Path; #[cfg(not(test))] use std::process::exit; -use std::process::{Command, Stdio}; +use std::process::Stdio; use std::sync::{Arc, Mutex}; use crate::debugger::{FileLocation, Variable}; @@ -21,9 +21,10 @@ use crate::util::{read_output, setup_stdin}; use bytes::Bytes; use regex::Regex; +use tokio::io::BufReader; +use tokio::net::process::{Command, Child, ChildStderr, ChildStdout}; use tokio::prelude::*; use tokio::sync::mpsc::Sender; -use tokio_process::{Child, ChildStderr, ChildStdout, CommandExt}; #[derive(Debug, Clone, PartialEq)] pub enum PDBStatus { @@ -91,9 +92,11 @@ impl Process { .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .spawn_async() + .spawn() .expect("Failed to spawn debugger"); + log_msg(LogLevel::INFO, &format!("Process launched with pid: {}", process.id())); + self.setup_stdout( process .stdout() @@ -139,39 +142,35 @@ impl Process { /// Send a message to write to stdin pub fn write_stdin(&mut self, bytes: Bytes) { let tx = self.stdin_tx.clone(); - tokio::spawn( + tokio::spawn(async move { tx.clone() .unwrap() .send(bytes) .map(move |_| {}) - .map_err(|e| eprintln!("Error sending to Python: {}", e)), - ); + .await + }); } /// Perform setup of reading Python stdout, analysing it and writing it back to stdout. fn setup_stdout(&mut self, stdout: ChildStdout) { let analyser = self.analyser.clone(); - tokio::spawn( - read_output(BufReader::new(stdout)) - .for_each(move |text| { - print!("{}", text); - analyser.lock().unwrap().analyse_stdout(&text); - Ok(()) - }) - .map_err(|e| eprintln!("Err reading Python stdout: {}", e)), - ); + tokio::spawn(async move { + let mut reader = read_output(BufReader::new(stdout)); + while let Some(Ok(text)) = reader.next().await { + print!("{}", text); + analyser.lock().unwrap().analyse_stdout(&text); + } + }); } /// Perform setup of reading Python stderr, analysing it and writing it back to stdout. fn setup_stderr(&mut self, stderr: ChildStderr) { - tokio::spawn( - read_output(BufReader::new(stderr)) - .for_each(move |text| { - eprint!("{}", text); - Ok(()) - }) - .map_err(|e| eprintln!("Err reading Python stderr: {}", e)), - ); + tokio::spawn(async { + let mut reader = read_output(BufReader::new(stderr)); + while let Some(Ok(text)) = reader.next().await { + eprint!("{}", text); + } + }); } } @@ -347,8 +346,10 @@ impl Analyser { fn python_launched(&mut self) { self.status = PDBStatus::Running; match self.listeners.remove(&Listener::Launch) { - Some(listener) => { - listener.send(Event::Launched).wait().unwrap(); + Some(mut listener) => { + tokio::spawn(async move { + listener.send(Event::Launched).await.unwrap(); + }); } None => {} } @@ -358,11 +359,13 @@ impl Analyser { breakpoint_set(&file, line); let file_location = FileLocation::new(file, line); match self.listeners.remove(&Listener::Breakpoint) { - Some(listener) => { - listener - .send(Event::BreakpointSet(file_location)) - .wait() - .unwrap(); + Some(mut listener) => { + tokio::spawn(async move { + listener + .send(Event::BreakpointSet(file_location)) + .await + .unwrap(); + }); } None => {} } @@ -376,11 +379,14 @@ impl Analyser { let to = data.len() - 2; match self.listeners.remove(&Listener::PrintVariable) { - Some(listener) => { - listener - .send(Event::PrintVariable(variable, data[0..to].to_string())) - .wait() - .unwrap(); + Some(mut listener) => { + let event = Event::PrintVariable(variable, data[0..to].to_string()); + tokio::spawn(async move { + listener + .send(event) + .await + .unwrap(); + }); } None => {} } diff --git a/padre/src/main.rs b/padre/src/main.rs index 9d921b0..45442c2 100644 --- a/padre/src/main.rs +++ b/padre/src/main.rs @@ -36,6 +36,7 @@ use tokio::prelude::*; use tokio::runtime::current_thread::Runtime; use tokio::timer::delay; use tokio_net::signal::unix::{signal, SignalKind}; +use tokio::sync::mpsc; mod config; mod debugger; @@ -116,10 +117,12 @@ async fn run_padre() -> () { .map(|x| x.to_string()) .collect::>(); + let (debugger_queue_tx, debugger_queue_rx) = mpsc::channel(128); + // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? let debugger = Arc::new(Mutex::new( - debugger::get_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd).await, + debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, )); let connection_addr = get_connection(&args); @@ -162,10 +165,9 @@ async fn run_padre() -> () { }); while let Some(Ok(stream)) = incoming.next().await { - let debugger_stream = debugger.clone(); - + let debugger_queue_tx = debugger_queue_tx.clone(); tokio::spawn(async move { - server::process_connection(stream, debugger_stream.clone()); + server::process_connection(stream, debugger_queue_tx.clone()); }); } } diff --git a/padre/src/server.rs b/padre/src/server.rs index 1c18d73..edb51b8 100644 --- a/padre/src/server.rs +++ b/padre/src/server.rs @@ -8,7 +8,6 @@ use std::io; use std::process::{Command, Stdio}; use std::str; use std::sync::{Arc, Mutex}; -use std::time::Duration; use crate::config::Config; use crate::debugger::{Debugger, DebuggerCmd}; @@ -18,7 +17,7 @@ use crate::vimcodec::VimCodec; use tokio::codec::Decoder; use tokio::net::TcpStream; use tokio::prelude::*; -use tokio::sync::mpsc; +use tokio::sync::mpsc::{self, Sender}; // TODO: Get some of this out of pub use and just in this module? @@ -147,10 +146,10 @@ pub enum PadreSend { /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. -pub fn process_connection(stream: TcpStream, debugger: Arc>) { +pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender) { let addr = stream.peer_addr().unwrap(); - let config = Arc::new(Mutex::new(Config::new())); + let mut config = Config::new(); let (mut request_tx, mut request_rx) = VimCodec::new().framed(stream).split(); @@ -166,7 +165,7 @@ pub fn process_connection(stream: TcpStream, debugger: Arc>) { tokio::spawn(async move { while let Some(req) = request_rx.next().await { - let resp = respond(req.unwrap(), debugger.clone(), config.clone()).unwrap(); + let resp = respond(req.unwrap(), debugger_queue_tx.clone(), &mut config).await.unwrap(); connection_tx .clone() .send(PadreSend::Response(resp)) @@ -181,10 +180,10 @@ pub fn process_connection(stream: TcpStream, debugger: Arc>) { /// Process a PadreRequest. /// /// Forwards the request to the appropriate place to handle it and responds appropriately. -fn respond( +async fn respond<'a>( request: PadreRequest, - debugger: Arc>, - config: Arc>, + mut debugger_queue_tx: Sender, + config: &mut Config<'a>, ) -> Result { match request.cmd() { RequestCmd::PadreCmd(cmd) => { @@ -205,22 +204,8 @@ fn respond( } } RequestCmd::DebuggerCmd(cmd) => { - //let f = match cmd { - // DebuggerCmd::V1(v1cmd) => debugger.lock().unwrap().handle_v1_cmd(v1cmd, config), - //}; - // - //Box::new( - // f.timeout(Duration::new(30, 0)) - // .then(move |resp| match resp { - // Ok(s) => Ok(Response::new(request.id(), s)), - // Err(e) => { - // log_msg(LogLevel::ERROR, &format!("{}", e)); - // let resp = serde_json::json!({"status":"ERROR"}); - // Ok(Response::new(request.id(), resp)) - // } - // }), - //) - panic!("BALLS"); + debugger_queue_tx.send(cmd.clone()).await.unwrap(); + Ok(Response::new(request.id(), serde_json::json!({"status":"OK"}))) } } } @@ -235,8 +220,8 @@ fn pings() -> Result { Ok(serde_json::json!({"status":"OK"})) } -fn get_config(config: Arc>, key: &str) -> Result { - let value = config.lock().unwrap().get_config(key); +fn get_config(config: &Config, key: &str) -> Result { + let value = config.get_config(key); match value { Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), None => Ok(serde_json::json!({"status":"ERROR"})), @@ -244,11 +229,11 @@ fn get_config(config: Arc>, key: &str) -> Result>, + config: &mut Config, key: &str, value: i64, ) -> Result { - let config_set = config.lock().unwrap().set_config(key, value); + let config_set = config.set_config(key, value); match config_set { true => Ok(serde_json::json!({"status":"OK"})), false => Ok(serde_json::json!({"status":"ERROR"})), diff --git a/padre/src/util.rs b/padre/src/util.rs index ae0a2f4..c319833 100644 --- a/padre/src/util.rs +++ b/padre/src/util.rs @@ -3,23 +3,24 @@ //! Various simple utilities for use in PADRE use std::env; -use std::io::{self, BufRead}; +use std::io::{self, BufRead, Write}; use std::mem; use std::net::TcpListener; use std::path::{Path, PathBuf}; +use std::pin::Pin; use std::process::{exit, Stdio}; -use std::thread; +use std::task::{Context, Poll}; use crate::notifier::{log_msg, LogLevel}; use bytes::Bytes; -use tokio::io::AsyncRead; +use pin_project::{pin_project, project}; +use tokio::codec::{FramedRead, LinesCodec}; +use tokio::io::{stdin, AsyncBufRead}; use tokio::net::process::{Child, ChildStdin, Command}; use tokio::prelude::*; use tokio::sync::mpsc::{self, Sender}; -const BUFSIZE: usize = 4096; - /// Get an unused port on the local system and return it. This port /// can subsequently be used. pub fn get_unused_localhost_port() -> u16 { @@ -84,54 +85,34 @@ pub fn check_and_spawn_process(mut debugger_cmd: Vec, run_cmd: Vec Sender { -// let (stdin_tx, stdin_rx) = mpsc::channel(1); -// let mut tx = stdin_tx.clone(); -// -// thread::spawn(move || { -// let mut stdin = io::stdin(); -// loop { -// let mut buf = vec![0; 1024]; -// let n = match stdin.read(&mut buf) { -// Err(_) | Ok(0) => break, -// Ok(n) => n, -// }; -// buf.truncate(n); -// tx = match tx.send(Bytes::from(buf)).wait() { -// Ok(tx) => tx, -// Err(_) => break, -// }; -// } -// }); -// -// // Current implementation needs a kick, this is all liable to change with -// // upcoming versions of tokio anyway so living with it for now. -// match stdin.write(&[13]) { -// Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {} -// _ => unreachable!(), -// } -// -// tokio::spawn( -// stdin_rx -// .for_each(move |text| { -// if output_stdin { -// io::stdout().write_all(&text).unwrap(); -// } -// match stdin.write(&text) { -// Ok(_) => {} -// Err(e) => { -// eprintln!("Writing stdin err e: {}", e); -// } -// }; -// Ok(()) -// }) -// .map_err(|e| { -// eprintln!("Reading stdin error {:?}", e); -// }), -// ); -// -// stdin_tx -//} +pub fn setup_stdin(mut child_stdin: ChildStdin, output_stdin: bool) -> Sender { + let (stdin_tx, mut stdin_rx) = mpsc::channel(1); + let mut tx = stdin_tx.clone(); + + tokio::spawn(async move { + let tokio_stdin = stdin(); + let mut reader = FramedRead::new(tokio_stdin, LinesCodec::new()); + while let Some(line) = reader.next().await { + tx.send(Bytes::from(line.unwrap() + "\n")).await.unwrap(); + } + }); + + tokio::spawn(async move { + while let Some(text) = stdin_rx.next().await { + if output_stdin { + io::stdout().write_all(&text).unwrap(); + } + match child_stdin.write(&text).await { + Ok(s) => {} + Err(e) => { + eprintln!("Writing stdin err e: {}", e); + } + }; + } + }); + + stdin_tx +} /// Find out if a file is a binary executable (either ELF or Mach-O /// executable). @@ -202,61 +183,75 @@ async fn get_file_type(cmd: &str) -> String { // The following largely taken from tokio::io::lines code. /// Combinator created by `read_output` method which is a stream over text on an I/O object. +#[pin_project] #[derive(Debug)] -pub struct ReadOutput { - io: A, - text: String, +pub struct ReadOutput { + #[pin] + reader: R, + buf: Vec } /// Creates a new stream from the I/O object /// -/// This method takes an asynchronous I/O object, `a`, and returns a `Stream` of text that the -/// object contains. The returned stream will reach its end once `a` reaches EOF. -pub fn read_output(a: A) -> ReadOutput +/// This method takes an asynchronous I/O object, `reader`, and returns a `Stream` of text that +/// the object contains. The returned stream will reach its end once `reader` reaches EOF. +pub fn read_output(reader: R) -> ReadOutput where - A: AsyncRead + BufRead, + R: AsyncBufRead, { ReadOutput { - io: a, - text: String::new(), + reader, + buf: Vec::new(), } } -//impl Stream for ReadOutput -//where -// A: AsyncRead + BufRead, -//{ -// type Item = String; -// type Error = io::Error; -// -// fn poll(&mut self) -> Poll, io::Error> { -// let mut buf = [0; BUFSIZE]; -// loop { -// let n = match self.io.read(&mut buf) { -// Ok(t) => t, -// Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { -// return Ok(Async::NotReady); -// } -// Err(e) => return Err(e.into()), -// }; -// -// if n == 0 && self.text.len() == 0 { -// return Ok(None.into()); -// } -// -// if n == BUFSIZE { -// let bufstr = String::from_utf8_lossy(&buf[0..n]); -// self.text.push_str(&bufstr); -// continue; -// } -// -// let bufstr = String::from_utf8_lossy(&buf[0..n]); -// self.text.push_str(&bufstr); -// break; -// } -// Ok(Some(mem::replace(&mut self.text, String::new())).into()) -// } -//} +impl Stream for ReadOutput { + type Item = io::Result; + + #[project] + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + #[project] + let ReadOutput { + mut reader, + buf, + } = self.project(); + + loop { + let used = { + match reader.as_mut().poll_fill_buf(cx) { + Poll::Ready(s) => { + match s { + Ok(t) => { + buf.extend_from_slice(t); + t.len() + } + Err(e) => { + println!("What to do here? {:?}", e); + 0 + } + } + } + Poll::Pending => { + 0 + } + } + }; + + if used == 0 { + break; + } + + reader.as_mut().consume(used); + } + + if buf.len() == 0 { + return Poll::Pending; + } + + let buf_freeze = mem::replace(buf, Vec::new()); + Poll::Ready(Some(Ok(String::from_utf8(buf_freeze).unwrap()))) + } +} #[cfg(test)] mod tests { diff --git a/padre/src/vimcodec.rs b/padre/src/vimcodec.rs index 967da1a..7e59b6e 100644 --- a/padre/src/vimcodec.rs +++ b/padre/src/vimcodec.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use std::io; -use crate::debugger::{DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +use crate::debugger::{DebuggerCmd, FileLocation, Variable}; use crate::server::{PadreCmd, PadreRequest, PadreSend, RequestCmd}; use crate::util; @@ -305,26 +305,26 @@ impl Decoder for VimCodec { ))), "run" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run)), + RequestCmd::DebuggerCmd(DebuggerCmd::Run), ))), "stepOver" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::StepOver)), + RequestCmd::DebuggerCmd(DebuggerCmd::StepOver), ))), "stepIn" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::StepIn)), + RequestCmd::DebuggerCmd(DebuggerCmd::StepIn), ))), "continue" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Continue)), + RequestCmd::DebuggerCmd(DebuggerCmd::Continue), ))), "breakpoint" => { let file_location = self.get_file_location(&mut args); match file_location { Some(fl) => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Breakpoint(fl))), + RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(fl)), ))), None => return Ok(None), } @@ -334,7 +334,7 @@ impl Decoder for VimCodec { match variable { Some(v) => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Print(v))), + RequestCmd::DebuggerCmd(DebuggerCmd::Print(v)), ))), None => return Ok(None), } @@ -420,7 +420,7 @@ impl Encoder for VimCodec { #[cfg(test)] mod tests { - use crate::debugger::{DebuggerCmd, DebuggerCmdV1}; + use crate::debugger::DebuggerCmd; use crate::server::{Notification, PadreCmd, PadreRequest, PadreSend, RequestCmd, Response}; use bytes::{BufMut, BytesMut}; @@ -436,10 +436,7 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); assert_eq!( - PadreRequest::new( - 123, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run)) - ), + PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), padre_request ); } @@ -454,10 +451,7 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); assert_eq!( - PadreRequest::new( - 123, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run)) - ), + PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), padre_request ); @@ -490,10 +484,7 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); assert_eq!( - PadreRequest::new( - 123, - RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run)) - ), + PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), padre_request ); } From 0372d3c31fe750ad73c0cb66024f388f90e240b9 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Fri, 29 Nov 2019 16:18:19 +0000 Subject: [PATCH 04/23] Initial refactoring into modules --- padre/Cargo.lock | 1460 ++++------------- padre/Cargo.toml | 29 +- padre/cli/Cargo.toml | 14 + padre/{ => cli}/src/debugger.rs | 4 +- padre/{ => cli}/src/main.rs | 64 +- padre/core/Cargo.lock | 311 ++++ padre/core/Cargo.toml | 22 + padre/{ => core}/src/config.rs | 0 padre/core/src/lib.rs | 11 + padre/{ => core}/src/notifier.rs | 1 - padre/{ => core}/src/server.rs | 44 +- padre/{ => core}/src/util.rs | 9 +- padre/{ => core}/src/vimcodec.rs | 16 +- .../debugger => debuggers}/lldb/debugger.rs | 0 padre/{src/debugger => debuggers}/lldb/mod.rs | 0 .../debugger => debuggers}/lldb/process.rs | 0 .../debugger => debuggers}/node/analyser.rs | 0 .../debugger => debuggers}/node/debugger.rs | 0 padre/{src/debugger => debuggers}/node/mod.rs | 0 .../debugger => debuggers}/node/process.rs | 0 padre/{src/debugger => debuggers}/node/ws.rs | 0 padre/debuggers/python/Cargo.lock | 311 ++++ padre/debuggers/python/Cargo.toml | 16 + .../python/src}/debugger.rs | 8 +- .../mod.rs => debuggers/python/src/lib.rs} | 0 .../python/src}/process.rs | 9 +- 26 files changed, 1057 insertions(+), 1272 deletions(-) create mode 100644 padre/cli/Cargo.toml rename padre/{ => cli}/src/debugger.rs (98%) rename padre/{ => cli}/src/main.rs (78%) create mode 100644 padre/core/Cargo.lock create mode 100644 padre/core/Cargo.toml rename padre/{ => core}/src/config.rs (100%) create mode 100644 padre/core/src/lib.rs rename padre/{ => core}/src/notifier.rs (99%) rename padre/{ => core}/src/server.rs (91%) rename padre/{ => core}/src/util.rs (97%) rename padre/{ => core}/src/vimcodec.rs (97%) rename padre/{src/debugger => debuggers}/lldb/debugger.rs (100%) rename padre/{src/debugger => debuggers}/lldb/mod.rs (100%) rename padre/{src/debugger => debuggers}/lldb/process.rs (100%) rename padre/{src/debugger => debuggers}/node/analyser.rs (100%) rename padre/{src/debugger => debuggers}/node/debugger.rs (100%) rename padre/{src/debugger => debuggers}/node/mod.rs (100%) rename padre/{src/debugger => debuggers}/node/process.rs (100%) rename padre/{src/debugger => debuggers}/node/ws.rs (100%) create mode 100644 padre/debuggers/python/Cargo.lock create mode 100644 padre/debuggers/python/Cargo.toml rename padre/{src/debugger/python => debuggers/python/src}/debugger.rs (98%) rename padre/{src/debugger/python/mod.rs => debuggers/python/src/lib.rs} (100%) rename padre/{src/debugger/python => debuggers/python/src}/process.rs (98%) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 26b153a..7640091 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -4,1554 +4,648 @@ name = "aho-corasick" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "arc-swap" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arrayvec" -version = "0.4.11" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.3.8", ] [[package]] name = "bitflags" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "c2-chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.40" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam-channel" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.28" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] [[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" +name = "futures-channel" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-sink", ] [[package]] -name = "futures-core-preview" -version = "0.3.0-alpha.19" +name = "futures-core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" [[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" +name = "futures-executor" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] [[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" +name = "futures-io" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" [[package]] -name = "getrandom" -version = "0.1.11" +name = "futures-macro" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "httparse" -version = "1.3.4" +name = "futures-sink" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" [[package]] -name = "hyper" -version = "0.10.16" +name = "futures-task" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", ] [[package]] -name = "idna" -version = "0.1.5" +name = "hermit-abi" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" [[package]] name = "mio" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow 0.2.1", + "net2", + "slab", + "winapi 0.2.8", ] [[package]] name = "mio-named-pipes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "mio", + "miow 0.3.3", + "winapi 0.3.8", ] [[package]] name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec", + "libc", + "mio", ] [[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] name = "miow" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" dependencies = [ - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-tls" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2", + "winapi 0.3.8", ] [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "winapi 0.3.8", ] -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl" -version = "0.10.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl-sys" -version = "0.9.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "padre" -version = "0.1.0" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.0" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "futures", + "libc", + "padre_core", + "tokio", ] [[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "padre_core" +version = "0.2.0" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "lazy_static", + "pin-project", + "regex", + "serde", + "serde_derive", + "serde_json", + "tokio", + "tokio-util", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "pin-project" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" dependencies = [ - "pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-utils" -version = "0.1.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pkg-config" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ppv-lite86" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "1.0.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "quote" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" +name = "pin-project-lite" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" [[package]] -name = "rand_hc" -version = "0.2.0" +name = "pin-utils" +version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" [[package]] -name = "rand_isaac" -version = "0.1.1" +name = "proc-macro-hack" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" +name = "proc-macro-nested" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" [[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "proc-macro2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "quote" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" [[package]] name = "ryu" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safemem" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "schannel" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "security-framework" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] name = "serde" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" [[package]] name = "serde_derive" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "signal-hook-registry" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" dependencies = [ - "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap", + "libc", ] [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallvec" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "socket2" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tempfile" -version = "3.1.0" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89693ae015201f8de93fd96bde2d065f8bfc3f97ce006d5bc9f900b97c0c7c0" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "tokio" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-macros" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-net" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.3.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tls" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beeef686ef92a222de07e089f455d9f8478bbba9651718f9e4b276babe829082" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-attributes 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-core" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "fnv", + "futures-core", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-named-pipes", + "mio-uds", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "slab", + "tokio-macros", + "winapi 0.3.8", ] [[package]] -name = "unicode-bidi" -version = "0.3.4" +name = "tokio-macros" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5795a71419535c6dcecc9b6ca95bdd3c2d6142f7e8343d7beb9923f129aa87e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] -name = "unicode-normalization" -version = "0.1.8" +name = "tokio-util" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", ] [[package]] name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "vcpkg" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "websocket" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] - -[metadata] -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" -"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" -"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" -"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" -"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "562cc58f3e865231cf1fa1760097159a642018f5953ffbfe4f2df2ef72bf0d90" -"checksum pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "21a5bc357e14eb5cc61f4e24867b3aec66b850d83ea830beffa2244ad7a97f1e" -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" -"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" -"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f17f5d6ab0f35c1506678b28fb1798bdf74fcb737e9843c7b17b73e426eba38" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9f5d22fd1e84bd4045d28813491cb7d7caae34d45c80517c2213f09a85e8787a" -"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" -"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" -"checksum tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf85e16971e06e680c622e0c1b455be94b086275c5ddcd6d4a83a2bfbb83cda" -"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "112784d5543df30660b04a72ca423bfbd90e8bb32f94dcf610f15401218b22c5" -"checksum tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "86b616374bcdadd95974e1f0dfca07dc913f1163c53840c0d664aca35114964e" -"checksum tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a441682cd32f3559383112c4a7f372f5c9fa1950c5cf8c8dd05274a2ce8c2654" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" -"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b97c1587fe71018eb245a4a9daa13a5a3b681bbc1f7fdadfe24720e141472c13" -"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tracing 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c21ff9457accc293386c20e8f754d0b059e67e325edf2284f04230d125d7e5ff" -"checksum tracing-attributes 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff978fd9c9afe2cc9c671e247713421c6406b3422305cbdce5de695d3ab4c3c" -"checksum tracing-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "528c8ebaaa16cdac34795180b046c031775b0d56402704d98c096788f33d646a" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" -"checksum websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0adcd2a64c5746c9702b354a1b992802b0c363df1dfa324a74cb7aebe10e0cbf" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/padre/Cargo.toml b/padre/Cargo.toml index ddda4fc..f5a7593 100644 --- a/padre/Cargo.toml +++ b/padre/Cargo.toml @@ -1,25 +1,6 @@ -[package] -name = "padre" -version = "0.1.0" -authors = ["Steven Trotter "] -edition = "2018" +[workspace] -[dependencies] -bytes = "0.4.12" -clap = "2.32.0" -lazy_static = "1.3.0" -libc = "0.2.65" -pin-project = "0.4" -regex = "1.1.2" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -websocket = "0.22.4" - -[dependencies.tokio] -version = "^0.2.0-alpha.6" -features = ["process"] - -[dependencies.tokio-net] -version = "^0.2.0-alpha.6" -features = ["signal"] +members = [ + "cli", + "core" +] diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml new file mode 100644 index 0000000..394bae4 --- /dev/null +++ b/padre/cli/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "padre" +version = "0.2.0" +authors = ["Steven Trotter "] +edition = "2018" +license = "APACHE" +repository = "https://github.com/strottos/vim-padre" + +[dependencies] +clap = "2.32.0" +futures = "0.3.1" +libc = "0.2.65" +padre_core = { path = "../core", version = "0.2.0" } +tokio = { version = "0.2.1", features = ["full"] } diff --git a/padre/src/debugger.rs b/padre/cli/src/debugger.rs similarity index 98% rename from padre/src/debugger.rs rename to padre/cli/src/debugger.rs index 70a50f4..bbddb57 100644 --- a/padre/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -7,8 +7,8 @@ use std::fmt::Debug; use std::io; use std::sync::{Arc, Mutex}; -use crate::config::Config; -use crate::util::{file_is_binary_executable, file_is_text}; +use padre_core::config::Config; +use padre_core::util::{file_is_binary_executable, file_is_text}; use tokio::prelude::*; use tokio::sync::mpsc::Receiver; diff --git a/padre/src/main.rs b/padre/cli/src/main.rs similarity index 78% rename from padre/src/main.rs rename to padre/cli/src/main.rs index 45442c2..b00af7a 100644 --- a/padre/src/main.rs +++ b/padre/cli/src/main.rs @@ -18,32 +18,23 @@ //! ``` //! will run the program `my_program arg1 arg2 3 4` in an `lldb` session. -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate serde_derive; - use std::io; use std::net::SocketAddr; use std::process::exit; use std::sync::{Arc, Mutex}; -use std::time::{Duration, Instant}; +use std::time::Duration; use clap::{App, Arg, ArgMatches}; +use futures::prelude::*; use libc::{SIGINT, SIGQUIT, SIGTERM}; use tokio::net::TcpListener; -use tokio::prelude::*; -use tokio::runtime::current_thread::Runtime; -use tokio::timer::delay; -use tokio_net::signal::unix::{signal, SignalKind}; +use tokio::runtime::Runtime; +use tokio::time::delay_for; +use tokio::signal::unix::{signal, SignalKind}; use tokio::sync::mpsc; -mod config; -mod debugger; -mod notifier; -mod server; -mod util; -mod vimcodec; +use padre_core::server; +use padre_core::util; fn get_app_args<'a>() -> ArgMatches<'a> { App::new("VIM Padre") @@ -96,16 +87,16 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -fn exit_padre(debugger: Arc>) { - let when = Instant::now() + Duration::new(5, 0); +fn exit_padre() { //debugger: Arc>) { + let when = Duration::new(5, 0); tokio::spawn(async move { - delay(when).await; + delay_for(when).await; println!("Timed out exiting!"); exit(-1); }); - debugger.lock().unwrap().stop(); + //debugger.lock().unwrap().stop(); } async fn run_padre() -> () { @@ -121,46 +112,47 @@ async fn run_padre() -> () { // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? - let debugger = Arc::new(Mutex::new( - debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, - )); + // let debugger = Arc::new(Mutex::new( + // debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, + // )); let connection_addr = get_connection(&args); - let mut incoming = TcpListener::bind(&connection_addr) + let mut connection = TcpListener::bind(&connection_addr) .map(|listener| { println!("Listening on {}", &connection_addr); listener }) .await - .expect(&format!("Can't open TCP listener on {}", &connection_addr)) - .incoming(); + .expect(&format!("Can't open TCP listener on {}", &connection_addr)); + + let mut incoming = connection.incoming(); // TODO: Merge the following into one lot of signals when we know how to - let debugger_signals = debugger.clone(); + //let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::interrupt()).unwrap(); - while let Some(_) = signals.next().await { - exit_padre(debugger_signals.clone()); + while let Some(_) = signals.recv().await { + exit_padre(); //debugger_signals.clone()); } }); - let debugger_signals = debugger.clone(); + //let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::quit()).unwrap(); - while let Some(_) = signals.next().await { - exit_padre(debugger_signals.clone()); + while let Some(_) = signals.recv().await { + exit_padre(); //debugger_signals.clone()); } }); - let debugger_signals = debugger.clone(); + //let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::terminate()).unwrap(); - while let Some(_) = signals.next().await { - exit_padre(debugger_signals.clone()); + while let Some(_) = signals.recv().await { + exit_padre(); //debugger_signals.clone()); } }); @@ -177,7 +169,5 @@ fn main() -> io::Result<()> { runtime.block_on(run_padre()); - runtime.run().unwrap(); - Ok(()) } diff --git a/padre/core/Cargo.lock b/padre/core/Cargo.lock new file mode 100644 index 0000000..d620e13 --- /dev/null +++ b/padre/core/Cargo.lock @@ -0,0 +1,311 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bytes" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "padre" +version = "0.2.0" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.1 (git+https://github.com/tokio-rs/tokio/)", +] + +[[package]] +name = "pin-project" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.2.1" +source = "git+https://github.com/tokio-rs/tokio/#524e66314faacd9803792ce2a9dc13befd2ceeeb" +dependencies = [ + "bytes 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum bytes 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum pin-project 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "562cc58f3e865231cf1fa1760097159a642018f5953ffbfe4f2df2ef72bf0d90" +"checksum pin-project-internal 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "21a5bc357e14eb5cc61f4e24867b3aec66b850d83ea830beffa2244ad7a97f1e" +"checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" +"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" +"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum tokio 0.2.1 (git+https://github.com/tokio-rs/tokio/)" = "" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml new file mode 100644 index 0000000..7fa24e4 --- /dev/null +++ b/padre/core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "padre_core" +version = "0.2.0" +authors = ["Steven Trotter "] +edition = "2018" +license = "APACHE" +repository = "https://github.com/strottos/vim-padre" + +[lib] +path = "src/lib.rs" + +[dependencies] +bytes = "0.5.0" +futures = "0.3.1" +lazy_static = "1.3.0" +pin-project = "0.4" +regex = "1.1.2" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +tokio = { version = "0.2.1", features = ["full"] } +tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/src/config.rs b/padre/core/src/config.rs similarity index 100% rename from padre/src/config.rs rename to padre/core/src/config.rs diff --git a/padre/core/src/lib.rs b/padre/core/src/lib.rs new file mode 100644 index 0000000..a82d775 --- /dev/null +++ b/padre/core/src/lib.rs @@ -0,0 +1,11 @@ +#[macro_use] +extern crate serde_derive; + +#[macro_use] +extern crate lazy_static; + +pub mod config; +pub mod notifier; +pub mod server; +pub mod util; +pub mod vimcodec; diff --git a/padre/src/notifier.rs b/padre/core/src/notifier.rs similarity index 99% rename from padre/src/notifier.rs rename to padre/core/src/notifier.rs index fbb20e4..e896411 100644 --- a/padre/src/notifier.rs +++ b/padre/core/src/notifier.rs @@ -8,7 +8,6 @@ use std::sync::Mutex; use crate::server::{Notification, PadreSend}; -use tokio::prelude::*; use tokio::sync::mpsc::Sender; lazy_static! { diff --git a/padre/src/server.rs b/padre/core/src/server.rs similarity index 91% rename from padre/src/server.rs rename to padre/core/src/server.rs index edb51b8..4b21ec0 100644 --- a/padre/src/server.rs +++ b/padre/core/src/server.rs @@ -7,20 +7,54 @@ use std::env::current_exe; use std::io; use std::process::{Command, Stdio}; use std::str; -use std::sync::{Arc, Mutex}; use crate::config::Config; -use crate::debugger::{Debugger, DebuggerCmd}; use crate::notifier::{add_listener, log_msg, remove_listener, LogLevel}; use crate::vimcodec::VimCodec; -use tokio::codec::Decoder; +use futures::{SinkExt, StreamExt}; use tokio::net::TcpStream; -use tokio::prelude::*; use tokio::sync::mpsc::{self, Sender}; +use tokio_util::codec::Decoder; // TODO: Get some of this out of pub use and just in this module? +/// All debugger commands +#[derive(Clone, Deserialize, Debug, PartialEq)] +pub enum DebuggerCmd { + Run, + Breakpoint(FileLocation), + StepIn, + StepOver, + Continue, + Print(Variable), +} + +/// File location +#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] +pub struct FileLocation { + name: String, + line_num: u64, +} + +impl FileLocation { + pub fn new(name: String, line_num: u64) -> Self { + FileLocation { name, line_num } + } +} + +/// Variable name +#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] +pub struct Variable { + name: String, +} + +impl Variable { + pub fn new(name: String) -> Self { + Variable { name } + } +} + /// All padre commands #[derive(Clone, Deserialize, Debug, PartialEq)] pub enum PadreCmd { @@ -153,7 +187,7 @@ pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender Sender {} + Ok(_) => {} Err(e) => { eprintln!("Writing stdin err e: {}", e); } diff --git a/padre/src/vimcodec.rs b/padre/core/src/vimcodec.rs similarity index 97% rename from padre/src/vimcodec.rs rename to padre/core/src/vimcodec.rs index 7e59b6e..0a1780c 100644 --- a/padre/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -5,12 +5,13 @@ use std::collections::HashMap; use std::io; -use crate::debugger::{DebuggerCmd, FileLocation, Variable}; -use crate::server::{PadreCmd, PadreRequest, PadreSend, RequestCmd}; +use crate::server::{ + DebuggerCmd, FileLocation, PadreCmd, PadreRequest, PadreSend, RequestCmd, Variable, +}; use crate::util; use bytes::{BufMut, BytesMut}; -use tokio::codec::{Decoder, Encoder}; +use tokio_util::codec::{Decoder, Encoder}; /// Decodes requests and encodes responses sent by or to VIM over VIM's socket communication /// @@ -412,7 +413,7 @@ impl Encoder for VimCodec { }; buf.reserve(response.len()); - buf.put(&response[..]); + buf.put(response[..].as_bytes()); Ok(()) } @@ -420,11 +421,12 @@ impl Encoder for VimCodec { #[cfg(test)] mod tests { - use crate::debugger::DebuggerCmd; - use crate::server::{Notification, PadreCmd, PadreRequest, PadreSend, RequestCmd, Response}; + use crate::server::{ + DebuggerCmd, Notification, PadreCmd, PadreRequest, PadreSend, RequestCmd, Response, + }; use bytes::{BufMut, BytesMut}; - use tokio::codec::{Decoder, Encoder}; + use tokio_util::codec::{Decoder, Encoder}; #[test] fn check_simple_json_decoding() { diff --git a/padre/src/debugger/lldb/debugger.rs b/padre/debuggers/lldb/debugger.rs similarity index 100% rename from padre/src/debugger/lldb/debugger.rs rename to padre/debuggers/lldb/debugger.rs diff --git a/padre/src/debugger/lldb/mod.rs b/padre/debuggers/lldb/mod.rs similarity index 100% rename from padre/src/debugger/lldb/mod.rs rename to padre/debuggers/lldb/mod.rs diff --git a/padre/src/debugger/lldb/process.rs b/padre/debuggers/lldb/process.rs similarity index 100% rename from padre/src/debugger/lldb/process.rs rename to padre/debuggers/lldb/process.rs diff --git a/padre/src/debugger/node/analyser.rs b/padre/debuggers/node/analyser.rs similarity index 100% rename from padre/src/debugger/node/analyser.rs rename to padre/debuggers/node/analyser.rs diff --git a/padre/src/debugger/node/debugger.rs b/padre/debuggers/node/debugger.rs similarity index 100% rename from padre/src/debugger/node/debugger.rs rename to padre/debuggers/node/debugger.rs diff --git a/padre/src/debugger/node/mod.rs b/padre/debuggers/node/mod.rs similarity index 100% rename from padre/src/debugger/node/mod.rs rename to padre/debuggers/node/mod.rs diff --git a/padre/src/debugger/node/process.rs b/padre/debuggers/node/process.rs similarity index 100% rename from padre/src/debugger/node/process.rs rename to padre/debuggers/node/process.rs diff --git a/padre/src/debugger/node/ws.rs b/padre/debuggers/node/ws.rs similarity index 100% rename from padre/src/debugger/node/ws.rs rename to padre/debuggers/node/ws.rs diff --git a/padre/debuggers/python/Cargo.lock b/padre/debuggers/python/Cargo.lock new file mode 100644 index 0000000..b7d8131 --- /dev/null +++ b/padre/debuggers/python/Cargo.lock @@ -0,0 +1,311 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + +[[package]] +name = "bytes" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" + +[[package]] +name = "padre" +version = "0.2.0" +dependencies = [ + "bytes 0.4.12", + "clap", + "lazy_static", + "libc", + "pin-project", + "regex", + "serde", + "serde_derive", + "serde_json", + "tokio", +] + +[[package]] +name = "padre-python" +version = "0.2.0" +dependencies = [ + "bytes 0.4.12", + "padre", + "regex", + "tokio", +] + +[[package]] +name = "pin-project" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" + +[[package]] +name = "ryu" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" + +[[package]] +name = "serde" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" + +[[package]] +name = "serde_derive" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89693ae015201f8de93fd96bde2d065f8bfc3f97ce006d5bc9f900b97c0c7c0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tokio" +version = "0.2.1" +source = "git+https://github.com/tokio-rs/tokio/#4261ab6627d1da5e5c70a4b88ccdfc329334716b" +dependencies = [ + "bytes 0.5.2", + "pin-project-lite", +] + +[[package]] +name = "unicode-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml new file mode 100644 index 0000000..d6b3657 --- /dev/null +++ b/padre/debuggers/python/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "padre-python" +version = "0.2.0" +authors = ["Steven Trotter "] +edition = "2018" +license = "MIT" +repository = "https://github.com/strottos/vim-padre" + +[lib] +path = "src/lib.rs" + +[dependencies] +bytes = "0.4.12" +regex = "1.1.2" +padre = { path = "../../core", version = "0.2.0" } +tokio = { git = "https://github.com/tokio-rs/tokio/", branch = "master" } diff --git a/padre/src/debugger/python/debugger.rs b/padre/debuggers/python/src/debugger.rs similarity index 98% rename from padre/src/debugger/python/debugger.rs rename to padre/debuggers/python/src/debugger.rs index 4edf7a9..f4a4a33 100644 --- a/padre/src/debugger/python/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -10,13 +10,13 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use super::process::{Event, Listener, PDBStatus, Process}; -use crate::config::Config; -use crate::debugger::{FileLocation, Variable}; -use crate::notifier::{log_msg, LogLevel}; +//use crate::config::Config; +//use crate::debugger::{FileLocation, Variable}; +//use crate::notifier::{log_msg, LogLevel}; use bytes::Bytes; use tokio::prelude::*; -use tokio::sync::mpsc; +//use tokio::sync::mpsc; #[derive(Debug)] pub struct ImplDebugger { diff --git a/padre/src/debugger/python/mod.rs b/padre/debuggers/python/src/lib.rs similarity index 100% rename from padre/src/debugger/python/mod.rs rename to padre/debuggers/python/src/lib.rs diff --git a/padre/src/debugger/python/process.rs b/padre/debuggers/python/src/process.rs similarity index 98% rename from padre/src/debugger/python/process.rs rename to padre/debuggers/python/src/process.rs index 8f47cec..695af71 100644 --- a/padre/src/debugger/python/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -12,12 +12,11 @@ use std::process::exit; use std::process::Stdio; use std::sync::{Arc, Mutex}; -use crate::debugger::{FileLocation, Variable}; -use crate::notifier::{breakpoint_set, jump_to_position, signal_exited}; -use crate::notifier::{log_msg, LogLevel}; +use padre::debugger::{FileLocation, Variable}; +use padre::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; #[cfg(not(test))] -use crate::util::{file_exists, get_file_full_path}; -use crate::util::{read_output, setup_stdin}; +use padre::util::{file_exists, get_file_full_path}; +use padre::util::{read_output, setup_stdin}; use bytes::Bytes; use regex::Regex; From cf1c3656da1602f9dd2bdf249d1823f0e453a059 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sat, 30 Nov 2019 16:39:30 +0000 Subject: [PATCH 05/23] Fixed tests and better infrastructure, lots to do still though --- padre/Cargo.lock | 17 +- padre/Cargo.toml | 2 +- padre/cli/Cargo.toml | 12 +- padre/cli/src/debugger.rs | 52 +--- padre/cli/src/main.rs | 32 +- padre/core/Cargo.toml | 10 +- padre/core/src/server.rs | 15 +- padre/core/src/util.rs | 56 ++-- padre/core/src/vimcodec.rs | 28 +- padre/debuggers/python/Cargo.lock | 400 +++++++++++++++++++++---- padre/debuggers/python/Cargo.toml | 10 +- padre/debuggers/python/src/debugger.rs | 31 +- padre/debuggers/python/src/lib.rs | 3 + padre/debuggers/python/src/process.rs | 13 +- 14 files changed, 478 insertions(+), 203 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 7640091..ba2c9a4 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -332,8 +332,11 @@ version = "0.2.0" dependencies = [ "clap", "futures", - "libc", "padre_core", + "padre_python", + "serde", + "serde_derive", + "serde_json", "tokio", ] @@ -353,6 +356,18 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "padre_python" +version = "0.2.0" +dependencies = [ + "bytes", + "futures", + "lazy_static", + "padre_core", + "regex", + "tokio", +] + [[package]] name = "pin-project" version = "0.4.6" diff --git a/padre/Cargo.toml b/padre/Cargo.toml index f5a7593..a2851d2 100644 --- a/padre/Cargo.toml +++ b/padre/Cargo.toml @@ -2,5 +2,5 @@ members = [ "cli", - "core" + "core", ] diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index 394bae4..e01e705 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -6,9 +6,19 @@ edition = "2018" license = "APACHE" repository = "https://github.com/strottos/vim-padre" +[features] + +default = ["python"] +python = ["padre_python"] + [dependencies] clap = "2.32.0" futures = "0.3.1" -libc = "0.2.65" padre_core = { path = "../core", version = "0.2.0" } +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" tokio = { version = "0.2.1", features = ["full"] } + +# The debuggers, all optional +padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index bbddb57..b64c6ea 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -4,18 +4,18 @@ //! and creates the main debugger objects. use std::fmt::Debug; -use std::io; use std::sync::{Arc, Mutex}; -use padre_core::config::Config; +use padre_core::server::DebuggerCmd; use padre_core::util::{file_is_binary_executable, file_is_text}; -use tokio::prelude::*; +use futures::StreamExt; use tokio::sync::mpsc::Receiver; //mod lldb; //mod node; -mod python; +#[cfg(feature = "python")] +use padre_python; /// Debuggers #[derive(Debug)] @@ -25,49 +25,13 @@ enum DebuggerType { Python, } -/// File location -#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] -pub struct FileLocation { - name: String, - line_num: u64, -} - -impl FileLocation { - pub fn new(name: String, line_num: u64) -> Self { - FileLocation { name, line_num } - } -} - -/// Variable name -#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] -pub struct Variable { - name: String, -} - -impl Variable { - pub fn new(name: String) -> Self { - Variable { name } - } -} - -/// All debugger commands -#[derive(Clone, Deserialize, Debug, PartialEq)] -pub enum DebuggerCmd { - Run, - Breakpoint(FileLocation), - StepIn, - StepOver, - Continue, - Print(Variable), -} - #[derive(Debug)] pub struct Debugger { - debugger: Arc>, + debugger: Arc>, } impl Debugger { - pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver) -> Debugger { + pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver) -> Debugger { let debugger = Debugger { debugger: impl_debugger.clone(), }; @@ -140,10 +104,10 @@ pub async fn create_debugger( }, }; - let mut debugger: python::ImplDebugger = python::ImplDebugger::new(debugger_cmd, run_cmd); + let debugger: padre_python::ImplDebugger = padre_python::ImplDebugger::new(debugger_cmd, run_cmd); // DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), // DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), - // DebuggerType::Python => Box::new(python::ImplDebugger::new(debugger_cmd, run_cmd)), + // DebuggerType::Python => Box::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd)), // }; Debugger::new(Arc::new(Mutex::new(debugger)), queue_rx) diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index b00af7a..42fdfca 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -18,6 +18,9 @@ //! ``` //! will run the program `my_program arg1 arg2 3 4` in an `lldb` session. +#[macro_use] +extern crate serde_derive; + use std::io; use std::net::SocketAddr; use std::process::exit; @@ -26,7 +29,6 @@ use std::time::Duration; use clap::{App, Arg, ArgMatches}; use futures::prelude::*; -use libc::{SIGINT, SIGQUIT, SIGTERM}; use tokio::net::TcpListener; use tokio::runtime::Runtime; use tokio::time::delay_for; @@ -36,6 +38,8 @@ use tokio::sync::mpsc; use padre_core::server; use padre_core::util; +mod debugger; + fn get_app_args<'a>() -> ArgMatches<'a> { App::new("VIM Padre") .version("0.1.0") @@ -87,7 +91,7 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -fn exit_padre() { //debugger: Arc>) { +fn exit_padre(debugger: Arc>) { let when = Duration::new(5, 0); tokio::spawn(async move { @@ -96,7 +100,7 @@ fn exit_padre() { //debugger: Arc>) { exit(-1); }); - //debugger.lock().unwrap().stop(); + debugger.lock().unwrap().stop(); } async fn run_padre() -> () { @@ -112,12 +116,12 @@ async fn run_padre() -> () { // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? - // let debugger = Arc::new(Mutex::new( - // debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, - // )); + let debugger = Arc::new(Mutex::new( + debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, + )); let connection_addr = get_connection(&args); - let mut connection = TcpListener::bind(&connection_addr) + let mut socket = TcpListener::bind(&connection_addr) .map(|listener| { println!("Listening on {}", &connection_addr); listener @@ -125,34 +129,34 @@ async fn run_padre() -> () { .await .expect(&format!("Can't open TCP listener on {}", &connection_addr)); - let mut incoming = connection.incoming(); + let mut incoming = socket.incoming(); // TODO: Merge the following into one lot of signals when we know how to - //let debugger_signals = debugger.clone(); + let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::interrupt()).unwrap(); while let Some(_) = signals.recv().await { - exit_padre(); //debugger_signals.clone()); + exit_padre(debugger_signals.clone()); } }); - //let debugger_signals = debugger.clone(); + let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::quit()).unwrap(); while let Some(_) = signals.recv().await { - exit_padre(); //debugger_signals.clone()); + exit_padre(debugger_signals.clone()); } }); - //let debugger_signals = debugger.clone(); + let debugger_signals = debugger.clone(); tokio::spawn(async move { let mut signals = signal(SignalKind::terminate()).unwrap(); while let Some(_) = signals.recv().await { - exit_padre(); //debugger_signals.clone()); + exit_padre(debugger_signals.clone()); } }); diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml index 7fa24e4..7303083 100644 --- a/padre/core/Cargo.toml +++ b/padre/core/Cargo.toml @@ -18,5 +18,13 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.1", features = ["full"] } +tokio = { version = "0.2.1", features = [ + "io-util", + "io-std", + "net", + "process", + "stream", + "sync", + "time" +] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index 4b21ec0..137a27d 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -9,7 +9,8 @@ use std::process::{Command, Stdio}; use std::str; use crate::config::Config; -use crate::notifier::{add_listener, log_msg, remove_listener, LogLevel}; +// TODO: Add in remove_listener +use crate::notifier::{add_listener, log_msg, LogLevel}; use crate::vimcodec::VimCodec; use futures::{SinkExt, StreamExt}; @@ -72,9 +73,15 @@ pub enum PadreCmd { /// Examples: /// /// ``` -/// let command = RequestCmd::Cmd("run") -/// let command = RequestCmd::CmdWithFileLocation("breakpoint", "test.c", 12) -/// let command = RequestCmd::CmdWithVariable("print", "abc") +/// use padre_core::server::{RequestCmd, DebuggerCmd, FileLocation, Variable}; +/// +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Run); +/// +/// let file_location = FileLocation::new("test.c".to_string(), 12); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(file_location)); +/// +/// let variable = Variable::new("abc".to_string()); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Print(variable)); /// ``` #[derive(Clone, Deserialize, Debug, PartialEq)] pub enum RequestCmd { diff --git a/padre/core/src/util.rs b/padre/core/src/util.rs index 994ad39..4d27056 100644 --- a/padre/core/src/util.rs +++ b/padre/core/src/util.rs @@ -161,11 +161,7 @@ pub fn get_file_full_path(cmd: &str) -> String { /// Return true if the path specified exists. pub fn file_exists(path: &str) -> bool { - if !Path::new(path).exists() { - false - } else { - true - } + Path::new(path).exists() } /// Get the file type as output by the UNIX `file` command. @@ -268,36 +264,22 @@ mod tests { assert_eq!(listener.local_addr().unwrap().port(), port); } - #[test] - fn is_file_executable() { - assert_eq!(true, super::file_is_binary_executable("./test_files/node")); - assert_eq!( - false, - super::file_is_binary_executable("./test_files/test_node.js") - ); - } - - #[test] - fn is_file_text() { - assert_eq!(false, super::file_is_text("./test_files/node")); - assert_eq!(true, super::file_is_text("./test_files/test_node.js")); - } - - #[test] - fn test_file_exists() { - assert_eq!(true, super::file_exists("./test_files/node")); - } - - #[test] - fn test_file_not_exists() { - assert_eq!(false, super::file_exists("./test_files/not_exists")); - } - - #[test] - fn test_getting_files_full_path_when_not_exists() { - assert_eq!( - "file_surely_doesnt_exist".to_string(), - super::get_file_full_path("file_surely_doesnt_exist") - ); - } + //#[test] + //fn is_file_executable() { + // tokio::spawn(async move { + // assert_eq!(true, super::file_is_binary_executable("./test_files/node").await); + // assert_eq!( + // false, + // super::file_is_binary_executable("./test_files/test_node.js").await + // ); + // }); + //} + + //#[test] + //fn is_file_text() { + // tokio::spawn(async move { + // assert_eq!(false, super::file_is_text("./test_files/node").await); + // assert_eq!(true, super::file_is_text("./test_files/test_node.js").await); + // }); + //} } diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index 0a1780c..0e23c7a 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -15,10 +15,7 @@ use tokio_util::codec::{Decoder, Encoder}; /// Decodes requests and encodes responses sent by or to VIM over VIM's socket communication /// -/// Given a request of the form -/// ``` -/// [1,{"cmd":"breakpoint","file":"test.c","line":1}] -/// ``` +/// Given a request of the form: `[1,{"cmd":"breakpoint","file":"test.c","line":1}]` /// it decodes this into a PadreRequest with an `id` of `1` and a RequestCmd of `Breakpoint` /// with the correct file location. #[derive(Debug)] @@ -433,7 +430,8 @@ mod tests { let mut codec = super::VimCodec::new(); let mut buf = BytesMut::new(); buf.reserve(19); - buf.put(r#"[123,{"cmd":"run"}]"#); + let s = r#"[123,{"cmd":"run"}]"#; + buf.put(s.as_bytes()); let padre_request = codec.decode(&mut buf).unwrap().unwrap(); @@ -448,7 +446,8 @@ mod tests { let mut codec = super::VimCodec::new(); let mut buf = BytesMut::new(); buf.reserve(19); - buf.put(r#"[123,{"cmd":"run"}]"#); + let s = r#"[123,{"cmd":"run"}]"#; + buf.put(s.as_bytes()); let padre_request = codec.decode(&mut buf).unwrap().unwrap(); @@ -459,7 +458,8 @@ mod tests { let mut buf = BytesMut::new(); buf.reserve(20); - buf.put(r#"[124,{"cmd":"ping"}]"#); + let s = r#"[124,{"cmd":"ping"}]"#; + buf.put(s.as_bytes()); let padre_request = codec.decode(&mut buf).unwrap().unwrap(); @@ -474,14 +474,16 @@ mod tests { let mut codec = super::VimCodec::new(); let mut buf = BytesMut::new(); buf.reserve(16); - buf.put(r#"[123,{"cmd":"run"#); + let s = r#"[123,{"cmd":"run"#; + buf.put(s.as_bytes()); let padre_request = codec.decode(&mut buf).unwrap(); assert_eq!(None, padre_request); buf.reserve(3); - buf.put(r#""}]"#); + let s = r#""}]"#; + buf.put(s.as_bytes()); let padre_request = codec.decode(&mut buf).unwrap().unwrap(); @@ -500,8 +502,8 @@ mod tests { let mut expected = BytesMut::new(); expected.reserve(22); - expected.put(r#"[123,{"ping":"pong"}]"#); - expected.put("\n"); + let s = format!("{}{}", r#"[123,{"ping":"pong"}]"#, "\n"); + expected.put(s.as_bytes()); assert_eq!(expected, buf); } @@ -518,8 +520,8 @@ mod tests { let mut expected = BytesMut::new(); expected.reserve(31); - expected.put(r#"["call","cmd_test",["test",1]]"#); - expected.put("\n"); + let s = format!("{}{}", r#"["call","cmd_test",["test",1]]"#, "\n"); + expected.put(s.as_bytes()); assert_eq!(expected, buf); } diff --git a/padre/debuggers/python/Cargo.lock b/padre/debuggers/python/Cargo.lock index b7d8131..d01fbff 100644 --- a/padre/debuggers/python/Cargo.lock +++ b/padre/debuggers/python/Cargo.lock @@ -10,65 +10,149 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.11.0" +name = "arc-swap" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytes" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "winapi", + "bitflags", + "fuchsia-zircon-sys", ] [[package]] -name = "atty" -version = "0.2.13" +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +checksum = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" dependencies = [ - "libc", - "winapi", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] -name = "bitflags" -version = "1.2.1" +name = "futures-channel" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +dependencies = [ + "futures-core", + "futures-sink", +] [[package]] -name = "byteorder" -version = "1.3.2" +name = "futures-core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" [[package]] -name = "bytes" -version = "0.4.12" +name = "futures-executor" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +checksum = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" dependencies = [ - "byteorder", - "iovec", + "futures-core", + "futures-task", + "futures-util", ] [[package]] -name = "bytes" -version = "0.5.2" +name = "futures-io" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" +checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" [[package]] -name = "clap" -version = "2.33.0" +name = "futures-macro" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" + +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +dependencies = [ + "libc", ] [[package]] @@ -86,6 +170,16 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -98,6 +192,15 @@ version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.2.1" @@ -105,27 +208,114 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" [[package]] -name = "padre" +name = "mio" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +dependencies = [ + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow 0.2.1", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" +dependencies = [ + "log", + "mio", + "miow 0.3.3", + "winapi 0.3.8", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "miow" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" +dependencies = [ + "socket2", + "winapi 0.3.8", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +dependencies = [ + "cfg-if", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "num_cpus" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "padre_core" version = "0.2.0" dependencies = [ - "bytes 0.4.12", - "clap", + "bytes", + "futures", "lazy_static", - "libc", "pin-project", "regex", "serde", "serde_derive", "serde_json", "tokio", + "tokio-util", ] [[package]] -name = "padre-python" +name = "padre_python" version = "0.2.0" dependencies = [ - "bytes 0.4.12", - "padre", + "bytes", + "futures", + "lazy_static", + "padre_core", "regex", "tokio", ] @@ -156,6 +346,29 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" + +[[package]] +name = "proc-macro-hack" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" + [[package]] name = "proc-macro2" version = "1.0.6" @@ -174,6 +387,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + [[package]] name = "regex" version = "1.3.1" @@ -227,10 +446,32 @@ dependencies = [ ] [[package]] -name = "strsim" -version = "0.8.0" +name = "signal-hook-registry" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +dependencies = [ + "arc-swap", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "socket2" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] [[package]] name = "syn" @@ -243,15 +484,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thread_local" version = "0.3.6" @@ -264,17 +496,49 @@ dependencies = [ [[package]] name = "tokio" version = "0.2.1" -source = "git+https://github.com/tokio-rs/tokio/#4261ab6627d1da5e5c70a4b88ccdfc329334716b" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beeef686ef92a222de07e089f455d9f8478bbba9651718f9e4b276babe829082" dependencies = [ - "bytes 0.5.2", + "bytes", + "fnv", + "futures-core", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-named-pipes", + "mio-uds", + "num_cpus", "pin-project-lite", + "signal-hook-registry", + "slab", + "tokio-macros", + "winapi 0.3.8", ] [[package]] -name = "unicode-width" -version = "0.1.6" +name = "tokio-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5795a71419535c6dcecc9b6ca95bdd3c2d6142f7e8343d7beb9923f129aa87e" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "tokio-util" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] [[package]] name = "unicode-xid" @@ -283,10 +547,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] -name = "vec_map" -version = "0.8.1" +name = "winapi" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" @@ -298,6 +562,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -309,3 +579,13 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml index d6b3657..a4432a5 100644 --- a/padre/debuggers/python/Cargo.toml +++ b/padre/debuggers/python/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "padre-python" +name = "padre_python" version = "0.2.0" authors = ["Steven Trotter "] edition = "2018" @@ -10,7 +10,9 @@ repository = "https://github.com/strottos/vim-padre" path = "src/lib.rs" [dependencies] -bytes = "0.4.12" +bytes = "0.5.0" +futures = "0.3.1" +lazy_static = "1.3.0" regex = "1.1.2" -padre = { path = "../../core", version = "0.2.0" } -tokio = { git = "https://github.com/tokio-rs/tokio/", branch = "master" } +padre_core = { path = "../../core", version = "0.2.0" } +tokio = { version = "0.2.1", features = ["full"] } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index f4a4a33..c20c718 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -3,19 +3,18 @@ //! The main Python Debugger entry point. Handles listening for instructions and //! communicating through the `Process`. -use std::io; -use std::path::PathBuf; +// use std::io; +// use std::path::PathBuf; use std::process::exit; use std::sync::{Arc, Mutex}; -use std::time::Duration; +// use std::time::Duration; -use super::process::{Event, Listener, PDBStatus, Process}; -//use crate::config::Config; -//use crate::debugger::{FileLocation, Variable}; -//use crate::notifier::{log_msg, LogLevel}; +use super::process::Process; +// use super::process::{Event, Listener, PDBStatus, Process}; +// use padre_core::config::Config; +use padre_core::server::{FileLocation, Variable}; +use padre_core::notifier::{log_msg, LogLevel}; -use bytes::Bytes; -use tokio::prelude::*; //use tokio::sync::mpsc; #[derive(Debug)] @@ -81,13 +80,13 @@ impl ImplDebugger { file_location: &FileLocation, //config: Arc>, ) { - log_msg( - LogLevel::INFO, - &format!( - "Setting breakpoint in file {} at line number {}", - file_location.name, file_location.line_num - ), - ); + //log_msg( + // LogLevel::INFO, + // &format!( + // "Setting breakpoint in file {} at line number {}", + // file_location.name, file_location.line_num + // ), + //); // // If not started yet add as a pending breakpoint that will get set during run period. // match self.process.lock().unwrap().get_status() { diff --git a/padre/debuggers/python/src/lib.rs b/padre/debuggers/python/src/lib.rs index 0cae22c..4a65e65 100644 --- a/padre/debuggers/python/src/lib.rs +++ b/padre/debuggers/python/src/lib.rs @@ -1,5 +1,8 @@ //! The Python debugger module +#[macro_use] +extern crate lazy_static; + mod debugger; mod process; diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 695af71..593ad18 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -5,24 +5,23 @@ //! happening then. use std::collections::HashMap; -use std::io; use std::path::Path; #[cfg(not(test))] use std::process::exit; use std::process::Stdio; use std::sync::{Arc, Mutex}; -use padre::debugger::{FileLocation, Variable}; -use padre::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::server::{FileLocation, Variable}; +use padre_core::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; #[cfg(not(test))] -use padre::util::{file_exists, get_file_full_path}; -use padre::util::{read_output, setup_stdin}; +use padre_core::util::{file_exists, get_file_full_path}; +use padre_core::util::{read_output, setup_stdin}; use bytes::Bytes; +use futures::prelude::*; use regex::Regex; use tokio::io::BufReader; -use tokio::net::process::{Command, Child, ChildStderr, ChildStdout}; -use tokio::prelude::*; +use tokio::process::{Command, Child, ChildStderr, ChildStdout}; use tokio::sync::mpsc::Sender; #[derive(Debug, Clone, PartialEq)] From f0c43d7fa5f7d08f2a49e26feac8a2c8b57299bb Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sun, 1 Dec 2019 16:18:22 +0000 Subject: [PATCH 06/23] Added various things into Python debugger Improved architecture of Python debugger such that it can determine if it's listening or processing Added timeouts to the architecture --- padre/Cargo.lock | 4 +- padre/cli/Cargo.toml | 2 +- padre/cli/src/debugger.rs | 22 +- padre/cli/src/main.rs | 3 - padre/core/Cargo.toml | 2 +- padre/core/src/config.rs | 1 + padre/core/src/notifier.rs | 9 - padre/core/src/server.rs | 48 ++-- padre/core/src/util.rs | 9 +- padre/core/src/vimcodec.rs | 95 +++++++- padre/debuggers/python/Cargo.toml | 2 +- padre/debuggers/python/src/debugger.rs | 266 ++++++++++------------ padre/debuggers/python/src/process.rs | 128 +++++------ padre/integration/features/basics.feature | 2 + padre/integration/features/python.feature | 61 +++-- 15 files changed, 352 insertions(+), 302 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index ba2c9a4..25e054b 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -558,9 +558,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beeef686ef92a222de07e089f455d9f8478bbba9651718f9e4b276babe829082" +checksum = "2e765bf9f550bd9b8a970633ca3b56b8120c4b6c5dcbe26a93744cb02fee4b17" dependencies = [ "bytes", "fnv", diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index e01e705..f3d574e 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -18,7 +18,7 @@ padre_core = { path = "../core", version = "0.2.0" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.1", features = ["full"] } +tokio = { version = "0.2.2", features = ["full"] } # The debuggers, all optional padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index b64c6ea..97a45ca 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -5,6 +5,7 @@ use std::fmt::Debug; use std::sync::{Arc, Mutex}; +use std::time::Instant; use padre_core::server::DebuggerCmd; use padre_core::util::{file_is_binary_executable, file_is_text}; @@ -31,7 +32,7 @@ pub struct Debugger { } impl Debugger { - pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver) -> Debugger { + pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver<(DebuggerCmd, Instant)>) -> Debugger { let debugger = Debugger { debugger: impl_debugger.clone(), }; @@ -41,13 +42,13 @@ impl Debugger { tokio::spawn(async move { while let Some(cmd) = queue_rx.next().await { let mut debugger = queue_processing_debugger.lock().unwrap(); - match cmd { - DebuggerCmd::Run => debugger.run(), - DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl), - DebuggerCmd::StepIn => debugger.step_in(), - DebuggerCmd::StepOver => debugger.step_over(), - DebuggerCmd::Continue => debugger.continue_(), - DebuggerCmd::Print(v) => debugger.print(&v), + match cmd.0 { + DebuggerCmd::Run => debugger.run(cmd.1), + DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), + DebuggerCmd::StepIn => debugger.step_in(cmd.1), + DebuggerCmd::StepOver => debugger.step_over(cmd.1), + DebuggerCmd::Continue => debugger.continue_(cmd.1), + DebuggerCmd::Print(v) => debugger.print(&v, cmd.1), }; }; }); @@ -56,8 +57,7 @@ impl Debugger { } pub fn stop(&mut self) { - //self.debugger.lock().unwrap().teardown(); - std::process::exit(-1); + self.debugger.lock().unwrap().teardown(); } } @@ -69,7 +69,7 @@ pub async fn create_debugger( debugger_cmd: Option<&str>, debugger_type: Option<&str>, run_cmd: Vec, - queue_rx: Receiver, + queue_rx: Receiver<(DebuggerCmd, Instant)>, ) -> Debugger { let debugger_type = match debugger_type { Some(s) => match s.to_ascii_lowercase().as_str() { diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index 42fdfca..4a6de9f 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -18,9 +18,6 @@ //! ``` //! will run the program `my_program arg1 arg2 3 4` in an `lldb` session. -#[macro_use] -extern crate serde_derive; - use std::io; use std::net::SocketAddr; use std::process::exit; diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml index 7303083..6cb5851 100644 --- a/padre/core/Cargo.toml +++ b/padre/core/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.1", features = [ +tokio = { version = "0.2.2", features = [ "io-util", "io-std", "net", diff --git a/padre/core/src/config.rs b/padre/core/src/config.rs index 15a1ae6..4dd8a8f 100644 --- a/padre/core/src/config.rs +++ b/padre/core/src/config.rs @@ -38,6 +38,7 @@ impl<'a> Config<'a> { config.insert("ProcessSpawnTimeout", 10); config.insert("BreakpointTimeout", 2); config.insert("PrintVariableTimeout", 2); + config.insert("StepTimeout", 2); Config { config } } diff --git a/padre/core/src/notifier.rs b/padre/core/src/notifier.rs index e896411..8d2bec1 100644 --- a/padre/core/src/notifier.rs +++ b/padre/core/src/notifier.rs @@ -122,15 +122,6 @@ pub fn jump_to_position(file: &str, line: u64) { NOTIFIER.lock().unwrap().send_msg(msg); } -/// Notify that a breakpoint has been set -pub fn breakpoint_set(file: &str, line: u64) { - let msg = Notification::new( - "padre#debugger#BreakpointSet".to_string(), - vec![serde_json::json!(file), serde_json::json!(line)], - ); - NOTIFIER.lock().unwrap().send_msg(msg); -} - #[cfg(test)] mod tests { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index 137a27d..ebdfec4 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -7,6 +7,8 @@ use std::env::current_exe; use std::io; use std::process::{Command, Stdio}; use std::str; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; use crate::config::Config; // TODO: Add in remove_listener @@ -21,7 +23,7 @@ use tokio_util::codec::Decoder; // TODO: Get some of this out of pub use and just in this module? /// All debugger commands -#[derive(Clone, Deserialize, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum DebuggerCmd { Run, Breakpoint(FileLocation), @@ -32,7 +34,7 @@ pub enum DebuggerCmd { } /// File location -#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct FileLocation { name: String, line_num: u64, @@ -42,10 +44,18 @@ impl FileLocation { pub fn new(name: String, line_num: u64) -> Self { FileLocation { name, line_num } } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn line_num(&self) -> u64 { + self.line_num + } } /// Variable name -#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Variable { name: String, } @@ -57,7 +67,7 @@ impl Variable { } /// All padre commands -#[derive(Clone, Deserialize, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum PadreCmd { Ping, Pings, @@ -83,14 +93,14 @@ pub enum PadreCmd { /// let variable = Variable::new("abc".to_string()); /// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Print(variable)); /// ``` -#[derive(Clone, Deserialize, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum RequestCmd { PadreCmd(PadreCmd), - DebuggerCmd(DebuggerCmd), + DebuggerCmd(DebuggerCmd, Instant), } /// Contains full details of a request including an id to respond to and a `RequestCmd` -#[derive(Deserialize, Debug, PartialEq)] +#[derive(Debug, PartialEq)] pub struct PadreRequest { id: u64, cmd: RequestCmd, @@ -187,12 +197,12 @@ pub enum PadreSend { /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. -pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender) { +pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender<(DebuggerCmd, Instant)>) { let addr = stream.peer_addr().unwrap(); - let mut config = Config::new(); + let config = Arc::new(Mutex::new(Config::new())); - let (mut request_tx, mut request_rx) = VimCodec::new().framed(stream).split(); + let (mut request_tx, mut request_rx) = VimCodec::new(config.clone()).framed(stream).split(); let (connection_tx, mut connection_rx) = mpsc::channel(1); @@ -206,7 +216,7 @@ pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender( request: PadreRequest, - mut debugger_queue_tx: Sender, - config: &mut Config<'a>, + mut debugger_queue_tx: Sender<(DebuggerCmd, Instant)>, + config: Arc>>, ) -> Result { match request.cmd() { RequestCmd::PadreCmd(cmd) => { @@ -244,8 +254,8 @@ async fn respond<'a>( } } } - RequestCmd::DebuggerCmd(cmd) => { - debugger_queue_tx.send(cmd.clone()).await.unwrap(); + RequestCmd::DebuggerCmd(cmd, timeout) => { + debugger_queue_tx.send((cmd.clone(), *timeout)).await.unwrap(); Ok(Response::new(request.id(), serde_json::json!({"status":"OK"}))) } } @@ -261,8 +271,8 @@ fn pings() -> Result { Ok(serde_json::json!({"status":"OK"})) } -fn get_config(config: &Config, key: &str) -> Result { - let value = config.get_config(key); +fn get_config(config: Arc>, key: &str) -> Result { + let value = config.lock().unwrap().get_config(key); match value { Some(v) => Ok(serde_json::json!({"status":"OK","value":v})), None => Ok(serde_json::json!({"status":"ERROR"})), @@ -270,11 +280,11 @@ fn get_config(config: &Config, key: &str) -> Result>, key: &str, value: i64, ) -> Result { - let config_set = config.set_config(key, value); + let config_set = config.lock().unwrap().set_config(key, value); match config_set { true => Ok(serde_json::json!({"status":"OK"})), false => Ok(serde_json::json!({"status":"ERROR"})), diff --git a/padre/core/src/util.rs b/padre/core/src/util.rs index 4d27056..96839ae 100644 --- a/padre/core/src/util.rs +++ b/padre/core/src/util.rs @@ -13,14 +13,14 @@ use std::task::{Context, Poll}; use crate::notifier::{log_msg, LogLevel}; -use bytes::Bytes; +use bytes::{Bytes, BufMut}; use futures::{Stream, StreamExt}; use pin_project::{pin_project, project}; use tokio::io::{stdin, AsyncBufRead}; use tokio::process::{Child, ChildStdin, Command}; use tokio::prelude::*; use tokio::sync::mpsc::{self, Sender}; -use tokio_util::codec::{FramedRead, LinesCodec}; +use tokio_util::codec::{FramedRead, BytesCodec}; /// Get an unused port on the local system and return it. This port /// can subsequently be used. @@ -92,9 +92,10 @@ pub fn setup_stdin(mut child_stdin: ChildStdin, output_stdin: bool) -> Sender { + config: Arc>>, +} -impl VimCodec { +impl<'a> VimCodec<'a> { /// Constructor for creating a new VimCodec /// /// Just creates the object at present. - pub fn new() -> Self { - VimCodec {} + pub fn new(config: Arc>>) -> Self { + VimCodec { config } } /// Get and remove a `file location` from the arguments @@ -166,7 +171,7 @@ impl VimCodec { } } -impl Decoder for VimCodec { +impl<'a> Decoder for VimCodec<'a> { type Item = PadreRequest; type Error = io::Error; @@ -303,26 +308,81 @@ impl Decoder for VimCodec { ))), "run" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::Run), + RequestCmd::DebuggerCmd( + DebuggerCmd::Run, + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("ProcessSpawnTimeout") + .unwrap() as u64, + 0, + ), + ), ))), "stepOver" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::StepOver), + RequestCmd::DebuggerCmd( + DebuggerCmd::StepOver, + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("StepTimeout") + .unwrap() as u64, + 0, + ), + ), ))), "stepIn" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::StepIn), + RequestCmd::DebuggerCmd( + DebuggerCmd::StepIn, + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("StepTimeout") + .unwrap() as u64, + 0, + ), + ), ))), "continue" => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::Continue), + RequestCmd::DebuggerCmd( + DebuggerCmd::Continue, + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("StepTimeout") + .unwrap() as u64, + 0, + ), + ), ))), "breakpoint" => { let file_location = self.get_file_location(&mut args); match file_location { Some(fl) => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(fl)), + RequestCmd::DebuggerCmd( + DebuggerCmd::Breakpoint(fl), + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("BreakpointTimeout") + .unwrap() as u64, + 0, + ), + ), ))), None => return Ok(None), } @@ -332,7 +392,18 @@ impl Decoder for VimCodec { match variable { Some(v) => Ok(Some(PadreRequest::new( id, - RequestCmd::DebuggerCmd(DebuggerCmd::Print(v)), + RequestCmd::DebuggerCmd( + DebuggerCmd::Print(v), + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("PrintVariableTimeout") + .unwrap() as u64, + 0, + ), + ), ))), None => return Ok(None), } @@ -389,7 +460,7 @@ impl Decoder for VimCodec { } } -impl Encoder for VimCodec { +impl<'a> Encoder for VimCodec<'a> { type Item = PadreSend; type Error = io::Error; diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml index a4432a5..5cb99e1 100644 --- a/padre/debuggers/python/Cargo.toml +++ b/padre/debuggers/python/Cargo.toml @@ -15,4 +15,4 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.1", features = ["full"] } +tokio = { version = "0.2.2", features = ["full"] } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index c20c718..d90c532 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -3,19 +3,18 @@ //! The main Python Debugger entry point. Handles listening for instructions and //! communicating through the `Process`. -// use std::io; -// use std::path::PathBuf; +use std::path::PathBuf; use std::process::exit; use std::sync::{Arc, Mutex}; -// use std::time::Duration; +use std::time::Instant; -use super::process::Process; -// use super::process::{Event, Listener, PDBStatus, Process}; -// use padre_core::config::Config; +use super::process::{PDBStatus, Process}; use padre_core::server::{FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; -//use tokio::sync::mpsc; +use bytes::Bytes; +use futures::StreamExt; +use tokio::sync::mpsc; #[derive(Debug)] pub struct ImplDebugger { @@ -31,45 +30,54 @@ impl ImplDebugger { } } - //fn check_process_running( - // &self, - //) -> Option + Send>> { - // match self.process.lock().unwrap().get_status() { - // PDBStatus::None => { - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"ERROR"}); - // Ok(resp) - // }); - // return Some(Box::new(f)); - // } - // _ => None, - // } - //} - - fn setup(&mut self) {} - - fn teardown(&mut self) { + pub fn teardown(&mut self) { exit(0); } /// Run python and perform any setup necessary - pub fn run<'a>(&mut self) { - // // TODO: Find a better way of doing this, this madness - // let pending_breakpoints = match self.pending_breakpoints.take() { - // Some(pb) => pb, - // None => { - // let msg = "Process already running, not launching"; - // eprintln!("{}", msg); - // log_msg(LogLevel::WARN, msg); - // return Ok(serde_json::json!({"status":"ERROR"})); - // } - // }; + pub fn run(&mut self, timeout: Instant) { //, config: Arc>) { + match self.process.lock().unwrap().get_status() { + PDBStatus::None => {}, + _ => { + let msg = "Process already running, not launching"; + eprintln!("{}", msg); + log_msg(LogLevel::WARN, msg); + return; + } + } log_msg(LogLevel::INFO, "Launching process"); + let pending_breakpoints = self.pending_breakpoints.take(); + + let process = self.process.clone(); + + tokio::spawn(async move { + match pending_breakpoints { + Some(pbs) => { + for pb in pbs { + // Check we're actually listening + let (tx, mut rx) = mpsc::channel(1); + process.lock().unwrap().add_listener(tx); + rx.next().await.unwrap(); + process.lock().unwrap().drop_listener(); + + // And send the breakpoint info + let stmt = format!( + "break {}:{}\n", + pb.name(), + pb.line_num() + ); + + process.lock().unwrap().write_stdin(Bytes::from(stmt)); + } + }, + None => {} + }; + }); + let process = self.process.clone(); - // TODO: Timeouts tokio::spawn(async move { process.lock().unwrap().run(); }); @@ -78,133 +86,89 @@ impl ImplDebugger { pub fn breakpoint( &mut self, file_location: &FileLocation, - //config: Arc>, + timeout: Instant, ) { - //log_msg( - // LogLevel::INFO, - // &format!( - // "Setting breakpoint in file {} at line number {}", - // file_location.name, file_location.line_num - // ), - //); + log_msg( + LogLevel::INFO, + &format!( + "Setting breakpoint in file {} at line number {}", + file_location.name(), file_location.line_num() + ), + ); + + // If not started yet add as a pending breakpoint that will get set during run period. + match self.process.lock().unwrap().get_status() { + PDBStatus::None => { + match self.pending_breakpoints { + Some(ref mut x) => x.push(file_location.clone()), + None => {} + }; + + log_msg( + LogLevel::INFO, + &format!( + "Breakpoint pending in file {} at line number {}", + file_location.name(), file_location.line_num() + ), + ); + + return; + } + _ => {} + } - // // If not started yet add as a pending breakpoint that will get set during run period. - // match self.process.lock().unwrap().get_status() { - // PDBStatus::None => { - // match self.pending_breakpoints { - // Some(ref mut x) => x.push(file_location.clone()), - // None => {} - // }; - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"PENDING"}); - // Ok(resp) - // }); - // return Box::new(f); - // } - // _ => {} - // } - // - // let (tx, rx) = mpsc::channel(1); - // - // self.process - // .lock() - // .unwrap() - // .add_listener(Listener::Breakpoint, tx); - // - // let f = rx - // .take(1) - // .into_future() - // .timeout(Duration::new( - // config - // .lock() - // .unwrap() - // .get_config("BreakpointTimeout") - // .unwrap() as u64, - // 0, - // )) - // .map(move |event| match event.0.unwrap() { - // Event::BreakpointSet(_) => serde_json::json!({"status":"OK"}), - // _ => unreachable!(), - // }) - // .map_err(|e| { - // eprintln!("Reading stdin error {:?}", e); - // io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") - // }); - // - // let full_file_path = PathBuf::from(format!("{}", file_location.name)); - // let full_file_name = full_file_path.canonicalize().unwrap(); - // let stmt = format!( - // "break {}:{}\n", - // full_file_name.to_str().unwrap(), - // file_location.line_num - // ); - // - // self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - // - // Box::new(f) + // TODO: Timeout and error + let full_file_path = PathBuf::from(format!("{}", file_location.name())); + let full_file_name = full_file_path.canonicalize().unwrap(); + let stmt = format!( + "break {}:{}\n", + full_file_name.to_str().unwrap(), + file_location.line_num() + ); + + self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); } - pub fn step_in(&mut self) { - // //match self.check_process_running() { - // // Some(f) => return f, - // // None => {} - // //}; - // - // self.process - // .lock() - // .unwrap() - // .write_stdin(Bytes::from("step\n")); - // - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"OK"}); - // Ok(resp) - // }); - // - // Box::new(f) + pub fn step_in(&mut self, timeout: Instant) { + //match self.check_process_running() { + // Some(f) => return f, + // None => {} + //}; + + self.process + .lock() + .unwrap() + .write_stdin(Bytes::from("step\n")); } - pub fn step_over(&mut self) { - // //match self.check_process_running() { - // // Some(f) => return f, - // // None => {} - // //}; - // - // self.process - // .lock() - // .unwrap() - // .write_stdin(Bytes::from("next\n")); - // - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"OK"}); - // Ok(resp) - // }); - // - // Box::new(f) + pub fn step_over(&mut self, timeout: Instant) { + //match self.check_process_running() { + // Some(f) => return f, + // None => {} + //}; + + self.process + .lock() + .unwrap() + .write_stdin(Bytes::from("next\n")); } - pub fn continue_(&mut self) { - // //match self.check_process_running() { - // // Some(f) => return f, - // // None => {} - // //}; - // - // self.process - // .lock() - // .unwrap() - // .write_stdin(Bytes::from("continue\n")); - // - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"OK"}); - // Ok(resp) - // }); - // - // Box::new(f) + pub fn continue_(&mut self, timeout: Instant) { + //match self.check_process_running() { + // Some(f) => return f, + // None => {} + //}; + + self.process + .lock() + .unwrap() + .write_stdin(Bytes::from("continue\n")); } pub fn print( &mut self, variable: &Variable, - //config: Arc>, + timeout: Instant, ) { // //match self.check_process_running() { // // Some(f) => return f, diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 593ad18..38859f8 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -12,7 +12,7 @@ use std::process::Stdio; use std::sync::{Arc, Mutex}; use padre_core::server::{FileLocation, Variable}; -use padre_core::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; #[cfg(not(test))] use padre_core::util::{file_exists, get_file_full_path}; use padre_core::util::{read_output, setup_stdin}; @@ -27,8 +27,8 @@ use tokio::sync::mpsc::Sender; #[derive(Debug, Clone, PartialEq)] pub enum PDBStatus { None, - Running, - Printing(Variable), + Listening, + Processing, } /// You can register to listen for one of the following events: @@ -41,15 +41,6 @@ pub enum Listener { PrintVariable, } -/// A Python event is something that can be registered for being listened to and can be triggered -/// when these events occur such that the listener is informed of them and passed some details -#[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub enum Event { - Launched, - BreakpointSet(FileLocation), - PrintVariable(Variable, String), -} - /// Main handler for spawning the Python process #[derive(Debug)] pub struct Process { @@ -121,26 +112,31 @@ impl Process { self.process = Some(process); } - pub fn add_listener(&self, kind: Listener, sender: Sender) { - self.analyser.lock().unwrap().add_listener(kind, sender); + /// Adds a Sender object that gets awoken when we are listening. + /// + /// Should only add a sender when we're about to go into or currently in the + /// processing status otherwise this will never wake up. + pub fn add_listener(&self, sender: Sender) { + self.analyser.lock().unwrap().add_listener(sender); } - pub fn get_pid(&self) -> u64 { - self.process.as_ref().unwrap().id() as u64 + /// Drop the listener + pub fn drop_listener(&mut self) { + self.analyser.lock().unwrap().drop_listener(); } + /// Check the current status, either not running (None), running Python code + /// (Processing) or listening for a message on PDB (Listening). pub fn get_status(&self) -> PDBStatus { self.analyser.lock().unwrap().get_status() } - pub fn set_status(&self, status: PDBStatus) { - self.analyser.lock().unwrap().status = status; - } - /// Send a message to write to stdin pub fn write_stdin(&mut self, bytes: Bytes) { let tx = self.stdin_tx.clone(); + let analyser = self.analyser.clone(); tokio::spawn(async move { + analyser.lock().unwrap().status = PDBStatus::Processing; tx.clone() .unwrap() .send(bytes) @@ -254,7 +250,7 @@ fn get_python_args<'a>(debugger_cmd: &str, run_cmd: Vec<&'a str>) -> Vec<&'a str pub struct Analyser { status: PDBStatus, pid: Option, - listeners: HashMap>, + listener: Option>, } impl Analyser { @@ -262,7 +258,7 @@ impl Analyser { Analyser { status: PDBStatus::None, pid: None, - listeners: HashMap::new(), + listener: None, } } @@ -270,6 +266,16 @@ impl Analyser { self.status.clone() } + /// Add the listener to ping when we awaken + pub fn add_listener(&mut self, sender: Sender) { + self.listener = Some(sender); + } + + /// Drop the listener to ping when we awaken + pub fn drop_listener(&mut self) { + self.listener = None; + } + pub fn analyse_stdout(&mut self, s: &str) { lazy_static! { static ref RE_BREAKPOINT: Regex = @@ -289,7 +295,7 @@ impl Analyser { if line.contains("(Pdb) ") { match self.status { PDBStatus::None => { - self.python_launched(); + self.status = PDBStatus::Processing; } _ => {} }; @@ -298,7 +304,8 @@ impl Analyser { for cap in RE_BREAKPOINT.captures_iter(line) { let file = cap[2].to_string(); let line = cap[3].parse::().unwrap(); - self.found_breakpoint(file, line); + log_msg(LogLevel::INFO, &format!("Breakpoint set at file {} and line number {}", file, line)); + self.set_listening(); } for cap in RE_RETURNING.captures_iter(line) { @@ -306,6 +313,7 @@ impl Analyser { let line = cap[2].parse::().unwrap(); let return_value = cap[3].to_string(); jump_to_position(&file, line); + self.set_listening(); log_msg(LogLevel::INFO, &format!("Returning value {}", return_value)); } @@ -313,6 +321,7 @@ impl Analyser { let file = cap[1].to_string(); let line = cap[2].parse::().unwrap(); jump_to_position(&file, line); + self.set_listening(); } for _ in RE_PROCESS_EXITED.captures_iter(line) { @@ -325,48 +334,29 @@ impl Analyser { } } - match self.status.clone() { - PDBStatus::Printing(var) => { - self.print_variable(var, s); - } - _ => {} - } - } - - pub fn add_listener(&mut self, kind: Listener, sender: Sender) { - self.listeners.insert(kind, sender); +// match self.status.clone() { +// PDBStatus::Printing(var) => { +// self.print_variable(var, s); +// } +// _ => {} +// } } pub fn set_pid(&mut self, pid: u64) { self.pid = Some(pid); } - fn python_launched(&mut self) { - self.status = PDBStatus::Running; - match self.listeners.remove(&Listener::Launch) { - Some(mut listener) => { + fn set_listening(&mut self) { + self.status = PDBStatus::Listening; + let listener = self.listener.take(); + match listener { + Some(mut x) => { tokio::spawn(async move { - listener.send(Event::Launched).await.unwrap(); + x.send(true).await.unwrap(); }); - } - None => {} - } - } - - fn found_breakpoint(&mut self, file: String, line: u64) { - breakpoint_set(&file, line); - let file_location = FileLocation::new(file, line); - match self.listeners.remove(&Listener::Breakpoint) { - Some(mut listener) => { - tokio::spawn(async move { - listener - .send(Event::BreakpointSet(file_location)) - .await - .unwrap(); - }); - } + }, None => {} - } + }; } fn print_variable(&mut self, variable: Variable, data: &str) { @@ -376,18 +366,18 @@ impl Analyser { } let to = data.len() - 2; - match self.listeners.remove(&Listener::PrintVariable) { - Some(mut listener) => { - let event = Event::PrintVariable(variable, data[0..to].to_string()); - tokio::spawn(async move { - listener - .send(event) - .await - .unwrap(); - }); - } - None => {} - } + // match self.listeners.remove(&Listener::PrintVariable) { + // Some(mut listener) => { + // let event = Event::PrintVariable(variable, data[0..to].to_string()); + // tokio::spawn(async move { + // listener + // .send(event) + // .await + // .unwrap(); + // }); + // } + // None => {} + // } } } diff --git a/padre/integration/features/basics.feature b/padre/integration/features/basics.feature index a2c62e0..05fc85e 100644 --- a/padre/integration/features/basics.feature +++ b/padre/integration/features/basics.feature @@ -237,3 +237,5 @@ Feature: Basics Then I receive a response '{"status":"OK","value":25}' on connection 0 When I send a request to PADRE '{"cmd":"getConfig","key":"BackPressure"}' on connection 1 Then I receive a response '{"status":"OK","value":20}' on connection 1 + When I terminate padre + Then padre is not running diff --git a/padre/integration/features/python.feature b/padre/integration/features/python.feature index 8e00266..788299f 100644 --- a/padre/integration/features/python.feature +++ b/padre/integration/features/python.feature @@ -6,14 +6,14 @@ Feature: Python When I debug the program with PADRE When I send a request to PADRE '{"cmd":"run"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,"Launching process"] | + | function | args | + | padre#debugger#Log | [4,"Launching process"] | | padre#debugger#Log | [4,"Process launched with pid: \\d+"] | - | padre#debugger#JumpToPosition | [".*test_prog.py",3] | + | padre#debugger#JumpToPosition | [".*test_prog.py",3] | When I send a command 'b a' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.py$", 20] | + | function | args | + | padre#debugger#Log | [4, "Breakpoint set.*test_prog.py.*20"] | When I send a command 's' using the terminal Then I expect to be called with | function | args | @@ -38,20 +38,34 @@ Feature: Python Given that we have only a test program './test_files/test_prog.py' When I debug the program with PADRE When I send a request to PADRE '{"cmd":"breakpoint","file":"`pwd`/test_files/test_prog.py","line":21}' - Then I receive both a response '{"status":"PENDING"}' and I expect to be called with + Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | - | padre#debugger#Log | [4, ".*test_prog.py.*21"] | - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,"Launching process"] | - | padre#debugger#JumpToPosition | [".*test_prog.py",3] | - | padre#debugger#BreakpointSet | [".*test_prog.py",21] | + | padre#debugger#Log | [4, "Setting breakpoint.*test_prog.py.*21"] | + | padre#debugger#Log | [4, "Breakpoint pending.*test_prog.py.*21"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"`pwd`/test_files/test_prog.py","line":22}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4, ".*test_prog.py.*22"] | - | padre#debugger#BreakpointSet | [".*test_prog.py",22] | + | function | args | + | padre#debugger#Log | [4, "Setting breakpoint.*test_prog.py.*22"] | + | padre#debugger#Log | [4, "Breakpoint pending.*test_prog.py.*22"] | + When I send a request to PADRE '{"cmd":"breakpoint","file":"`pwd`/test_files/test_prog.py","line":23}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4, "Setting breakpoint.*test_prog.py.*23"] | + | padre#debugger#Log | [4, "Breakpoint pending.*test_prog.py.*23"] | + When I send a request to PADRE '{"cmd":"run"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Launching process"] | + | padre#debugger#Log | [4,"Process launched with pid: \\d+"] | + | padre#debugger#JumpToPosition | [".*test_prog.py",3] | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.py.*21"] | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.py.*22"] | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.py.*23"] | + When I send a request to PADRE '{"cmd":"breakpoint","file":"`pwd`/test_files/test_prog.py","line":24}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Setting breakpoint.*test_prog.py.*24"] | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.py.*24"] | When I send a request to PADRE '{"cmd":"stepOver"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | @@ -64,13 +78,22 @@ Feature: Python Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#JumpToPosition | [".*test_prog.py",6] | - When I send a request to PADRE '{"cmd":"continue"}' + When I send a request to PADRE '{"cmd":"stepOver"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.py",22] | + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",22] | + | padre#debugger#Log | [4,"Returning.*test string"] | When I send a request to PADRE '{"cmd":"print","variable":"b"}' Then I receive a response '{"status":"OK","variable":"b","value":"123"}' When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",23] | + When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",24] | + When I send a request to PADRE '{"cmd":"continue"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#ProcessExited | [0,"\\d+"] | From ed78fdddb40587826120509eff75f408cb13d387 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sun, 1 Dec 2019 20:50:42 +0000 Subject: [PATCH 07/23] Some reworking and full tests passing in Python, need to implement timeouts next --- padre/core/src/server.rs | 4 + padre/debuggers/python/src/debugger.rs | 55 ++--- padre/debuggers/python/src/process.rs | 272 ++++++++++++---------- padre/integration/features/python.feature | 18 +- 4 files changed, 184 insertions(+), 165 deletions(-) diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index ebdfec4..7524d34 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -64,6 +64,10 @@ impl Variable { pub fn new(name: String) -> Self { Variable { name } } + + pub fn name(&self) -> &str { + &self.name + } } /// All padre commands diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index d90c532..208d429 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -8,11 +8,10 @@ use std::process::exit; use std::sync::{Arc, Mutex}; use std::time::Instant; -use super::process::{PDBStatus, Process}; +use super::process::{Message, PDBStatus, Process}; use padre_core::server::{FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; -use bytes::Bytes; use futures::StreamExt; use tokio::sync::mpsc; @@ -35,7 +34,7 @@ impl ImplDebugger { } /// Run python and perform any setup necessary - pub fn run(&mut self, timeout: Instant) { //, config: Arc>) { + pub fn run(&mut self, timeout: Instant) { match self.process.lock().unwrap().get_status() { PDBStatus::None => {}, _ => { @@ -58,18 +57,12 @@ impl ImplDebugger { for pb in pbs { // Check we're actually listening let (tx, mut rx) = mpsc::channel(1); - process.lock().unwrap().add_listener(tx); + process.lock().unwrap().add_awakener(tx); rx.next().await.unwrap(); - process.lock().unwrap().drop_listener(); + process.lock().unwrap().drop_awakener(); // And send the breakpoint info - let stmt = format!( - "break {}:{}\n", - pb.name(), - pb.line_num() - ); - - process.lock().unwrap().write_stdin(Bytes::from(stmt)); + process.lock().unwrap().send_msg(Message::Breakpoint(pb)); } }, None => {} @@ -88,6 +81,10 @@ impl ImplDebugger { file_location: &FileLocation, timeout: Instant, ) { + let full_file_path = PathBuf::from(format!("{}", file_location.name())); + let full_file_name = full_file_path.canonicalize().unwrap(); + let file_location = FileLocation::new(full_file_name.to_str().unwrap().to_string(), file_location.line_num()); + log_msg( LogLevel::INFO, &format!( @@ -117,16 +114,7 @@ impl ImplDebugger { _ => {} } - // TODO: Timeout and error - let full_file_path = PathBuf::from(format!("{}", file_location.name())); - let full_file_name = full_file_path.canonicalize().unwrap(); - let stmt = format!( - "break {}:{}\n", - full_file_name.to_str().unwrap(), - file_location.line_num() - ); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + self.process.lock().unwrap().send_msg(Message::Breakpoint(file_location)); } pub fn step_in(&mut self, timeout: Instant) { @@ -135,10 +123,7 @@ impl ImplDebugger { // None => {} //}; - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("step\n")); + self.process.lock().unwrap().send_msg(Message::StepIn); } pub fn step_over(&mut self, timeout: Instant) { @@ -147,10 +132,7 @@ impl ImplDebugger { // None => {} //}; - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("next\n")); + self.process.lock().unwrap().send_msg(Message::StepOver); } pub fn continue_(&mut self, timeout: Instant) { @@ -159,10 +141,7 @@ impl ImplDebugger { // None => {} //}; - self.process - .lock() - .unwrap() - .write_stdin(Bytes::from("continue\n")); + self.process.lock().unwrap().send_msg(Message::Continue); } pub fn print( @@ -210,11 +189,7 @@ impl ImplDebugger { // eprintln!("Reading stdin error {:?}", e); // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") // }); - // - // let stmt = format!("print({})\n", variable.name); - // - // self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - // - // Box::new(f) + + self.process.lock().unwrap().send_msg(Message::PrintVariable(variable.clone())); } } diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 38859f8..b14e0b2 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -4,7 +4,6 @@ //! the pdb module. It will analyse the output of the text and work out what is //! happening then. -use std::collections::HashMap; use std::path::Path; #[cfg(not(test))] use std::process::exit; @@ -24,21 +23,106 @@ use tokio::io::BufReader; use tokio::process::{Command, Child, ChildStderr, ChildStdout}; use tokio::sync::mpsc::Sender; +/// You can register to listen for one of the following events: +/// - Launching +/// - Breakpoint +/// - StepIn +/// - StepOver +/// - Continue +/// - PrintVariable +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +pub enum Message { + Launching, + Breakpoint(FileLocation), + StepIn, + StepOver, + Continue, + PrintVariable(Variable), +} + #[derive(Debug, Clone, PartialEq)] pub enum PDBStatus { None, Listening, - Processing, + Processing(Message), } -/// You can register to listen for one of the following events: -/// - Breakpoint: A breakpoint event has happened -/// - PrintVariable: A variable printing event -#[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub enum Listener { - Launch, - Breakpoint, - PrintVariable, +/// Work out the arguments to send to python based on the python command given and the +/// run command specified +fn get_python_args<'a>(debugger_cmd: &str, run_cmd: Vec<&'a str>) -> Vec<&'a str> { + let mut python_args = vec![]; + let mut script_args = vec![]; + + // Now check the debugger and program to debug exist, if not error + #[cfg(not(test))] + { + // Try getting the full path if the debugger doesn't exist + if !file_exists(&debugger_cmd) { + let debugger_cmd = get_file_full_path(&debugger_cmd); + + if !file_exists(&debugger_cmd) { + let msg = format!("Can't spawn debugger as {} does not exist", debugger_cmd); + log_msg(LogLevel::CRITICAL, &msg); + println!("{}", msg); + + exit(1); + } + } + } + + python_args.push("-m"); + python_args.push("pdb"); + + // If we have the command `python -m mymod` say and `python` is specified + // as the debugger then we have then we don't want to run + // `python -m pdb -- -m mymod` + // On the other hand if we specified `./script.py -a test` we want that to + // run + // `python -m pdb -- ./script.py -a test` + // so we keep track of whether they're likely to be a python arg or a script + // arg here. + // + // tl;dr We assume all args are script args if the 0th element doesn't + // match the debugger, if it does we wait until we see `--` and then we + // assume script args. + let mut is_script_arg = true; + + for (i, arg) in run_cmd.iter().enumerate() { + // Skip the python part if specified as we add that from the -d option + if i == 0 { + let debugger_cmd_path = Path::new(debugger_cmd); + + let debugger_cmd = match debugger_cmd_path.file_name() { + Some(s) => s.to_str().unwrap(), + None => debugger_cmd, + }; + + if debugger_cmd == *arg { + is_script_arg = false; + continue; + } else { + is_script_arg = true; + } + } + + if *arg == "--" { + is_script_arg = true; + continue; + } + + if is_script_arg { + script_args.push(&arg[..]); + } else { + python_args.push(arg); + } + } + + if script_args.len() > 0 { + python_args.push("--"); + python_args.append(&mut script_args); + } + + python_args } /// Main handler for spawning the Python process @@ -116,30 +200,44 @@ impl Process { /// /// Should only add a sender when we're about to go into or currently in the /// processing status otherwise this will never wake up. - pub fn add_listener(&self, sender: Sender) { - self.analyser.lock().unwrap().add_listener(sender); + pub fn add_awakener(&self, sender: Sender) { + self.analyser.lock().unwrap().add_awakener(sender); } - /// Drop the listener - pub fn drop_listener(&mut self) { - self.analyser.lock().unwrap().drop_listener(); + /// Drop the awakener + pub fn drop_awakener(&mut self) { + self.analyser.lock().unwrap().drop_awakener(); } - /// Check the current status, either not running (None), running Python code + /// Check the current status, either not running (None), running something /// (Processing) or listening for a message on PDB (Listening). pub fn get_status(&self) -> PDBStatus { self.analyser.lock().unwrap().get_status() } /// Send a message to write to stdin - pub fn write_stdin(&mut self, bytes: Bytes) { + pub fn send_msg(&mut self, message: Message) { let tx = self.stdin_tx.clone(); let analyser = self.analyser.clone(); + tokio::spawn(async move { - analyser.lock().unwrap().status = PDBStatus::Processing; + let msg = match message.clone() { + Message::Breakpoint(fl) => { + Bytes::from(format!("break {}:{}\n", fl.name(), fl.line_num())) + }, + Message::StepIn => Bytes::from("step\n"), + Message::StepOver => Bytes::from("next\n"), + Message::Continue => Bytes::from("continue\n"), + Message::Launching => unreachable!(), + Message::PrintVariable(v) => { + Bytes::from(format!("print({})\n", v.name())) + } + }; + + analyser.lock().unwrap().status = PDBStatus::Processing(message); tx.clone() .unwrap() - .send(bytes) + .send(Bytes::from(msg)) .map(move |_| {}) .await }); @@ -168,89 +266,11 @@ impl Process { } } -/// Work out the arguments to send to python based on the python command given and the -/// run command specified -fn get_python_args<'a>(debugger_cmd: &str, run_cmd: Vec<&'a str>) -> Vec<&'a str> { - let mut python_args = vec![]; - let mut script_args = vec![]; - - // Now check the debugger and program to debug exist, if not error - #[cfg(not(test))] - { - // Try getting the full path if the debugger doesn't exist - if !file_exists(&debugger_cmd) { - let debugger_cmd = get_file_full_path(&debugger_cmd); - - if !file_exists(&debugger_cmd) { - let msg = format!("Can't spawn debugger as {} does not exist", debugger_cmd); - log_msg(LogLevel::CRITICAL, &msg); - println!("{}", msg); - - exit(1); - } - } - } - - python_args.push("-m"); - python_args.push("pdb"); - - // If we have the command `python -m mymod` say and `python` is specified - // as the debugger then we have then we don't want to run - // `python -m pdb -- -m mymod` - // On the other hand if we specified `./script.py -a test` we want that to - // run - // `python -m pdb -- ./script.py -a test` - // so we keep track of whether they're likely to be a python arg or a script - // arg here. - // - // tl;dr We assume all args are script args if the 0th element doesn't - // match the debugger, if it does we wait until we see `--` and then we - // assume script args. - let mut is_script_arg = true; - - for (i, arg) in run_cmd.iter().enumerate() { - // Skip the python part if specified as we add that from the -d option - if i == 0 { - let debugger_cmd_path = Path::new(debugger_cmd); - - let debugger_cmd = match debugger_cmd_path.file_name() { - Some(s) => s.to_str().unwrap(), - None => debugger_cmd, - }; - - if debugger_cmd == *arg { - is_script_arg = false; - continue; - } else { - is_script_arg = true; - } - } - - if *arg == "--" { - is_script_arg = true; - continue; - } - - if is_script_arg { - script_args.push(&arg[..]); - } else { - python_args.push(arg); - } - } - - if script_args.len() > 0 { - python_args.push("--"); - python_args.append(&mut script_args); - } - - python_args -} - #[derive(Debug)] pub struct Analyser { status: PDBStatus, pid: Option, - listener: Option>, + awakener: Option>, } impl Analyser { @@ -258,7 +278,7 @@ impl Analyser { Analyser { status: PDBStatus::None, pid: None, - listener: None, + awakener: None, } } @@ -266,14 +286,14 @@ impl Analyser { self.status.clone() } - /// Add the listener to ping when we awaken - pub fn add_listener(&mut self, sender: Sender) { - self.listener = Some(sender); + /// Add the awakener to send a message to when we awaken + pub fn add_awakener(&mut self, sender: Sender) { + self.awakener = Some(sender); } - /// Drop the listener to ping when we awaken - pub fn drop_listener(&mut self) { - self.listener = None; + /// Drop the awakener + pub fn drop_awakener(&mut self) { + self.awakener = None; } pub fn analyse_stdout(&mut self, s: &str) { @@ -292,14 +312,14 @@ impl Analyser { } for line in s.split("\n") { - if line.contains("(Pdb) ") { - match self.status { - PDBStatus::None => { - self.status = PDBStatus::Processing; + match self.status { + PDBStatus::None => { + if line.contains("(Pdb) ") { + self.status = PDBStatus::Processing(Message::Launching); } - _ => {} - }; - } + } + _ => {} + }; for cap in RE_BREAKPOINT.captures_iter(line) { let file = cap[2].to_string(); @@ -334,12 +354,17 @@ impl Analyser { } } -// match self.status.clone() { -// PDBStatus::Printing(var) => { -// self.print_variable(var, s); -// } -// _ => {} -// } + match &self.status { + PDBStatus::Processing(msg) => { + match msg { + Message::PrintVariable(var) => { + self.print_variable(var.clone(), s); + } + _ => {}, + }; + }, + _ => {}, + }; } pub fn set_pid(&mut self, pid: u64) { @@ -348,8 +373,8 @@ impl Analyser { fn set_listening(&mut self) { self.status = PDBStatus::Listening; - let listener = self.listener.take(); - match listener { + let awakener = self.awakener.take(); + match awakener { Some(mut x) => { tokio::spawn(async move { x.send(true).await.unwrap(); @@ -359,13 +384,18 @@ impl Analyser { }; } - fn print_variable(&mut self, variable: Variable, data: &str) { + fn print_variable(&self, variable: Variable, data: &str) { let len = data.len(); if len < 2 { return; } let to = data.len() - 2; + + let msg = format!("variable {}={}", variable.name(), &data[0..to]); + + log_msg(LogLevel::INFO, &msg); + // match self.listeners.remove(&Listener::PrintVariable) { // Some(mut listener) => { // let event = Event::PrintVariable(variable, data[0..to].to_string()); diff --git a/padre/integration/features/python.feature b/padre/integration/features/python.feature index 788299f..1644371 100644 --- a/padre/integration/features/python.feature +++ b/padre/integration/features/python.feature @@ -80,11 +80,21 @@ Feature: Python | padre#debugger#JumpToPosition | [".*test_prog.py",6] | When I send a request to PADRE '{"cmd":"stepOver"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.py",22] | - | padre#debugger#Log | [4,"Returning.*test string"] | + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",7] | + When I send a request to PADRE '{"cmd":"stepOver"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",7] | + | padre#debugger#Log | [4,"Returning.*'test string'"] | + When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.py",22] | When I send a request to PADRE '{"cmd":"print","variable":"b"}' - Then I receive a response '{"status":"OK","variable":"b","value":"123"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"variable b=123"] | When I send a request to PADRE '{"cmd":"continue"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | From 42cd5cf678ef6894360bbc7c6d50dfd496a63cec Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sun, 1 Dec 2019 21:25:59 +0000 Subject: [PATCH 08/23] Fixed cargo tests --- ci/install-rust.yml | 3 +- padre/cli/src/debugger.rs | 10 ++-- padre/cli/src/main.rs | 10 +++- padre/core/src/server.rs | 23 +++++--- padre/core/src/util.rs | 37 ++++++------- padre/core/src/vimcodec.rs | 75 +++++++++++++++++--------- padre/debuggers/python/src/debugger.rs | 55 ++++++++++--------- padre/debuggers/python/src/process.rs | 41 ++++++-------- 8 files changed, 144 insertions(+), 110 deletions(-) diff --git a/ci/install-rust.yml b/ci/install-rust.yml index 8504c12..4274253 100644 --- a/ci/install-rust.yml +++ b/ci/install-rust.yml @@ -2,7 +2,8 @@ steps: - script: | set -e curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable - echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin" + echo "##vso[task.setvariable variable=PATH;]$HOME/.cargo/bin:$PATH" + rustup update displayName: Install rust - script: | diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 97a45ca..224bc90 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -32,7 +32,10 @@ pub struct Debugger { } impl Debugger { - pub fn new(impl_debugger: Arc>, mut queue_rx: Receiver<(DebuggerCmd, Instant)>) -> Debugger { + pub fn new( + impl_debugger: Arc>, + mut queue_rx: Receiver<(DebuggerCmd, Instant)>, + ) -> Debugger { let debugger = Debugger { debugger: impl_debugger.clone(), }; @@ -50,7 +53,7 @@ impl Debugger { DebuggerCmd::Continue => debugger.continue_(cmd.1), DebuggerCmd::Print(v) => debugger.print(&v, cmd.1), }; - }; + } }); debugger @@ -104,7 +107,8 @@ pub async fn create_debugger( }, }; - let debugger: padre_python::ImplDebugger = padre_python::ImplDebugger::new(debugger_cmd, run_cmd); + let debugger: padre_python::ImplDebugger = + padre_python::ImplDebugger::new(debugger_cmd, run_cmd); // DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), // DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), // DebuggerType::Python => Box::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd)), diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index 4a6de9f..558ecfb 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -28,9 +28,9 @@ use clap::{App, Arg, ArgMatches}; use futures::prelude::*; use tokio::net::TcpListener; use tokio::runtime::Runtime; -use tokio::time::delay_for; use tokio::signal::unix::{signal, SignalKind}; use tokio::sync::mpsc; +use tokio::time::delay_for; use padre_core::server; use padre_core::util; @@ -114,7 +114,13 @@ async fn run_padre() -> () { // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? let debugger = Arc::new(Mutex::new( - debugger::create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx).await, + debugger::create_debugger( + args.value_of("debugger"), + args.value_of("type"), + debug_cmd, + debugger_queue_rx, + ) + .await, )); let connection_addr = get_connection(&args); diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index 7524d34..d8256fa 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -8,7 +8,7 @@ use std::io; use std::process::{Command, Stdio}; use std::str; use std::sync::{Arc, Mutex}; -use std::time::{Duration, Instant}; +use std::time::Instant; use crate::config::Config; // TODO: Add in remove_listener @@ -87,15 +87,16 @@ pub enum PadreCmd { /// Examples: /// /// ``` +/// use std::time::{Duration, Instant}; /// use padre_core::server::{RequestCmd, DebuggerCmd, FileLocation, Variable}; /// -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Run); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Run, Instant::now() + Duration::new(5,0)); /// /// let file_location = FileLocation::new("test.c".to_string(), 12); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(file_location)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(file_location), Instant::now() + Duration::new(5,0)); /// /// let variable = Variable::new("abc".to_string()); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Print(variable)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Print(variable), Instant::now() + Duration::new(5,0)); /// ``` #[derive(Clone, Debug, PartialEq)] pub enum RequestCmd { @@ -220,7 +221,9 @@ pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender<(Debugger tokio::spawn(async move { while let Some(req) = request_rx.next().await { - let resp = respond(req.unwrap(), debugger_queue_tx.clone(), config.clone()).await.unwrap(); + let resp = respond(req.unwrap(), debugger_queue_tx.clone(), config.clone()) + .await + .unwrap(); connection_tx .clone() .send(PadreSend::Response(resp)) @@ -259,8 +262,14 @@ async fn respond<'a>( } } RequestCmd::DebuggerCmd(cmd, timeout) => { - debugger_queue_tx.send((cmd.clone(), *timeout)).await.unwrap(); - Ok(Response::new(request.id(), serde_json::json!({"status":"OK"}))) + debugger_queue_tx + .send((cmd.clone(), *timeout)) + .await + .unwrap(); + Ok(Response::new( + request.id(), + serde_json::json!({"status":"OK"}), + )) } } } diff --git a/padre/core/src/util.rs b/padre/core/src/util.rs index 96839ae..a266d79 100644 --- a/padre/core/src/util.rs +++ b/padre/core/src/util.rs @@ -13,14 +13,14 @@ use std::task::{Context, Poll}; use crate::notifier::{log_msg, LogLevel}; -use bytes::{Bytes, BufMut}; +use bytes::Bytes; use futures::{Stream, StreamExt}; use pin_project::{pin_project, project}; use tokio::io::{stdin, AsyncBufRead}; -use tokio::process::{Child, ChildStdin, Command}; use tokio::prelude::*; +use tokio::process::{Child, ChildStdin, Command}; use tokio::sync::mpsc::{self, Sender}; -use tokio_util::codec::{FramedRead, BytesCodec}; +use tokio_util::codec::{BytesCodec, FramedRead}; /// Get an unused port on the local system and return it. This port /// can subsequently be used. @@ -186,7 +186,7 @@ async fn get_file_type(cmd: &str) -> String { pub struct ReadOutput { #[pin] reader: R, - buf: Vec + buf: Vec, } /// Creates a new stream from the I/O object @@ -209,29 +209,22 @@ impl Stream for ReadOutput { #[project] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { #[project] - let ReadOutput { - mut reader, - buf, - } = self.project(); + let ReadOutput { mut reader, buf } = self.project(); loop { let used = { match reader.as_mut().poll_fill_buf(cx) { - Poll::Ready(s) => { - match s { - Ok(t) => { - buf.extend_from_slice(t); - t.len() - } - Err(e) => { - println!("What to do here? {:?}", e); - 0 - } + Poll::Ready(s) => match s { + Ok(t) => { + buf.extend_from_slice(t); + t.len() } - } - Poll::Pending => { - 0 - } + Err(e) => { + println!("What to do here? {:?}", e); + 0 + } + }, + Poll::Pending => 0, } }; diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index 01304af..1fef6a8 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -489,16 +489,19 @@ impl<'a> Encoder for VimCodec<'a> { #[cfg(test)] mod tests { - use crate::server::{ - DebuggerCmd, Notification, PadreCmd, PadreRequest, PadreSend, RequestCmd, Response, - }; + use std::sync::{Arc, Mutex}; + + use crate::config::Config; + use crate::server::{DebuggerCmd, Notification, PadreCmd, PadreSend, RequestCmd, Response}; use bytes::{BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder}; #[test] fn check_simple_json_decoding() { - let mut codec = super::VimCodec::new(); + let config = Arc::new(Mutex::new(Config::new())); + + let mut codec = super::VimCodec::new(config); let mut buf = BytesMut::new(); buf.reserve(19); let s = r#"[123,{"cmd":"run"}]"#; @@ -506,15 +509,21 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); - assert_eq!( - PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), - padre_request - ); + assert_eq!(123, padre_request.id()); + + match padre_request.cmd() { + RequestCmd::DebuggerCmd(cmd, _) => { + assert_eq!(DebuggerCmd::Run, *cmd); + } + _ => panic!("Wrong command type"), + } } #[test] fn check_two_simple_json_decoding() { - let mut codec = super::VimCodec::new(); + let config = Arc::new(Mutex::new(Config::new())); + + let mut codec = super::VimCodec::new(config); let mut buf = BytesMut::new(); buf.reserve(19); let s = r#"[123,{"cmd":"run"}]"#; @@ -522,10 +531,14 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); - assert_eq!( - PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), - padre_request - ); + assert_eq!(123, padre_request.id()); + + match padre_request.cmd() { + RequestCmd::DebuggerCmd(cmd, _) => { + assert_eq!(DebuggerCmd::Run, *cmd); + } + _ => panic!("Wrong command type"), + } let mut buf = BytesMut::new(); buf.reserve(20); @@ -534,15 +547,21 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); - assert_eq!( - PadreRequest::new(124, RequestCmd::PadreCmd(PadreCmd::Ping)), - padre_request - ); + assert_eq!(124, padre_request.id()); + + match padre_request.cmd() { + RequestCmd::PadreCmd(cmd) => { + assert_eq!(PadreCmd::Ping, *cmd); + } + _ => panic!("Wrong command type"), + } } #[test] fn check_two_buffers_json_decodings() { - let mut codec = super::VimCodec::new(); + let config = Arc::new(Mutex::new(Config::new())); + + let mut codec = super::VimCodec::new(config); let mut buf = BytesMut::new(); buf.reserve(16); let s = r#"[123,{"cmd":"run"#; @@ -558,15 +577,21 @@ mod tests { let padre_request = codec.decode(&mut buf).unwrap().unwrap(); - assert_eq!( - PadreRequest::new(123, RequestCmd::DebuggerCmd(DebuggerCmd::Run)), - padre_request - ); + assert_eq!(123, padre_request.id()); + + match padre_request.cmd() { + RequestCmd::DebuggerCmd(cmd, _) => { + assert_eq!(DebuggerCmd::Run, *cmd); + } + _ => panic!("Wrong command type"), + } } #[test] fn check_json_encoding_response() { - let mut codec = super::VimCodec::new(); + let config = Arc::new(Mutex::new(Config::new())); + + let mut codec = super::VimCodec::new(config); let resp = PadreSend::Response(Response::new(123, serde_json::json!({"ping":"pong"}))); let mut buf = BytesMut::new(); codec.encode(resp, &mut buf).unwrap(); @@ -581,7 +606,9 @@ mod tests { #[test] fn check_json_encoding_notify() { - let mut codec = super::VimCodec::new(); + let config = Arc::new(Mutex::new(Config::new())); + + let mut codec = super::VimCodec::new(config); let resp = PadreSend::Notification(Notification::new( "cmd_test".to_string(), vec![serde_json::json!("test"), serde_json::json!(1)], diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 208d429..622027c 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -9,8 +9,8 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; -use padre_core::server::{FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; +use padre_core::server::{FileLocation, Variable}; use futures::StreamExt; use tokio::sync::mpsc; @@ -34,14 +34,14 @@ impl ImplDebugger { } /// Run python and perform any setup necessary - pub fn run(&mut self, timeout: Instant) { + pub fn run(&mut self, _timeout: Instant) { match self.process.lock().unwrap().get_status() { - PDBStatus::None => {}, + PDBStatus::None => {} _ => { - let msg = "Process already running, not launching"; - eprintln!("{}", msg); - log_msg(LogLevel::WARN, msg); - return; + let msg = "Process already running, not launching"; + eprintln!("{}", msg); + log_msg(LogLevel::WARN, msg); + return; } } @@ -64,7 +64,7 @@ impl ImplDebugger { // And send the breakpoint info process.lock().unwrap().send_msg(Message::Breakpoint(pb)); } - }, + } None => {} }; }); @@ -76,20 +76,20 @@ impl ImplDebugger { }); } - pub fn breakpoint( - &mut self, - file_location: &FileLocation, - timeout: Instant, - ) { + pub fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { let full_file_path = PathBuf::from(format!("{}", file_location.name())); let full_file_name = full_file_path.canonicalize().unwrap(); - let file_location = FileLocation::new(full_file_name.to_str().unwrap().to_string(), file_location.line_num()); + let file_location = FileLocation::new( + full_file_name.to_str().unwrap().to_string(), + file_location.line_num(), + ); log_msg( LogLevel::INFO, &format!( "Setting breakpoint in file {} at line number {}", - file_location.name(), file_location.line_num() + file_location.name(), + file_location.line_num() ), ); @@ -105,7 +105,8 @@ impl ImplDebugger { LogLevel::INFO, &format!( "Breakpoint pending in file {} at line number {}", - file_location.name(), file_location.line_num() + file_location.name(), + file_location.line_num() ), ); @@ -114,10 +115,13 @@ impl ImplDebugger { _ => {} } - self.process.lock().unwrap().send_msg(Message::Breakpoint(file_location)); + self.process + .lock() + .unwrap() + .send_msg(Message::Breakpoint(file_location)); } - pub fn step_in(&mut self, timeout: Instant) { + pub fn step_in(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -126,7 +130,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::StepIn); } - pub fn step_over(&mut self, timeout: Instant) { + pub fn step_over(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -135,7 +139,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::StepOver); } - pub fn continue_(&mut self, timeout: Instant) { + pub fn continue_(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -144,11 +148,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::Continue); } - pub fn print( - &mut self, - variable: &Variable, - timeout: Instant, - ) { + pub fn print(&mut self, variable: &Variable, _timeout: Instant) { // //match self.check_process_running() { // // Some(f) => return f, // // None => {} @@ -190,6 +190,9 @@ impl ImplDebugger { // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") // }); - self.process.lock().unwrap().send_msg(Message::PrintVariable(variable.clone())); + self.process + .lock() + .unwrap() + .send_msg(Message::PrintVariable(variable.clone())); } } diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index b14e0b2..356470d 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -10,8 +10,8 @@ use std::process::exit; use std::process::Stdio; use std::sync::{Arc, Mutex}; -use padre_core::server::{FileLocation, Variable}; use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::server::{FileLocation, Variable}; #[cfg(not(test))] use padre_core::util::{file_exists, get_file_full_path}; use padre_core::util::{read_output, setup_stdin}; @@ -20,7 +20,7 @@ use bytes::Bytes; use futures::prelude::*; use regex::Regex; use tokio::io::BufReader; -use tokio::process::{Command, Child, ChildStderr, ChildStdout}; +use tokio::process::{Child, ChildStderr, ChildStdout, Command}; use tokio::sync::mpsc::Sender; /// You can register to listen for one of the following events: @@ -168,7 +168,10 @@ impl Process { .spawn() .expect("Failed to spawn debugger"); - log_msg(LogLevel::INFO, &format!("Process launched with pid: {}", process.id())); + log_msg( + LogLevel::INFO, + &format!("Process launched with pid: {}", process.id()), + ); self.setup_stdout( process @@ -224,14 +227,12 @@ impl Process { let msg = match message.clone() { Message::Breakpoint(fl) => { Bytes::from(format!("break {}:{}\n", fl.name(), fl.line_num())) - }, + } Message::StepIn => Bytes::from("step\n"), Message::StepOver => Bytes::from("next\n"), Message::Continue => Bytes::from("continue\n"), Message::Launching => unreachable!(), - Message::PrintVariable(v) => { - Bytes::from(format!("print({})\n", v.name())) - } + Message::PrintVariable(v) => Bytes::from(format!("print({})\n", v.name())), }; analyser.lock().unwrap().status = PDBStatus::Processing(message); @@ -324,7 +325,10 @@ impl Analyser { for cap in RE_BREAKPOINT.captures_iter(line) { let file = cap[2].to_string(); let line = cap[3].parse::().unwrap(); - log_msg(LogLevel::INFO, &format!("Breakpoint set at file {} and line number {}", file, line)); + log_msg( + LogLevel::INFO, + &format!("Breakpoint set at file {} and line number {}", file, line), + ); self.set_listening(); } @@ -360,10 +364,10 @@ impl Analyser { Message::PrintVariable(var) => { self.print_variable(var.clone(), s); } - _ => {}, + _ => {} }; - }, - _ => {}, + } + _ => {} }; } @@ -379,7 +383,7 @@ impl Analyser { tokio::spawn(async move { x.send(true).await.unwrap(); }); - }, + } None => {} }; } @@ -395,19 +399,6 @@ impl Analyser { let msg = format!("variable {}={}", variable.name(), &data[0..to]); log_msg(LogLevel::INFO, &msg); - - // match self.listeners.remove(&Listener::PrintVariable) { - // Some(mut listener) => { - // let event = Event::PrintVariable(variable, data[0..to].to_string()); - // tokio::spawn(async move { - // listener - // .send(event) - // .await - // .unwrap(); - // }); - // } - // None => {} - // } } } From 67f279d9285dbb9cbbe868dc65f730e5a05e1334 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Mon, 2 Dec 2019 09:21:04 +0000 Subject: [PATCH 09/23] Don't need async traits, beautiful :) --- padre/cli/src/debugger.rs | 57 ++++++++++++++++++-------- padre/core/src/server.rs | 14 +++++++ padre/debuggers/python/src/debugger.rs | 31 ++++++++++---- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 224bc90..9b003b2 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -7,33 +7,38 @@ use std::fmt::Debug; use std::sync::{Arc, Mutex}; use std::time::Instant; -use padre_core::server::DebuggerCmd; +use padre_core::server::{DebuggerCmd, DebuggerV1}; use padre_core::util::{file_is_binary_executable, file_is_text}; use futures::StreamExt; use tokio::sync::mpsc::Receiver; -//mod lldb; -//mod node; +#[cfg(feature = "lldb")] +mod lldb; +#[cfg(feature = "node")] +mod node; #[cfg(feature = "python")] use padre_python; /// Debuggers #[derive(Debug)] enum DebuggerType { + #[cfg(feature = "lldb")] LLDB, + #[cfg(feature = "node")] Node, + #[cfg(feature = "python")] Python, } #[derive(Debug)] pub struct Debugger { - debugger: Arc>, + debugger: Arc>, } impl Debugger { pub fn new( - impl_debugger: Arc>, + impl_debugger: Arc>, mut queue_rx: Receiver<(DebuggerCmd, Instant)>, ) -> Debugger { let debugger = Debugger { @@ -76,8 +81,11 @@ pub async fn create_debugger( ) -> Debugger { let debugger_type = match debugger_type { Some(s) => match s.to_ascii_lowercase().as_str() { + #[cfg(feature = "lldb")] "lldb" => DebuggerType::LLDB, + #[cfg(feature = "python")] "python" => DebuggerType::Python, + #[cfg(feature = "node")] "node" => DebuggerType::Node, _ => panic!("Couldn't understand debugger type {}", s), }, @@ -85,8 +93,11 @@ pub async fn create_debugger( Some(s) => s, None => match debugger_cmd { Some(s) => match s { + #[cfg(feature = "lldb")] "lldb" => DebuggerType::LLDB, + #[cfg(feature = "python")] "python" | "python3" => DebuggerType::Python, + #[cfg(feature = "node")] "node" => DebuggerType::Node, _ => panic!( "Can't find debugger type for {}, try specifying with -d or -t", @@ -101,33 +112,45 @@ pub async fn create_debugger( let debugger_cmd = match debugger_cmd { Some(s) => s.to_string(), None => match debugger_type { + #[cfg(feature = "lldb")] DebuggerType::LLDB => "lldb".to_string(), + #[cfg(feature = "node")] DebuggerType::Node => "node".to_string(), + #[cfg(feature = "python")] DebuggerType::Python => "python3".to_string(), }, }; - let debugger: padre_python::ImplDebugger = - padre_python::ImplDebugger::new(debugger_cmd, run_cmd); - // DebuggerType::LLDB => Box::new(lldb::ImplDebugger::new(debugger_cmd, run_cmd)), - // DebuggerType::Node => Box::new(node::ImplDebugger::new(debugger_cmd, run_cmd)), - // DebuggerType::Python => Box::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd)), - // }; + let debugger: Arc> = match debugger_type { + #[cfg(feature = "lldb")] + DebuggerType::LLDB => Arc::new(Mutex::new(padre_lldb::ImplDebugger::new(debugger_cmd, run_cmd))), + #[cfg(feature = "node")] + DebuggerType::Node => Arc::new(Mutex::new(padre_node::ImplDebugger::new(debugger_cmd, run_cmd))), + #[cfg(feature = "python")] + DebuggerType::Python => Arc::new(Mutex::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd))), + }; + + debugger.lock().unwrap().setup(); + // let debugger: padre_python::ImplDebugger = + // padre_python::ImplDebugger::new(debugger_cmd, run_cmd); - Debugger::new(Arc::new(Mutex::new(debugger)), queue_rx) + Debugger::new(debugger, queue_rx) } /// Guesses the debugger type async fn get_debugger_type(run_cmd: &str) -> Option { if is_node(&run_cmd).await { - Some(DebuggerType::Node) + #[cfg(feature = "node")] + return Some(DebuggerType::Node); } else if is_python(&run_cmd).await { - Some(DebuggerType::Python) + #[cfg(feature = "python")] + return Some(DebuggerType::Python); } else if is_lldb(&run_cmd).await { - Some(DebuggerType::LLDB) - } else { - None + #[cfg(feature = "lldb")] + return Some(DebuggerType::LLDB); } + + None } /// Checks if the file is a binary executable diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index d8256fa..cac0c5c 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -4,6 +4,7 @@ //! padre and debuggers for actioning. use std::env::current_exe; +use std::fmt::Debug; use std::io; use std::process::{Command, Stdio}; use std::str; @@ -199,6 +200,19 @@ pub enum PadreSend { Notification(Notification), } +/// Debugger trait that implements the basics +pub trait DebuggerV1: Debug { + fn setup(&mut self); + fn teardown(&mut self); + fn run(&mut self, timeout: Instant); + fn breakpoint(&mut self, file_location: &FileLocation, timeout: Instant); + fn unbreakpoint(&mut self, file_location: &FileLocation, timeout: Instant); + fn step_in(&mut self, timeout: Instant); + fn step_over(&mut self, timeout: Instant); + fn continue_(&mut self, timeout: Instant); + fn print(&mut self, variable: &Variable, _timeout: Instant); +} + /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 622027c..c7fe2fb 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -10,7 +10,7 @@ use std::time::Instant; use super::process::{Message, PDBStatus, Process}; use padre_core::notifier::{log_msg, LogLevel}; -use padre_core::server::{FileLocation, Variable}; +use padre_core::server::{FileLocation, Variable, DebuggerV1}; use futures::StreamExt; use tokio::sync::mpsc; @@ -28,13 +28,18 @@ impl ImplDebugger { pending_breakpoints: Some(vec![]), } } +} + +impl DebuggerV1 for ImplDebugger { + + fn setup(&mut self) {} - pub fn teardown(&mut self) { + fn teardown(&mut self) { exit(0); } /// Run python and perform any setup necessary - pub fn run(&mut self, _timeout: Instant) { + fn run(&mut self, _timeout: Instant) { match self.process.lock().unwrap().get_status() { PDBStatus::None => {} _ => { @@ -76,7 +81,7 @@ impl ImplDebugger { }); } - pub fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { + fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { let full_file_path = PathBuf::from(format!("{}", file_location.name())); let full_file_name = full_file_path.canonicalize().unwrap(); let file_location = FileLocation::new( @@ -121,7 +126,17 @@ impl ImplDebugger { .send_msg(Message::Breakpoint(file_location)); } - pub fn step_in(&mut self, _timeout: Instant) { + fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { + let full_file_path = PathBuf::from(format!("{}", file_location.name())); + let full_file_name = full_file_path.canonicalize().unwrap(); + let file_location = FileLocation::new( + full_file_name.to_str().unwrap().to_string(), + file_location.line_num(), + ); + + } + + fn step_in(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -130,7 +145,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::StepIn); } - pub fn step_over(&mut self, _timeout: Instant) { + fn step_over(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -139,7 +154,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::StepOver); } - pub fn continue_(&mut self, _timeout: Instant) { + fn continue_(&mut self, _timeout: Instant) { //match self.check_process_running() { // Some(f) => return f, // None => {} @@ -148,7 +163,7 @@ impl ImplDebugger { self.process.lock().unwrap().send_msg(Message::Continue); } - pub fn print(&mut self, variable: &Variable, _timeout: Instant) { + fn print(&mut self, variable: &Variable, _timeout: Instant) { // //match self.check_process_running() { // // Some(f) => return f, // // None => {} From 477fb96d7f8969270bf1206a603ca247654a942a Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 5 Dec 2019 15:44:29 +0000 Subject: [PATCH 10/23] WIP: Mostly started working on LLDB and NodeJS but both are tricky at the moment. LLDB is tricky because it's hard to know when the LLDB prompt comes up without spawning it in a PTY (and Tokio doesn't currently support this). May be able to put a process in between that does this quickly. Node is tricky because websocket crates on Tokio 0.2 don't really exist yet --- padre/Cargo.lock | 481 +++++++++++++++++++- padre/cli/Cargo.toml | 6 +- padre/cli/src/debugger.rs | 21 +- padre/debuggers/lldb/debugger.rs | 298 ------------ padre/debuggers/lldb/src/debugger.rs | 245 ++++++++++ padre/debuggers/lldb/{mod.rs => src/lib.rs} | 3 + padre/debuggers/lldb/{ => src}/process.rs | 416 ++++++++++------- padre/debuggers/node/debugger.rs | 303 ------------ padre/debuggers/node/{ => src}/analyser.rs | 101 ++-- padre/debuggers/node/src/debugger.rs | 308 +++++++++++++ padre/debuggers/node/{mod.rs => src/lib.rs} | 3 + padre/debuggers/node/{ => src}/process.rs | 69 +-- padre/debuggers/node/src/ws.rs | 176 +++++++ padre/debuggers/node/ws.rs | 174 ------- padre/debuggers/python/src/debugger.rs | 6 +- padre/debuggers/python/src/process.rs | 11 +- padre/integration/features/lldb.feature | 370 +++++++-------- padre/integration/features/steps/shared.py | 10 + 18 files changed, 1781 insertions(+), 1220 deletions(-) delete mode 100644 padre/debuggers/lldb/debugger.rs create mode 100644 padre/debuggers/lldb/src/debugger.rs rename padre/debuggers/lldb/{mod.rs => src/lib.rs} (70%) rename padre/debuggers/lldb/{ => src}/process.rs (50%) delete mode 100644 padre/debuggers/node/debugger.rs rename padre/debuggers/node/{ => src}/analyser.rs (80%) create mode 100644 padre/debuggers/node/src/debugger.rs rename padre/debuggers/node/{mod.rs => src/lib.rs} (74%) rename padre/debuggers/node/{ => src}/process.rs (61%) create mode 100644 padre/debuggers/node/src/ws.rs delete mode 100644 padre/debuggers/node/ws.rs diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 25e054b..aacabd1 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -34,18 +34,88 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] + +[[package]] +name = "cc" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" + [[package]] name = "cfg-if" version = "0.1.10" @@ -67,12 +137,58 @@ dependencies = [ "vec_map", ] +[[package]] +name = "core-foundation" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -180,6 +296,26 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hermit-abi" version = "0.1.3" @@ -189,6 +325,43 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2790658cddc82e82b08e25176c431d7015a0adeb1718498715cbd20138a0bf68" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "input_buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf" +dependencies = [ + "bytes 0.4.12", +] + [[package]] name = "iovec" version = "0.1.4" @@ -235,6 +408,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "memchr" version = "2.2.1" @@ -305,6 +484,24 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "native-tls" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "net2" version = "0.2.33" @@ -326,6 +523,45 @@ dependencies = [ "libc", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "openssl" +version = "0.10.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "padre" version = "0.2.0" @@ -333,6 +569,8 @@ dependencies = [ "clap", "futures", "padre_core", + "padre_lldb", + "padre_node", "padre_python", "serde", "serde_derive", @@ -344,7 +582,7 @@ dependencies = [ name = "padre_core" version = "0.2.0" dependencies = [ - "bytes", + "bytes 0.5.2", "futures", "lazy_static", "pin-project", @@ -356,11 +594,42 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "padre_lldb" +version = "0.2.0" +dependencies = [ + "bytes 0.5.2", + "futures", + "lazy_static", + "padre_core", + "regex", + "tokio", + "tokio-util", +] + +[[package]] +name = "padre_node" +version = "0.2.0" +dependencies = [ + "bytes 0.5.2", + "futures", + "lazy_static", + "padre_core", + "regex", + "serde", + "serde_derive", + "serde_json", + "tokio", + "tokio-util", + "tungstenite", + "url", +] + [[package]] name = "padre_python" version = "0.2.0" dependencies = [ - "bytes", + "bytes 0.5.2", "futures", "lazy_static", "padre_core", @@ -368,6 +637,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pin-project" version = "0.4.6" @@ -400,6 +675,18 @@ version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + [[package]] name = "proc-macro-hack" version = "0.5.11" @@ -435,6 +722,47 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +dependencies = [ + "c2-chacha", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.1.56" @@ -459,12 +787,52 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "ryu" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +[[package]] +name = "schannel" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +dependencies = [ + "lazy_static", + "winapi 0.3.8", +] + +[[package]] +name = "security-framework" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +dependencies = [ + "core-foundation-sys", +] + [[package]] name = "serde" version = "1.0.103" @@ -493,6 +861,18 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "signal-hook-registry" version = "1.2.0" @@ -509,6 +889,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" + [[package]] name = "socket2" version = "0.3.11" @@ -538,6 +924,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.8", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -562,7 +962,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e765bf9f550bd9b8a970633ca3b56b8120c4b6c5dcbe26a93744cb02fee4b17" dependencies = [ - "bytes", + "bytes 0.5.2", "fnv", "futures-core", "lazy_static", @@ -595,7 +995,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "bytes", + "bytes 0.5.2", "futures-core", "futures-sink", "log", @@ -603,6 +1003,50 @@ dependencies = [ "tokio", ] +[[package]] +name = "tungstenite" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0c2bd5aeb7dcd2bb32e472c8872759308495e5eccc942e929a513cd8d36110" +dependencies = [ + "base64", + "byteorder", + "bytes 0.4.12", + "http", + "httparse", + "input_buffer", + "log", + "native-tls", + "rand", + "sha-1", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +dependencies = [ + "smallvec", +] + [[package]] name = "unicode-width" version = "0.1.6" @@ -615,12 +1059,41 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "url" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + +[[package]] +name = "vcpkg" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" + [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" + [[package]] name = "winapi" version = "0.2.8" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index f3d574e..1fddce3 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -8,7 +8,9 @@ repository = "https://github.com/strottos/vim-padre" [features] -default = ["python"] +default = ["lldb", "node", "python"] +lldb = ["padre_lldb"] +node = ["padre_node"] python = ["padre_python"] [dependencies] @@ -21,4 +23,6 @@ serde_json = "1.0" tokio = { version = "0.2.2", features = ["full"] } # The debuggers, all optional +padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } +padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 9b003b2..8236fca 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -14,9 +14,9 @@ use futures::StreamExt; use tokio::sync::mpsc::Receiver; #[cfg(feature = "lldb")] -mod lldb; +use padre_lldb; #[cfg(feature = "node")] -mod node; +use padre_node; #[cfg(feature = "python")] use padre_python; @@ -123,16 +123,23 @@ pub async fn create_debugger( let debugger: Arc> = match debugger_type { #[cfg(feature = "lldb")] - DebuggerType::LLDB => Arc::new(Mutex::new(padre_lldb::ImplDebugger::new(debugger_cmd, run_cmd))), + DebuggerType::LLDB => Arc::new(Mutex::new(padre_lldb::ImplDebugger::new( + debugger_cmd, + run_cmd, + ))), #[cfg(feature = "node")] - DebuggerType::Node => Arc::new(Mutex::new(padre_node::ImplDebugger::new(debugger_cmd, run_cmd))), + DebuggerType::Node => Arc::new(Mutex::new(padre_node::ImplDebugger::new( + debugger_cmd, + run_cmd, + ))), #[cfg(feature = "python")] - DebuggerType::Python => Arc::new(Mutex::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd))), + DebuggerType::Python => Arc::new(Mutex::new(padre_python::ImplDebugger::new( + debugger_cmd, + run_cmd, + ))), }; debugger.lock().unwrap().setup(); - // let debugger: padre_python::ImplDebugger = - // padre_python::ImplDebugger::new(debugger_cmd, run_cmd); Debugger::new(debugger, queue_rx) } diff --git a/padre/debuggers/lldb/debugger.rs b/padre/debuggers/lldb/debugger.rs deleted file mode 100644 index a0f5dbc..0000000 --- a/padre/debuggers/lldb/debugger.rs +++ /dev/null @@ -1,298 +0,0 @@ -//! lldb client debugger -//! -//! The main LLDB Debugger entry point. Handles listening for instructions and -//! communicating through the `LLDBProcess`. - -use std::io; -use std::process::exit; -use std::sync::{Arc, Mutex}; -use std::time::Duration; - -use super::process::{Event, LLDBProcess, Listener}; -use crate::config::Config; -use crate::debugger::{FileLocation, Variable}; -use crate::notifier::{log_msg, LogLevel}; - -use bytes::Bytes; -use tokio::prelude::*; -use tokio::sync::mpsc; - -#[derive(Debug)] -pub struct ImplDebugger { - process: Arc>, -} - -impl ImplDebugger { - pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { - ImplDebugger { - process: Arc::new(Mutex::new(LLDBProcess::new(debugger_cmd, run_cmd))), - } - } - - /// Perform any initial setup including starting LLDB and setting up the stdio analyser stuff - /// - startup lldb and setup the stdio analyser - /// - perform initial setup so we can analyse LLDB properly - fn setup(&mut self) { - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::LLDBLaunched, tx); - - let process = self.process.clone(); - - tokio::spawn( - rx.take(1) - .for_each(move |event| { - match event { - Event::LLDBLaunched => { - process.lock().unwrap().write_stdin(Bytes::from(&b"settings set stop-line-count-after 0\n"[..])); - process.lock().unwrap().write_stdin(Bytes::from(&b"settings set stop-line-count-before 0\n"[..])); - process.lock().unwrap().write_stdin(Bytes::from(&b"settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n"[..])); - } - _ => unreachable!() - } - Ok(()) - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - }) - ); - - self.process.lock().unwrap().setup(); - } - - fn teardown(&mut self) { - self.process.lock().unwrap().teardown(); - exit(0); - } - - async fn run( - &mut self, - config: Arc>, - ) -> Result { - log_msg(LogLevel::INFO, "Launching process"); - - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::Breakpoint, tx); - - let process = self.process.clone(); - - let f = rx - .take(1) - .into_future() - .and_then(move |lldb_output| { - let lldb_output = lldb_output.0.unwrap(); - - match lldb_output { - Event::BreakpointSet(_) | Event::BreakpointMultiple => {} - _ => { - panic!("Don't understand output {:?}", lldb_output); - } - }; - - Ok(()) - }) - .and_then(move |_| { - let (tx, rx) = mpsc::channel(1); - - process - .lock() - .unwrap() - .add_listener(Listener::ProcessLaunched, tx); - - process - .lock() - .unwrap() - .write_stdin(Bytes::from("process launch\n")); - - rx.take(1).into_future() - }) - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("ProcessSpawnTimeout") - .unwrap() as u64, - 0, - )) - .map(move |event| match event.0.unwrap() { - Event::ProcessLaunched(pid) => { - serde_json::json!({"status":"OK","pid":pid.to_string()}) - } - _ => unreachable!(), - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out spawning process") - }); - - let stmt = "breakpoint set --name main\n"; - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - Box::new(f) - } - - async fn breakpoint( - &mut self, - file_location: &FileLocation, - config: Arc>, - ) -> Result { - log_msg( - LogLevel::INFO, - &format!( - "Setting breakpoint in file {} at line number {}", - file_location.name, file_location.line_num - ), - ); - - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::Breakpoint, tx); - - let f = rx - .take(1) - .into_future() - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("BreakpointTimeout") - .unwrap() as u64, - 0, - )) - .map(move |event| match event.0.unwrap() { - Event::BreakpointSet(_) => serde_json::json!({"status":"OK"}), - Event::BreakpointPending => serde_json::json!({"status":"PENDING"}), - _ => unreachable!(), - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") - }); - - let stmt = format!( - "breakpoint set --file {} --line {}\n", - file_location.name, file_location.line_num - ); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - Box::new(f) - } - - async fn step_in(&mut self) -> Result { - self.step("step-in") - } - - async fn step_over(&mut self) -> Result { - self.step("step-over") - } - - async fn continue_(&mut self) -> Result { - self.step("continue") - } - - async fn print( - &mut self, - variable: &Variable, - config: Arc>, - ) -> Result { - //match self.check_process() { - // Some(f) => return f, - // _ => {} - //} - - let (tx, rx) = mpsc::channel(1); - - self.process - .lock() - .unwrap() - .add_listener(Listener::PrintVariable, tx); - - let f = rx - .take(1) - .into_future() - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("PrintVariableTimeout") - .unwrap() as u64, - 0, - )) - .map(move |event| match event.0.unwrap() { - Event::PrintVariable(variable, value) => serde_json::json!({ - "status": "OK", - "variable": variable.name, - "value": value.value(), - "type": value.type_() - }), - Event::VariableNotFound(variable) => { - log_msg( - LogLevel::WARN, - &format!("variable '{}' doesn't exist here", variable.name), - ); - serde_json::json!({"status":"ERROR"}) - } - _ => unreachable!(), - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out printing variable") - }); - - let stmt = format!("frame variable {}\n", variable.name); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - Box::new(f) - } - - async fn step( - &mut self, - kind: &str, - ) -> Result { - //match self.check_process() { - // Some(f) => return f, - // _ => {} - //} - - let stmt = format!("thread {}\n", kind); - - self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - let f = future::lazy(move || { - let resp = serde_json::json!({"status":"OK"}); - Ok(resp) - }); - - Box::new(f) - } - - //fn check_process( - // &mut self, - //) -> Option> { - // match self.process.lock().unwrap().is_process_running() { - // false => { - // log_msg(LogLevel::WARN, "No process running"); - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"ERROR"}); - // Ok(resp) - // }); - - // Some(Box::new(f)) - // } - // true => None, - // } - //} -} diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs new file mode 100644 index 0000000..410fe34 --- /dev/null +++ b/padre/debuggers/lldb/src/debugger.rs @@ -0,0 +1,245 @@ +//! lldb client debugger +//! +//! The main LLDB Debugger entry point. Handles listening for instructions and +//! communicating through the `LLDBProcess`. + +use std::io; +use std::process::exit; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; + +use super::process::{LLDBProcess, Message}; +use padre_core::config::Config; +use padre_core::notifier::{log_msg, LogLevel}; +use padre_core::server::{DebuggerV1, FileLocation, Variable}; + +use bytes::Bytes; +use futures::prelude::*; +use tokio::sync::mpsc; + +#[derive(Debug)] +pub struct ImplDebugger { + process: Arc>, +} + +impl ImplDebugger { + pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { + ImplDebugger { + process: Arc::new(Mutex::new(LLDBProcess::new(debugger_cmd, run_cmd))), + } + } + + fn step(&mut self, kind: &str) { + //match self.check_process() { + // Some(f) => return f, + // _ => {} + //} + + //let stmt = format!("thread {}\n", kind); + + //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + + //let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"OK"}); + // Ok(resp) + //}); + } + + //fn check_process( + // &mut self, + //) -> Option> { + // match self.process.lock().unwrap().is_process_running() { + // false => { + // log_msg(LogLevel::WARN, "No process running"); + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"ERROR"}); + // Ok(resp) + // }); + + // Some(Box::new(f)) + // } + // true => None, + // } + //} +} + +impl DebuggerV1 for ImplDebugger { + /// Perform any initial setup including starting LLDB and setting up the stdio analyser stuff + /// - startup lldb and setup the stdio analyser + /// - perform initial setup so we can analyse LLDB properly + fn setup(&mut self) { + let process = self.process.clone(); + + tokio::spawn(async move { + let msgs = [ + "settings set stop-line-count-after 0\n", + "settings set stop-line-count-before 0\n", + "settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n", + "breakpoint set --name main\n", + ]; + + for msg in msgs.iter() { + // Check we're actually listening + let (tx, mut rx) = mpsc::channel(1); + process.lock().unwrap().add_awakener(tx); + rx.next().await.unwrap(); + process.lock().unwrap().drop_awakener(); + + process.lock().unwrap().write_stdin(Bytes::from(msg.as_bytes())); + } + }); + + self.process.lock().unwrap().setup(); + } + + fn teardown(&mut self) { + self.process.lock().unwrap().teardown(); + exit(0); + } + + fn run(&mut self, _timeout: Instant) { + log_msg(LogLevel::INFO, "Launching process"); + + //let (tx, rx) = mpsc::channel(1); + + //self.process + // .lock() + // .unwrap() + // .add_listener(Listener::Breakpoint, tx); + + //let process = self.process.clone(); + + //let f = rx + // .take(1) + // .into_future() + // .and_then(move |lldb_output| { + // let lldb_output = lldb_output.0.unwrap(); + + // match lldb_output { + // Event::BreakpointSet(_) | Event::BreakpointMultiple => {} + // _ => { + // panic!("Don't understand output {:?}", lldb_output); + // } + // }; + + // Ok(()) + // }) + // .and_then(move |_| { + // let (tx, rx) = mpsc::channel(1); + + // process + // .lock() + // .unwrap() + // .add_listener(Listener::ProcessLaunched, tx); + + // process + // .lock() + // .unwrap() + // .write_stdin(Bytes::from("process launch\n")); + + // rx.take(1).into_future() + // }) + // .timeout(Duration::new( + // config + // .lock() + // .unwrap() + // .get_config("ProcessSpawnTimeout") + // .unwrap() as u64, + // 0, + // )) + // .map(move |event| match event.0.unwrap() { + // Event::ProcessLaunched(pid) => { + // serde_json::json!({"status":"OK","pid":pid.to_string()}) + // } + // _ => unreachable!(), + // }) + // .map_err(|e| { + // eprintln!("Reading stdin error {:?}", e); + // io::Error::new(io::ErrorKind::Other, "Timed out spawning process") + // }); + + //let stmt = "breakpoint set --name main\n"; + + //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + } + + fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { + log_msg( + LogLevel::INFO, + &format!( + "Setting breakpoint in file {} at line number {}", + file_location.name(), + file_location.line_num() + ), + ); + + self.process + .lock() + .unwrap() + .send_msg(Message::Breakpoint(file_location.clone())); + } + + fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) {} + + fn step_in(&mut self, _timeout: Instant) { + self.step("step-in"); + } + + fn step_over(&mut self, _timeout: Instant) { + self.step("step-over"); + } + + fn continue_(&mut self, _timeout: Instant) { + self.step("continue"); + } + + fn print(&mut self, variable: &Variable, _timeout: Instant) { + //match self.check_process() { + // Some(f) => return f, + // _ => {} + //} + + //let (tx, rx) = mpsc::channel(1); + + //self.process + // .lock() + // .unwrap() + // .add_listener(Listener::PrintVariable, tx); + + //let f = rx + // .take(1) + // .into_future() + // .timeout(Duration::new( + // config + // .lock() + // .unwrap() + // .get_config("PrintVariableTimeout") + // .unwrap() as u64, + // 0, + // )) + // .map(move |event| match event.0.unwrap() { + // Event::PrintVariable(variable, value) => serde_json::json!({ + // "status": "OK", + // "variable": variable.name, + // "value": value.value(), + // "type": value.type_() + // }), + // Event::VariableNotFound(variable) => { + // log_msg( + // LogLevel::WARN, + // &format!("variable '{}' doesn't exist here", variable.name), + // ); + // serde_json::json!({"status":"ERROR"}) + // } + // _ => unreachable!(), + // }) + // .map_err(|e| { + // eprintln!("Reading stdin error {:?}", e); + // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") + // }); + + //let stmt = format!("frame variable {}\n", variable.name); + + //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + } +} diff --git a/padre/debuggers/lldb/mod.rs b/padre/debuggers/lldb/src/lib.rs similarity index 70% rename from padre/debuggers/lldb/mod.rs rename to padre/debuggers/lldb/src/lib.rs index c940825..a278ebe 100644 --- a/padre/debuggers/lldb/mod.rs +++ b/padre/debuggers/lldb/src/lib.rs @@ -1,5 +1,8 @@ //! The LLDB debugger module +#[macro_use] +extern crate lazy_static; + mod debugger; mod process; diff --git a/padre/debuggers/lldb/process.rs b/padre/debuggers/lldb/src/process.rs similarity index 50% rename from padre/debuggers/lldb/process.rs rename to padre/debuggers/lldb/src/process.rs index e6ded9b..74e2aa5 100644 --- a/padre/debuggers/lldb/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -3,49 +3,40 @@ //! This module performs the basic setup of and interfacing with LLDB. It will //! analyse the output of the text and work out what is happening then. -use std::collections::HashMap; -use std::io::BufReader; +use std::io::{self, Write}; use std::sync::{Arc, Mutex}; -use crate::debugger::{FileLocation, Variable}; -use crate::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; -use crate::util::{check_and_spawn_process, read_output}; //, setup_stdin}; +use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::server::{FileLocation, Variable}; +use padre_core::util::{check_and_spawn_process, read_output}; use bytes::Bytes; +use futures::prelude::*; use regex::Regex; -use tokio::net::process::{Child, ChildStderr, ChildStdout}; +use tokio::io::{stdin, BufReader}; use tokio::prelude::*; -use tokio::sync::mpsc::Sender; - -/// You can register to listen for one of the following events: -/// - LLDBLaunched: LLDB has started up initially -/// - ProcessLaunched: LLDB has launched a process for debugging -/// - ProcessExited: The process spawned by LLDB has exited -/// - Breakpoint: A breakpoint event has happened -/// - PrintVariable: A variable has been requested to print and this is the response +use tokio::process::{Child, ChildStdin, ChildStderr, ChildStdout}; +use tokio::sync::mpsc::{self, Sender}; +use tokio_util::codec::{BytesCodec, FramedRead}; + +/// Messages that can be sent to LLDB for processing #[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub enum Listener { - LLDBLaunched, - ProcessLaunched, - ProcessExited, - Breakpoint, - PrintVariable, +pub enum Message { + ProcessLaunching, + Breakpoint(FileLocation), + UnknownBreakpoint, + StepIn, + StepOver, + Continue, + PrintVariable(Variable), } -/// An LLDB event is something that can be registered for being listened to and can be triggered -/// when these events occur such that the listener is informed of them and passed some details -#[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub enum Event { - LLDBLaunched, - // (PID) - ProcessLaunched(u64), - // (PID, Exit code) - ProcessExited(u64, i64), - BreakpointSet(FileLocation), - BreakpointMultiple, - BreakpointPending, - PrintVariable(Variable, VariableValue), - VariableNotFound(Variable), +/// Current status of LLDB +#[derive(Debug, Clone, PartialEq)] +pub enum LLDBStatus { + None, + Listening, + Processing(Message), } /// The value of a variable @@ -69,6 +60,7 @@ impl VariableValue { } } +/// Main handler for spawning the LLDB process #[derive(Debug)] pub struct LLDBProcess { debugger_cmd: Option, @@ -114,15 +106,14 @@ impl LLDBProcess { .take() .expect("LLDB process did not have a handle to stderr"), ); - //let stdin_tx = setup_stdin( - // lldb_process - // .stdin() - // .take() - // .expect("LLDB process did not have a handle to stdin"), - // false, - //); - - //self.lldb_stdin_tx = Some(stdin_tx); + self.setup_stdin( + lldb_process + .stdin() + .take() + .expect("Python process did not have a handle to stdin"), + true, + ); + self.lldb_process = Some(lldb_process); } @@ -132,73 +123,169 @@ impl LLDBProcess { /// Send a message to write to stdin pub fn write_stdin(&mut self, bytes: Bytes) { - //let tx = self.lldb_stdin_tx.clone(); - //tokio::spawn( - // tx.clone() - // .unwrap() - // .send(bytes) - // .map(move |_| {}) - // .map_err(|e| eprintln!("Error sending to LLDB: {}", e)), - //); + let lldb_stdin_tx = self.lldb_stdin_tx.clone(); + tokio::spawn(async move { + lldb_stdin_tx.clone() + .unwrap() + .send(bytes) + .map(move |_| {}) + .await; + }); } - pub fn add_listener(&mut self, kind: Listener, sender: Sender) { - self.analyser.lock().unwrap().add_listener(kind, sender); + pub fn send_msg(&mut self, message: Message) { + let msg_bytes = match message.clone() { + Message::ProcessLaunching => Bytes::from("process launch\n"), + Message::Breakpoint(fl) => { + Bytes::from(format!( + "breakpoint set --file {} --line {}\n", + fl.name(), fl.line_num() + )) + }, + Message::UnknownBreakpoint => unreachable!(), + Message::StepIn => Bytes::from("thread step-in\n"), + Message::StepOver => Bytes::from("thread step-over\n"), + Message::Continue => Bytes::from("thread continue\n"), + Message::PrintVariable(v) => Bytes::from(format!("frame variable {}\n", v.name())), + }; + + self.analyser.lock().unwrap().status = LLDBStatus::Processing(message); + self.write_stdin(msg_bytes); + } + + /// Adds a Sender object that gets awoken when we are listening. + /// + /// Should only add a sender when we're about to go into or currently in the + /// processing status otherwise this will never wake up. + pub fn add_awakener(&mut self, sender: Sender) { + self.analyser.lock().unwrap().add_awakener(sender); + } + + /// Drop the awakener + pub fn drop_awakener(&mut self) { + self.analyser.lock().unwrap().drop_awakener(); } pub fn is_process_running(&self) -> bool { self.analyser.lock().unwrap().is_process_running() } + /// Perform setup of listening and forwarding of stdin and return a sender that will forward to the + /// stdin of a process. + fn setup_stdin(&mut self, mut child_stdin: ChildStdin, output_stdin: bool) { + let (stdin_tx, mut stdin_rx) = mpsc::channel(32); + let mut tx = stdin_tx.clone(); + + let analyser = self.analyser.clone(); + + tokio::spawn(async move { + let tokio_stdin = stdin(); + let mut reader = FramedRead::new(tokio_stdin, BytesCodec::new()); + while let Some(line) = reader.next().await { + let buf = line.unwrap().freeze(); + + let mut start = 0; + + if buf.len() >= 7 && buf[0..7] == b"(lldb) "[..] { + println!("DETECTED `(lldb) `, skipping"); + start = 7; + } + + if buf.len() >= start + 2 { + println!("stuff {:?}", &buf[start..start + 2]); + } + if buf.len() >= start + 3 { + println!("stuff {:?}", &buf[start..start + 3]); + } + if buf.len() >= start + 11 { + println!("stuff {:?}", &buf[start..start + 11]); + } + + if (buf.len() >= start + 2 && buf[start..start + 2] == b"b "[..]) || + (buf.len() >= start + 3 && buf[start..start + 3] == b"br "[..]) || + (buf.len() >= start + 11 && buf[start..start + 11] == b"breakpoint "[..]) { + println!("UNKNOWN BREAKPOINT"); + analyser.lock().unwrap().status = LLDBStatus::Processing(Message::UnknownBreakpoint); + } + + tx.send(buf).await.unwrap(); + } + }); + + tokio::spawn(async move { + while let Some(text) = stdin_rx.next().await { + if output_stdin { + io::stdout().write_all(&text).unwrap(); + } + match child_stdin.write(&text).await { + Ok(_) => {} + Err(e) => { + eprintln!("Writing stdin err e: {}", e); + } + }; + } + }); + + self.lldb_stdin_tx = Some(stdin_tx); + } + /// Perform setup of reading LLDB stdout, analysing it and writing it back to stdout. fn setup_stdout(&mut self, stdout: ChildStdout) { let analyser = self.analyser.clone(); - tokio::spawn( - read_output(BufReader::new(stdout)) - .for_each(move |text| { - print!("{}", text); - analyser.lock().unwrap().analyse_stdout(&text); - Ok(()) - }) - .map_err(|e| eprintln!("Err reading LLDB stdout: {}", e)), - ); + tokio::spawn(async move { + let mut reader = read_output(BufReader::new(stdout)); + while let Some(Ok(text)) = reader.next().await { + print!("{}", text); + analyser.lock().unwrap().analyse_stdout(&text); + } + }); } /// Perform setup of reading LLDB stderr, analysing it and writing it back to stdout. fn setup_stderr(&mut self, stderr: ChildStderr) { let analyser = self.analyser.clone(); - tokio::spawn( - read_output(BufReader::new(stderr)) - .for_each(move |text| { - eprint!("{}", text); - analyser.lock().unwrap().analyse_stderr(&text); - Ok(()) - }) - .map_err(|e| eprintln!("Err reading LLDB stderr: {}", e)), - ); + tokio::spawn(async move { + let mut reader = read_output(BufReader::new(stderr)); + while let Some(Ok(text)) = reader.next().await { + eprint!("{}", text); + analyser.lock().unwrap().analyse_stderr(&text); + } + }); } } #[derive(Debug)] pub struct Analyser { + status: LLDBStatus, stdout: String, stderr: String, process_pid: Option, - listeners: HashMap>, + awakener: Option>, } impl Analyser { pub fn new() -> Self { Analyser { + status: LLDBStatus::None, stdout: "".to_string(), stderr: "".to_string(), process_pid: None, - listeners: HashMap::new(), + awakener: None, } } - pub fn add_listener(&mut self, kind: Listener, sender: Sender) { - self.listeners.insert(kind, sender); + /// Add the awakener to send a message to when we awaken + pub fn add_awakener(&mut self, sender: Sender) { + self.awakener = Some(sender); + } + + /// Drop the awakener + pub fn drop_awakener(&mut self) { + self.awakener = None; + } + + pub fn get_status(&self) -> &LLDBStatus { + &self.status } pub fn analyse_stdout(&mut self, s: &str) { @@ -230,6 +317,7 @@ impl Analyser { Regex::new("^\\((.*)\\) ([\\S+]*) = .*$").unwrap(); static ref RE_PROCESS_NOT_RUNNING: Regex = Regex::new("error: invalid process$").unwrap(); + static ref RE_SETTINGS: Regex = Regex::new("settings ").unwrap(); } let s = self.stdout.clone(); @@ -257,6 +345,7 @@ impl Analyser { let file = cap[2].to_string(); let line = cap[3].parse::().unwrap(); self.found_breakpoint(file, line); + self.set_listening(); } if !found_breakpoint { @@ -265,6 +354,7 @@ impl Analyser { let file = cap[2].to_string(); let line = cap[3].parse::().unwrap(); self.found_breakpoint(file, line); + self.set_listening(); } } @@ -272,12 +362,14 @@ impl Analyser { for _ in RE_BREAKPOINT_MULTIPLE.captures_iter(line) { found_breakpoint = true; self.found_multiple_breakpoints(); + self.set_listening(); } } if !found_breakpoint { for _ in RE_BREAKPOINT_PENDING.captures_iter(line) { self.found_pending_breakpoint(); + self.set_listening(); } } @@ -288,10 +380,12 @@ impl Analyser { let file = cap[1].to_string(); let line = cap[2].parse::().unwrap(); self.jump_to_position(file, line); + self.set_listening(); } if !found { self.jump_to_unknown_position(); + self.set_listening(); } } @@ -304,6 +398,10 @@ impl Analyser { for _ in RE_PROCESS_NOT_RUNNING.captures_iter(line) { self.process_not_running(); } + + for _ in RE_SETTINGS.captures_iter(line) { + self.set_listening(); + } } self.clear_analyser(); @@ -329,6 +427,19 @@ impl Analyser { self.clear_analyser(); } + fn set_listening(&mut self) { + self.status = LLDBStatus::Listening; + let awakener = self.awakener.take(); + match awakener { + Some(mut x) => { + tokio::spawn(async move { + x.send(true).await.unwrap(); + }); + } + None => {} + }; + } + fn clear_analyser(&mut self) { self.stdout = "".to_string(); self.stderr = "".to_string(); @@ -342,68 +453,63 @@ impl Analyser { } fn lldb_started(&mut self) { - match self.listeners.remove(&Listener::LLDBLaunched) { - Some(listener) => { - listener.send(Event::LLDBLaunched).wait().unwrap(); - } - None => {} - } + self.set_listening(); } fn process_started(&mut self, pid: u64) { - self.process_pid = Some(pid); - match self.listeners.remove(&Listener::ProcessLaunched) { - Some(listener) => { - listener.send(Event::ProcessLaunched(pid)).wait().unwrap(); - } - None => {} - } + self.set_listening(); } fn process_exited(&mut self, pid: u64, exit_code: i64) { self.process_pid = None; signal_exited(pid, exit_code); - match self.listeners.remove(&Listener::ProcessExited) { - Some(listener) => { - listener - .send(Event::ProcessExited(pid, exit_code)) - .wait() - .unwrap(); - } - None => {} - } + self.set_listening(); } fn found_breakpoint(&mut self, file: String, line: u64) { - breakpoint_set(&file, line); - let file_location = FileLocation::new(file, line); - match self.listeners.remove(&Listener::Breakpoint) { - Some(listener) => { - listener - .send(Event::BreakpointSet(file_location)) - .wait() - .unwrap(); - } - None => {} - } + match &self.status { + LLDBStatus::Processing(msg) => { + match msg { + Message::Breakpoint(_) | Message::UnknownBreakpoint => { + log_msg( + LogLevel::INFO, + &format!("Breakpoint set at file {} and line number {}", file, line), + ); + }, + _ => {}, + }; + }, + _ => {}, + }; + //breakpoint_set(&file, line); + //let file_location = FileLocation::new(file, line); + //match self.listeners.remove(&Listener::Breakpoint) { + // Some(listener) => { + // listener + // .send(Event::BreakpointSet(file_location)) + // .wait() + // .unwrap(); + // } + // None => {} + //} } fn found_multiple_breakpoints(&mut self) { - match self.listeners.remove(&Listener::Breakpoint) { - Some(listener) => { - listener.send(Event::BreakpointMultiple).wait().unwrap(); - } - None => {} - } + //match self.listeners.remove(&Listener::Breakpoint) { + // Some(listener) => { + // listener.send(Event::BreakpointMultiple).wait().unwrap(); + // } + // None => {} + //} } fn found_pending_breakpoint(&mut self) { - match self.listeners.remove(&Listener::Breakpoint) { - Some(listener) => { - listener.send(Event::BreakpointPending).wait().unwrap(); - } - None => {} - } + //match self.listeners.remove(&Listener::Breakpoint) { + // Some(listener) => { + // listener.send(Event::BreakpointPending).wait().unwrap(); + // } + // None => {} + //} } fn jump_to_position(&mut self, file: String, line: u64) { @@ -415,31 +521,31 @@ impl Analyser { } fn printed_variable(&mut self, variable: String, variable_type: String, data: &str) { - let mut start = 1; - - while &data[start..start + 1] != ")" { - start += 1; - } - while &data[start..start + 1] != "=" { - start += 1; - } - start += 2; - - // TODO: Need a better way of doing this to strip of the last \n, - // it's possible one day we'll screw the UTF-8 pooch here. - let value = data[start..data.len() - 1].to_string(); - - match self.listeners.remove(&Listener::PrintVariable) { - Some(listener) => { - let variable = Variable::new(variable); - let value = VariableValue::new(variable_type, value); - listener - .send(Event::PrintVariable(variable, value)) - .wait() - .unwrap(); - } - None => {} - } + // let mut start = 1; + + // while &data[start..start + 1] != ")" { + // start += 1; + // } + // while &data[start..start + 1] != "=" { + // start += 1; + // } + // start += 2; + + // // TODO: Need a better way of doing this to strip of the last \n, + // // it's possible one day we'll screw the UTF-8 pooch here. + // let value = data[start..data.len() - 1].to_string(); + + // match self.listeners.remove(&Listener::PrintVariable) { + // Some(listener) => { + // let variable = Variable::new(variable); + // let value = VariableValue::new(variable_type, value); + // listener + // .send(Event::PrintVariable(variable, value)) + // .wait() + // .unwrap(); + // } + // None => {} + // } } fn process_not_running(&self) { @@ -447,15 +553,15 @@ impl Analyser { } fn variable_not_found(&mut self, variable: String) { - match self.listeners.remove(&Listener::PrintVariable) { - Some(listener) => { - let variable = Variable::new(variable); - listener - .send(Event::VariableNotFound(variable)) - .wait() - .unwrap(); - } - None => {} - } + //match self.listeners.remove(&Listener::PrintVariable) { + // Some(listener) => { + // let variable = Variable::new(variable); + // listener + // .send(Event::VariableNotFound(variable)) + // .wait() + // .unwrap(); + // } + // None => {} + //} } } diff --git a/padre/debuggers/node/debugger.rs b/padre/debuggers/node/debugger.rs deleted file mode 100644 index 74688ff..0000000 --- a/padre/debuggers/node/debugger.rs +++ /dev/null @@ -1,303 +0,0 @@ -//! Node debugger -//! -//! The main Node Debugger entry point. Handles spawning processes and communicating -//! with it through the websocket. - -use std::io; -use std::path::Path; -use std::process::exit; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -use super::analyser::Analyser; -use super::process::Process; -use super::ws::WSHandler; -use crate::config::Config; -use crate::debugger::{DebuggerV1, FileLocation, Variable}; -use crate::notifier::{breakpoint_set, log_msg, LogLevel}; - -use tokio::prelude::*; -use tokio::sync::mpsc; -use websocket::OwnedMessage; - -#[derive(Debug)] -pub struct ImplDebugger { - process: Arc>, - ws_handler: Arc>, - analyser: Arc>, -} - -impl ImplDebugger { - pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { - let process = Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))); - let ws_handler = Arc::new(Mutex::new(WSHandler::new())); - let analyser = Arc::new(Mutex::new(Analyser::new(ws_handler.clone()))); - ImplDebugger { - process, - ws_handler, - analyser, - } - } -} - -impl DebuggerV1 for ImplDebugger { - fn setup(&mut self) {} - - fn teardown(&mut self) { - exit(0); - } - - fn run( - &mut self, - config: Arc>, - ) -> Box + Send> { - log_msg(LogLevel::INFO, "Launching process"); - - let (tx, rx) = mpsc::channel(1); - - self.process.lock().unwrap().run(tx); - - let process = self.process.clone(); - let analyser = self.analyser.clone(); - let analyser2 = self.analyser.clone(); - let ws_handler = self.ws_handler.clone(); - let ws_handler2 = self.ws_handler.clone(); - - let f = rx - .take(1) - .into_future() - .and_then(move |uri| { - // We need a little sleep otherwise we fail to connect, - // shame to block the thread but can live with it while - // starting up the process - thread::sleep(Duration::new(2, 0)); - - ws_handler - .lock() - .unwrap() - .connect(&uri.0.unwrap(), move |msg| { - analyser.lock().unwrap().analyse_message(msg); - None - }); - - Ok(()) - }) - .then(move |_| { - let msg = OwnedMessage::Text("{\"method\":\"Runtime.enable\"}".to_string()); - let f1 = ws_handler2 - .clone() - .lock() - .unwrap() - .send_and_receive_message(msg); - let msg = OwnedMessage::Text("{\"method\":\"Debugger.enable\"}".to_string()); - let f2 = ws_handler2.lock().unwrap().send_and_receive_message(msg); - let msg = OwnedMessage::Text( - "{\"method\":\"Runtime.runIfWaitingForDebugger\"}".to_string(), - ); - let f3 = ws_handler2.lock().unwrap().send_and_receive_message(msg); - - f1.join(f2).join(f3) - }) - .timeout(Duration::new( - config - .lock() - .unwrap() - .get_config("ProcessSpawnTimeout") - .unwrap() as u64, - 0, - )) - .map(move |responses| { - let resp1 = (responses.0).0; - let resp2 = (responses.0).1; - let resp3 = responses.1; - if !resp1["error"].is_null() - || !resp2["error"].is_null() - || !resp3["error"].is_null() - { - serde_json::json!({"status":"ERROR"}) - } else { - let pid = process.lock().unwrap().get_pid(); - analyser2.lock().unwrap().set_pid(pid); - serde_json::json!({"status":"OK","pid":pid}) - } - }) - .map_err(|e| { - eprintln!("Reading stdin error {:?}", e); - io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") - }); - - Box::new(f) - } - - fn breakpoint( - &mut self, - file_location: &FileLocation, - _: Arc>, - ) -> Box + Send> { - let full_file_name = Path::new(&file_location.name).canonicalize(); - let f = match full_file_name { - Ok(s) => { - let filename = s.to_string_lossy().to_string(); - let mut analyser = self.analyser.lock().unwrap(); - match analyser.get_script_from_filename(&filename) { - Some(script) => { - let msg = OwnedMessage::Text(format!( - "{{\ - \"method\":\"Debugger.setBreakpoint\",\ - \"params\":{{\ - \"location\":{{\ - \"scriptId\":\"{}\",\ - \"lineNumber\":{}\ - }}\ - }}\ - }}", - script.get_script_id(), - file_location.line_num - 1 - )); - - let line_num = file_location.line_num; - - self.ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(move |response| { - if response["error"].is_null() { - breakpoint_set(&filename, line_num); - - serde_json::json!({"status":"OK"}) - } else { - serde_json::json!({"status":"ERROR"}) - } - }) - } - None => { - analyser.add_pending_breakpoint(FileLocation::new( - filename, - file_location.line_num, - )); - - return Box::new(future::lazy(move || { - let resp = serde_json::json!({"status":"PENDING"}); - Ok(resp) - })); - } - } - } - Err(e) => { - log_msg( - LogLevel::ERROR, - &format!("Can't find file {}: {}", file_location.name, e), - ); - - return Box::new(future::lazy(move || { - let resp = serde_json::json!({"status":"ERROR"}); - Ok(resp) - })); - } - }; - - Box::new(f) - } - - fn step_in(&mut self) -> Box + Send> { - let msg = OwnedMessage::Text("{\"method\":\"Debugger.stepInto\"}".to_string()); - - let f = self - .ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(|response| { - if response["error"].is_null() { - serde_json::json!({"status":"OK"}) - } else { - serde_json::json!({"status":"ERROR"}) - } - }); - - Box::new(f) - } - - fn step_over(&mut self) -> Box + Send> { - let msg = OwnedMessage::Text("{\"method\":\"Debugger.stepOver\"}".to_string()); - - let f = self - .ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(|response| { - if response["error"].is_null() { - serde_json::json!({"status":"OK"}) - } else { - serde_json::json!({"status":"ERROR"}) - } - }); - - Box::new(f) - } - - fn continue_(&mut self) -> Box + Send> { - let msg = OwnedMessage::Text("{\"method\":\"Debugger.resume\"}".to_string()); - - let f = self - .ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(|response| { - if response["error"].is_null() { - serde_json::json!({"status":"OK"}) - } else { - serde_json::json!({"status":"ERROR"}) - } - }); - - Box::new(f) - } - - fn print( - &mut self, - variable: &Variable, - _: Arc>, - ) -> Box + Send> { - let msg = OwnedMessage::Text(format!( - "{{\ - \"method\":\"Debugger.evaluateOnCallFrame\",\ - \"params\":{{\ - \"callFrameId\":\"{{\\\"ordinal\\\":0,\\\"injectedScriptId\\\":1}}\",\ - \"expression\":\"{}\",\ - \"returnByValue\":true\ - }}\ - }}", - variable.name, - )); - - let variable = variable.name.clone(); - - let f = self - .ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(move |response| { - if response["error"].is_null() { - let mut json = response; - let variable_type = json["result"]["result"]["type"].take(); - let value = json["result"]["result"]["value"].take(); - serde_json::json!({ - "status": "OK", - "type": variable_type, - "variable": variable, - "value": value, - }) - } else { - serde_json::json!({"status":"ERROR"}) - } - }); - - Box::new(f) - } -} diff --git a/padre/debuggers/node/analyser.rs b/padre/debuggers/node/src/analyser.rs similarity index 80% rename from padre/debuggers/node/analyser.rs rename to padre/debuggers/node/src/analyser.rs index 510a28d..e912828 100644 --- a/padre/debuggers/node/analyser.rs +++ b/padre/debuggers/node/src/analyser.rs @@ -5,11 +5,10 @@ use std::sync::{Arc, Mutex}; use super::ws::WSHandler; -use crate::debugger::FileLocation; -use crate::notifier::{breakpoint_set, jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; +use padre_core::server::FileLocation; use tokio::prelude::*; -use websocket::OwnedMessage; /// Node script, indicated by receiving a 'Debugger.scriptParsed' message from Node #[derive(Debug, Eq, PartialEq)] @@ -125,54 +124,54 @@ impl Analyser { let mut i = 0; while i != self.pending_breakpoints.len() { - if self.pending_breakpoints[i].name == file { - let bkpt = self.pending_breakpoints.remove(i); - - let msg = OwnedMessage::Text(format!( - "{{\ - \"method\":\"Debugger.setBreakpoint\",\ - \"params\":{{\ - \"location\":{{\ - \"scriptId\":\"{}\",\ - \"lineNumber\":{}\ - }}\ - }}\ - }}", - script_id, - bkpt.line_num - 1 - )); - - let file = file.clone(); - - let ws_handler = self.ws_handler.clone(); - - tokio::spawn( - ws_handler - .lock() - .unwrap() - .send_and_receive_message(msg) - .map(move |response| { - if response["error"].is_null() { - breakpoint_set(&file, bkpt.line_num); - } else { - log_msg( - LogLevel::CRITICAL, - &format!("Can't set breakpoint {:?}", bkpt), - ); - panic!("Can't set breakpoint, panicking"); - } - }) - .map_err(|e| { - log_msg( - LogLevel::CRITICAL, - &format!("Can't set breakpoint, error: {}", e), - ); - panic!("Can't set breakpoint, panicking"); - }), - ); - } else { - i += 1; - } + //if self.pending_breakpoints[i].name() == file { + // let bkpt = self.pending_breakpoints.remove(i); + + // let msg = OwnedMessage::Text(format!( + // "{{\ + // \"method\":\"Debugger.setBreakpoint\",\ + // \"params\":{{\ + // \"location\":{{\ + // \"scriptId\":\"{}\",\ + // \"lineNumber\":{}\ + // }}\ + // }}\ + // }}", + // script_id, + // bkpt.line_num() - 1 + // )); + + // let file = file.clone(); + + // let ws_handler = self.ws_handler.clone(); + + // tokio::spawn( + // ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(move |response| { + // if response["error"].is_null() { + // //breakpoint_set(&file, bkpt.line_num); + // } else { + // log_msg( + // LogLevel::CRITICAL, + // &format!("Can't set breakpoint {:?}", bkpt), + // ); + // panic!("Can't set breakpoint, panicking"); + // } + // }) + // .map_err(|e| { + // log_msg( + // LogLevel::CRITICAL, + // &format!("Can't set breakpoint, error: {}", e), + // ); + // panic!("Can't set breakpoint, panicking"); + // }), + // ); + //} else { + // i += 1; + //} } self.scripts.push(Script::new(file, script_id, is_internal)); diff --git a/padre/debuggers/node/src/debugger.rs b/padre/debuggers/node/src/debugger.rs new file mode 100644 index 0000000..c5cb118 --- /dev/null +++ b/padre/debuggers/node/src/debugger.rs @@ -0,0 +1,308 @@ +//! Node debugger +//! +//! The main Node Debugger entry point. Handles spawning processes and communicating +//! with it through the websocket. + +use std::io; +use std::path::Path; +use std::process::exit; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant}; + +use super::analyser::Analyser; +use super::process::Process; +use super::ws::WSHandler; +use padre_core::notifier::{log_msg, LogLevel}; +use padre_core::server::{DebuggerV1, FileLocation, Variable}; + +use futures::prelude::*; +use tokio::sync::mpsc; + +#[derive(Debug)] +pub struct ImplDebugger { + process: Arc>, + ws_handler: Arc>, + analyser: Arc>, +} + +impl ImplDebugger { + pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { + let process = Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))); + let ws_handler = Arc::new(Mutex::new(WSHandler::new())); + let analyser = Arc::new(Mutex::new(Analyser::new(ws_handler.clone()))); + ImplDebugger { + process, + ws_handler, + analyser, + } + } +} + +impl DebuggerV1 for ImplDebugger { + fn setup(&mut self) {} + + fn teardown(&mut self) { + exit(0); + } + + fn run(&mut self, _timeout: Instant) { + log_msg(LogLevel::INFO, "Launching process"); + + let (tx, mut rx) = mpsc::channel(1); + + self.process.lock().unwrap().run(tx); + + let process = self.process.clone(); + let analyser = self.analyser.clone(); + let ws_handler = self.ws_handler.clone(); + + tokio::spawn(async move { + let uri = rx.next().await.unwrap(); + + // We need a little sleep otherwise we fail to connect, shame to block + // the thread but can live with it while starting up the process + thread::sleep(Duration::new(2, 0)); + + ws_handler + .lock() + .unwrap() + .connect(&uri, move |msg| { + analyser.lock().unwrap().analyse_message(msg); + None + }); + + //let msg = OwnedMessage::Text("{\"method\":\"Runtime.enable\"}".to_string()); + //let resp1 = ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .await; + //let msg = OwnedMessage::Text("{\"method\":\"Debugger.enable\"}".to_string()); + //let resp2 = ws_handler.lock().unwrap().send_and_receive_message(msg); + //let msg = OwnedMessage::Text( + // "{\"method\":\"Runtime.runIfWaitingForDebugger\"}".to_string(), + //); + //let resp3 = ws_handler.lock().unwrap().send_and_receive_message(msg); + + //if !resp1["error"].is_null() + // || !resp2["error"].is_null() + // || !resp3["error"].is_null() + //{ + // serde_json::json!({"status":"ERROR"}) + //} else { + // let pid = process.lock().unwrap().get_pid(); + // analyser.lock().unwrap().set_pid(pid); + // serde_json::json!({"status":"OK","pid":pid}) + //} + }); + + //let f = rx + // .take(1) + // .into_future() + // .and_then(move |uri| { + // // We need a little sleep otherwise we fail to connect, + // // shame to block the thread but can live with it while + // // starting up the process + // thread::sleep(Duration::new(2, 0)); + + // ws_handler + // .lock() + // .unwrap() + // .connect(&uri.0.unwrap(), move |msg| { + // analyser.lock().unwrap().analyse_message(msg); + // None + // }); + + // Ok(()) + // }) + // .then(move |_| { + // let msg = OwnedMessage::Text("{\"method\":\"Runtime.enable\"}".to_string()); + // let f1 = ws_handler2 + // .clone() + // .lock() + // .unwrap() + // .send_and_receive_message(msg); + // let msg = OwnedMessage::Text("{\"method\":\"Debugger.enable\"}".to_string()); + // let f2 = ws_handler2.lock().unwrap().send_and_receive_message(msg); + // let msg = OwnedMessage::Text( + // "{\"method\":\"Runtime.runIfWaitingForDebugger\"}".to_string(), + // ); + // let f3 = ws_handler2.lock().unwrap().send_and_receive_message(msg); + + // f1.join(f2).join(f3) + // }) + // .timeout(Duration::new( + // config + // .lock() + // .unwrap() + // .get_config("ProcessSpawnTimeout") + // .unwrap() as u64, + // 0, + // )) + // .map(move |responses| { + // let resp1 = (responses.0).0; + // let resp2 = (responses.0).1; + // let resp3 = responses.1; + // if !resp1["error"].is_null() + // || !resp2["error"].is_null() + // || !resp3["error"].is_null() + // { + // serde_json::json!({"status":"ERROR"}) + // } else { + // let pid = process.lock().unwrap().get_pid(); + // analyser2.lock().unwrap().set_pid(pid); + // serde_json::json!({"status":"OK","pid":pid}) + // } + // }) + // .map_err(|e| { + // eprintln!("Reading stdin error {:?}", e); + // io::Error::new(io::ErrorKind::Other, "Timed out setting breakpoint") + // }); + } + + fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { + let full_file_name = Path::new(&file_location.name()).canonicalize(); + let f = match full_file_name { + Ok(s) => { + let filename = s.to_string_lossy().to_string(); + let mut analyser = self.analyser.lock().unwrap(); + match analyser.get_script_from_filename(&filename) { + Some(script) => { + //let msg = OwnedMessage::Text(format!( + // "{{\ + // \"method\":\"Debugger.setBreakpoint\",\ + // \"params\":{{\ + // \"location\":{{\ + // \"scriptId\":\"{}\",\ + // \"lineNumber\":{}\ + // }}\ + // }}\ + // }}", + // script.get_script_id(), + // file_location.line_num - 1 + //)); + + //let line_num = file_location.line_num; + + //self.ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(move |response| { + // if response["error"].is_null() { + // //breakpoint_set(&filename, line_num); + + // serde_json::json!({"status":"OK"}) + // } else { + // serde_json::json!({"status":"ERROR"}) + // } + // }) + } + None => { + //analyser.add_pending_breakpoint(FileLocation::new( + // filename, + // file_location.line_num, + //)); + } + } + } + Err(e) => { + log_msg( + LogLevel::ERROR, + &format!("Can't find file {}: {}", file_location.name(), e), + ); + } + }; + } + + fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) {} + + fn step_in(&mut self, _timeout: Instant) { + //let msg = OwnedMessage::Text("{\"method\":\"Debugger.stepInto\"}".to_string()); + + //let f = self + // .ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(|response| { + // if response["error"].is_null() { + // serde_json::json!({"status":"OK"}) + // } else { + // serde_json::json!({"status":"ERROR"}) + // } + // }); + } + + fn step_over(&mut self, _timeout: Instant) { + //let msg = OwnedMessage::Text("{\"method\":\"Debugger.stepOver\"}".to_string()); + + //let f = self + // .ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(|response| { + // if response["error"].is_null() { + // serde_json::json!({"status":"OK"}) + // } else { + // serde_json::json!({"status":"ERROR"}) + // } + // }); + } + + fn continue_(&mut self, _timeout: Instant) { + //let msg = OwnedMessage::Text("{\"method\":\"Debugger.resume\"}".to_string()); + + //let f = self + // .ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(|response| { + // if response["error"].is_null() { + // serde_json::json!({"status":"OK"}) + // } else { + // serde_json::json!({"status":"ERROR"}) + // } + // }); + } + + fn print(&mut self, variable: &Variable, _timeout: Instant) { + let variable = variable.name().clone(); + + // let msg = OwnedMessage::Text(format!( + // "{{\ + // \"method\":\"Debugger.evaluateOnCallFrame\",\ + // \"params\":{{\ + // \"callFrameId\":\"{{\\\"ordinal\\\":0,\\\"injectedScriptId\\\":1}}\",\ + // \"expression\":\"{}\",\ + // \"returnByValue\":true\ + // }}\ + // }}", + // variable, + // )); + + //let f = self + // .ws_handler + // .lock() + // .unwrap() + // .send_and_receive_message(msg) + // .map(move |response| { + // if response["error"].is_null() { + // let mut json = response; + // let variable_type = json["result"]["result"]["type"].take(); + // let value = json["result"]["result"]["value"].take(); + // serde_json::json!({ + // "status": "OK", + // "type": variable_type, + // "variable": variable, + // "value": value, + // }) + // } else { + // serde_json::json!({"status":"ERROR"}) + // } + // }); + } +} diff --git a/padre/debuggers/node/mod.rs b/padre/debuggers/node/src/lib.rs similarity index 74% rename from padre/debuggers/node/mod.rs rename to padre/debuggers/node/src/lib.rs index e814ffb..3c484b8 100644 --- a/padre/debuggers/node/mod.rs +++ b/padre/debuggers/node/src/lib.rs @@ -1,5 +1,8 @@ //! The Node debugger module +#[macro_use] +extern crate lazy_static; + mod analyser; mod debugger; mod process; diff --git a/padre/debuggers/node/process.rs b/padre/debuggers/node/src/process.rs similarity index 61% rename from padre/debuggers/node/process.rs rename to padre/debuggers/node/src/process.rs index 181c683..d662063 100644 --- a/padre/debuggers/node/process.rs +++ b/padre/debuggers/node/src/process.rs @@ -2,14 +2,14 @@ //! //! This module performs the basic setup and spawning of the Node process. -use std::io::BufReader; - -use crate::util::{check_and_spawn_process, read_output, setup_stdin}; +use padre_core::util::{check_and_spawn_process, read_output, setup_stdin}; use regex::Regex; +use futures::prelude::*; +use tokio::io::BufReader; use tokio::prelude::*; +use tokio::process::{Child, ChildStderr, ChildStdout}; use tokio::sync::mpsc::Sender; -use tokio_process::{Child, ChildStderr, ChildStdout}; /// Main handler for spawning the Node process #[derive(Debug)] @@ -72,14 +72,12 @@ impl Process { /// Perform setup of reading Node stdout and writing it back to PADRE stdout. fn setup_stdout(&mut self, stdout: ChildStdout) { - tokio::spawn( - read_output(BufReader::new(stdout)) - .for_each(move |text| { - print!("{}", text); - Ok(()) - }) - .map_err(|e| eprintln!("Err reading Node stdout: {}", e)), - ); + tokio::spawn(async move { + let mut reader = read_output(BufReader::new(stdout)); + while let Some(Ok(text)) = reader.next().await { + print!("{}", text); + } + }); } /// Perform setup of reading Node stderr and writing it back to PADRE stderr. @@ -87,30 +85,37 @@ impl Process { /// Also checks for the line about where the Debugger is listening as this is /// required for the websocket setup. fn setup_stderr(&mut self, stderr: ChildStderr, tx: Sender) { - lazy_static! { - static ref RE_NODE_STARTED: Regex = - Regex::new("^Debugger listening on (ws://127.0.0.1:\\d+/.*)$").unwrap(); - } + tokio::spawn(async move { + lazy_static! { + static ref RE_NODE_STARTED: Regex = + Regex::new("^Debugger listening on (ws://127.0.0.1:\\d+/.*)$").unwrap(); + } + + let mut node_setup = false; - let mut node_setup = false; + let mut reader = read_output(BufReader::new(stderr)); - tokio::spawn( - read_output(BufReader::new(stderr)) - .for_each(move |text| { - if !node_setup { - 'node_setup_start: for line in text.split("\n") { - for cap in RE_NODE_STARTED.captures_iter(&line) { - tx.clone().send(cap[1].to_string()).wait().unwrap(); - node_setup = true; + while let Some(Ok(text)) = reader.next().await { + + if !node_setup { + 'node_setup_start: for line in text.split("\n") { + let mut uri = None; + for cap in RE_NODE_STARTED.captures_iter(&line) { + uri = Some(cap[1].to_string().clone()); + node_setup = true; + } + match uri { + Some(uri) => { + tx.clone().send(uri).await.unwrap(); break 'node_setup_start; } - } - } else { - eprint!("{}", text); + None => {} + }; } - Ok(()) - }) - .map_err(|e| eprintln!("Err reading Node stderr: {}", e)), - ); + } else { + eprint!("{}", text); + } + } + }); } } diff --git a/padre/debuggers/node/src/ws.rs b/padre/debuggers/node/src/ws.rs new file mode 100644 index 0000000..bea76c3 --- /dev/null +++ b/padre/debuggers/node/src/ws.rs @@ -0,0 +1,176 @@ +//! Websocket connection + +use std::collections::HashMap; +use std::io; +use std::net::TcpListener; +use std::sync::{Arc, Mutex}; + +use padre_core::notifier::{log_msg, LogLevel}; + +use tokio::prelude::*; +use tokio::sync::mpsc::{self, Sender}; +use tungstenite::{connect, Message}; +use url::Url; +//use websocket::result::WebSocketError; +//use websocket::{ClientBuilder, OwnedMessage}; + +#[derive(Debug)] +pub struct WSHandler { + response_listeners: Arc>>>, + ws_tx: Option>, + ws_id: u64, +} + +impl WSHandler { + pub fn new() -> WSHandler { + WSHandler { + response_listeners: Arc::new(Mutex::new(HashMap::new())), + ws_tx: None, + ws_id: 1, + } + } + + pub fn connect(&mut self, uri: &str, f: F) + where + F: Fn(serde_json::Value) -> Option + Sync + Send + 'static, + { + let (tx, rx) = mpsc::channel(1); + + self.ws_tx = Some(tx.clone()); + let response_listeners = self.response_listeners.clone(); + + let (mut socket, response) = + connect(Url::parse(uri).unwrap()).expect("Can't connect to Websocket"); + + tokio::spawn(async move { + loop { + let msg = socket.read_message().expect("Error reading message"); + println!("Received: {}", msg); + } + }); + + //let fut = ClientBuilder::new(uri) + // .unwrap() + // .async_connect_insecure() + // .and_then(move |(duplex, _)| { + // let (sink, stream) = duplex.split(); + + // stream + // .filter_map(move |message| { + // let json: serde_json::Value; + // if let OwnedMessage::Text(s) = &message { + // json = serde_json::from_str(s).unwrap(); + // } else if message.is_close() { + // return Some(OwnedMessage::Close(None)); + // } else { + // panic!("Can't understand message: {:?}", message) + // } + + // if json["method"].is_string() { + // f(json); + // } else if json["id"].is_number() { + // let id = json["id"].clone(); + // let id: u64 = match serde_json::from_value(id) { + // Ok(s) => s, + // Err(e) => { + // panic!("Can't understand id: {:?}", e); + // } + // }; + + // match response_listeners.lock().unwrap().remove(&id) { + // Some(listener_tx) => { + // tokio::spawn(listener_tx.send(json).map(|_| {}).map_err(|e| { + // eprintln!("Error spawning node: {:?}", e); + // })); + // } + // None => {} + // }; + // } else { + // log_msg(LogLevel::ERROR, &format!("Response error: {}", json)); + // }; + // None + // }) + // .select(rx.map_err(|_| WebSocketError::NoDataAvailable)) + // .forward(sink) + // }) + // .map(|_| ()) + // .map_err(|e| eprintln!("WebSocket err: {:?}", e)); + + //tokio::spawn(fut); + } + + pub fn close(&self) { + let tx = self.ws_tx.clone(); + + //tokio::spawn( + // tx.unwrap() + // .send(OwnedMessage::Close(None)) + // .map(|_| {}) + // .map_err(|e| { + // eprintln!("Error sending message: {:?}", e); + // }), + //); + } + + pub async fn send_and_receive_message(&mut self, msg: String) { + let id = self.get_next_ws_id(); + //let msg = self.add_id_to_message(msg, id); + + let (listener_tx, listener_rx) = mpsc::channel(1); + + self.response_listeners + .lock() + .unwrap() + .insert(id, listener_tx); + + let tx = self.ws_tx.clone(); + + //tokio::spawn(tx.unwrap().send(msg).map(|_| {}).map_err(|e| { + // eprintln!("Error sending message: {:?}", e); + //})); + + //let resp = listener_rx.next().await.unwrap(); + } + + fn get_next_ws_id(&mut self) -> u64 { + let id = self.ws_id; + self.ws_id += 1; + id + } + + //fn add_id_to_message(&self, msg: OwnedMessage, id: u64) -> OwnedMessage { + // if let OwnedMessage::Text(s) = &msg { + // let mut json: serde_json::Value = serde_json::from_str(s).unwrap(); + // json["id"] = serde_json::json!(id); + // OwnedMessage::Text(json.to_string()) + // } else { + // unreachable!(); + // } + //} +} + +#[cfg(test)] +mod tests { + use websocket::OwnedMessage; + + #[test] + fn check_add_message_id() { + let mut ws_handler = super::WSHandler::new(); + + let msg = OwnedMessage::Text("{\"TEST\":1}".to_string()); + let id = ws_handler.get_next_ws_id(); + let msg = ws_handler.add_id_to_message(msg, id); + let json: serde_json::Value; + if let OwnedMessage::Text(s) = msg { + json = serde_json::from_str(&s).unwrap(); + } else { + unreachable!(); + } + + let expected = "{\"id\":1,\"TEST\":1}"; + let expected: serde_json::Value = serde_json::from_str(expected).unwrap(); + + assert_eq!(expected, json); + assert_eq!(2, ws_handler.ws_id); + } +} diff --git a/padre/debuggers/node/ws.rs b/padre/debuggers/node/ws.rs deleted file mode 100644 index f5fb060..0000000 --- a/padre/debuggers/node/ws.rs +++ /dev/null @@ -1,174 +0,0 @@ -//! Websocket connection - -use std::collections::HashMap; -use std::io; -use std::sync::{Arc, Mutex}; - -use crate::notifier::{log_msg, LogLevel}; - -use tokio::prelude::*; -use tokio::sync::mpsc::{self, Sender}; -use websocket::result::WebSocketError; -use websocket::{ClientBuilder, OwnedMessage}; - -#[derive(Debug)] -pub struct WSHandler { - response_listeners: Arc>>>, - ws_tx: Option>, - ws_id: u64, -} - -impl WSHandler { - pub fn new() -> WSHandler { - WSHandler { - response_listeners: Arc::new(Mutex::new(HashMap::new())), - ws_tx: None, - ws_id: 1, - } - } - - pub fn connect(&mut self, uri: &str, f: F) - where - F: Fn(serde_json::Value) -> Option + Sync + Send + 'static, - { - let (tx, rx) = mpsc::channel(1); - - self.ws_tx = Some(tx.clone()); - let response_listeners = self.response_listeners.clone(); - - let fut = ClientBuilder::new(uri) - .unwrap() - .async_connect_insecure() - .and_then(move |(duplex, _)| { - let (sink, stream) = duplex.split(); - - stream - .filter_map(move |message| { - let json: serde_json::Value; - if let OwnedMessage::Text(s) = &message { - json = serde_json::from_str(s).unwrap(); - } else if message.is_close() { - return Some(OwnedMessage::Close(None)); - } else { - panic!("Can't understand message: {:?}", message) - } - - if json["method"].is_string() { - f(json); - } else if json["id"].is_number() { - let id = json["id"].clone(); - let id: u64 = match serde_json::from_value(id) { - Ok(s) => s, - Err(e) => { - panic!("Can't understand id: {:?}", e); - } - }; - - match response_listeners.lock().unwrap().remove(&id) { - Some(listener_tx) => { - tokio::spawn(listener_tx.send(json).map(|_| {}).map_err(|e| { - eprintln!("Error spawning node: {:?}", e); - })); - } - None => {} - }; - } else { - log_msg(LogLevel::ERROR, &format!("Response error: {}", json)); - }; - None - }) - .select(rx.map_err(|_| WebSocketError::NoDataAvailable)) - .forward(sink) - }) - .map(|_| ()) - .map_err(|e| eprintln!("WebSocket err: {:?}", e)); - - tokio::spawn(fut); - } - - pub fn close(&self) { - let tx = self.ws_tx.clone(); - - tokio::spawn( - tx.unwrap() - .send(OwnedMessage::Close(None)) - .map(|_| {}) - .map_err(|e| { - eprintln!("Error sending message: {:?}", e); - }), - ); - } - - pub fn send_and_receive_message( - &mut self, - msg: OwnedMessage, - ) -> Box + Send> { - let id = self.get_next_ws_id(); - let msg = self.add_id_to_message(msg, id); - - let (listener_tx, listener_rx) = mpsc::channel(1); - - self.response_listeners - .lock() - .unwrap() - .insert(id, listener_tx); - - let tx = self.ws_tx.clone(); - - tokio::spawn(tx.unwrap().send(msg).map(|_| {}).map_err(|e| { - eprintln!("Error sending message: {:?}", e); - })); - - let f = listener_rx - .into_future() - .map(move |response| response.0.unwrap()) - .map_err(|e| { - eprintln!("Error sending to node: {:?}", e.0); - io::Error::new(io::ErrorKind::Other, "Timed out sending to node") - }); - - Box::new(f) - } - - fn get_next_ws_id(&mut self) -> u64 { - let id = self.ws_id; - self.ws_id += 1; - id - } - - fn add_id_to_message(&self, msg: OwnedMessage, id: u64) -> OwnedMessage { - if let OwnedMessage::Text(s) = &msg { - let mut json: serde_json::Value = serde_json::from_str(s).unwrap(); - json["id"] = serde_json::json!(id); - OwnedMessage::Text(json.to_string()) - } else { - unreachable!(); - } - } -} - -#[cfg(test)] -mod tests { - use websocket::OwnedMessage; - - #[test] - fn check_add_message_id() { - let mut ws_handler = super::WSHandler::new(); - - let msg = OwnedMessage::Text("{\"TEST\":1}".to_string()); - let id = ws_handler.get_next_ws_id(); - let msg = ws_handler.add_id_to_message(msg, id); - let json: serde_json::Value; - if let OwnedMessage::Text(s) = msg { - json = serde_json::from_str(&s).unwrap(); - } else { - unreachable!(); - } - - let expected = "{\"id\":1,\"TEST\":1}"; - let expected: serde_json::Value = serde_json::from_str(expected).unwrap(); - - assert_eq!(expected, json); - assert_eq!(2, ws_handler.ws_id); - } -} diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index c7fe2fb..6072897 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -10,7 +10,7 @@ use std::time::Instant; use super::process::{Message, PDBStatus, Process}; use padre_core::notifier::{log_msg, LogLevel}; -use padre_core::server::{FileLocation, Variable, DebuggerV1}; +use padre_core::server::{DebuggerV1, FileLocation, Variable}; use futures::StreamExt; use tokio::sync::mpsc; @@ -31,7 +31,8 @@ impl ImplDebugger { } impl DebuggerV1 for ImplDebugger { - + // Ideally this would be async but currently we don't have async traits yet. + // Means that we can be waiting for setup still when we start using PADRE. fn setup(&mut self) {} fn teardown(&mut self) { @@ -133,7 +134,6 @@ impl DebuggerV1 for ImplDebugger { full_file_name.to_str().unwrap().to_string(), file_location.line_num(), ); - } fn step_in(&mut self, _timeout: Instant) { diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 356470d..308d6d5 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -23,13 +23,7 @@ use tokio::io::BufReader; use tokio::process::{Child, ChildStderr, ChildStdout, Command}; use tokio::sync::mpsc::Sender; -/// You can register to listen for one of the following events: -/// - Launching -/// - Breakpoint -/// - StepIn -/// - StepOver -/// - Continue -/// - PrintVariable +/// Messages that can be sent to PDB for processing #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub enum Message { Launching, @@ -40,6 +34,7 @@ pub enum Message { PrintVariable(Variable), } +/// Current status of PDB #[derive(Debug, Clone, PartialEq)] pub enum PDBStatus { None, @@ -238,7 +233,7 @@ impl Process { analyser.lock().unwrap().status = PDBStatus::Processing(message); tx.clone() .unwrap() - .send(Bytes::from(msg)) + .send(msg) .map(move |_| {}) .await }); diff --git a/padre/integration/features/lldb.feature b/padre/integration/features/lldb.feature index f5994a7..8011d5f 100644 --- a/padre/integration/features/lldb.feature +++ b/padre/integration/features/lldb.feature @@ -6,10 +6,11 @@ Feature: LLDB And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' And that we have a test program 'test_prog' that runs with 'lldb' debugger When I debug the program with PADRE - When I send a command 'b main' using the terminal + And I give PADRE chance to start + And I send a command 'b main' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$", 22] | + | function | args | + | padre#debugger#Log | [4, "Breakpoint set.*test_prog.c.*22"] | When I send a command 'run' using the terminal Then I expect to be called with | function | args | @@ -34,13 +35,14 @@ Feature: LLDB And I have compiled the test program 'test_prog.c' with compiler '' to program 'test_prog' And that we have a test program 'test_prog' that runs with 'lldb' debugger When I debug the program with PADRE + And I give PADRE chance to start When I send a request to PADRE '{"cmd":"breakpoint","file":"test_prog.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4, ".*test_prog.c.*17"] | - | padre#debugger#BreakpointSet | [".*test_prog.c$", 17] | + | function | args | + | padre#debugger#Log | [4, ".*test_prog.c.*17"] | + | padre#debugger#Log | [4, "Breakpoint set.*test_prog.c.*17"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"not_exists.c","line":17}' - Then I receive both a response '{"status":"PENDING"}' and I expect to be called with + Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#Log | [4,".*not_exists.c.*17"] | When I send a request to PADRE '{"cmd":"run"}' @@ -83,186 +85,186 @@ Feature: LLDB | gcc -g -O0 | | clang -g -O0 | - Scenario: Debug a basic program with LLDB using the both the LLDB command line and the PADRE connection - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with 'lldb' debugger - When I debug the program with PADRE - When I send a command 'b func3' using the terminal - Then I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$", 17] | - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - | padre#debugger#Log | [4,"Launching process"] | - When I send a command 's' using the terminal - Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 8] | - When I send a request to PADRE '{"cmd":"stepOver"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | - When I send a command 'n' using the terminal - Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 17] | - When I send a command 'n' using the terminal - Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 18] | - When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive a response '{"status":"OK","variable":"a","value":"1","type":"int"}' - When I send a command 'c' using the terminal - Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 10] | - When I send a request to PADRE '{"cmd":"continue"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#ProcessExited | [0,"\\d+"] | - When I terminate padre - Then padre is not running + #Scenario: Debug a basic program with LLDB using the both the LLDB command line and the PADRE connection + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with 'lldb' debugger + # When I debug the program with PADRE + # When I send a command 'b func3' using the terminal + # Then I expect to be called with + # | function | args | + # | padre#debugger#BreakpointSet | [".*test_prog.c$", 17] | + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + # | function | args | + # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | + # When I send a command 's' using the terminal + # Then I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$", 8] | + # When I send a request to PADRE '{"cmd":"stepOver"}' + # Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | + # When I send a command 'n' using the terminal + # Then I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$", 17] | + # When I send a command 'n' using the terminal + # Then I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$", 18] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive a response '{"status":"OK","variable":"a","value":"1","type":"int"}' + # When I send a command 'c' using the terminal + # Then I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$", 10] | + # When I send a request to PADRE '{"cmd":"continue"}' + # Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#ProcessExited | [0,"\\d+"] | + # When I terminate padre + # Then padre is not running - Scenario: PADRE error reporting when program not running - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with 'lldb' debugger - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"stepIn"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"No process running"] | - When I send a request to PADRE '{"cmd":"stepOver"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"No process running"] | - When I send a request to PADRE '{"cmd":"continue"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"No process running"] | - When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"No process running"] | - When I terminate padre - Then padre is not running + #Scenario: PADRE error reporting when program not running + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with 'lldb' debugger + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"stepIn"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"No process running"] | + # When I send a request to PADRE '{"cmd":"stepOver"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"No process running"] | + # When I send a request to PADRE '{"cmd":"continue"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"No process running"] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"No process running"] | + # When I terminate padre + # Then padre is not running - Scenario: General error handling over PADRE when program is running - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with 'lldb' debugger - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - | padre#debugger#Log | [4,"Launching process"] | - When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"variable 'a' doesn't exist here"] | - When I terminate padre - Then padre is not running + #Scenario: General error handling over PADRE when program is running + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with 'lldb' debugger + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + # | function | args | + # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"variable 'a' doesn't exist here"] | + # When I terminate padre + # Then padre is not running - Scenario: Printing variables in rust - Given that we have a file 'test_print_variables.rs' - And I have compiled the test program 'test_print_variables.rs' with compiler 'rustc -g' to program 'test_print_variables' - And that we have a test program 'test_print_variables' that runs with 'lldb' debugger - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [3,"Stopped at unknown position"] | - | padre#debugger#Log | [4,"Launching process"] | - When I send a request to PADRE '{"cmd":"continue"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",16] | - When I send a request to PADRE '{"cmd":"stepOver"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",17] | - When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive a response '{"status":"OK","variable":"a","value":"42","type":"int"}' - When I send a request to PADRE '{"cmd":"stepOver"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",18] | - #When I send a request to PADRE '{"cmd":"print","variable":"b"}' - #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"int","value":"42"},"type":"int \\*","value":"^&0x[0-9a-f]*$"}' - #When I send a request to PADRE '{"cmd":"stepOver"}' - #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",19] | - #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - #Then I receive a response '{"status":"OK","variable":"a","value":"^42.[0-9][0-9]*$","type":"float"}' - #When I send a request to PADRE '{"cmd":"stepOver"}' - #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",20] | - #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - #Then I receive a response '{"status":"OK","variable":"a","value":"true","type":"bool"}' - #When I send a request to PADRE '{"cmd":"stepOver"}' - #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",21] | - #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - #Then I receive a response '{"status":"OK","variable":"a","value":"TEST","type":"&str"}' - #When I send a request to PADRE '{"cmd":"stepOver"}' - #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",22] | - #When I send a request to PADRE '{"cmd":"print","variable":"b"}' - #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"&str","value":"TEST"},"type":"&str *","value":"^&0x[0-9a-f]*$"}' - When I terminate padre - Then padre is not running + #Scenario: Printing variables in rust + # Given that we have a file 'test_print_variables.rs' + # And I have compiled the test program 'test_print_variables.rs' with compiler 'rustc -g' to program 'test_print_variables' + # And that we have a test program 'test_print_variables' that runs with 'lldb' debugger + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [3,"Stopped at unknown position"] | + # | padre#debugger#Log | [4,"Launching process"] | + # When I send a request to PADRE '{"cmd":"continue"}' + # Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",16] | + # When I send a request to PADRE '{"cmd":"stepOver"}' + # Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",17] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive a response '{"status":"OK","variable":"a","value":"42","type":"int"}' + # When I send a request to PADRE '{"cmd":"stepOver"}' + # Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",18] | + # #When I send a request to PADRE '{"cmd":"print","variable":"b"}' + # #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"int","value":"42"},"type":"int \\*","value":"^&0x[0-9a-f]*$"}' + # #When I send a request to PADRE '{"cmd":"stepOver"}' + # #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # # | function | args | + # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",19] | + # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # #Then I receive a response '{"status":"OK","variable":"a","value":"^42.[0-9][0-9]*$","type":"float"}' + # #When I send a request to PADRE '{"cmd":"stepOver"}' + # #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # # | function | args | + # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",20] | + # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # #Then I receive a response '{"status":"OK","variable":"a","value":"true","type":"bool"}' + # #When I send a request to PADRE '{"cmd":"stepOver"}' + # #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # # | function | args | + # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",21] | + # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # #Then I receive a response '{"status":"OK","variable":"a","value":"TEST","type":"&str"}' + # #When I send a request to PADRE '{"cmd":"stepOver"}' + # #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # # | function | args | + # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",22] | + # #When I send a request to PADRE '{"cmd":"print","variable":"b"}' + # #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"&str","value":"TEST"},"type":"&str *","value":"^&0x[0-9a-f]*$"}' + # When I terminate padre + # Then padre is not running - Scenario: Test spawning process timeout - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with './test_files/lldb_spawn_timeout.py' debugger of type 'lldb' - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"setConfig","key":"ProcessSpawnTimeout","value":1}' - Then I receive a response '{"status":"OK"}' - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,"Launching process"] | - | padre#debugger#BreakpointSet | ["test.c",25] | - | padre#debugger#Log | [2,"Timed out spawning process"] | + #Scenario: Test spawning process timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_spawn_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"ProcessSpawnTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [4,"Launching process"] | + # | padre#debugger#BreakpointSet | ["test.c",25] | + # | padre#debugger#Log | [2,"Timed out spawning process"] | - Scenario: Test breakpoint timeout - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with './test_files/lldb_breakpoint_timeout.py' debugger of type 'lldb' - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"setConfig","key":"BreakpointTimeout","value":1}' - Then I receive a response '{"status":"OK"}' - When I send a request to PADRE '{"cmd":"breakpoint","file":"test.c","line":17}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,"Setting breakpoint in file test.c at line number 17"] | - | padre#debugger#Log | [2,"Timed out setting breakpoint"] | + #Scenario: Test breakpoint timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_breakpoint_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"BreakpointTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"breakpoint","file":"test.c","line":17}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [4,"Setting breakpoint in file test.c at line number 17"] | + # | padre#debugger#Log | [2,"Timed out setting breakpoint"] | - Scenario: Test print timeout - Given that we have a file 'test_prog.c' - And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - And that we have a test program 'test_prog' that runs with './test_files/lldb_print_variable_timeout.py' debugger of type 'lldb' - When I debug the program with PADRE - When I send a request to PADRE '{"cmd":"setConfig","key":"PrintVariableTimeout","value":1}' - Then I receive a response '{"status":"OK"}' - When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - | padre#debugger#Log | [4,"Launching process"] | - When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [2,"Timed out printing variable"] | + #Scenario: Test print timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_print_variable_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"PrintVariableTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + # | function | args | + # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [2,"Timed out printing variable"] | diff --git a/padre/integration/features/steps/shared.py b/padre/integration/features/steps/shared.py index 2904087..9f1a894 100644 --- a/padre/integration/features/steps/shared.py +++ b/padre/integration/features/steps/shared.py @@ -381,6 +381,16 @@ def padre_debugger(context): context.padre.get_children() +@when("I give PADRE chance to start") +def sleep_at_startup(context): + """ + This is a bit rubbish but it's for tests that interfere with writing to + stdin. This gives PADRE a chance to fully startup before we start confusing + it. + """ + time.sleep(1) + + @when("I open another connection to PADRE") def connect_padre(context): """ From 5b727e90ea8782a52c55da5c2f8d6d775ad35349 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Wed, 1 Jan 2020 23:29:23 +0000 Subject: [PATCH 11/23] Implemented most of the basic Python --- Makefile | 3 + padre/Cargo.lock | 65 +++--- padre/cli/Cargo.toml | 3 +- padre/cli/src/debugger.rs | 65 +++++- padre/core/Cargo.toml | 2 +- padre/core/src/notifier.rs | 2 + padre/core/src/server.rs | 11 +- padre/core/src/util.rs | 71 +----- padre/core/src/vimcodec.rs | 27 ++- padre/debuggers/lldb/Cargo.toml | 19 ++ padre/debuggers/lldb/src/debugger.rs | 55 ++--- padre/debuggers/lldb/src/process.rs | 238 +++++++++----------- padre/debuggers/node/Cargo.toml | 24 ++ padre/debuggers/node/src/debugger.rs | 11 +- padre/debuggers/node/src/process.rs | 3 +- padre/debuggers/python/Cargo.toml | 2 +- padre/debuggers/python/src/debugger.rs | 97 ++++---- padre/debuggers/python/src/lib.rs | 1 + padre/debuggers/python/src/process.rs | 257 +++++++++++++++------- padre/integration/features/lldb.feature | 3 +- padre/integration/features/python.feature | 22 +- padre/ptywrapper.py | 6 + 22 files changed, 592 insertions(+), 395 deletions(-) create mode 100644 padre/debuggers/lldb/Cargo.toml create mode 100644 padre/debuggers/node/Cargo.toml create mode 100755 padre/ptywrapper.py diff --git a/Makefile b/Makefile index 702cf98..fe2976f 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ all: cd padre && cargo build + +clean: + cd padre && cargo clean diff --git a/padre/Cargo.lock b/padre/Cargo.lock index aacabd1..9a9cd52 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "bytes" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c85319f157e4e26c703678e68e26ab71a46c0199286fa670b21cc9fec13d895" +checksum = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" [[package]] name = "c2-chacha" @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" [[package]] name = "cfg-if" @@ -318,18 +318,18 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +checksum = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" dependencies = [ "libc", ] [[package]] name = "http" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2790658cddc82e82b08e25176c431d7015a0adeb1718498715cbd20138a0bf68" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ "bytes 0.4.12", "fnv", @@ -395,9 +395,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" [[package]] name = "log" @@ -582,7 +582,7 @@ dependencies = [ name = "padre_core" version = "0.2.0" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "futures", "lazy_static", "pin-project", @@ -598,7 +598,7 @@ dependencies = [ name = "padre_lldb" version = "0.2.0" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "futures", "lazy_static", "padre_core", @@ -611,7 +611,7 @@ dependencies = [ name = "padre_node" version = "0.2.0" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "futures", "lazy_static", "padre_core", @@ -629,7 +629,7 @@ dependencies = [ name = "padre_python" version = "0.2.0" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "futures", "lazy_static", "padre_core", @@ -835,15 +835,15 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" [[package]] name = "serde_derive" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" dependencies = [ "proc-macro2", "quote", @@ -852,9 +852,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" +checksum = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" dependencies = [ "itoa", "ryu", @@ -891,9 +891,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +checksum = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" [[package]] name = "socket2" @@ -915,9 +915,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89693ae015201f8de93fd96bde2d065f8bfc3f97ce006d5bc9f900b97c0c7c0" +checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" dependencies = [ "proc-macro2", "quote", @@ -958,13 +958,14 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e765bf9f550bd9b8a970633ca3b56b8120c4b6c5dcbe26a93744cb02fee4b17" +checksum = "0e1bef565a52394086ecac0a6fa3b8ace4cb3a138ee1d96bd2b93283b56824e3" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "fnv", "futures-core", + "iovec", "lazy_static", "libc", "memchr", @@ -981,9 +982,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5795a71419535c6dcecc9b6ca95bdd3c2d6142f7e8343d7beb9923f129aa87e" +checksum = "7de6c21a09bab0ce34614bb1071403ad9996db62715eb61e63be5d82f91342bc" dependencies = [ "quote", "syn", @@ -995,7 +996,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "bytes 0.5.2", + "bytes 0.5.3", "futures-core", "futures-sink", "log", @@ -1049,9 +1050,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] name = "unicode-xid" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index 1fddce3..ed182cd 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -7,7 +7,6 @@ license = "APACHE" repository = "https://github.com/strottos/vim-padre" [features] - default = ["lldb", "node", "python"] lldb = ["padre_lldb"] node = ["padre_node"] @@ -20,7 +19,7 @@ padre_core = { path = "../core", version = "0.2.0" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.2", features = ["full"] } +tokio = { version = "0.2.6", features = ["full"] } # The debuggers, all optional padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 8236fca..130baa5 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -8,9 +8,9 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use padre_core::server::{DebuggerCmd, DebuggerV1}; -use padre_core::util::{file_is_binary_executable, file_is_text}; use futures::StreamExt; +use tokio::process::Command; use tokio::sync::mpsc::Receiver; #[cfg(feature = "lldb")] @@ -53,6 +53,7 @@ impl Debugger { match cmd.0 { DebuggerCmd::Run => debugger.run(cmd.1), DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), + DebuggerCmd::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), DebuggerCmd::StepIn => debugger.step_in(cmd.1), DebuggerCmd::StepOver => debugger.step_over(cmd.1), DebuggerCmd::Continue => debugger.continue_(cmd.1), @@ -194,3 +195,65 @@ async fn is_python(cmd: &str) -> bool { false } + +/// Find out if a file is a binary executable (either ELF or Mach-O +/// executable). +async fn file_is_binary_executable(cmd: &str) -> bool { + let output = get_file_type(cmd).await; + + if output.contains("ELF") + || (output.contains("Mach-O") && output.to_ascii_lowercase().contains("executable")) + { + true + } else { + false + } +} + +/// Find out if a file is a text file (either ASCII or UTF-8). +async fn file_is_text(cmd: &str) -> bool { + let output = get_file_type(cmd).await; + + if output.contains("ASCII") || output.contains("UTF-8") { + true + } else { + false + } +} + +/// Get the file type as output by the UNIX `file` command. +async fn get_file_type(cmd: &str) -> String { + let output = Command::new("file") + .arg("-L") // Follow symlinks + .arg(cmd) + .output(); + let output = output + .await + .expect(&format!("Can't run file on {} to find file type", cmd)); + + String::from_utf8_lossy(&output.stdout).to_string() +} + +#[cfg(test)] +mod tests { + #[tokio::test] + async fn is_file_executable() { + assert_eq!( + true, + super::file_is_binary_executable("../test_files/node").await + ); + assert_eq!( + false, + super::file_is_binary_executable("../test_files/test_node.js").await + ); + } + + #[tokio::test] + async fn is_file_text() { + assert_eq!(false, super::file_is_text("../test_files/node").await); + assert_eq!( + true, + super::file_is_text("../test_files/test_node.js").await + ); + } +} diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml index 6cb5851..e14cae6 100644 --- a/padre/core/Cargo.toml +++ b/padre/core/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.2", features = [ +tokio = { version = "0.2.6", features = [ "io-util", "io-std", "net", diff --git a/padre/core/src/notifier.rs b/padre/core/src/notifier.rs index 8d2bec1..8ecd5e2 100644 --- a/padre/core/src/notifier.rs +++ b/padre/core/src/notifier.rs @@ -113,6 +113,8 @@ pub fn log_msg(level: LogLevel, msg: &str) { NOTIFIER.lock().unwrap().send_msg(msg); } +/// TODO: Allow to send to a specific socket + /// Notify about a code position change pub fn jump_to_position(file: &str, line: u64) { let msg = Notification::new( diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index cac0c5c..cab7616 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -28,6 +28,7 @@ use tokio_util::codec::Decoder; pub enum DebuggerCmd { Run, Breakpoint(FileLocation), + Unbreakpoint(FileLocation), StepIn, StepOver, Continue, @@ -56,7 +57,7 @@ impl FileLocation { } /// Variable name -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct Variable { name: String, } @@ -71,6 +72,14 @@ impl Variable { } } +impl PartialEq for Variable { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Eq for Variable {} + /// All padre commands #[derive(Clone, Debug, PartialEq)] pub enum PadreCmd { diff --git a/padre/core/src/util.rs b/padre/core/src/util.rs index a266d79..543880a 100644 --- a/padre/core/src/util.rs +++ b/padre/core/src/util.rs @@ -65,7 +65,7 @@ pub fn check_and_spawn_process(mut debugger_cmd: Vec, run_cmd: Vec, run_cmd: Vec Sender bool { - let output = get_file_type(cmd).await; - - if output.contains("ELF") - || (output.contains("Mach-O") && output.to_ascii_lowercase().contains("executable")) - { - true - } else { - false - } -} - -/// Find out if a file is a text file (either ASCII or UTF-8). -pub async fn file_is_text(cmd: &str) -> bool { - let output = get_file_type(cmd).await; - - if output.contains("ASCII") || output.contains("UTF-8") { - true - } else { - false - } -} - /// Find out the full path of a file based on the PATH environment variable. pub fn get_file_full_path(cmd: &str) -> String { let cmd_full_path_buf = env::var_os("PATH") @@ -165,20 +146,7 @@ pub fn file_exists(path: &str) -> bool { Path::new(path).exists() } -/// Get the file type as output by the UNIX `file` command. -async fn get_file_type(cmd: &str) -> String { - let output = Command::new("file") - .arg("-L") // Follow symlinks - .arg(cmd) - .output(); - let output = output - .await - .expect(&format!("Can't run file on {} to find file type", cmd)); - - String::from_utf8_lossy(&output.stdout).to_string() -} - -// The following largely taken from tokio::io::lines code. +// The following largely taken from tokio::io::lines code but for our bytes specific needs. /// Combinator created by `read_output` method which is a stream over text on an I/O object. #[pin_project] @@ -220,7 +188,7 @@ impl Stream for ReadOutput { t.len() } Err(e) => { - println!("What to do here? {:?}", e); + println!("TODO: What to do here? Error reading: {:?}", e); 0 } }, @@ -257,23 +225,4 @@ mod tests { let listener = TcpListener::bind(format!("127.0.0.1:{}", port)).unwrap(); assert_eq!(listener.local_addr().unwrap().port(), port); } - - //#[test] - //fn is_file_executable() { - // tokio::spawn(async move { - // assert_eq!(true, super::file_is_binary_executable("./test_files/node").await); - // assert_eq!( - // false, - // super::file_is_binary_executable("./test_files/test_node.js").await - // ); - // }); - //} - - //#[test] - //fn is_file_text() { - // tokio::spawn(async move { - // assert_eq!(false, super::file_is_text("./test_files/node").await); - // assert_eq!(true, super::file_is_text("./test_files/test_node.js").await); - // }); - //} } diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index 1fef6a8..0d73c9c 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -13,7 +13,7 @@ use crate::server::{ }; use crate::util; -use bytes::{BufMut, BytesMut}; +use bytes::{Buf, BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder}; /// Decodes requests and encodes responses sent by or to VIM over VIM's socket communication @@ -200,7 +200,7 @@ impl<'a> Decoder for VimCodec<'a> { } }; - src.split_to(src.len()); + src.advance(src.len()); util::send_error_and_debug( "Must be valid JSON", @@ -220,7 +220,7 @@ impl<'a> Decoder for VimCodec<'a> { } }; - src.split_to(src.len()); + src.advance(src.len()); if !v.is_array() { util::send_error_and_debug( @@ -387,6 +387,27 @@ impl<'a> Decoder for VimCodec<'a> { None => return Ok(None), } } + "unbreakpoint" => { + let file_location = self.get_file_location(&mut args); + match file_location { + Some(fl) => Ok(Some(PadreRequest::new( + id, + RequestCmd::DebuggerCmd( + DebuggerCmd::Unbreakpoint(fl), + Instant::now() + + Duration::new( + self.config + .lock() + .unwrap() + .get_config("BreakpointTimeout") + .unwrap() as u64, + 0, + ), + ), + ))), + None => return Ok(None), + } + } "print" => { let variable = self.get_variable(&mut args); match variable { diff --git a/padre/debuggers/lldb/Cargo.toml b/padre/debuggers/lldb/Cargo.toml new file mode 100644 index 0000000..0d05dd8 --- /dev/null +++ b/padre/debuggers/lldb/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "padre_lldb" +version = "0.2.0" +authors = ["Steven Trotter "] +edition = "2018" +license = "MIT" +repository = "https://github.com/strottos/vim-padre" + +[lib] +path = "src/lib.rs" + +[dependencies] +bytes = "0.5.0" +futures = "0.3.1" +lazy_static = "1.3.0" +regex = "1.1.2" +padre_core = { path = "../../core", version = "0.2.0" } +tokio = { version = "0.2.6", features = ["full"] } +tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs index 410fe34..5206360 100644 --- a/padre/debuggers/lldb/src/debugger.rs +++ b/padre/debuggers/lldb/src/debugger.rs @@ -68,28 +68,31 @@ impl DebuggerV1 for ImplDebugger { /// - startup lldb and setup the stdio analyser /// - perform initial setup so we can analyse LLDB properly fn setup(&mut self) { - let process = self.process.clone(); - - tokio::spawn(async move { - let msgs = [ - "settings set stop-line-count-after 0\n", - "settings set stop-line-count-before 0\n", - "settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n", - "breakpoint set --name main\n", - ]; - - for msg in msgs.iter() { - // Check we're actually listening - let (tx, mut rx) = mpsc::channel(1); - process.lock().unwrap().add_awakener(tx); - rx.next().await.unwrap(); - process.lock().unwrap().drop_awakener(); - - process.lock().unwrap().write_stdin(Bytes::from(msg.as_bytes())); - } - }); - - self.process.lock().unwrap().setup(); + //let process = self.process.clone(); + + //tokio::spawn(async move { + // let msgs = [ + // "settings set stop-line-count-after 0\n", + // "settings set stop-line-count-before 0\n", + // "settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n", + // "breakpoint set --name main\n", + // ]; + + // for msg in msgs.iter() { + // // Check we're actually listening + // let (tx, mut rx) = mpsc::channel(1); + // process.lock().unwrap().add_awakener(tx); + // rx.next().await.unwrap(); + // process.lock().unwrap().drop_awakener(); + + // process + // .lock() + // .unwrap() + // .write_stdin(Bytes::from(msg.as_bytes())); + // } + //}); + + //self.process.lock().unwrap().setup(); } fn teardown(&mut self) { @@ -173,10 +176,10 @@ impl DebuggerV1 for ImplDebugger { ), ); - self.process - .lock() - .unwrap() - .send_msg(Message::Breakpoint(file_location.clone())); + //self.process + // .lock() + // .unwrap() + // .send_msg(Message::Breakpoint(file_location.clone())); } fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) {} diff --git a/padre/debuggers/lldb/src/process.rs b/padre/debuggers/lldb/src/process.rs index 74e2aa5..9f68c2e 100644 --- a/padre/debuggers/lldb/src/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -15,26 +15,28 @@ use futures::prelude::*; use regex::Regex; use tokio::io::{stdin, BufReader}; use tokio::prelude::*; -use tokio::process::{Child, ChildStdin, ChildStderr, ChildStdout}; +use tokio::process::{Child, ChildStdin, ChildStdout}; use tokio::sync::mpsc::{self, Sender}; use tokio_util::codec::{BytesCodec, FramedRead}; /// Messages that can be sent to LLDB for processing -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum Message { ProcessLaunching, Breakpoint(FileLocation), + Unbreakpoint(FileLocation), UnknownBreakpoint, StepIn, StepOver, Continue, PrintVariable(Variable), + Custom, } /// Current status of LLDB #[derive(Debug, Clone, PartialEq)] pub enum LLDBStatus { - None, + NotLaunched, Listening, Processing(Message), } @@ -63,121 +65,104 @@ impl VariableValue { /// Main handler for spawning the LLDB process #[derive(Debug)] pub struct LLDBProcess { - debugger_cmd: Option, - run_cmd: Option>, lldb_process: Option, - lldb_stdin_tx: Option>, - analyser: Arc>, + lldb_status: Arc>, + lldb_stdin_tx: Sender, } impl LLDBProcess { - /// Create a new LLDBProcess - pub fn new(debugger_cmd: String, run_cmd: Vec) -> Self { - LLDBProcess { - debugger_cmd: Some(debugger_cmd), - run_cmd: Some(run_cmd), - lldb_process: None, - lldb_stdin_tx: None, - analyser: Arc::new(Mutex::new(Analyser::new())), - } - } - - /// Setup LLDB + /// Create and setup LLDB /// /// Includes spawning the LLDB process and all the relevant stdio handlers. In particular: - /// - Sets up a `ReadOutput` from `util.rs` in order to read stdout and stderr; + /// - Sets up a `ReadOutput` from `util.rs` in order to read output from LLDB; /// - Sets up a thread to read stdin and forward it onto LLDB stdin; /// - Checks that LLDB and the program to be ran both exist, otherwise panics. - pub fn setup(&mut self) { - let mut lldb_process = check_and_spawn_process( - vec![self.debugger_cmd.take().unwrap()], - self.run_cmd.take().unwrap(), - ); + pub fn new(debugger_cmd: String, run_cmd: Vec) -> Self { + let mut lldb_process = check_and_spawn_process(vec![debugger_cmd], run_cmd); - self.setup_stdout( + let lldb_status = Arc::new(Mutex::new(LLDBStatus::NotLaunched)); + + LLDBProcess::setup_stdout( lldb_process .stdout() .take() .expect("LLDB process did not have a handle to stdout"), + lldb_status, ); - self.setup_stderr( - lldb_process - .stderr() - .take() - .expect("LLDB process did not have a handle to stderr"), - ); - self.setup_stdin( + let stdin_tx = LLDBProcess::setup_stdin( lldb_process .stdin() .take() .expect("Python process did not have a handle to stdin"), - true, ); - self.lldb_process = Some(lldb_process); + LLDBProcess { + lldb_process: Some(lldb_process), + lldb_status, + lldb_stdin_tx: stdin_tx, + } } pub fn teardown(&mut self) { self.lldb_process = None; } + pub fn get_status(&self) -> LLDBStatus { + self.lldb_status.lock().unwrap().clone() + } + /// Send a message to write to stdin - pub fn write_stdin(&mut self, bytes: Bytes) { - let lldb_stdin_tx = self.lldb_stdin_tx.clone(); + fn write_stdin(&mut self, bytes: Bytes) { + let mut lldb_stdin_tx = self.lldb_stdin_tx.clone(); tokio::spawn(async move { - lldb_stdin_tx.clone() - .unwrap() + lldb_stdin_tx .send(bytes) .map(move |_| {}) .await; }); } - pub fn send_msg(&mut self, message: Message) { - let msg_bytes = match message.clone() { - Message::ProcessLaunching => Bytes::from("process launch\n"), - Message::Breakpoint(fl) => { - Bytes::from(format!( - "breakpoint set --file {} --line {}\n", - fl.name(), fl.line_num() - )) - }, - Message::UnknownBreakpoint => unreachable!(), - Message::StepIn => Bytes::from("thread step-in\n"), - Message::StepOver => Bytes::from("thread step-over\n"), - Message::Continue => Bytes::from("thread continue\n"), - Message::PrintVariable(v) => Bytes::from(format!("frame variable {}\n", v.name())), - }; - - self.analyser.lock().unwrap().status = LLDBStatus::Processing(message); - self.write_stdin(msg_bytes); - } - - /// Adds a Sender object that gets awoken when we are listening. - /// - /// Should only add a sender when we're about to go into or currently in the - /// processing status otherwise this will never wake up. - pub fn add_awakener(&mut self, sender: Sender) { - self.analyser.lock().unwrap().add_awakener(sender); - } - - /// Drop the awakener - pub fn drop_awakener(&mut self) { - self.analyser.lock().unwrap().drop_awakener(); - } - - pub fn is_process_running(&self) -> bool { - self.analyser.lock().unwrap().is_process_running() - } + // pub fn send_msg(&mut self, message: Message) { + // let msg_bytes = match message.clone() { + // Message::ProcessLaunching => Bytes::from("process launch\n"), + // Message::Breakpoint(fl) => Bytes::from(format!( + // "breakpoint set --file {} --line {}\n", + // fl.name(), + // fl.line_num() + // )), + // Message::UnknownBreakpoint => unreachable!(), + // Message::StepIn => Bytes::from("thread step-in\n"), + // Message::StepOver => Bytes::from("thread step-over\n"), + // Message::Continue => Bytes::from("thread continue\n"), + // Message::PrintVariable(v) => Bytes::from(format!("frame variable {}\n", v.name())), + // }; + + // self.write_stdin(msg_bytes); + // } + + // /// Adds a Sender object that gets awoken when we are listening. + // /// + // /// Should only add a sender when we're about to go into or currently in the + // /// processing status otherwise this will never wake up. + // pub fn add_awakener(&mut self, sender: Sender) { + // self.analyser.lock().unwrap().add_awakener(sender); + // } + + // /// Drop the awakener + // pub fn drop_awakener(&mut self) { + // self.analyser.lock().unwrap().drop_awakener(); + // } + + // pub fn is_process_running(&self) -> bool { + // self.analyser.lock().unwrap().is_process_running() + // } /// Perform setup of listening and forwarding of stdin and return a sender that will forward to the /// stdin of a process. - fn setup_stdin(&mut self, mut child_stdin: ChildStdin, output_stdin: bool) { + fn setup_stdin(mut child_stdin: ChildStdin) -> Sender { let (stdin_tx, mut stdin_rx) = mpsc::channel(32); let mut tx = stdin_tx.clone(); - let analyser = self.analyser.clone(); - tokio::spawn(async move { let tokio_stdin = stdin(); let mut reader = FramedRead::new(tokio_stdin, BytesCodec::new()); @@ -201,11 +186,11 @@ impl LLDBProcess { println!("stuff {:?}", &buf[start..start + 11]); } - if (buf.len() >= start + 2 && buf[start..start + 2] == b"b "[..]) || - (buf.len() >= start + 3 && buf[start..start + 3] == b"br "[..]) || - (buf.len() >= start + 11 && buf[start..start + 11] == b"breakpoint "[..]) { + if (buf.len() >= start + 2 && buf[start..start + 2] == b"b "[..]) + || (buf.len() >= start + 3 && buf[start..start + 3] == b"br "[..]) + || (buf.len() >= start + 11 && buf[start..start + 11] == b"breakpoint "[..]) + { println!("UNKNOWN BREAKPOINT"); - analyser.lock().unwrap().status = LLDBStatus::Processing(Message::UnknownBreakpoint); } tx.send(buf).await.unwrap(); @@ -214,9 +199,7 @@ impl LLDBProcess { tokio::spawn(async move { while let Some(text) = stdin_rx.next().await { - if output_stdin { - io::stdout().write_all(&text).unwrap(); - } + io::stdout().write_all(&text).unwrap(); match child_stdin.write(&text).await { Ok(_) => {} Err(e) => { @@ -226,29 +209,18 @@ impl LLDBProcess { } }); - self.lldb_stdin_tx = Some(stdin_tx); + stdin_tx } /// Perform setup of reading LLDB stdout, analysing it and writing it back to stdout. - fn setup_stdout(&mut self, stdout: ChildStdout) { - let analyser = self.analyser.clone(); + fn setup_stdout(stdout: ChildStdout, lldb_status: Arc>) { tokio::spawn(async move { let mut reader = read_output(BufReader::new(stdout)); + let mut analyser = Analyser::new(lldb_status); while let Some(Ok(text)) = reader.next().await { print!("{}", text); - analyser.lock().unwrap().analyse_stdout(&text); - } - }); - } - - /// Perform setup of reading LLDB stderr, analysing it and writing it back to stdout. - fn setup_stderr(&mut self, stderr: ChildStderr) { - let analyser = self.analyser.clone(); - tokio::spawn(async move { - let mut reader = read_output(BufReader::new(stderr)); - while let Some(Ok(text)) = reader.next().await { - eprint!("{}", text); - analyser.lock().unwrap().analyse_stderr(&text); + io::stdout().flush().unwrap(); + analyser.analyse_output(&text[..]); } }); } @@ -256,19 +228,17 @@ impl LLDBProcess { #[derive(Debug)] pub struct Analyser { - status: LLDBStatus, + lldb_status: Arc>, stdout: String, - stderr: String, process_pid: Option, awakener: Option>, } impl Analyser { - pub fn new() -> Self { + pub fn new(lldb_status: Arc>) -> Self { Analyser { - status: LLDBStatus::None, + lldb_status, stdout: "".to_string(), - stderr: "".to_string(), process_pid: None, awakener: None, } @@ -284,11 +254,7 @@ impl Analyser { self.awakener = None; } - pub fn get_status(&self) -> &LLDBStatus { - &self.status - } - - pub fn analyse_stdout(&mut self, s: &str) { + pub fn analyse_output(&mut self, s: &str) { self.stdout.push_str(s); lazy_static! { @@ -318,6 +284,8 @@ impl Analyser { static ref RE_PROCESS_NOT_RUNNING: Regex = Regex::new("error: invalid process$").unwrap(); static ref RE_SETTINGS: Regex = Regex::new("settings ").unwrap(); + static ref RE_VARIABLE_NOT_FOUND: Regex = + Regex::new("error: no variable named '([^']*)' found in this frame$").unwrap(); } let s = self.stdout.clone(); @@ -402,22 +370,7 @@ impl Analyser { for _ in RE_SETTINGS.captures_iter(line) { self.set_listening(); } - } - - self.clear_analyser(); - } - - pub fn analyse_stderr(&mut self, s: &str) { - self.stderr.push_str(s); - - lazy_static! { - static ref RE_VARIABLE_NOT_FOUND: Regex = - Regex::new("error: no variable named '([^']*)' found in this frame$").unwrap(); - } - - let s = self.stderr.clone(); - for line in s.split("\n") { for cap in RE_VARIABLE_NOT_FOUND.captures_iter(line) { let variable = cap[1].to_string(); self.variable_not_found(variable); @@ -428,7 +381,10 @@ impl Analyser { } fn set_listening(&mut self) { - self.status = LLDBStatus::Listening; + { + let status = self.lldb_status.lock().unwrap(); + *status = LLDBStatus::Listening; + } let awakener = self.awakener.take(); match awakener { Some(mut x) => { @@ -442,7 +398,6 @@ impl Analyser { fn clear_analyser(&mut self) { self.stdout = "".to_string(); - self.stderr = "".to_string(); } pub fn is_process_running(&self) -> bool { @@ -467,7 +422,8 @@ impl Analyser { } fn found_breakpoint(&mut self, file: String, line: u64) { - match &self.status { + let status = *self.lldb_status.lock().unwrap(); + match status { LLDBStatus::Processing(msg) => { match msg { Message::Breakpoint(_) | Message::UnknownBreakpoint => { @@ -475,11 +431,11 @@ impl Analyser { LogLevel::INFO, &format!("Breakpoint set at file {} and line number {}", file, line), ); - }, - _ => {}, + } + _ => {} }; - }, - _ => {}, + } + _ => {} }; //breakpoint_set(&file, line); //let file_location = FileLocation::new(file, line); @@ -565,3 +521,19 @@ impl Analyser { //} } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn process_startup() { + // analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n"); + // assert_eq!( + // analyser.get_status(), + // PDBStatus::Processing(Message::Launching) + // ); + // analyser.analyse_stdout("(Pdb) "); + // assert_eq!(analyser.get_status(), PDBStatus::Listening); + } +} diff --git a/padre/debuggers/node/Cargo.toml b/padre/debuggers/node/Cargo.toml new file mode 100644 index 0000000..8d498a5 --- /dev/null +++ b/padre/debuggers/node/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "padre_node" +version = "0.2.0" +authors = ["Steven Trotter "] +edition = "2018" +license = "MIT" +repository = "https://github.com/strottos/vim-padre" + +[lib] +path = "src/lib.rs" + +[dependencies] +bytes = "0.5.0" +futures = "0.3.1" +lazy_static = "1.3.0" +padre_core = { path = "../../core", version = "0.2.0" } +regex = "1.1.2" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +tokio = { version = "0.2.6", features = ["full"] } +tokio-util = { version = "0.2.0", features = ["codec"] } +tungstenite = "0.9.2" +url = "2.1.0" diff --git a/padre/debuggers/node/src/debugger.rs b/padre/debuggers/node/src/debugger.rs index c5cb118..5d75ec4 100644 --- a/padre/debuggers/node/src/debugger.rs +++ b/padre/debuggers/node/src/debugger.rs @@ -64,13 +64,10 @@ impl DebuggerV1 for ImplDebugger { // the thread but can live with it while starting up the process thread::sleep(Duration::new(2, 0)); - ws_handler - .lock() - .unwrap() - .connect(&uri, move |msg| { - analyser.lock().unwrap().analyse_message(msg); - None - }); + ws_handler.lock().unwrap().connect(&uri, move |msg| { + analyser.lock().unwrap().analyse_message(msg); + None + }); //let msg = OwnedMessage::Text("{\"method\":\"Runtime.enable\"}".to_string()); //let resp1 = ws_handler diff --git a/padre/debuggers/node/src/process.rs b/padre/debuggers/node/src/process.rs index d662063..992c2fc 100644 --- a/padre/debuggers/node/src/process.rs +++ b/padre/debuggers/node/src/process.rs @@ -4,8 +4,8 @@ use padre_core::util::{check_and_spawn_process, read_output, setup_stdin}; -use regex::Regex; use futures::prelude::*; +use regex::Regex; use tokio::io::BufReader; use tokio::prelude::*; use tokio::process::{Child, ChildStderr, ChildStdout}; @@ -96,7 +96,6 @@ impl Process { let mut reader = read_output(BufReader::new(stderr)); while let Some(Ok(text)) = reader.next().await { - if !node_setup { 'node_setup_start: for line in text.split("\n") { let mut uri = None; diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml index 5cb99e1..46ce617 100644 --- a/padre/debuggers/python/Cargo.toml +++ b/padre/debuggers/python/Cargo.toml @@ -15,4 +15,4 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.2", features = ["full"] } +tokio = { version = "0.2.6", features = ["full"] } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 6072897..a2240fc 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -31,8 +31,6 @@ impl ImplDebugger { } impl DebuggerV1 for ImplDebugger { - // Ideally this would be async but currently we don't have async traits yet. - // Means that we can be waiting for setup still when we start using PADRE. fn setup(&mut self) {} fn teardown(&mut self) { @@ -84,6 +82,8 @@ impl DebuggerV1 for ImplDebugger { fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { let full_file_path = PathBuf::from(format!("{}", file_location.name())); + + // TODO: What happens when it doesn't exist let full_file_name = full_file_path.canonicalize().unwrap(); let file_location = FileLocation::new( full_file_name.to_str().unwrap().to_string(), @@ -134,6 +134,55 @@ impl DebuggerV1 for ImplDebugger { full_file_name.to_str().unwrap().to_string(), file_location.line_num(), ); + + log_msg( + LogLevel::INFO, + &format!( + "Removing breakpoint in file {} at line number {}", + file_location.name(), + file_location.line_num() + ), + ); + + // If not started yet remove any pending breakpoint that will get set during run period. + match self.process.lock().unwrap().get_status() { + PDBStatus::None => { + match self.pending_breakpoints { + Some(ref mut x) => { + let mut index = None; + for (i, elem) in x.iter().enumerate() { + if *elem == file_location { + index = Some(i); + } + } + match index { + Some(i) => { + x.remove(i); + }, + None => {} + }; + }, + None => {} + }; + + log_msg( + LogLevel::INFO, + &format!( + "Pending breakpoint removed in file {} at line number {}", + file_location.name(), + file_location.line_num() + ), + ); + + return; + } + _ => {} + } + + self.process + .lock() + .unwrap() + .send_msg(Message::Unbreakpoint(file_location)); } fn step_in(&mut self, _timeout: Instant) { @@ -164,46 +213,10 @@ impl DebuggerV1 for ImplDebugger { } fn print(&mut self, variable: &Variable, _timeout: Instant) { - // //match self.check_process_running() { - // // Some(f) => return f, - // // None => {} - // //}; - // - // let (tx, rx) = mpsc::channel(1); - // - // self.process - // .lock() - // .unwrap() - // .set_status(PDBStatus::Printing(variable.clone())); - // - // self.process - // .lock() - // .unwrap() - // .add_listener(Listener::PrintVariable, tx); - // - // let f = rx - // .take(1) - // .into_future() - // .timeout(Duration::new( - // config - // .lock() - // .unwrap() - // .get_config("PrintVariableTimeout") - // .unwrap() as u64, - // 0, - // )) - // .map(move |event| match event.0.unwrap() { - // Event::PrintVariable(variable, value) => serde_json::json!({ - // "status": "OK", - // "variable": variable.name, - // "value": value, - // }), - // _ => unreachable!(), - // }) - // .map_err(|e| { - // eprintln!("Reading stdin error {:?}", e); - // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") - // }); + //match self.check_process_running() { + // Some(f) => return f, + // None => {} + //}; self.process .lock() diff --git a/padre/debuggers/python/src/lib.rs b/padre/debuggers/python/src/lib.rs index 4a65e65..c933ddb 100644 --- a/padre/debuggers/python/src/lib.rs +++ b/padre/debuggers/python/src/lib.rs @@ -1,5 +1,6 @@ //! The Python debugger module +#![feature(proc_macro_hygiene)] #[macro_use] extern crate lazy_static; diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 308d6d5..762aed6 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -4,6 +4,8 @@ //! the pdb module. It will analyse the output of the text and work out what is //! happening then. +use std::env; +use std::io::{self, Write}; use std::path::Path; #[cfg(not(test))] use std::process::exit; @@ -20,18 +22,20 @@ use bytes::Bytes; use futures::prelude::*; use regex::Regex; use tokio::io::BufReader; -use tokio::process::{Child, ChildStderr, ChildStdout, Command}; +use tokio::process::{Child, ChildStdout, Command}; use tokio::sync::mpsc::Sender; /// Messages that can be sent to PDB for processing -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum Message { Launching, Breakpoint(FileLocation), + Unbreakpoint(FileLocation), StepIn, StepOver, Continue, PrintVariable(Variable), + Custom, } /// Current status of PDB @@ -155,7 +159,14 @@ impl Process { let args = get_python_args(&debugger_cmd[..], run_cmd.iter().map(|x| &x[..]).collect()); - let mut process = Command::new(&debugger_cmd) + let mut pty_wrapper = env::current_exe().unwrap(); + pty_wrapper.pop(); + pty_wrapper.pop(); + pty_wrapper.pop(); + pty_wrapper.push("ptywrapper.py"); + + let mut process = Command::new(pty_wrapper) + .arg(&debugger_cmd) .args(&args) .stdin(Stdio::piped()) .stdout(Stdio::piped()) @@ -174,18 +185,12 @@ impl Process { .take() .expect("Python process did not have a handle to stdout"), ); - self.setup_stderr( - process - .stderr() - .take() - .expect("Python process did not have a handle to stderr"), - ); let stdin_tx = setup_stdin( process .stdin() .take() .expect("Python process did not have a handle to stdin"), - true, + false, ); self.analyser.lock().unwrap().set_pid(process.id() as u64); @@ -219,23 +224,24 @@ impl Process { let analyser = self.analyser.clone(); tokio::spawn(async move { - let msg = match message.clone() { + let msg = match &message { Message::Breakpoint(fl) => { Bytes::from(format!("break {}:{}\n", fl.name(), fl.line_num())) } + Message::Unbreakpoint(fl) => { + Bytes::from(format!("clear {}:{}\n", fl.name(), fl.line_num())) + }, Message::StepIn => Bytes::from("step\n"), Message::StepOver => Bytes::from("next\n"), Message::Continue => Bytes::from("continue\n"), Message::Launching => unreachable!(), Message::PrintVariable(v) => Bytes::from(format!("print({})\n", v.name())), + Message::Custom => todo!(), }; - analyser.lock().unwrap().status = PDBStatus::Processing(message); - tx.clone() - .unwrap() - .send(msg) - .map(move |_| {}) - .await + analyser.lock().unwrap().analyse_message(message); + + tx.clone().unwrap().send(msg).map(move |_| {}).await }); } @@ -246,20 +252,11 @@ impl Process { let mut reader = read_output(BufReader::new(stdout)); while let Some(Ok(text)) = reader.next().await { print!("{}", text); + io::stdout().flush().unwrap(); analyser.lock().unwrap().analyse_stdout(&text); } }); } - - /// Perform setup of reading Python stderr, analysing it and writing it back to stdout. - fn setup_stderr(&mut self, stderr: ChildStderr) { - tokio::spawn(async { - let mut reader = read_output(BufReader::new(stderr)); - while let Some(Ok(text)) = reader.next().await { - eprint!("{}", text); - } - }); - } } #[derive(Debug)] @@ -267,6 +264,8 @@ pub struct Analyser { status: PDBStatus, pid: Option, awakener: Option>, + // For keeping track of the variable that we were told to print + variable_value: String, } impl Analyser { @@ -275,6 +274,7 @@ impl Analyser { status: PDBStatus::None, pid: None, awakener: None, + variable_value: "".to_string(), } } @@ -294,10 +294,6 @@ impl Analyser { pub fn analyse_stdout(&mut self, s: &str) { lazy_static! { - static ref RE_BREAKPOINT: Regex = - Regex::new("^Breakpoint (\\d*) at (.*):(\\d*)$").unwrap(); - static ref RE_JUMP_TO_POSITION: Regex = - Regex::new("^> (.*)\\((\\d*)\\)[<>\\w]*\\(\\)$").unwrap(); static ref RE_RETURNING: Regex = Regex::new("^> (.*)\\((\\d*)\\)[<>\\w]*\\(\\)->(.*)$").unwrap(); static ref RE_PROCESS_EXITED: Regex = @@ -307,26 +303,81 @@ impl Analyser { .unwrap(); } - for line in s.split("\n") { - match self.status { - PDBStatus::None => { - if line.contains("(Pdb) ") { - self.status = PDBStatus::Processing(Message::Launching); + match self.get_status() { + PDBStatus::Processing(msg) => { + match msg { + Message::PrintVariable(var) => { + let mut from = 0; + let mut to = s.len(); + + let print_cmd_size = 7 + var.name().len(); + if to >= print_cmd_size + 2 + && &s[0..print_cmd_size] == &format!("print({})", var.name()) + { + // 2 extra for \r\n + from += print_cmd_size + 2; + } + + println!("s: {}", s); + println!("from: {}", from); + println!("to: {}", to); + + let pdb_length = "(Pdb) ".len(); + if to >= pdb_length && &s[to - pdb_length..to] == "(Pdb) " { + to -= pdb_length; + } + + self.variable_value += &s[from..to]; } + _ => {} + } + } + _ => {} + } + + for line in s.split("\r\n") { + if line == "(Pdb) " { + match self.get_status() { + PDBStatus::Processing(msg) => match msg { + Message::PrintVariable(var) => { + let mut to = self.variable_value.len(); + if to >= 2 && &self.variable_value[to - 2..to] == "\r\n" { + to -= 2; + } + let msg = format!("{}={}", var.name(), &self.variable_value[0..to]); + log_msg(LogLevel::INFO, &msg); + self.variable_value = "".to_string(); + } + _ => {} + }, + _ => {} } - _ => {} - }; - for cap in RE_BREAKPOINT.captures_iter(line) { - let file = cap[2].to_string(); - let line = cap[3].parse::().unwrap(); - log_msg( - LogLevel::INFO, - &format!("Breakpoint set at file {} and line number {}", file, line), - ); self.set_listening(); + return; } + match self.get_status() { + PDBStatus::None => { + self.check_location(line); + self.status = PDBStatus::Processing(Message::Launching) + } + PDBStatus::Listening => self.status = PDBStatus::Processing(Message::Custom), + PDBStatus::Processing(msg) => match msg { + Message::Breakpoint(_) => { + self.check_breakpoint(line); + } + Message::StepIn | Message::StepOver | Message::Continue => { + self.check_location(line); + } + Message::Custom => { + self.check_breakpoint(line); + self.check_location(line); + } + _ => {} + }, + }; + for cap in RE_RETURNING.captures_iter(line) { let file = cap[1].to_string(); let line = cap[2].parse::().unwrap(); @@ -336,13 +387,6 @@ impl Analyser { log_msg(LogLevel::INFO, &format!("Returning value {}", return_value)); } - for cap in RE_JUMP_TO_POSITION.captures_iter(line) { - let file = cap[1].to_string(); - let line = cap[2].parse::().unwrap(); - jump_to_position(&file, line); - self.set_listening(); - } - for _ in RE_PROCESS_EXITED.captures_iter(line) { signal_exited(self.pid.unwrap(), 0); } @@ -352,18 +396,10 @@ impl Analyser { signal_exited(self.pid.unwrap(), exit_code); } } + } - match &self.status { - PDBStatus::Processing(msg) => { - match msg { - Message::PrintVariable(var) => { - self.print_variable(var.clone(), s); - } - _ => {} - }; - } - _ => {} - }; + pub fn analyse_message(&mut self, msg: Message) { + self.status = PDBStatus::Processing(msg); } pub fn set_pid(&mut self, pid: u64) { @@ -383,43 +419,61 @@ impl Analyser { }; } - fn print_variable(&self, variable: Variable, data: &str) { - let len = data.len(); - if len < 2 { - return; + fn check_breakpoint(&self, line: &str) { + lazy_static! { + static ref RE_BREAKPOINT: Regex = + Regex::new("^Breakpoint (\\d*) at (.*):(\\d*)$").unwrap(); } - let to = data.len() - 2; + for cap in RE_BREAKPOINT.captures_iter(line) { + let file = cap[2].to_string(); + let line = cap[3].parse::().unwrap(); + log_msg( + LogLevel::INFO, + &format!("Breakpoint set at file {} and line number {}", file, line), + ); + } + } - let msg = format!("variable {}={}", variable.name(), &data[0..to]); + fn check_location(&self, line: &str) { + lazy_static! { + static ref RE_JUMP_TO_POSITION: Regex = + Regex::new("^> (.*)\\((\\d*)\\)[<>\\w]*\\(\\)$").unwrap(); + } - log_msg(LogLevel::INFO, &msg); + for cap in RE_JUMP_TO_POSITION.captures_iter(line) { + let file = cap[1].to_string(); + let line = cap[2].parse::().unwrap(); + jump_to_position(&file, line); + } } } #[cfg(test)] mod tests { + use super::*; + #[test] fn check_get_args_basic_command() { - let args = super::get_python_args("/usr/bin/python3", vec!["test.py", "arg1"]); + let args = get_python_args("/usr/bin/python3", vec!["test.py", "arg1"]); assert_eq!(args, vec!["-m", "pdb", "--", "test.py", "arg1"]); } #[test] fn check_get_args_recognises_matching_python_command() { - let args = super::get_python_args("/usr/bin/python3", vec!["python3", "test.py", "arg1"]); + let args = get_python_args("/usr/bin/python3", vec!["python3", "test.py", "arg1"]); assert_eq!(args, vec!["-m", "pdb", "test.py", "arg1"]); } #[test] fn check_get_args_leaves_non_matching_python_command() { - let args = super::get_python_args("/usr/bin/python3.7", vec!["python3", "test.py", "arg1"]); + let args = get_python_args("/usr/bin/python3.7", vec!["python3", "test.py", "arg1"]); assert_eq!(args, vec!["-m", "pdb", "--", "python3", "test.py", "arg1"]); } #[test] fn check_get_args_accepts_module_running() { - let args = super::get_python_args( + let args = get_python_args( "/usr/bin/python3", vec!["python3", "-m", "abc", "--", "arg1"], ); @@ -428,10 +482,63 @@ mod tests { #[test] fn check_get_args_accepts_command_arguments() { - let args = super::get_python_args( + let args = get_python_args( "/usr/bin/python3", vec!["python3", "-c", "print('Hello, World!')"], ); assert_eq!(args, vec!["-m", "pdb", "-c", "print('Hello, World!')"]); } + + #[test] + fn analyser_startup() { + let mut analyser = Analyser::new(); + assert_eq!(analyser.get_status(), PDBStatus::None); + analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n"); + assert_eq!( + analyser.get_status(), + PDBStatus::Processing(Message::Launching) + ); + analyser.analyse_stdout("(Pdb) "); + assert_eq!(analyser.get_status(), PDBStatus::Listening); + } + + #[test] + fn analyser_custom_syntax_error() { + let mut analyser = Analyser::new(); + analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n(Pdb) "); + analyser.analyse_stdout("do something nonsensical\r\n"); + assert_eq!( + analyser.get_status(), + PDBStatus::Processing(Message::Custom) + ); + analyser.analyse_stdout("*** SyntaxError: invalid syntax\r\n(Pdb) "); + assert_eq!(analyser.get_status(), PDBStatus::Listening); + } + + #[test] + fn analyser_padre_message() { + let mut analyser = Analyser::new(); + analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n(Pdb) "); + let msg = Message::Breakpoint(FileLocation::new("test.py".to_string(), 2)); + analyser.analyse_message(msg.clone()); + assert_eq!(analyser.get_status(), PDBStatus::Processing(msg)); + analyser.analyse_stdout("Breakpoint 1 at test.py:2\r\n(Pdb) "); + assert_eq!(analyser.get_status(), PDBStatus::Listening); + } + + #[test] + fn analyser_print_message() { + let mut analyser = Analyser::new(); + analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n(Pdb) "); + let msg = Message::PrintVariable(Variable::new("abc".to_string())); + analyser.analyse_message(msg.clone()); + analyser.analyse_stdout("print(abc)\r\n"); + analyser.analyse_stdout("123\r\n"); + assert_eq!(analyser.variable_value, "123\r\n"); + analyser.analyse_stdout("(Pdb) "); + analyser.analyse_message(msg.clone()); + analyser.analyse_stdout("print(abc)\r\n\"abcd1234\"\r\n"); + assert_eq!(analyser.variable_value, "\"abcd1234\"\r\n"); + analyser.analyse_stdout("(Pdb) "); + } } diff --git a/padre/integration/features/lldb.feature b/padre/integration/features/lldb.feature index 8011d5f..dfeccb6 100644 --- a/padre/integration/features/lldb.feature +++ b/padre/integration/features/lldb.feature @@ -1,5 +1,5 @@ Feature: LLDB - Debug with PADRE for a program needing LLDB + Debug with PADRE a program needing LLDB Scenario: Debug a basic program with LLDB using the LLDB command line Given that we have a file 'test_prog.c' @@ -40,7 +40,6 @@ Feature: LLDB Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#Log | [4, ".*test_prog.c.*17"] | - | padre#debugger#Log | [4, "Breakpoint set.*test_prog.c.*17"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"not_exists.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | diff --git a/padre/integration/features/python.feature b/padre/integration/features/python.feature index 1644371..34b8ebe 100644 --- a/padre/integration/features/python.feature +++ b/padre/integration/features/python.feature @@ -52,6 +52,16 @@ Feature: Python | function | args | | padre#debugger#Log | [4, "Setting breakpoint.*test_prog.py.*23"] | | padre#debugger#Log | [4, "Breakpoint pending.*test_prog.py.*23"] | + When I send a request to PADRE '{"cmd":"breakpoint","file":"`pwd`/test_files/test_prog.py","line":24}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4, "Setting breakpoint.*test_prog.py.*24"] | + | padre#debugger#Log | [4, "Breakpoint pending.*test_prog.py.*24"] | + When I send a request to PADRE '{"cmd":"unbreakpoint","file":"`pwd`/test_files/test_prog.py","line":24}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Removing breakpoint.*test_prog.py.*24"] | + | padre#debugger#Log | [4,"Pending breakpoint removed.*test_prog.py.*24"] | When I send a request to PADRE '{"cmd":"run"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | @@ -66,6 +76,10 @@ Feature: Python | function | args | | padre#debugger#Log | [4,"Setting breakpoint.*test_prog.py.*24"] | | padre#debugger#Log | [4,"Breakpoint set.*test_prog.py.*24"] | + When I send a request to PADRE '{"cmd":"unbreakpoint","file":"`pwd`/test_files/test_prog.py","line":24}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Removing breakpoint.*test_prog.py.*24"] | When I send a request to PADRE '{"cmd":"stepOver"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | @@ -93,17 +107,13 @@ Feature: Python | padre#debugger#JumpToPosition | [".*test_prog.py",22] | When I send a request to PADRE '{"cmd":"print","variable":"b"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,"variable b=123"] | + | function | args | + | padre#debugger#Log | [4,"b=123"] | When I send a request to PADRE '{"cmd":"continue"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#JumpToPosition | [".*test_prog.py",23] | When I send a request to PADRE '{"cmd":"continue"}' - Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.py",24] | - When I send a request to PADRE '{"cmd":"continue"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | | padre#debugger#ProcessExited | [0,"\\d+"] | diff --git a/padre/ptywrapper.py b/padre/ptywrapper.py new file mode 100755 index 0000000..f3cf888 --- /dev/null +++ b/padre/ptywrapper.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +import pty +import sys + +pty.spawn(sys.argv[1:]) From 1b6c108da2a72beb2728c8a9e976da433fbea8b0 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 27 Feb 2020 11:30:51 +0000 Subject: [PATCH 12/23] Update to Tokio 0.2.11 --- padre/Cargo.lock | 608 +++----------------------- padre/cli/Cargo.toml | 20 +- padre/core/Cargo.toml | 10 +- padre/debuggers/lldb/Cargo.toml | 2 +- padre/debuggers/node/Cargo.toml | 2 +- padre/debuggers/python/Cargo.toml | 2 +- padre/debuggers/python/src/process.rs | 4 +- 7 files changed, 77 insertions(+), 571 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 9a9cd52..e1e837e 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +checksum = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" dependencies = [ "memchr", ] @@ -26,95 +26,26 @@ checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ + "hermit-abi", "libc", "winapi 0.3.8", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "byteorder" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" - [[package]] name = "bytes" -version = "0.4.12" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - -[[package]] -name = "bytes" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" - -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - -[[package]] -name = "cc" -version = "1.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" [[package]] name = "cfg-if" @@ -137,58 +68,12 @@ dependencies = [ "vec_map", ] -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -207,9 +92,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" dependencies = [ "futures-channel", "futures-core", @@ -222,9 +107,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" dependencies = [ "futures-core", "futures-sink", @@ -232,15 +117,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" [[package]] name = "futures-executor" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" dependencies = [ "futures-core", "futures-task", @@ -249,15 +134,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" [[package]] name = "futures-macro" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -267,21 +152,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" [[package]] name = "futures-task" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" [[package]] name = "futures-util" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" dependencies = [ "futures-channel", "futures-core", @@ -296,72 +181,15 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -dependencies = [ - "typenum", -] - -[[package]] -name = "getrandom" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "hermit-abi" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" +checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" dependencies = [ "libc", ] -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -dependencies = [ - "bytes 0.4.12", - "fnv", - "itoa", -] - -[[package]] -name = "httparse" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" - -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "input_buffer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf" -dependencies = [ - "bytes 0.4.12", -] - [[package]] name = "iovec" version = "0.1.4" @@ -373,9 +201,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "kernel32-sys" @@ -395,9 +223,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" [[package]] name = "log" @@ -408,17 +236,11 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - [[package]] name = "memchr" -version = "2.2.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "mio" @@ -484,24 +306,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "native-tls" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "net2" version = "0.2.33" @@ -513,55 +317,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "num_cpus" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "openssl" -version = "0.10.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "lazy_static", - "libc", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" - -[[package]] -name = "openssl-sys" -version = "0.9.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "padre" version = "0.2.0" @@ -569,8 +324,6 @@ dependencies = [ "clap", "futures", "padre_core", - "padre_lldb", - "padre_node", "padre_python", "serde", "serde_derive", @@ -582,7 +335,7 @@ dependencies = [ name = "padre_core" version = "0.2.0" dependencies = [ - "bytes 0.5.3", + "bytes", "futures", "lazy_static", "pin-project", @@ -594,42 +347,11 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "padre_lldb" -version = "0.2.0" -dependencies = [ - "bytes 0.5.3", - "futures", - "lazy_static", - "padre_core", - "regex", - "tokio", - "tokio-util", -] - -[[package]] -name = "padre_node" -version = "0.2.0" -dependencies = [ - "bytes 0.5.3", - "futures", - "lazy_static", - "padre_core", - "regex", - "serde", - "serde_derive", - "serde_json", - "tokio", - "tokio-util", - "tungstenite", - "url", -] - [[package]] name = "padre_python" version = "0.2.0" dependencies = [ - "bytes 0.5.3", + "bytes", "futures", "lazy_static", "padre_core", @@ -637,26 +359,20 @@ dependencies = [ "tokio", ] -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - [[package]] name = "pin-project" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" +checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" dependencies = [ "proc-macro2", "quote", @@ -665,9 +381,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" +checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" [[package]] name = "pin-utils" @@ -675,18 +391,6 @@ version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" - [[package]] name = "proc-macro-hack" version = "0.5.11" @@ -706,9 +410,9 @@ checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" dependencies = [ "unicode-xid", ] @@ -722,47 +426,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -dependencies = [ - "c2-chacha", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" version = "0.1.56" @@ -771,9 +434,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.3.1" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" dependencies = [ "aho-corasick", "memchr", @@ -783,18 +446,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.12" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -dependencies = [ - "winapi 0.3.8", -] +checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" [[package]] name = "ryu" @@ -802,37 +456,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -[[package]] -name = "schannel" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" -dependencies = [ - "lazy_static", - "winapi 0.3.8", -] - -[[package]] -name = "security-framework" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" -dependencies = [ - "core-foundation-sys", -] - [[package]] name = "serde" version = "1.0.104" @@ -852,27 +475,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" +checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" dependencies = [ "itoa", "ryu", "serde", ] -[[package]] -name = "sha-1" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - [[package]] name = "signal-hook-registry" version = "1.2.0" @@ -889,12 +500,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -[[package]] -name = "smallvec" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" - [[package]] name = "socket2" version = "0.3.11" @@ -915,29 +520,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.11" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi 0.3.8", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -949,20 +540,20 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ "lazy_static", ] [[package]] name = "tokio" -version = "0.2.6" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1bef565a52394086ecac0a6fa3b8ace4cb3a138ee1d96bd2b93283b56824e3" +checksum = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" dependencies = [ - "bytes 0.5.3", + "bytes", "fnv", "futures-core", "iovec", @@ -972,31 +563,19 @@ dependencies = [ "mio", "mio-named-pipes", "mio-uds", - "num_cpus", "pin-project-lite", "signal-hook-registry", "slab", - "tokio-macros", "winapi 0.3.8", ] -[[package]] -name = "tokio-macros" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de6c21a09bab0ce34614bb1071403ad9996db62715eb61e63be5d82f91342bc" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "tokio-util" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "bytes 0.5.3", + "bytes", "futures-core", "futures-sink", "log", @@ -1004,50 +583,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tungstenite" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0c2bd5aeb7dcd2bb32e472c8872759308495e5eccc942e929a513cd8d36110" -dependencies = [ - "base64", - "byteorder", - "bytes 0.4.12", - "http", - "httparse", - "input_buffer", - "log", - "native-tls", - "rand", - "sha-1", - "url", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" -dependencies = [ - "smallvec", -] - [[package]] name = "unicode-width" version = "0.1.7" @@ -1060,41 +595,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -[[package]] -name = "url" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" -dependencies = [ - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "utf-8" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" - -[[package]] -name = "vcpkg" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" - [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" - [[package]] name = "winapi" version = "0.2.8" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index ed182cd..005facc 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -7,9 +7,9 @@ license = "APACHE" repository = "https://github.com/strottos/vim-padre" [features] -default = ["lldb", "node", "python"] -lldb = ["padre_lldb"] -node = ["padre_node"] +default = ["python"] # ["lldb", "node", "python"] +# lldb = ["padre_lldb"] +# node = ["padre_node"] python = ["padre_python"] [dependencies] @@ -19,9 +19,17 @@ padre_core = { path = "../core", version = "0.2.0" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.6", features = ["full"] } +tokio = { version = "0.2.11", features = [ + "io-util", + "io-std", + "net", + "process", + "stream", + "sync", + "time" +] } # The debuggers, all optional -padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } -padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } +# padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } +# padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml index e14cae6..128ac6d 100644 --- a/padre/core/Cargo.toml +++ b/padre/core/Cargo.toml @@ -18,13 +18,5 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.6", features = [ - "io-util", - "io-std", - "net", - "process", - "stream", - "sync", - "time" -] } +tokio = { version = "0.2.11", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/debuggers/lldb/Cargo.toml b/padre/debuggers/lldb/Cargo.toml index 0d05dd8..a83cfc7 100644 --- a/padre/debuggers/lldb/Cargo.toml +++ b/padre/debuggers/lldb/Cargo.toml @@ -15,5 +15,5 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.6", features = ["full"] } +tokio = { version = "0.2.11", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/debuggers/node/Cargo.toml b/padre/debuggers/node/Cargo.toml index 8d498a5..287c023 100644 --- a/padre/debuggers/node/Cargo.toml +++ b/padre/debuggers/node/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.6", features = ["full"] } +tokio = { version = "0.2.11", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } tungstenite = "0.9.2" url = "2.1.0" diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml index 46ce617..6ca705c 100644 --- a/padre/debuggers/python/Cargo.toml +++ b/padre/debuggers/python/Cargo.toml @@ -15,4 +15,4 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.6", features = ["full"] } +tokio = { version = "0.2.11", features = [] } diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 762aed6..0b1eeb9 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -181,13 +181,13 @@ impl Process { self.setup_stdout( process - .stdout() + .stdout .take() .expect("Python process did not have a handle to stdout"), ); let stdin_tx = setup_stdin( process - .stdin() + .stdin .take() .expect("Python process did not have a handle to stdin"), false, From e346aca5ff68990e2b03d403a12c3e6e7aef21ae Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 27 Feb 2020 16:11:11 +0000 Subject: [PATCH 13/23] Various structural improvements --- padre/Cargo.lock | 12 ++ padre/cli/Cargo.toml | 2 + padre/cli/src/debugger.rs | 154 +++++++++++-------------- padre/cli/src/main.rs | 96 ++++++++------- padre/core/src/lib.rs | 1 + padre/core/src/server.rs | 119 ++++--------------- padre/core/src/vimcodec.rs | 25 ++-- padre/debuggers/python/src/debugger.rs | 14 ++- padre/debuggers/python/src/process.rs | 4 +- 9 files changed, 179 insertions(+), 248 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index e1e837e..8336ab5 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -566,9 +566,21 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", + "tokio-macros", "winapi 0.3.8", ] +[[package]] +name = "tokio-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4b1e7ed7d5d4c2af3d999904b0eebe76544897cdbfb2b9684bed2174ab20f7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-util" version = "0.2.0" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index 005facc..a8993bf 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -22,7 +22,9 @@ serde_json = "1.0" tokio = { version = "0.2.11", features = [ "io-util", "io-std", + "macros", "net", + "rt-core", "process", "stream", "sync", diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 130baa5..a6b3094 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -1,16 +1,13 @@ -//! Debugger Module +//! Handle creating the debugger dependent on the type of debugger specified //! -//! Main module for handling the debuggers, defines the standard versioned debugger interfaces -//! and creates the main debugger objects. +//! See core/debugger.rs for more centric/shared debugger material once one is created use std::fmt::Debug; -use std::sync::{Arc, Mutex}; +use std::process::Command; use std::time::Instant; -use padre_core::server::{DebuggerCmd, DebuggerV1}; +use padre_core::debugger::{Debugger, DebuggerCmd}; -use futures::StreamExt; -use tokio::process::Command; use tokio::sync::mpsc::Receiver; #[cfg(feature = "lldb")] @@ -31,55 +28,55 @@ enum DebuggerType { Python, } -#[derive(Debug)] -pub struct Debugger { - debugger: Arc>, -} - -impl Debugger { - pub fn new( - impl_debugger: Arc>, - mut queue_rx: Receiver<(DebuggerCmd, Instant)>, - ) -> Debugger { - let debugger = Debugger { - debugger: impl_debugger.clone(), - }; - - let queue_processing_debugger = impl_debugger.clone(); - - tokio::spawn(async move { - while let Some(cmd) = queue_rx.next().await { - let mut debugger = queue_processing_debugger.lock().unwrap(); - match cmd.0 { - DebuggerCmd::Run => debugger.run(cmd.1), - DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), - DebuggerCmd::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), - DebuggerCmd::StepIn => debugger.step_in(cmd.1), - DebuggerCmd::StepOver => debugger.step_over(cmd.1), - DebuggerCmd::Continue => debugger.continue_(cmd.1), - DebuggerCmd::Print(v) => debugger.print(&v, cmd.1), - }; - } - }); - - debugger - } - - pub fn stop(&mut self) { - self.debugger.lock().unwrap().teardown(); - } -} +// #[derive(Debug)] +// pub struct Debugger { +// debugger: Arc>, +// } +// +// impl Debugger { +// pub fn new( +// impl_debugger: Arc>, +// mut queue_rx: Receiver<(DebuggerCmd, Instant)>, +// ) -> Debugger { +// let debugger = Debugger { +// debugger: impl_debugger.clone(), +// }; +// +// let queue_processing_debugger = impl_debugger.clone(); +// +// tokio::spawn(async move { +// while let Some(cmd) = queue_rx.next().await { +// let mut debugger = queue_processing_debugger.lock().unwrap(); +// match cmd.0 { +// DebuggerCmd::Run => debugger.run(cmd.1), +// DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), +// DebuggerCmd::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), +// DebuggerCmd::StepIn => debugger.step_in(cmd.1), +// DebuggerCmd::StepOver => debugger.step_over(cmd.1), +// DebuggerCmd::Continue => debugger.continue_(cmd.1), +// DebuggerCmd::Print(v) => debugger.print(&v, cmd.1), +// }; +// } +// }); +// +// debugger +// } +// +// pub fn stop(&mut self) { +// self.debugger.lock().unwrap().teardown(); +// } +// } /// Get the debugger implementation /// /// If the debugger type is not specified it will try it's best to guess what kind of debugger to /// return. -pub async fn create_debugger( +pub fn create_debugger( debugger_cmd: Option<&str>, debugger_type: Option<&str>, run_cmd: Vec, queue_rx: Receiver<(DebuggerCmd, Instant)>, -) -> Debugger { +) -> Box { let debugger_type = match debugger_type { Some(s) => match s.to_ascii_lowercase().as_str() { #[cfg(feature = "lldb")] @@ -90,7 +87,7 @@ pub async fn create_debugger( "node" => DebuggerType::Node, _ => panic!("Couldn't understand debugger type {}", s), }, - None => match get_debugger_type(&run_cmd[0]).await { + None => match get_debugger_type(&run_cmd[0]) { Some(s) => s, None => match debugger_cmd { Some(s) => match s { @@ -122,38 +119,29 @@ pub async fn create_debugger( }, }; - let debugger: Arc> = match debugger_type { + let debugger = match debugger_type { #[cfg(feature = "lldb")] - DebuggerType::LLDB => Arc::new(Mutex::new(padre_lldb::ImplDebugger::new( - debugger_cmd, - run_cmd, - ))), + DebuggerType::LLDB => padre_lldb::ImplDebugger::new(debugger_cmd, run_cmd), #[cfg(feature = "node")] - DebuggerType::Node => Arc::new(Mutex::new(padre_node::ImplDebugger::new( - debugger_cmd, - run_cmd, - ))), + DebuggerType::Node => padre_node::ImplDebugger::new(debugger_cmd, run_cmd), #[cfg(feature = "python")] - DebuggerType::Python => Arc::new(Mutex::new(padre_python::ImplDebugger::new( - debugger_cmd, - run_cmd, - ))), + DebuggerType::Python => padre_python::ImplDebugger::new(debugger_cmd, run_cmd), }; - debugger.lock().unwrap().setup(); + debugger.setup_handler(queue_rx); - Debugger::new(debugger, queue_rx) + Box::new(debugger) } /// Guesses the debugger type -async fn get_debugger_type(run_cmd: &str) -> Option { - if is_node(&run_cmd).await { +fn get_debugger_type(run_cmd: &str) -> Option { + if is_node(&run_cmd) { #[cfg(feature = "node")] return Some(DebuggerType::Node); - } else if is_python(&run_cmd).await { + } else if is_python(&run_cmd) { #[cfg(feature = "python")] return Some(DebuggerType::Python); - } else if is_lldb(&run_cmd).await { + } else if is_lldb(&run_cmd) { #[cfg(feature = "lldb")] return Some(DebuggerType::LLDB); } @@ -162,8 +150,8 @@ async fn get_debugger_type(run_cmd: &str) -> Option { } /// Checks if the file is a binary executable -async fn is_lldb(cmd: &str) -> bool { - if file_is_binary_executable(cmd).await { +fn is_lldb(cmd: &str) -> bool { + if file_is_binary_executable(cmd) { return true; } @@ -171,8 +159,8 @@ async fn is_lldb(cmd: &str) -> bool { } /// Checks if the file is a NodeJS script -async fn is_node(cmd: &str) -> bool { - if file_is_text(cmd).await && cmd.ends_with(".js") { +fn is_node(cmd: &str) -> bool { + if file_is_text(cmd) && cmd.ends_with(".js") { return true; } @@ -184,8 +172,8 @@ async fn is_node(cmd: &str) -> bool { } /// Checks if the file is a Python script -async fn is_python(cmd: &str) -> bool { - if file_is_text(cmd).await && cmd.ends_with(".py") { +fn is_python(cmd: &str) -> bool { + if file_is_text(cmd) && cmd.ends_with(".py") { return true; } @@ -198,8 +186,8 @@ async fn is_python(cmd: &str) -> bool { /// Find out if a file is a binary executable (either ELF or Mach-O /// executable). -async fn file_is_binary_executable(cmd: &str) -> bool { - let output = get_file_type(cmd).await; +fn file_is_binary_executable(cmd: &str) -> bool { + let output = get_file_type(cmd); if output.contains("ELF") || (output.contains("Mach-O") && output.to_ascii_lowercase().contains("executable")) @@ -211,8 +199,8 @@ async fn file_is_binary_executable(cmd: &str) -> bool { } /// Find out if a file is a text file (either ASCII or UTF-8). -async fn file_is_text(cmd: &str) -> bool { - let output = get_file_type(cmd).await; +fn file_is_text(cmd: &str) -> bool { + let output = get_file_type(cmd); if output.contains("ASCII") || output.contains("UTF-8") { true @@ -222,22 +210,19 @@ async fn file_is_text(cmd: &str) -> bool { } /// Get the file type as output by the UNIX `file` command. -async fn get_file_type(cmd: &str) -> String { +fn get_file_type(cmd: &str) -> String { let output = Command::new("file") .arg("-L") // Follow symlinks .arg(cmd) .output(); - let output = output - .await - .expect(&format!("Can't run file on {} to find file type", cmd)); + let output = output.expect(&format!("Can't run file on {} to find file type", cmd)); String::from_utf8_lossy(&output.stdout).to_string() } #[cfg(test)] mod tests { - #[tokio::test] - async fn is_file_executable() { + fn is_file_executable() { assert_eq!( true, super::file_is_binary_executable("../test_files/node").await @@ -248,8 +233,7 @@ mod tests { ); } - #[tokio::test] - async fn is_file_text() { + fn is_file_text() { assert_eq!(false, super::file_is_text("../test_files/node").await); assert_eq!( true, diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index 558ecfb..23951e1 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -36,6 +36,7 @@ use padre_core::server; use padre_core::util; mod debugger; +use debugger::create_debugger; fn get_app_args<'a>() -> ArgMatches<'a> { App::new("VIM Padre") @@ -88,19 +89,19 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -fn exit_padre(debugger: Arc>) { - let when = Duration::new(5, 0); - - tokio::spawn(async move { - delay_for(when).await; - println!("Timed out exiting!"); - exit(-1); - }); - - debugger.lock().unwrap().stop(); -} - -async fn run_padre() -> () { +// fn exit_padre(debugger: Arc>) { +// let when = Duration::new(5, 0); +// +// tokio::spawn(async move { +// delay_for(when).await; +// println!("Timed out exiting!"); +// exit(-1); +// }); +// +// debugger.lock().unwrap().stop(); +// } + +async fn run_padre() -> io::Result<()> { let args = get_app_args(); let debug_cmd: Vec = args @@ -113,15 +114,12 @@ async fn run_padre() -> () { // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? - let debugger = Arc::new(Mutex::new( - debugger::create_debugger( - args.value_of("debugger"), - args.value_of("type"), - debug_cmd, - debugger_queue_rx, - ) - .await, - )); + let debugger = Arc::new(Mutex::new(create_debugger( + args.value_of("debugger"), + args.value_of("type"), + debug_cmd, + debugger_queue_rx, + ))); let connection_addr = get_connection(&args); let mut socket = TcpListener::bind(&connection_addr) @@ -136,32 +134,32 @@ async fn run_padre() -> () { // TODO: Merge the following into one lot of signals when we know how to - let debugger_signals = debugger.clone(); - tokio::spawn(async move { - let mut signals = signal(SignalKind::interrupt()).unwrap(); + // let debugger_signals = debugger.clone(); + // tokio::spawn(async move { + // let mut signals = signal(SignalKind::interrupt()).unwrap(); - while let Some(_) = signals.recv().await { - exit_padre(debugger_signals.clone()); - } - }); + // while let Some(_) = signals.recv().await { + // exit_padre(debugger_signals.clone()); + // } + // }); - let debugger_signals = debugger.clone(); - tokio::spawn(async move { - let mut signals = signal(SignalKind::quit()).unwrap(); + // let debugger_signals = debugger.clone(); + // tokio::spawn(async move { + // let mut signals = signal(SignalKind::quit()).unwrap(); - while let Some(_) = signals.recv().await { - exit_padre(debugger_signals.clone()); - } - }); + // while let Some(_) = signals.recv().await { + // exit_padre(debugger_signals.clone()); + // } + // }); - let debugger_signals = debugger.clone(); - tokio::spawn(async move { - let mut signals = signal(SignalKind::terminate()).unwrap(); + // let debugger_signals = debugger.clone(); + // tokio::spawn(async move { + // let mut signals = signal(SignalKind::terminate()).unwrap(); - while let Some(_) = signals.recv().await { - exit_padre(debugger_signals.clone()); - } - }); + // while let Some(_) = signals.recv().await { + // exit_padre(debugger_signals.clone()); + // } + // }); while let Some(Ok(stream)) = incoming.next().await { let debugger_queue_tx = debugger_queue_tx.clone(); @@ -169,12 +167,12 @@ async fn run_padre() -> () { server::process_connection(stream, debugger_queue_tx.clone()); }); } -} - -fn main() -> io::Result<()> { - let mut runtime = Runtime::new().unwrap(); - - runtime.block_on(run_padre()); Ok(()) } + +#[tokio::main] +async fn main() -> io::Result<()> { + let padre = tokio::spawn(run_padre()); + padre.await.unwrap() +} diff --git a/padre/core/src/lib.rs b/padre/core/src/lib.rs index a82d775..ee5badc 100644 --- a/padre/core/src/lib.rs +++ b/padre/core/src/lib.rs @@ -5,6 +5,7 @@ extern crate serde_derive; extern crate lazy_static; pub mod config; +pub mod debugger; pub mod notifier; pub mod server; pub mod util; diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index cab7616..3055569 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -13,73 +13,17 @@ use std::time::Instant; use crate::config::Config; // TODO: Add in remove_listener +use crate::debugger::DebuggerCmd; use crate::notifier::{add_listener, log_msg, LogLevel}; use crate::vimcodec::VimCodec; use futures::{SinkExt, StreamExt}; use tokio::net::TcpStream; -use tokio::sync::mpsc::{self, Sender}; +use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio_util::codec::Decoder; // TODO: Get some of this out of pub use and just in this module? -/// All debugger commands -#[derive(Clone, Debug, PartialEq)] -pub enum DebuggerCmd { - Run, - Breakpoint(FileLocation), - Unbreakpoint(FileLocation), - StepIn, - StepOver, - Continue, - Print(Variable), -} - -/// File location -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct FileLocation { - name: String, - line_num: u64, -} - -impl FileLocation { - pub fn new(name: String, line_num: u64) -> Self { - FileLocation { name, line_num } - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn line_num(&self) -> u64 { - self.line_num - } -} - -/// Variable name -#[derive(Clone, Debug)] -pub struct Variable { - name: String, -} - -impl Variable { - pub fn new(name: String) -> Self { - Variable { name } - } - - pub fn name(&self) -> &str { - &self.name - } -} - -impl PartialEq for Variable { - fn eq(&self, other: &Self) -> bool { - self.name == other.name - } -} - -impl Eq for Variable {} - /// All padre commands #[derive(Clone, Debug, PartialEq)] pub enum PadreCmd { @@ -147,15 +91,15 @@ impl PadreRequest { /// /// Normally kept simple with important information relegated to an event based notification. #[derive(Clone, Debug, PartialEq, Serialize)] -pub struct Response { +pub struct PadreResponse { id: u64, resp: serde_json::Value, } -impl Response { +impl PadreResponse { /// Create a response pub fn new(id: u64, resp: serde_json::Value) -> Self { - Response { id, resp } + PadreResponse { id, resp } } /// Return the response id @@ -196,32 +140,20 @@ impl Notification { } } -/// Data to be sent back to connection in the form of either a `Notification` or a `Response` +/// Data to be sent back to connection in the form of either a `Notification` or a +/// `PadreResponse` /// -/// A `Response` takes a u64 as the first argument to represent the id and a JSON object as -/// the second argument to represent the response. For example a response with an id of `1` +/// A `PadreResponse` takes a u64 as the first argument to represent the id and a JSON object +/// as the second argument to represent the response. For example a response with an id of `1` /// and a JSON object of `{"status":"OK"}` will be decoded by the `VIMCodec` as /// `[1,{"status":"OK"}]` and sent as a response to the requesting socket. /// #[derive(Clone, Debug, PartialEq, Serialize)] pub enum PadreSend { - Response(Response), + Response(PadreResponse), Notification(Notification), } -/// Debugger trait that implements the basics -pub trait DebuggerV1: Debug { - fn setup(&mut self); - fn teardown(&mut self); - fn run(&mut self, timeout: Instant); - fn breakpoint(&mut self, file_location: &FileLocation, timeout: Instant); - fn unbreakpoint(&mut self, file_location: &FileLocation, timeout: Instant); - fn step_in(&mut self, timeout: Instant); - fn step_over(&mut self, timeout: Instant); - fn continue_(&mut self, timeout: Instant); - fn print(&mut self, variable: &Variable, _timeout: Instant); -} - /// Process a TCP socket connection. /// /// Fully sets up a new socket connection including listening for requests and sending responses. @@ -230,42 +162,41 @@ pub fn process_connection(stream: TcpStream, debugger_queue_tx: Sender<(Debugger let config = Arc::new(Mutex::new(Config::new())); - let (mut request_tx, mut request_rx) = VimCodec::new(config.clone()).framed(stream).split(); + let (mut connection_tx, mut connection_rx) = + VimCodec::new(config.clone()).framed(stream).split(); - let (connection_tx, mut connection_rx) = mpsc::channel(1); + // Just here as an abstraction around the connection so that we can send both responses + // to requests and to notify of an event (debugger paused for example). + let (tx, mut rx) = mpsc::channel(1); - add_listener(connection_tx.clone(), addr.clone()); + add_listener(tx.clone(), addr.clone()); tokio::spawn(async move { - while let Some(msg) = connection_rx.next().await { - request_tx.send(msg).await.unwrap(); + while let Some(msg) = rx.next().await { + connection_tx.send(msg).await.unwrap(); } }); tokio::spawn(async move { - while let Some(req) = request_rx.next().await { + while let Some(req) = connection_rx.next().await { let resp = respond(req.unwrap(), debugger_queue_tx.clone(), config.clone()) .await .unwrap(); - connection_tx - .clone() - .send(PadreSend::Response(resp)) - .await - .unwrap(); + tx.clone().send(PadreSend::Response(resp)).await.unwrap(); } }); tokio::spawn(check_for_and_report_padre_updates()); } -/// Process a PadreRequest. +/// Process a PadreRequest and figure out the response. /// /// Forwards the request to the appropriate place to handle it and responds appropriately. async fn respond<'a>( request: PadreRequest, mut debugger_queue_tx: Sender<(DebuggerCmd, Instant)>, config: Arc>>, -) -> Result { +) -> Result { match request.cmd() { RequestCmd::PadreCmd(cmd) => { let json_response = match cmd { @@ -276,11 +207,11 @@ async fn respond<'a>( }; match json_response { - Ok(args) => Ok(Response::new(request.id(), args)), + Ok(args) => Ok(PadreResponse::new(request.id(), args)), Err(e) => { log_msg(LogLevel::ERROR, &format!("{}", e)); let resp = serde_json::json!({"status":"ERROR"}); - Ok(Response::new(request.id(), resp)) + Ok(PadreResponse::new(request.id(), resp)) } } } @@ -289,7 +220,7 @@ async fn respond<'a>( .send((cmd.clone(), *timeout)) .await .unwrap(); - Ok(Response::new( + Ok(PadreResponse::new( request.id(), serde_json::json!({"status":"OK"}), )) diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index 0d73c9c..cdca0af 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -8,9 +8,8 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use crate::config::Config; -use crate::server::{ - DebuggerCmd, FileLocation, PadreCmd, PadreRequest, PadreSend, RequestCmd, Variable, -}; +use crate::debugger::{DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +use crate::server::{PadreCmd, PadreRequest, PadreSend, RequestCmd}; use crate::util; use bytes::{Buf, BufMut, BytesMut}; @@ -309,7 +308,7 @@ impl<'a> Decoder for VimCodec<'a> { "run" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::Run, + DebuggerCmd::V1(DebuggerCmdV1::Run), Instant::now() + Duration::new( self.config @@ -324,7 +323,7 @@ impl<'a> Decoder for VimCodec<'a> { "stepOver" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::StepOver, + DebuggerCmd::V1(DebuggerCmdV1::StepOver), Instant::now() + Duration::new( self.config @@ -339,7 +338,7 @@ impl<'a> Decoder for VimCodec<'a> { "stepIn" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::StepIn, + DebuggerCmd::V1(DebuggerCmdV1::StepIn), Instant::now() + Duration::new( self.config @@ -354,7 +353,7 @@ impl<'a> Decoder for VimCodec<'a> { "continue" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::Continue, + DebuggerCmd::V1(DebuggerCmdV1::Continue), Instant::now() + Duration::new( self.config @@ -372,7 +371,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(fl) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::Breakpoint(fl), + DebuggerCmd::V1(DebuggerCmdV1::Breakpoint(fl)), Instant::now() + Duration::new( self.config @@ -393,7 +392,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(fl) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::Unbreakpoint(fl), + DebuggerCmd::V1(DebuggerCmdV1::Unbreakpoint(fl)), Instant::now() + Duration::new( self.config @@ -414,7 +413,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(v) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::Print(v), + DebuggerCmd::V1(DebuggerCmdV1::Print(v)), Instant::now() + Duration::new( self.config @@ -513,7 +512,9 @@ mod tests { use std::sync::{Arc, Mutex}; use crate::config::Config; - use crate::server::{DebuggerCmd, Notification, PadreCmd, PadreSend, RequestCmd, Response}; + use crate::server::{ + DebuggerCmd, Notification, PadreCmd, PadreResponse, PadreSend, RequestCmd, + }; use bytes::{BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder}; @@ -613,7 +614,7 @@ mod tests { let config = Arc::new(Mutex::new(Config::new())); let mut codec = super::VimCodec::new(config); - let resp = PadreSend::Response(Response::new(123, serde_json::json!({"ping":"pong"}))); + let resp = PadreSend::Response(PadreResponse::new(123, serde_json::json!({"ping":"pong"}))); let mut buf = BytesMut::new(); codec.encode(resp, &mut buf).unwrap(); diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index a2240fc..9f55291 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -9,11 +9,11 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; +use padre_core::debugger::{Debugger, DebuggerCmd, FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; -use padre_core::server::{DebuggerV1, FileLocation, Variable}; use futures::StreamExt; -use tokio::sync::mpsc; +use tokio::sync::mpsc::{self, Receiver}; #[derive(Debug)] pub struct ImplDebugger { @@ -30,13 +30,15 @@ impl ImplDebugger { } } -impl DebuggerV1 for ImplDebugger { - fn setup(&mut self) {} +impl Debugger for ImplDebugger { + fn setup_handler(&self, queue_rx: Receiver<(DebuggerCmd, Instant)>) {} fn teardown(&mut self) { exit(0); } +} +impl ImplDebugger { /// Run python and perform any setup necessary fn run(&mut self, _timeout: Instant) { match self.process.lock().unwrap().get_status() { @@ -158,10 +160,10 @@ impl DebuggerV1 for ImplDebugger { match index { Some(i) => { x.remove(i); - }, + } None => {} }; - }, + } None => {} }; diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 0b1eeb9..16f4b0a 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -12,8 +12,8 @@ use std::process::exit; use std::process::Stdio; use std::sync::{Arc, Mutex}; +use padre_core::debugger::{FileLocation, Variable}; use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; -use padre_core::server::{FileLocation, Variable}; #[cfg(not(test))] use padre_core::util::{file_exists, get_file_full_path}; use padre_core::util::{read_output, setup_stdin}; @@ -230,7 +230,7 @@ impl Process { } Message::Unbreakpoint(fl) => { Bytes::from(format!("clear {}:{}\n", fl.name(), fl.line_num())) - }, + } Message::StepIn => Bytes::from("step\n"), Message::StepOver => Bytes::from("next\n"), Message::Continue => Bytes::from("continue\n"), From 99d5e158b9855cac851cd3689dd3043a91b362f0 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 27 Feb 2020 21:28:48 +0000 Subject: [PATCH 14/23] Got Python debugger working again --- padre/core/src/debugger.rs | 79 ++++++++++++++++++++++++++ padre/debuggers/python/src/debugger.rs | 49 +++++++++++++--- 2 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 padre/core/src/debugger.rs diff --git a/padre/core/src/debugger.rs b/padre/core/src/debugger.rs new file mode 100644 index 0000000..fb77d6e --- /dev/null +++ b/padre/core/src/debugger.rs @@ -0,0 +1,79 @@ +//! Debugger Module +//! +//! Main module for handling the debuggers, defines the standard versioned debugger interfaces. + +use std::fmt::Debug; +use std::time::Instant; + +use tokio::sync::mpsc::Receiver; + +// TODO: Get some of this out of pub use and just in this module?? + +/// Debugger trait that implements the basics +pub trait Debugger: Debug { + fn setup_handler(&self, queue_rx: Receiver<(DebuggerCmd, Instant)>); + fn teardown(&mut self); +} + +/// All debugger commands +#[derive(Clone, Debug, PartialEq)] +pub enum DebuggerCmd { + V1(DebuggerCmdV1), +} + +/// All debugger commands +#[derive(Clone, Debug, PartialEq)] +pub enum DebuggerCmdV1 { + Run, + Breakpoint(FileLocation), + Unbreakpoint(FileLocation), + StepIn, + StepOver, + Continue, + Print(Variable), +} + +/// File location +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct FileLocation { + name: String, + line_num: u64, +} + +impl FileLocation { + pub fn new(name: String, line_num: u64) -> Self { + FileLocation { name, line_num } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn line_num(&self) -> u64 { + self.line_num + } +} + +/// Variable name +#[derive(Clone, Debug)] +pub struct Variable { + name: String, +} + +impl Variable { + pub fn new(name: String) -> Self { + Variable { name } + } + + pub fn name(&self) -> &str { + &self.name + } +} + +impl PartialEq for Variable { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Eq for Variable {} diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 9f55291..ff57897 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; -use padre_core::debugger::{Debugger, DebuggerCmd, FileLocation, Variable}; +use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; use futures::StreamExt; @@ -17,28 +17,63 @@ use tokio::sync::mpsc::{self, Receiver}; #[derive(Debug)] pub struct ImplDebugger { - process: Arc>, - pending_breakpoints: Option>, + debugger_cmd: String, + run_cmd: Vec, } impl ImplDebugger { pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { ImplDebugger { - process: Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))), - pending_breakpoints: Some(vec![]), + debugger_cmd, + run_cmd, } } } impl Debugger for ImplDebugger { - fn setup_handler(&self, queue_rx: Receiver<(DebuggerCmd, Instant)>) {} + #[allow(unreachable_patterns)] + fn setup_handler(&self, mut queue_rx: Receiver<(DebuggerCmd, Instant)>) { + let debugger_cmd = self.debugger_cmd.clone(); + let run_cmd = self.run_cmd.clone(); + + tokio::spawn(async move { + let mut debugger = PythonDebugger::new(debugger_cmd, run_cmd); + + while let Some(cmd) = queue_rx.next().await { + match cmd.0 { + DebuggerCmd::V1(v1cmd) => match v1cmd { + DebuggerCmdV1::Run => debugger.run(cmd.1), + DebuggerCmdV1::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), + DebuggerCmdV1::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), + DebuggerCmdV1::StepIn => debugger.step_in(cmd.1), + DebuggerCmdV1::StepOver => debugger.step_over(cmd.1), + DebuggerCmdV1::Continue => debugger.continue_(cmd.1), + DebuggerCmdV1::Print(v) => debugger.print(&v, cmd.1), + }, + _ => unimplemented!(), + }; + } + }); + } fn teardown(&mut self) { exit(0); } } -impl ImplDebugger { +struct PythonDebugger { + process: Arc>, + pending_breakpoints: Option>, +} + +impl PythonDebugger { + pub fn new(debugger_cmd: String, run_cmd: Vec) -> PythonDebugger { + PythonDebugger { + process: Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))), + pending_breakpoints: Some(vec![]), + } + } + /// Run python and perform any setup necessary fn run(&mut self, _timeout: Instant) { match self.process.lock().unwrap().get_status() { From ec4f247e44ea40bc66e2cc163fe5cc8c5eefb339 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Thu, 27 Feb 2020 22:09:37 +0000 Subject: [PATCH 15/23] Tests fixed --- padre/cli/src/debugger.rs | 14 ++++---------- padre/core/src/server.rs | 11 ++++++----- padre/core/src/vimcodec.rs | 11 +++++------ padre/debuggers/python/src/debugger.rs | 4 +++- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index a6b3094..6785b6f 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -223,21 +223,15 @@ fn get_file_type(cmd: &str) -> String { #[cfg(test)] mod tests { fn is_file_executable() { - assert_eq!( - true, - super::file_is_binary_executable("../test_files/node").await - ); + assert_eq!(true, super::file_is_binary_executable("../test_files/node")); assert_eq!( false, - super::file_is_binary_executable("../test_files/test_node.js").await + super::file_is_binary_executable("../test_files/test_node.js") ); } fn is_file_text() { - assert_eq!(false, super::file_is_text("../test_files/node").await); - assert_eq!( - true, - super::file_is_text("../test_files/test_node.js").await - ); + assert_eq!(false, super::file_is_text("../test_files/node")); + assert_eq!(true, super::file_is_text("../test_files/test_node.js")); } } diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index 3055569..13ff4fd 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -19,7 +19,7 @@ use crate::vimcodec::VimCodec; use futures::{SinkExt, StreamExt}; use tokio::net::TcpStream; -use tokio::sync::mpsc::{self, Receiver, Sender}; +use tokio::sync::mpsc::{self, Sender}; use tokio_util::codec::Decoder; // TODO: Get some of this out of pub use and just in this module? @@ -42,15 +42,16 @@ pub enum PadreCmd { /// /// ``` /// use std::time::{Duration, Instant}; -/// use padre_core::server::{RequestCmd, DebuggerCmd, FileLocation, Variable}; +/// use padre_core::debugger::{DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +/// use padre_core::server::RequestCmd; /// -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Run, Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run), Instant::now() + Duration::new(5,0)); /// /// let file_location = FileLocation::new("test.c".to_string(), 12); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Breakpoint(file_location), Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Breakpoint(file_location)), Instant::now() + Duration::new(5,0)); /// /// let variable = Variable::new("abc".to_string()); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Print(variable), Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Print(variable)), Instant::now() + Duration::new(5,0)); /// ``` #[derive(Clone, Debug, PartialEq)] pub enum RequestCmd { diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index cdca0af..6060a2a 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -512,9 +512,8 @@ mod tests { use std::sync::{Arc, Mutex}; use crate::config::Config; - use crate::server::{ - DebuggerCmd, Notification, PadreCmd, PadreResponse, PadreSend, RequestCmd, - }; + use crate::debugger::{DebuggerCmd, DebuggerCmdV1}; + use crate::server::{Notification, PadreCmd, PadreResponse, PadreSend, RequestCmd}; use bytes::{BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder}; @@ -535,7 +534,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::Run, *cmd); + assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); } _ => panic!("Wrong command type"), } @@ -557,7 +556,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::Run, *cmd); + assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); } _ => panic!("Wrong command type"), } @@ -603,7 +602,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::Run, *cmd); + assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); } _ => panic!("Wrong command type"), } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index ff57897..d9a9fc7 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -50,7 +50,9 @@ impl Debugger for ImplDebugger { DebuggerCmdV1::Continue => debugger.continue_(cmd.1), DebuggerCmdV1::Print(v) => debugger.print(&v, cmd.1), }, - _ => unimplemented!(), + _ => { + log_msg(LogLevel::WARN, "Got a command that wasn't understood"); + } }; } }); From 9f918211b629db32157b1083239754269ddf8722 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Fri, 28 Feb 2020 00:47:58 +0000 Subject: [PATCH 16/23] Finish off teardown bits of latest refactor --- padre/Cargo.lock | 8 +-- padre/cli/Cargo.toml | 4 +- padre/cli/src/debugger.rs | 41 +----------- padre/cli/src/main.rs | 89 +++++++++++++------------- padre/core/Cargo.toml | 2 +- padre/core/src/debugger.rs | 7 +- padre/core/src/server.rs | 8 +-- padre/core/src/vimcodec.rs | 24 +++---- padre/debuggers/lldb/Cargo.toml | 2 +- padre/debuggers/node/Cargo.toml | 2 +- padre/debuggers/python/Cargo.toml | 2 +- padre/debuggers/python/src/debugger.rs | 35 ++++++---- 12 files changed, 99 insertions(+), 125 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 8336ab5..5a01d37 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +checksum = "b34bee1facdc352fba10c9c58b654e6ecb6a2250167772bf86071f7c5f2f5061" dependencies = [ "bytes", "fnv", @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b1e7ed7d5d4c2af3d999904b0eebe76544897cdbfb2b9684bed2174ab20f7c" +checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ "proc-macro2", "quote", diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index a8993bf..ddeac07 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -14,12 +14,12 @@ python = ["padre_python"] [dependencies] clap = "2.32.0" -futures = "0.3.1" +futures = "0.3.4" padre_core = { path = "../core", version = "0.2.0" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.11", features = [ +tokio = { version = "0.2.12", features = [ "io-util", "io-std", "macros", diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index 6785b6f..e7436e5 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -28,45 +28,6 @@ enum DebuggerType { Python, } -// #[derive(Debug)] -// pub struct Debugger { -// debugger: Arc>, -// } -// -// impl Debugger { -// pub fn new( -// impl_debugger: Arc>, -// mut queue_rx: Receiver<(DebuggerCmd, Instant)>, -// ) -> Debugger { -// let debugger = Debugger { -// debugger: impl_debugger.clone(), -// }; -// -// let queue_processing_debugger = impl_debugger.clone(); -// -// tokio::spawn(async move { -// while let Some(cmd) = queue_rx.next().await { -// let mut debugger = queue_processing_debugger.lock().unwrap(); -// match cmd.0 { -// DebuggerCmd::Run => debugger.run(cmd.1), -// DebuggerCmd::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), -// DebuggerCmd::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), -// DebuggerCmd::StepIn => debugger.step_in(cmd.1), -// DebuggerCmd::StepOver => debugger.step_over(cmd.1), -// DebuggerCmd::Continue => debugger.continue_(cmd.1), -// DebuggerCmd::Print(v) => debugger.print(&v, cmd.1), -// }; -// } -// }); -// -// debugger -// } -// -// pub fn stop(&mut self) { -// self.debugger.lock().unwrap().teardown(); -// } -// } - /// Get the debugger implementation /// /// If the debugger type is not specified it will try it's best to guess what kind of debugger to @@ -222,6 +183,7 @@ fn get_file_type(cmd: &str) -> String { #[cfg(test)] mod tests { + #[test] fn is_file_executable() { assert_eq!(true, super::file_is_binary_executable("../test_files/node")); assert_eq!( @@ -230,6 +192,7 @@ mod tests { ); } + #[test] fn is_file_text() { assert_eq!(false, super::file_is_text("../test_files/node")); assert_eq!(true, super::file_is_text("../test_files/test_node.js")); diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index 23951e1..ddfa85d 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -21,17 +21,16 @@ use std::io; use std::net::SocketAddr; use std::process::exit; -use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::time::{Duration, Instant}; use clap::{App, Arg, ArgMatches}; use futures::prelude::*; use tokio::net::TcpListener; -use tokio::runtime::Runtime; use tokio::signal::unix::{signal, SignalKind}; -use tokio::sync::mpsc; -use tokio::time::delay_for; +use tokio::sync::mpsc::{self, Sender}; +use tokio::time::delay_until; +use padre_core::debugger::{DebuggerCmd, DebuggerCmdBasic}; use padre_core::server; use padre_core::util; @@ -89,17 +88,16 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { return format!("{}:{}", host, port).parse::().unwrap(); } -// fn exit_padre(debugger: Arc>) { -// let when = Duration::new(5, 0); -// -// tokio::spawn(async move { -// delay_for(when).await; -// println!("Timed out exiting!"); -// exit(-1); -// }); -// -// debugger.lock().unwrap().stop(); -// } +fn exit_padre(mut debugger_queue_tx: Sender<(DebuggerCmd, Instant)>) { + tokio::spawn(async move { + let instant = Instant::now() + Duration::new(5,0); + let command = (DebuggerCmd::Basic(DebuggerCmdBasic::Exit), instant); + debugger_queue_tx.send(command).await.unwrap(); + delay_until(tokio::time::Instant::from_std(instant)).await; + println!("Timed out exiting!"); + exit(-1); + }); +} async fn run_padre() -> io::Result<()> { let args = get_app_args(); @@ -114,12 +112,12 @@ async fn run_padre() -> io::Result<()> { // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in // the case of multiple connections but is there a way around it? - let debugger = Arc::new(Mutex::new(create_debugger( + let _debugger = create_debugger( args.value_of("debugger"), args.value_of("type"), debug_cmd, debugger_queue_rx, - ))); + ); let connection_addr = get_connection(&args); let mut socket = TcpListener::bind(&connection_addr) @@ -134,32 +132,35 @@ async fn run_padre() -> io::Result<()> { // TODO: Merge the following into one lot of signals when we know how to - // let debugger_signals = debugger.clone(); - // tokio::spawn(async move { - // let mut signals = signal(SignalKind::interrupt()).unwrap(); - - // while let Some(_) = signals.recv().await { - // exit_padre(debugger_signals.clone()); - // } - // }); - - // let debugger_signals = debugger.clone(); - // tokio::spawn(async move { - // let mut signals = signal(SignalKind::quit()).unwrap(); - - // while let Some(_) = signals.recv().await { - // exit_padre(debugger_signals.clone()); - // } - // }); - - // let debugger_signals = debugger.clone(); - // tokio::spawn(async move { - // let mut signals = signal(SignalKind::terminate()).unwrap(); - - // while let Some(_) = signals.recv().await { - // exit_padre(debugger_signals.clone()); - // } - // }); + let debugger_signals_queue_tx = debugger_queue_tx.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::interrupt()).unwrap(); + let debugger_signals_queue_tx = debugger_signals_queue_tx.clone(); + + while let Some(_) = signals.recv().await { + exit_padre(debugger_signals_queue_tx.clone()); + } + }); + + let debugger_signals_queue_tx = debugger_queue_tx.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::quit()).unwrap(); + let debugger_signals_queue_tx = debugger_signals_queue_tx.clone(); + + while let Some(_) = signals.recv().await { + exit_padre(debugger_signals_queue_tx.clone()); + } + }); + + let debugger_signals_queue_tx = debugger_queue_tx.clone(); + tokio::spawn(async move { + let mut signals = signal(SignalKind::terminate()).unwrap(); + let debugger_signals_queue_tx = debugger_signals_queue_tx.clone(); + + while let Some(_) = signals.recv().await { + exit_padre(debugger_signals_queue_tx.clone()); + } + }); while let Some(Ok(stream)) = incoming.next().await { let debugger_queue_tx = debugger_queue_tx.clone(); diff --git a/padre/core/Cargo.toml b/padre/core/Cargo.toml index 128ac6d..422028a 100644 --- a/padre/core/Cargo.toml +++ b/padre/core/Cargo.toml @@ -18,5 +18,5 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.11", features = [] } +tokio = { version = "0.2.12", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/core/src/debugger.rs b/padre/core/src/debugger.rs index fb77d6e..338677e 100644 --- a/padre/core/src/debugger.rs +++ b/padre/core/src/debugger.rs @@ -12,19 +12,20 @@ use tokio::sync::mpsc::Receiver; /// Debugger trait that implements the basics pub trait Debugger: Debug { fn setup_handler(&self, queue_rx: Receiver<(DebuggerCmd, Instant)>); - fn teardown(&mut self); } /// All debugger commands #[derive(Clone, Debug, PartialEq)] pub enum DebuggerCmd { - V1(DebuggerCmdV1), + Basic(DebuggerCmdBasic), } /// All debugger commands #[derive(Clone, Debug, PartialEq)] -pub enum DebuggerCmdV1 { +pub enum DebuggerCmdBasic { Run, + Exit, + Interrupt, Breakpoint(FileLocation), Unbreakpoint(FileLocation), StepIn, diff --git a/padre/core/src/server.rs b/padre/core/src/server.rs index 13ff4fd..eb9ece0 100644 --- a/padre/core/src/server.rs +++ b/padre/core/src/server.rs @@ -42,16 +42,16 @@ pub enum PadreCmd { /// /// ``` /// use std::time::{Duration, Instant}; -/// use padre_core::debugger::{DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +/// use padre_core::debugger::{DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; /// use padre_core::server::RequestCmd; /// -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Run), Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Basic(DebuggerCmdBasic::Run), Instant::now() + Duration::new(5,0)); /// /// let file_location = FileLocation::new("test.c".to_string(), 12); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Breakpoint(file_location)), Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Basic(DebuggerCmdBasic::Breakpoint(file_location)), Instant::now() + Duration::new(5,0)); /// /// let variable = Variable::new("abc".to_string()); -/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::V1(DebuggerCmdV1::Print(variable)), Instant::now() + Duration::new(5,0)); +/// let command = RequestCmd::DebuggerCmd(DebuggerCmd::Basic(DebuggerCmdBasic::Print(variable)), Instant::now() + Duration::new(5,0)); /// ``` #[derive(Clone, Debug, PartialEq)] pub enum RequestCmd { diff --git a/padre/core/src/vimcodec.rs b/padre/core/src/vimcodec.rs index 6060a2a..37a01ec 100644 --- a/padre/core/src/vimcodec.rs +++ b/padre/core/src/vimcodec.rs @@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use crate::config::Config; -use crate::debugger::{DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +use crate::debugger::{DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; use crate::server::{PadreCmd, PadreRequest, PadreSend, RequestCmd}; use crate::util; @@ -308,7 +308,7 @@ impl<'a> Decoder for VimCodec<'a> { "run" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::Run), + DebuggerCmd::Basic(DebuggerCmdBasic::Run), Instant::now() + Duration::new( self.config @@ -323,7 +323,7 @@ impl<'a> Decoder for VimCodec<'a> { "stepOver" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::StepOver), + DebuggerCmd::Basic(DebuggerCmdBasic::StepOver), Instant::now() + Duration::new( self.config @@ -338,7 +338,7 @@ impl<'a> Decoder for VimCodec<'a> { "stepIn" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::StepIn), + DebuggerCmd::Basic(DebuggerCmdBasic::StepIn), Instant::now() + Duration::new( self.config @@ -353,7 +353,7 @@ impl<'a> Decoder for VimCodec<'a> { "continue" => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::Continue), + DebuggerCmd::Basic(DebuggerCmdBasic::Continue), Instant::now() + Duration::new( self.config @@ -371,7 +371,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(fl) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::Breakpoint(fl)), + DebuggerCmd::Basic(DebuggerCmdBasic::Breakpoint(fl)), Instant::now() + Duration::new( self.config @@ -392,7 +392,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(fl) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::Unbreakpoint(fl)), + DebuggerCmd::Basic(DebuggerCmdBasic::Unbreakpoint(fl)), Instant::now() + Duration::new( self.config @@ -413,7 +413,7 @@ impl<'a> Decoder for VimCodec<'a> { Some(v) => Ok(Some(PadreRequest::new( id, RequestCmd::DebuggerCmd( - DebuggerCmd::V1(DebuggerCmdV1::Print(v)), + DebuggerCmd::Basic(DebuggerCmdBasic::Print(v)), Instant::now() + Duration::new( self.config @@ -512,7 +512,7 @@ mod tests { use std::sync::{Arc, Mutex}; use crate::config::Config; - use crate::debugger::{DebuggerCmd, DebuggerCmdV1}; + use crate::debugger::{DebuggerCmd, DebuggerCmdBasic}; use crate::server::{Notification, PadreCmd, PadreResponse, PadreSend, RequestCmd}; use bytes::{BufMut, BytesMut}; @@ -534,7 +534,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); + assert_eq!(DebuggerCmd::Basic(DebuggerCmdBasic::Run), *cmd); } _ => panic!("Wrong command type"), } @@ -556,7 +556,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); + assert_eq!(DebuggerCmd::Basic(DebuggerCmdBasic::Run), *cmd); } _ => panic!("Wrong command type"), } @@ -602,7 +602,7 @@ mod tests { match padre_request.cmd() { RequestCmd::DebuggerCmd(cmd, _) => { - assert_eq!(DebuggerCmd::V1(DebuggerCmdV1::Run), *cmd); + assert_eq!(DebuggerCmd::Basic(DebuggerCmdBasic::Run), *cmd); } _ => panic!("Wrong command type"), } diff --git a/padre/debuggers/lldb/Cargo.toml b/padre/debuggers/lldb/Cargo.toml index a83cfc7..8583e1d 100644 --- a/padre/debuggers/lldb/Cargo.toml +++ b/padre/debuggers/lldb/Cargo.toml @@ -15,5 +15,5 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.11", features = [] } +tokio = { version = "0.2.12", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/debuggers/node/Cargo.toml b/padre/debuggers/node/Cargo.toml index 287c023..8837590 100644 --- a/padre/debuggers/node/Cargo.toml +++ b/padre/debuggers/node/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.1.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = { version = "0.2.11", features = [] } +tokio = { version = "0.2.12", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } tungstenite = "0.9.2" url = "2.1.0" diff --git a/padre/debuggers/python/Cargo.toml b/padre/debuggers/python/Cargo.toml index 6ca705c..93ab616 100644 --- a/padre/debuggers/python/Cargo.toml +++ b/padre/debuggers/python/Cargo.toml @@ -15,4 +15,4 @@ futures = "0.3.1" lazy_static = "1.3.0" regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } -tokio = { version = "0.2.11", features = [] } +tokio = { version = "0.2.12", features = [] } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index d9a9fc7..376b95f 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; -use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdV1, FileLocation, Variable}; +use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; use futures::StreamExt; @@ -41,25 +41,28 @@ impl Debugger for ImplDebugger { while let Some(cmd) = queue_rx.next().await { match cmd.0 { - DebuggerCmd::V1(v1cmd) => match v1cmd { - DebuggerCmdV1::Run => debugger.run(cmd.1), - DebuggerCmdV1::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), - DebuggerCmdV1::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), - DebuggerCmdV1::StepIn => debugger.step_in(cmd.1), - DebuggerCmdV1::StepOver => debugger.step_over(cmd.1), - DebuggerCmdV1::Continue => debugger.continue_(cmd.1), - DebuggerCmdV1::Print(v) => debugger.print(&v, cmd.1), + DebuggerCmd::Basic(v1cmd) => match v1cmd { + DebuggerCmdBasic::Run => debugger.run(cmd.1), + DebuggerCmdBasic::Interrupt => debugger.interrupt(), + DebuggerCmdBasic::Exit => { + debugger.teardown(); + break + } + DebuggerCmdBasic::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), + DebuggerCmdBasic::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), + DebuggerCmdBasic::StepIn => debugger.step_in(cmd.1), + DebuggerCmdBasic::StepOver => debugger.step_over(cmd.1), + DebuggerCmdBasic::Continue => debugger.continue_(cmd.1), + DebuggerCmdBasic::Print(v) => debugger.print(&v, cmd.1), }, _ => { log_msg(LogLevel::WARN, "Got a command that wasn't understood"); } }; } - }); - } - fn teardown(&mut self) { - exit(0); + exit(0); + }); } } @@ -76,6 +79,9 @@ impl PythonDebugger { } } + fn teardown(&mut self) { + } + /// Run python and perform any setup necessary fn run(&mut self, _timeout: Instant) { match self.process.lock().unwrap().get_status() { @@ -119,6 +125,9 @@ impl PythonDebugger { }); } + fn interrupt(&mut self) { + } + fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { let full_file_path = PathBuf::from(format!("{}", file_location.name())); From 4750f936b531990b8aa6a4009e7fa23556889cb5 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Fri, 28 Feb 2020 08:20:14 +0000 Subject: [PATCH 17/23] Removed non-useful Arc/Mutex around Python process --- padre/debuggers/python/src/debugger.rs | 72 ++++++++++---------------- padre/debuggers/python/src/process.rs | 4 -- 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 376b95f..48a3a9c 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -5,7 +5,6 @@ use std::path::PathBuf; use std::process::exit; -use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; @@ -41,7 +40,7 @@ impl Debugger for ImplDebugger { while let Some(cmd) = queue_rx.next().await { match cmd.0 { - DebuggerCmd::Basic(v1cmd) => match v1cmd { + DebuggerCmd::Basic(basic_cmd) => match basic_cmd { DebuggerCmdBasic::Run => debugger.run(cmd.1), DebuggerCmdBasic::Interrupt => debugger.interrupt(), DebuggerCmdBasic::Exit => { @@ -67,14 +66,14 @@ impl Debugger for ImplDebugger { } struct PythonDebugger { - process: Arc>, + process: Process, pending_breakpoints: Option>, } impl PythonDebugger { pub fn new(debugger_cmd: String, run_cmd: Vec) -> PythonDebugger { PythonDebugger { - process: Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))), + process: Process::new(debugger_cmd, run_cmd), pending_breakpoints: Some(vec![]), } } @@ -84,7 +83,7 @@ impl PythonDebugger { /// Run python and perform any setup necessary fn run(&mut self, _timeout: Instant) { - match self.process.lock().unwrap().get_status() { + match self.process.get_status() { PDBStatus::None => {} _ => { let msg = "Process already running, not launching"; @@ -98,31 +97,23 @@ impl PythonDebugger { let pending_breakpoints = self.pending_breakpoints.take(); - let process = self.process.clone(); - - tokio::spawn(async move { - match pending_breakpoints { - Some(pbs) => { - for pb in pbs { - // Check we're actually listening - let (tx, mut rx) = mpsc::channel(1); - process.lock().unwrap().add_awakener(tx); - rx.next().await.unwrap(); - process.lock().unwrap().drop_awakener(); - - // And send the breakpoint info - process.lock().unwrap().send_msg(Message::Breakpoint(pb)); - } + match pending_breakpoints { + Some(pbs) => { + for pb in pbs { + // TODO: Check we're actually listening + // let (tx, mut rx) = mpsc::channel(1); + // process.lock().unwrap().add_awakener(tx); + // rx.next().await.unwrap(); + // process.lock().unwrap().drop_awakener(); + + // And send the breakpoint info + self.process.send_msg(Message::Breakpoint(pb)); } - None => {} - }; - }); - - let process = self.process.clone(); + } + None => {} + }; - tokio::spawn(async move { - process.lock().unwrap().run(); - }); + self.process.run(); } fn interrupt(&mut self) { @@ -148,7 +139,7 @@ impl PythonDebugger { ); // If not started yet add as a pending breakpoint that will get set during run period. - match self.process.lock().unwrap().get_status() { + match self.process.get_status() { PDBStatus::None => { match self.pending_breakpoints { Some(ref mut x) => x.push(file_location.clone()), @@ -169,10 +160,7 @@ impl PythonDebugger { _ => {} } - self.process - .lock() - .unwrap() - .send_msg(Message::Breakpoint(file_location)); + self.process.send_msg(Message::Breakpoint(file_location)); } fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { @@ -193,7 +181,7 @@ impl PythonDebugger { ); // If not started yet remove any pending breakpoint that will get set during run period. - match self.process.lock().unwrap().get_status() { + match self.process.get_status() { PDBStatus::None => { match self.pending_breakpoints { Some(ref mut x) => { @@ -227,10 +215,7 @@ impl PythonDebugger { _ => {} } - self.process - .lock() - .unwrap() - .send_msg(Message::Unbreakpoint(file_location)); + self.process.send_msg(Message::Unbreakpoint(file_location)); } fn step_in(&mut self, _timeout: Instant) { @@ -239,7 +224,7 @@ impl PythonDebugger { // None => {} //}; - self.process.lock().unwrap().send_msg(Message::StepIn); + self.process.send_msg(Message::StepIn); } fn step_over(&mut self, _timeout: Instant) { @@ -248,7 +233,7 @@ impl PythonDebugger { // None => {} //}; - self.process.lock().unwrap().send_msg(Message::StepOver); + self.process.send_msg(Message::StepOver); } fn continue_(&mut self, _timeout: Instant) { @@ -257,7 +242,7 @@ impl PythonDebugger { // None => {} //}; - self.process.lock().unwrap().send_msg(Message::Continue); + self.process.send_msg(Message::Continue); } fn print(&mut self, variable: &Variable, _timeout: Instant) { @@ -266,9 +251,6 @@ impl PythonDebugger { // None => {} //}; - self.process - .lock() - .unwrap() - .send_msg(Message::PrintVariable(variable.clone())); + self.process.send_msg(Message::PrintVariable(variable.clone())); } } diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index 16f4b0a..b294a59 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -318,10 +318,6 @@ impl Analyser { from += print_cmd_size + 2; } - println!("s: {}", s); - println!("from: {}", from); - println!("to: {}", to); - let pdb_length = "(Pdb) ".len(); if to >= pdb_length && &s[to - pdb_length..to] == "(Pdb) " { to -= pdb_length; From f2e41b7522d6ea0a77ec2c454e398b466f7afc37 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sun, 1 Mar 2020 10:18:10 +0000 Subject: [PATCH 18/23] Reworked Python such that it is now working --- padre/cli/src/main.rs | 2 +- padre/debuggers/python/src/debugger.rs | 76 +++++++++++-------- padre/debuggers/python/src/process.rs | 100 +++++++++++-------------- 3 files changed, 91 insertions(+), 87 deletions(-) diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index ddfa85d..56423b1 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -90,7 +90,7 @@ fn get_connection(args: &ArgMatches) -> SocketAddr { fn exit_padre(mut debugger_queue_tx: Sender<(DebuggerCmd, Instant)>) { tokio::spawn(async move { - let instant = Instant::now() + Duration::new(5,0); + let instant = Instant::now() + Duration::new(5, 0); let command = (DebuggerCmd::Basic(DebuggerCmdBasic::Exit), instant); debugger_queue_tx.send(command).await.unwrap(); delay_until(tokio::time::Instant::from_std(instant)).await; diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index 48a3a9c..d232e34 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -5,6 +5,7 @@ use std::path::PathBuf; use std::process::exit; +use std::sync::{Arc, Mutex}; use std::time::Instant; use super::process::{Message, PDBStatus, Process}; @@ -12,7 +13,7 @@ use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdBasic, FileLocation use padre_core::notifier::{log_msg, LogLevel}; use futures::StreamExt; -use tokio::sync::mpsc::{self, Receiver}; +use tokio::sync::{mpsc, oneshot}; #[derive(Debug)] pub struct ImplDebugger { @@ -31,7 +32,7 @@ impl ImplDebugger { impl Debugger for ImplDebugger { #[allow(unreachable_patterns)] - fn setup_handler(&self, mut queue_rx: Receiver<(DebuggerCmd, Instant)>) { + fn setup_handler(&self, mut queue_rx: mpsc::Receiver<(DebuggerCmd, Instant)>) { let debugger_cmd = self.debugger_cmd.clone(); let run_cmd = self.run_cmd.clone(); @@ -45,7 +46,7 @@ impl Debugger for ImplDebugger { DebuggerCmdBasic::Interrupt => debugger.interrupt(), DebuggerCmdBasic::Exit => { debugger.teardown(); - break + break; } DebuggerCmdBasic::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), DebuggerCmdBasic::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), @@ -66,28 +67,24 @@ impl Debugger for ImplDebugger { } struct PythonDebugger { - process: Process, + process: Arc>, pending_breakpoints: Option>, } impl PythonDebugger { pub fn new(debugger_cmd: String, run_cmd: Vec) -> PythonDebugger { PythonDebugger { - process: Process::new(debugger_cmd, run_cmd), + process: Arc::new(Mutex::new(Process::new(debugger_cmd, run_cmd))), pending_breakpoints: Some(vec![]), } } - fn teardown(&mut self) { - } - /// Run python and perform any setup necessary fn run(&mut self, _timeout: Instant) { - match self.process.get_status() { + match self.process.lock().unwrap().get_status() { PDBStatus::None => {} _ => { let msg = "Process already running, not launching"; - eprintln!("{}", msg); log_msg(LogLevel::WARN, msg); return; } @@ -97,26 +94,30 @@ impl PythonDebugger { let pending_breakpoints = self.pending_breakpoints.take(); + let (tx, rx) = oneshot::channel(); + match pending_breakpoints { Some(pbs) => { - for pb in pbs { - // TODO: Check we're actually listening - // let (tx, mut rx) = mpsc::channel(1); - // process.lock().unwrap().add_awakener(tx); - // rx.next().await.unwrap(); - // process.lock().unwrap().drop_awakener(); - - // And send the breakpoint info - self.process.send_msg(Message::Breakpoint(pb)); - } + let process = self.process.clone(); + tokio::spawn(async move { + rx.await.unwrap(); + for pb in pbs { + let (tx, rx) = oneshot::channel(); + process.lock().unwrap().send_msg(Message::Breakpoint(pb), Some(tx)); + rx.await.unwrap(); + } + }); } None => {} }; - self.process.run(); + self.process.lock().unwrap().run(Some(tx)); } - fn interrupt(&mut self) { + fn interrupt(&mut self) {} + + fn teardown(&mut self) { + self.process.lock().unwrap().stop(); } fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { @@ -139,7 +140,7 @@ impl PythonDebugger { ); // If not started yet add as a pending breakpoint that will get set during run period. - match self.process.get_status() { + match self.process.lock().unwrap().get_status() { PDBStatus::None => { match self.pending_breakpoints { Some(ref mut x) => x.push(file_location.clone()), @@ -160,7 +161,10 @@ impl PythonDebugger { _ => {} } - self.process.send_msg(Message::Breakpoint(file_location)); + self.process + .lock() + .unwrap() + .send_msg(Message::Breakpoint(file_location), None); } fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { @@ -181,7 +185,7 @@ impl PythonDebugger { ); // If not started yet remove any pending breakpoint that will get set during run period. - match self.process.get_status() { + match self.process.lock().unwrap().get_status() { PDBStatus::None => { match self.pending_breakpoints { Some(ref mut x) => { @@ -215,7 +219,10 @@ impl PythonDebugger { _ => {} } - self.process.send_msg(Message::Unbreakpoint(file_location)); + self.process + .lock() + .unwrap() + .send_msg(Message::Unbreakpoint(file_location), None); } fn step_in(&mut self, _timeout: Instant) { @@ -224,7 +231,7 @@ impl PythonDebugger { // None => {} //}; - self.process.send_msg(Message::StepIn); + self.process.lock().unwrap().send_msg(Message::StepIn, None); } fn step_over(&mut self, _timeout: Instant) { @@ -233,7 +240,10 @@ impl PythonDebugger { // None => {} //}; - self.process.send_msg(Message::StepOver); + self.process + .lock() + .unwrap() + .send_msg(Message::StepOver, None); } fn continue_(&mut self, _timeout: Instant) { @@ -242,7 +252,10 @@ impl PythonDebugger { // None => {} //}; - self.process.send_msg(Message::Continue); + self.process + .lock() + .unwrap() + .send_msg(Message::Continue, None); } fn print(&mut self, variable: &Variable, _timeout: Instant) { @@ -251,6 +264,9 @@ impl PythonDebugger { // None => {} //}; - self.process.send_msg(Message::PrintVariable(variable.clone())); + self.process + .lock() + .unwrap() + .send_msg(Message::PrintVariable(variable.clone()), None); } } diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index b294a59..bff603e 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -23,7 +23,7 @@ use futures::prelude::*; use regex::Regex; use tokio::io::BufReader; use tokio::process::{Child, ChildStdout, Command}; -use tokio::sync::mpsc::Sender; +use tokio::sync::{mpsc, oneshot}; /// Messages that can be sent to PDB for processing #[derive(Debug, Clone, Eq, PartialEq)] @@ -130,7 +130,7 @@ pub struct Process { debugger_cmd: Option, run_cmd: Option>, process: Option, - stdin_tx: Option>, + stdin_tx: Option>, analyser: Arc>, } @@ -153,7 +153,9 @@ impl Process { /// - Sets up a `ReadOutput` from `util.rs` in order to read stdout and stderr; /// - Sets up a thread to read stdin and forward it onto Python interpreter; /// - Checks that Python and the program to be ran both exist, otherwise panics. - pub fn run(&mut self) { + pub fn run(&mut self, tx_done: Option>) { + self.analyser.lock().unwrap().analyse_message(Message::Launching, tx_done); + let debugger_cmd = self.debugger_cmd.take().unwrap(); let run_cmd = self.run_cmd.take().unwrap(); @@ -199,17 +201,8 @@ impl Process { self.process = Some(process); } - /// Adds a Sender object that gets awoken when we are listening. - /// - /// Should only add a sender when we're about to go into or currently in the - /// processing status otherwise this will never wake up. - pub fn add_awakener(&self, sender: Sender) { - self.analyser.lock().unwrap().add_awakener(sender); - } - - /// Drop the awakener - pub fn drop_awakener(&mut self) { - self.analyser.lock().unwrap().drop_awakener(); + pub fn stop(&mut self) { + self.process = None; } /// Check the current status, either not running (None), running something @@ -219,27 +212,29 @@ impl Process { } /// Send a message to write to stdin - pub fn send_msg(&mut self, message: Message) { + pub fn send_msg(&mut self, message: Message, tx_done: Option>) { let tx = self.stdin_tx.clone(); let analyser = self.analyser.clone(); + let msg = match &message { + Message::Breakpoint(fl) => { + Bytes::from(format!("break {}:{}\n", fl.name(), fl.line_num())) + } + Message::Unbreakpoint(fl) => { + Bytes::from(format!("clear {}:{}\n", fl.name(), fl.line_num())) + } + Message::StepIn => Bytes::from("step\n"), + Message::StepOver => Bytes::from("next\n"), + Message::Continue => Bytes::from("continue\n"), + Message::Launching => unreachable!(), + Message::PrintVariable(v) => Bytes::from(format!("print({})\n", v.name())), + Message::Custom => todo!(), + }; + tokio::spawn(async move { - let msg = match &message { - Message::Breakpoint(fl) => { - Bytes::from(format!("break {}:{}\n", fl.name(), fl.line_num())) - } - Message::Unbreakpoint(fl) => { - Bytes::from(format!("clear {}:{}\n", fl.name(), fl.line_num())) - } - Message::StepIn => Bytes::from("step\n"), - Message::StepOver => Bytes::from("next\n"), - Message::Continue => Bytes::from("continue\n"), - Message::Launching => unreachable!(), - Message::PrintVariable(v) => Bytes::from(format!("print({})\n", v.name())), - Message::Custom => todo!(), - }; + // TODO: Interrupt and set and carry on - analyser.lock().unwrap().analyse_message(message); + analyser.lock().unwrap().analyse_message(message, tx_done); tx.clone().unwrap().send(msg).map(move |_| {}).await }); @@ -263,7 +258,7 @@ impl Process { pub struct Analyser { status: PDBStatus, pid: Option, - awakener: Option>, + awakener: Option>, // For keeping track of the variable that we were told to print variable_value: String, } @@ -282,16 +277,6 @@ impl Analyser { self.status.clone() } - /// Add the awakener to send a message to when we awaken - pub fn add_awakener(&mut self, sender: Sender) { - self.awakener = Some(sender); - } - - /// Drop the awakener - pub fn drop_awakener(&mut self) { - self.awakener = None; - } - pub fn analyse_stdout(&mut self, s: &str) { lazy_static! { static ref RE_RETURNING: Regex = @@ -363,7 +348,7 @@ impl Analyser { Message::Breakpoint(_) => { self.check_breakpoint(line); } - Message::StepIn | Message::StepOver | Message::Continue => { + Message::Launching | Message::StepIn | Message::StepOver | Message::Continue => { self.check_location(line); } Message::Custom => { @@ -394,27 +379,30 @@ impl Analyser { } } - pub fn analyse_message(&mut self, msg: Message) { + fn set_listening(&mut self) { + self.status = PDBStatus::Listening; + match self.awakener.take() { + Some(tx) => { + tx.send(true).unwrap(); + } + None => {} + } + } + + /// Sets up the analyser ready for analysing the message. + /// + /// It sets the status of the analyser to Processing for that message and if given + /// it marks the analyser to send a message to `tx_done` to indicate when the + /// message is processed. + pub fn analyse_message(&mut self, msg: Message, tx_done: Option>) { self.status = PDBStatus::Processing(msg); + self.awakener = tx_done; } pub fn set_pid(&mut self, pid: u64) { self.pid = Some(pid); } - fn set_listening(&mut self) { - self.status = PDBStatus::Listening; - let awakener = self.awakener.take(); - match awakener { - Some(mut x) => { - tokio::spawn(async move { - x.send(true).await.unwrap(); - }); - } - None => {} - }; - } - fn check_breakpoint(&self, line: &str) { lazy_static! { static ref RE_BREAKPOINT: Regex = From 98f1ecdc00da4525741a7b9af19fa327fa71e037 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Mon, 2 Mar 2020 23:10:44 +0000 Subject: [PATCH 19/23] Worked up LLDB to all bar printing variables --- padre/Cargo.lock | 14 + padre/cli/Cargo.toml | 6 +- padre/cli/src/debugger.rs | 20 +- padre/cli/src/main.rs | 11 +- padre/debuggers/lldb/src/debugger.rs | 240 +++++----- padre/debuggers/lldb/src/process.rs | 529 +++++++++------------ padre/debuggers/python/src/debugger.rs | 5 +- padre/debuggers/python/src/process.rs | 82 ++-- padre/integration/features/lldb.feature | 95 ++-- padre/integration/features/steps/shared.py | 2 +- padre/ptywrapper.py | 99 +++- 11 files changed, 571 insertions(+), 532 deletions(-) diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 5a01d37..2a464bb 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -324,6 +324,7 @@ dependencies = [ "clap", "futures", "padre_core", + "padre_lldb", "padre_python", "serde", "serde_derive", @@ -347,6 +348,19 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "padre_lldb" +version = "0.2.0" +dependencies = [ + "bytes", + "futures", + "lazy_static", + "padre_core", + "regex", + "tokio", + "tokio-util", +] + [[package]] name = "padre_python" version = "0.2.0" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index ddeac07..3c8f64c 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -7,8 +7,8 @@ license = "APACHE" repository = "https://github.com/strottos/vim-padre" [features] -default = ["python"] # ["lldb", "node", "python"] -# lldb = ["padre_lldb"] +default = ["lldb", "python"] # ["node"] +lldb = ["padre_lldb"] # node = ["padre_node"] python = ["padre_python"] @@ -32,6 +32,6 @@ tokio = { version = "0.2.12", features = [ ] } # The debuggers, all optional -# padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } +padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } # padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/cli/src/debugger.rs b/padre/cli/src/debugger.rs index e7436e5..d24622d 100644 --- a/padre/cli/src/debugger.rs +++ b/padre/cli/src/debugger.rs @@ -4,11 +4,8 @@ use std::fmt::Debug; use std::process::Command; -use std::time::Instant; -use padre_core::debugger::{Debugger, DebuggerCmd}; - -use tokio::sync::mpsc::Receiver; +use padre_core::debugger::Debugger; #[cfg(feature = "lldb")] use padre_lldb; @@ -36,7 +33,6 @@ pub fn create_debugger( debugger_cmd: Option<&str>, debugger_type: Option<&str>, run_cmd: Vec, - queue_rx: Receiver<(DebuggerCmd, Instant)>, ) -> Box { let debugger_type = match debugger_type { Some(s) => match s.to_ascii_lowercase().as_str() { @@ -80,18 +76,14 @@ pub fn create_debugger( }, }; - let debugger = match debugger_type { + match debugger_type { #[cfg(feature = "lldb")] - DebuggerType::LLDB => padre_lldb::ImplDebugger::new(debugger_cmd, run_cmd), + DebuggerType::LLDB => Box::new(padre_lldb::ImplDebugger::new(debugger_cmd, run_cmd)), #[cfg(feature = "node")] - DebuggerType::Node => padre_node::ImplDebugger::new(debugger_cmd, run_cmd), + DebuggerType::Node => Box::new(padre_node::ImplDebugger::new(debugger_cmd, run_cmd)), #[cfg(feature = "python")] - DebuggerType::Python => padre_python::ImplDebugger::new(debugger_cmd, run_cmd), - }; - - debugger.setup_handler(queue_rx); - - Box::new(debugger) + DebuggerType::Python => Box::new(padre_python::ImplDebugger::new(debugger_cmd, run_cmd)), + } } /// Guesses the debugger type diff --git a/padre/cli/src/main.rs b/padre/cli/src/main.rs index 56423b1..242d04d 100644 --- a/padre/cli/src/main.rs +++ b/padre/cli/src/main.rs @@ -110,14 +110,9 @@ async fn run_padre() -> io::Result<()> { let (debugger_queue_tx, debugger_queue_rx) = mpsc::channel(128); - // TODO: Do we need to wrap in Arc/Mutex any more now/when we're on new tokio 0.2? Probably in - // the case of multiple connections but is there a way around it? - let _debugger = create_debugger( - args.value_of("debugger"), - args.value_of("type"), - debug_cmd, - debugger_queue_rx, - ); + let debugger = create_debugger(args.value_of("debugger"), args.value_of("type"), debug_cmd); + + debugger.setup_handler(debugger_queue_rx); let connection_addr = get_connection(&args); let mut socket = TcpListener::bind(&connection_addr) diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs index 5206360..da35215 100644 --- a/padre/debuggers/lldb/src/debugger.rs +++ b/padre/debuggers/lldb/src/debugger.rs @@ -10,160 +10,110 @@ use std::time::{Duration, Instant}; use super::process::{LLDBProcess, Message}; use padre_core::config::Config; +use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; -use padre_core::server::{DebuggerV1, FileLocation, Variable}; use bytes::Bytes; use futures::prelude::*; -use tokio::sync::mpsc; +use tokio::sync::{mpsc, oneshot}; #[derive(Debug)] pub struct ImplDebugger { - process: Arc>, + debugger_cmd: String, + run_cmd: Vec, } impl ImplDebugger { pub fn new(debugger_cmd: String, run_cmd: Vec) -> ImplDebugger { ImplDebugger { - process: Arc::new(Mutex::new(LLDBProcess::new(debugger_cmd, run_cmd))), + debugger_cmd, + run_cmd, } } - - fn step(&mut self, kind: &str) { - //match self.check_process() { - // Some(f) => return f, - // _ => {} - //} - - //let stmt = format!("thread {}\n", kind); - - //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); - - //let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"OK"}); - // Ok(resp) - //}); - } - - //fn check_process( - // &mut self, - //) -> Option> { - // match self.process.lock().unwrap().is_process_running() { - // false => { - // log_msg(LogLevel::WARN, "No process running"); - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"ERROR"}); - // Ok(resp) - // }); - - // Some(Box::new(f)) - // } - // true => None, - // } - //} } -impl DebuggerV1 for ImplDebugger { +impl Debugger for ImplDebugger { /// Perform any initial setup including starting LLDB and setting up the stdio analyser stuff /// - startup lldb and setup the stdio analyser /// - perform initial setup so we can analyse LLDB properly - fn setup(&mut self) { - //let process = self.process.clone(); - - //tokio::spawn(async move { - // let msgs = [ - // "settings set stop-line-count-after 0\n", - // "settings set stop-line-count-before 0\n", - // "settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n", - // "breakpoint set --name main\n", - // ]; - - // for msg in msgs.iter() { - // // Check we're actually listening - // let (tx, mut rx) = mpsc::channel(1); - // process.lock().unwrap().add_awakener(tx); - // rx.next().await.unwrap(); - // process.lock().unwrap().drop_awakener(); - - // process - // .lock() - // .unwrap() - // .write_stdin(Bytes::from(msg.as_bytes())); - // } - //}); + #[allow(unreachable_patterns)] + fn setup_handler(&self, mut queue_rx: mpsc::Receiver<(DebuggerCmd, Instant)>) { + let debugger_cmd = self.debugger_cmd.clone(); + let run_cmd = self.run_cmd.clone(); + + tokio::spawn(async move { + let mut debugger = LLDBDebugger::new(debugger_cmd, run_cmd); + + while let Some(cmd) = queue_rx.next().await { + match cmd.0 { + DebuggerCmd::Basic(basic_cmd) => match basic_cmd { + DebuggerCmdBasic::Run => debugger.run(cmd.1), + DebuggerCmdBasic::Interrupt => debugger.interrupt(), + DebuggerCmdBasic::Exit => { + debugger.teardown(); + break; + } + DebuggerCmdBasic::Breakpoint(fl) => debugger.breakpoint(&fl, cmd.1), + DebuggerCmdBasic::Unbreakpoint(fl) => debugger.unbreakpoint(&fl, cmd.1), + DebuggerCmdBasic::StepIn => debugger.step_in(cmd.1), + DebuggerCmdBasic::StepOver => debugger.step_over(cmd.1), + DebuggerCmdBasic::Continue => debugger.continue_(cmd.1), + DebuggerCmdBasic::Print(v) => debugger.print(&v, cmd.1), + }, + _ => { + log_msg(LogLevel::WARN, "Got a command that wasn't understood"); + } + }; + } + + exit(0); + }); + } +} + +#[derive(Debug)] +pub struct LLDBDebugger { + process: Arc>, +} - //self.process.lock().unwrap().setup(); +impl LLDBDebugger { + pub fn new(debugger_cmd: String, run_cmd: Vec) -> Self { + let (tx, rx) = oneshot::channel(); + + let process = Arc::new(Mutex::new(LLDBProcess::new( + debugger_cmd, + run_cmd, + Some(tx), + ))); + + let debugger = LLDBDebugger { + process: process.clone(), + }; + + // Send a lot of startup messages to LLDB when ready + tokio::spawn(async move { + rx.await.unwrap(); + process + .clone() + .lock() + .unwrap() + .send_msg(Message::LLDBSetup, None); + }); + + debugger } + fn interrupt(&mut self) {} + fn teardown(&mut self) { - self.process.lock().unwrap().teardown(); + self.process.lock().unwrap().stop(); exit(0); } fn run(&mut self, _timeout: Instant) { log_msg(LogLevel::INFO, "Launching process"); - //let (tx, rx) = mpsc::channel(1); - - //self.process - // .lock() - // .unwrap() - // .add_listener(Listener::Breakpoint, tx); - - //let process = self.process.clone(); - - //let f = rx - // .take(1) - // .into_future() - // .and_then(move |lldb_output| { - // let lldb_output = lldb_output.0.unwrap(); - - // match lldb_output { - // Event::BreakpointSet(_) | Event::BreakpointMultiple => {} - // _ => { - // panic!("Don't understand output {:?}", lldb_output); - // } - // }; - - // Ok(()) - // }) - // .and_then(move |_| { - // let (tx, rx) = mpsc::channel(1); - - // process - // .lock() - // .unwrap() - // .add_listener(Listener::ProcessLaunched, tx); - - // process - // .lock() - // .unwrap() - // .write_stdin(Bytes::from("process launch\n")); - - // rx.take(1).into_future() - // }) - // .timeout(Duration::new( - // config - // .lock() - // .unwrap() - // .get_config("ProcessSpawnTimeout") - // .unwrap() as u64, - // 0, - // )) - // .map(move |event| match event.0.unwrap() { - // Event::ProcessLaunched(pid) => { - // serde_json::json!({"status":"OK","pid":pid.to_string()}) - // } - // _ => unreachable!(), - // }) - // .map_err(|e| { - // eprintln!("Reading stdin error {:?}", e); - // io::Error::new(io::ErrorKind::Other, "Timed out spawning process") - // }); - - //let stmt = "breakpoint set --name main\n"; - - //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + self.process.lock().unwrap().send_msg(Message::ProcessLaunching, None); } fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { @@ -176,24 +126,50 @@ impl DebuggerV1 for ImplDebugger { ), ); - //self.process - // .lock() - // .unwrap() - // .send_msg(Message::Breakpoint(file_location.clone())); + self.process + .lock() + .unwrap() + .send_msg(Message::Breakpoint(file_location.clone()), None); } fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) {} + //fn check_process( + // &mut self, + //) -> Option> { + // match self.process.lock().unwrap().is_process_running() { + // false => { + // log_msg(LogLevel::WARN, "No process running"); + // let f = future::lazy(move || { + // let resp = serde_json::json!({"status":"ERROR"}); + // Ok(resp) + // }); + + // Some(Box::new(f)) + // } + // true => None, + // } + //} + fn step_in(&mut self, _timeout: Instant) { - self.step("step-in"); + self.process + .lock() + .unwrap() + .send_msg(Message::StepIn, None); } fn step_over(&mut self, _timeout: Instant) { - self.step("step-over"); + self.process + .lock() + .unwrap() + .send_msg(Message::StepOver, None); } fn continue_(&mut self, _timeout: Instant) { - self.step("continue"); + self.process + .lock() + .unwrap() + .send_msg(Message::Continue, None); } fn print(&mut self, variable: &Variable, _timeout: Instant) { diff --git a/padre/debuggers/lldb/src/process.rs b/padre/debuggers/lldb/src/process.rs index 9f68c2e..c2142ff 100644 --- a/padre/debuggers/lldb/src/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -6,8 +6,8 @@ use std::io::{self, Write}; use std::sync::{Arc, Mutex}; +use padre_core::debugger::{FileLocation, Variable}; use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; -use padre_core::server::{FileLocation, Variable}; use padre_core::util::{check_and_spawn_process, read_output}; use bytes::Bytes; @@ -16,16 +16,17 @@ use regex::Regex; use tokio::io::{stdin, BufReader}; use tokio::prelude::*; use tokio::process::{Child, ChildStdin, ChildStdout}; -use tokio::sync::mpsc::{self, Sender}; +use tokio::sync::{mpsc, oneshot}; use tokio_util::codec::{BytesCodec, FramedRead}; /// Messages that can be sent to LLDB for processing -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Message { + LLDBLaunching, + LLDBSetup, ProcessLaunching, Breakpoint(FileLocation), Unbreakpoint(FileLocation), - UnknownBreakpoint, StepIn, StepOver, Continue, @@ -34,9 +35,9 @@ pub enum Message { } /// Current status of LLDB -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum LLDBStatus { - NotLaunched, + NotRunning, Listening, Processing(Message), } @@ -66,8 +67,8 @@ impl VariableValue { #[derive(Debug)] pub struct LLDBProcess { lldb_process: Option, - lldb_status: Arc>, - lldb_stdin_tx: Sender, + lldb_stdin_tx: mpsc::Sender, + analyser: Arc>, } impl LLDBProcess { @@ -77,89 +78,120 @@ impl LLDBProcess { /// - Sets up a `ReadOutput` from `util.rs` in order to read output from LLDB; /// - Sets up a thread to read stdin and forward it onto LLDB stdin; /// - Checks that LLDB and the program to be ran both exist, otherwise panics. - pub fn new(debugger_cmd: String, run_cmd: Vec) -> Self { - let mut lldb_process = check_and_spawn_process(vec![debugger_cmd], run_cmd); + pub fn new( + debugger_cmd: String, + run_cmd: Vec, + tx_done: Option>, + ) -> Self { + let analyser = Arc::new(Mutex::new(LLDBAnalyser::new())); + + analyser + .lock() + .unwrap() + .analyse_message(Message::LLDBLaunching, tx_done); - let lldb_status = Arc::new(Mutex::new(LLDBStatus::NotLaunched)); + let mut lldb_process = check_and_spawn_process(vec![debugger_cmd], run_cmd); LLDBProcess::setup_stdout( lldb_process - .stdout() + .stdout .take() .expect("LLDB process did not have a handle to stdout"), - lldb_status, + analyser.clone(), ); - let stdin_tx = LLDBProcess::setup_stdin( + let lldb_stdin_tx = LLDBProcess::setup_stdin( lldb_process - .stdin() + .stdin .take() .expect("Python process did not have a handle to stdin"), ); LLDBProcess { lldb_process: Some(lldb_process), - lldb_status, - lldb_stdin_tx: stdin_tx, + lldb_stdin_tx, + analyser, } } - pub fn teardown(&mut self) { + pub fn stop(&mut self) { self.lldb_process = None; } + /// Check the current status, either not running (None), running something + /// (Processing) or listening for a message on LLDB (Listening). pub fn get_status(&self) -> LLDBStatus { - self.lldb_status.lock().unwrap().clone() + self.analyser.lock().unwrap().get_status() } /// Send a message to write to stdin - fn write_stdin(&mut self, bytes: Bytes) { + pub fn send_msg(&mut self, message: Message, tx_done: Option>) { let mut lldb_stdin_tx = self.lldb_stdin_tx.clone(); + let analyser = self.analyser.clone(); + + let msg = match &message { + Message::LLDBSetup => vec![ + Bytes::from("settings set stop-line-count-after 0\n"), + Bytes::from("settings set stop-line-count-before 0\n"), + Bytes::from("settings set frame-format frame #${frame.index}{ at ${line.file.fullpath}:${line.number}}\\n\n"), + Bytes::from("breakpoint set --name main\n"), + ], + Message::ProcessLaunching => vec![Bytes::from("process launch\n")], + Message::Breakpoint(fl) => vec![Bytes::from(format!( + "breakpoint set --file {} --line {}\n", + fl.name(), + fl.line_num() + ))], + Message::StepIn => vec![Bytes::from("thread step-in\n")], + Message::StepOver => vec![Bytes::from("thread step-over\n")], + Message::Continue => vec![Bytes::from("thread continue\n")], + Message::PrintVariable(v) => vec![Bytes::from(format!("frame variable {}\n", v.name()))], + _ => unreachable!(), + }; + tokio::spawn(async move { - lldb_stdin_tx - .send(bytes) - .map(move |_| {}) - .await; + // TODO: Interrupt, set and then carry on as before? + // + // Something like: + // let (tx, rx) = oneshot::channel(); + // + // match self.analyser.lock().unwrap().get_status() { + // NotRunning => {}, + // Listening => {}, + // Processing(Message) => { + // analyser.lock().unwrap().analyse_message(message, Some(tx)); + // rx.await.unwrap(); + // }, + // } + + for b in msg { + let (tx, rx) = oneshot::channel(); + + analyser + .lock() + .unwrap() + .analyse_message(message.clone(), Some(tx)); + + lldb_stdin_tx.send(b).map(move |_| {}).await; + + rx.await.unwrap(); + } + + match tx_done { + Some(tx) => { + tx.send(true).unwrap(); + } + _ => {} + } }); } - // pub fn send_msg(&mut self, message: Message) { - // let msg_bytes = match message.clone() { - // Message::ProcessLaunching => Bytes::from("process launch\n"), - // Message::Breakpoint(fl) => Bytes::from(format!( - // "breakpoint set --file {} --line {}\n", - // fl.name(), - // fl.line_num() - // )), - // Message::UnknownBreakpoint => unreachable!(), - // Message::StepIn => Bytes::from("thread step-in\n"), - // Message::StepOver => Bytes::from("thread step-over\n"), - // Message::Continue => Bytes::from("thread continue\n"), - // Message::PrintVariable(v) => Bytes::from(format!("frame variable {}\n", v.name())), - // }; - - // self.write_stdin(msg_bytes); - // } - - // /// Adds a Sender object that gets awoken when we are listening. - // /// - // /// Should only add a sender when we're about to go into or currently in the - // /// processing status otherwise this will never wake up. - // pub fn add_awakener(&mut self, sender: Sender) { - // self.analyser.lock().unwrap().add_awakener(sender); - // } - - // /// Drop the awakener - // pub fn drop_awakener(&mut self) { - // self.analyser.lock().unwrap().drop_awakener(); - // } - // pub fn is_process_running(&self) -> bool { // self.analyser.lock().unwrap().is_process_running() // } /// Perform setup of listening and forwarding of stdin and return a sender that will forward to the /// stdin of a process. - fn setup_stdin(mut child_stdin: ChildStdin) -> Sender { + fn setup_stdin(mut child_stdin: ChildStdin) -> mpsc::Sender { let (stdin_tx, mut stdin_rx) = mpsc::channel(32); let mut tx = stdin_tx.clone(); @@ -168,38 +200,12 @@ impl LLDBProcess { let mut reader = FramedRead::new(tokio_stdin, BytesCodec::new()); while let Some(line) = reader.next().await { let buf = line.unwrap().freeze(); - - let mut start = 0; - - if buf.len() >= 7 && buf[0..7] == b"(lldb) "[..] { - println!("DETECTED `(lldb) `, skipping"); - start = 7; - } - - if buf.len() >= start + 2 { - println!("stuff {:?}", &buf[start..start + 2]); - } - if buf.len() >= start + 3 { - println!("stuff {:?}", &buf[start..start + 3]); - } - if buf.len() >= start + 11 { - println!("stuff {:?}", &buf[start..start + 11]); - } - - if (buf.len() >= start + 2 && buf[start..start + 2] == b"b "[..]) - || (buf.len() >= start + 3 && buf[start..start + 3] == b"br "[..]) - || (buf.len() >= start + 11 && buf[start..start + 11] == b"breakpoint "[..]) - { - println!("UNKNOWN BREAKPOINT"); - } - tx.send(buf).await.unwrap(); } }); tokio::spawn(async move { while let Some(text) = stdin_rx.next().await { - io::stdout().write_all(&text).unwrap(); match child_stdin.write(&text).await { Ok(_) => {} Err(e) => { @@ -213,149 +219,92 @@ impl LLDBProcess { } /// Perform setup of reading LLDB stdout, analysing it and writing it back to stdout. - fn setup_stdout(stdout: ChildStdout, lldb_status: Arc>) { + fn setup_stdout(stdout: ChildStdout, analyser: Arc>) { tokio::spawn(async move { let mut reader = read_output(BufReader::new(stdout)); - let mut analyser = Analyser::new(lldb_status); while let Some(Ok(text)) = reader.next().await { print!("{}", text); io::stdout().flush().unwrap(); - analyser.analyse_output(&text[..]); + analyser.lock().unwrap().analyse_stdout(&text[..]); } }); } } #[derive(Debug)] -pub struct Analyser { - lldb_status: Arc>, - stdout: String, +pub struct LLDBAnalyser { + status: LLDBStatus, process_pid: Option, - awakener: Option>, + awakener: Option>, + // For keeping track of output over mulitple reads + stdout: String, } -impl Analyser { - pub fn new(lldb_status: Arc>) -> Self { - Analyser { - lldb_status, +impl LLDBAnalyser { + pub fn new() -> Self { + LLDBAnalyser { + status: LLDBStatus::NotRunning, stdout: "".to_string(), - process_pid: None, awakener: None, + process_pid: None, } } - /// Add the awakener to send a message to when we awaken - pub fn add_awakener(&mut self, sender: Sender) { - self.awakener = Some(sender); - } - - /// Drop the awakener - pub fn drop_awakener(&mut self) { - self.awakener = None; + pub fn get_status(&mut self) -> LLDBStatus { + self.status.clone() } - pub fn analyse_output(&mut self, s: &str) { + pub fn analyse_stdout(&mut self, s: &str) { self.stdout.push_str(s); lazy_static! { - static ref RE_LLDB_STARTED: Regex = - Regex::new("^Current executable set to '.*' (.*)\\.$").unwrap(); - static ref RE_PROCESS_STARTED: Regex = - Regex::new("^Process (\\d+) launched: '.*' \\((.*)\\)$").unwrap(); - static ref RE_PROCESS_EXITED: Regex = - Regex::new("^Process (\\d+) exited with status = (\\d+) \\(0x[0-9a-f]*\\) *$") - .unwrap(); - static ref RE_BREAKPOINT: Regex = Regex::new( - "Breakpoint (\\d+): where = .* at (.*):(\\d+):\\d+, address = 0x[0-9a-f]*$" - ) - .unwrap(); - static ref RE_BREAKPOINT_2: Regex = - Regex::new("Breakpoint (\\d+): where = .* at (.*):(\\d+), address = 0x[0-9a-f]*$") - .unwrap(); - static ref RE_BREAKPOINT_MULTIPLE: Regex = - Regex::new("Breakpoint (\\d+): (\\d+) locations\\.$").unwrap(); - static ref RE_BREAKPOINT_PENDING: Regex = - Regex::new("Breakpoint (\\d+): no locations \\(pending\\)\\.$").unwrap(); - static ref RE_STOPPED_AT_POSITION: Regex = Regex::new(" *frame #\\d.*$").unwrap(); - static ref RE_JUMP_TO_POSITION: Regex = - Regex::new("^ *frame #\\d at (\\S+):(\\d+)$").unwrap(); static ref RE_PRINTED_VARIABLE: Regex = Regex::new("^\\((.*)\\) ([\\S+]*) = .*$").unwrap(); - static ref RE_PROCESS_NOT_RUNNING: Regex = - Regex::new("error: invalid process$").unwrap(); - static ref RE_SETTINGS: Regex = Regex::new("settings ").unwrap(); static ref RE_VARIABLE_NOT_FOUND: Regex = Regex::new("error: no variable named '([^']*)' found in this frame$").unwrap(); } let s = self.stdout.clone(); - for line in s.split("\n") { - for _ in RE_LLDB_STARTED.captures_iter(line) { - self.lldb_started(); - } - - for cap in RE_PROCESS_STARTED.captures_iter(line) { - let pid = cap[1].parse::().unwrap(); - self.process_started(pid); - } - - for cap in RE_PROCESS_EXITED.captures_iter(line) { - let pid = cap[1].parse::().unwrap(); - let exit_code = cap[2].parse::().unwrap(); - self.process_exited(pid, exit_code); - } - - let mut found_breakpoint = false; - - for cap in RE_BREAKPOINT.captures_iter(line) { - found_breakpoint = true; - let file = cap[2].to_string(); - let line = cap[3].parse::().unwrap(); - self.found_breakpoint(file, line); + for line in s.split("\r\n") { + println!("Line: {:?}", line); + if line == "(lldb) " { self.set_listening(); + self.clear_analyser(); + return; } - if !found_breakpoint { - for cap in RE_BREAKPOINT_2.captures_iter(line) { - found_breakpoint = true; - let file = cap[2].to_string(); - let line = cap[3].parse::().unwrap(); - self.found_breakpoint(file, line); - self.set_listening(); - } - } - - if !found_breakpoint { - for _ in RE_BREAKPOINT_MULTIPLE.captures_iter(line) { - found_breakpoint = true; - self.found_multiple_breakpoints(); - self.set_listening(); - } + match self.get_status() { + LLDBStatus::Listening => self.status = LLDBStatus::Processing(Message::Custom), + _ => {} } - if !found_breakpoint { - for _ in RE_BREAKPOINT_PENDING.captures_iter(line) { - self.found_pending_breakpoint(); - self.set_listening(); - } - } - - for _ in RE_STOPPED_AT_POSITION.captures_iter(line) { - let mut found = false; - for cap in RE_JUMP_TO_POSITION.captures_iter(line) { - found = true; - let file = cap[1].to_string(); - let line = cap[2].parse::().unwrap(); - self.jump_to_position(file, line); - self.set_listening(); - } - - if !found { - self.jump_to_unknown_position(); - self.set_listening(); - } - } + println!("Status: {:?}", self.get_status()); + match self.get_status() { + LLDBStatus::Processing(msg) => match msg { + Message::LLDBSetup | Message::Breakpoint(_) => { + self.check_breakpoint(line); + } + Message::ProcessLaunching + | Message::StepIn + | Message::StepOver + | Message::Continue => { + self.check_location(line); + self.check_process_running(line); + self.check_process_exited(line); + self.check_process_not_running(line); + } + Message::Custom => { + self.check_breakpoint(line); + self.check_location(line); + self.check_process_running(line); + self.check_process_exited(line); + self.check_process_not_running(line); + } + _ => {} + }, + _ => {}, + }; for cap in RE_PRINTED_VARIABLE.captures_iter(line) { let variable_type = cap[1].to_string(); @@ -363,17 +312,8 @@ impl Analyser { self.printed_variable(variable, variable_type, &s); } - for _ in RE_PROCESS_NOT_RUNNING.captures_iter(line) { - self.process_not_running(); - } - - for _ in RE_SETTINGS.captures_iter(line) { - self.set_listening(); - } - for cap in RE_VARIABLE_NOT_FOUND.captures_iter(line) { let variable = cap[1].to_string(); - self.variable_not_found(variable); } } @@ -381,21 +321,25 @@ impl Analyser { } fn set_listening(&mut self) { - { - let status = self.lldb_status.lock().unwrap(); - *status = LLDBStatus::Listening; - } - let awakener = self.awakener.take(); - match awakener { - Some(mut x) => { - tokio::spawn(async move { - x.send(true).await.unwrap(); - }); + self.status = LLDBStatus::Listening; + match self.awakener.take() { + Some(tx) => { + tx.send(true).unwrap(); } None => {} }; } + /// Sets up the analyser ready for analysing the message. + /// + /// It sets the status of the analyser to Processing for that message and if given + /// it marks the analyser to send a message to `tx_done` to indicate when the + /// message is processed. + pub fn analyse_message(&mut self, msg: Message, tx_done: Option>) { + self.status = LLDBStatus::Processing(msg); + self.awakener = tx_done; + } + fn clear_analyser(&mut self) { self.stdout = "".to_string(); } @@ -407,73 +351,101 @@ impl Analyser { } } - fn lldb_started(&mut self) { - self.set_listening(); - } + fn check_breakpoint(&mut self, line: &str) { + lazy_static! { + static ref RE_BREAKPOINT: Regex = Regex::new( + "Breakpoint (\\d+): where = .* at (.*):(\\d+):\\d+, address = 0x[0-9a-f]*$" + ) + .unwrap(); + static ref RE_BREAKPOINT_2: Regex = + Regex::new("Breakpoint (\\d+): where = .* at (.*):(\\d+), address = 0x[0-9a-f]*$") + .unwrap(); + static ref RE_BREAKPOINT_PENDING: Regex = + Regex::new("Breakpoint (\\d+): no locations \\(pending\\)\\.$").unwrap(); + } - fn process_started(&mut self, pid: u64) { - self.set_listening(); - } + for cap in RE_BREAKPOINT.captures_iter(line) { + let file = cap[2].to_string(); + let line = cap[3].parse::().unwrap(); + log_msg( + LogLevel::INFO, + &format!("Breakpoint set at file {} and line number {}", file, line), + ); + return; + } - fn process_exited(&mut self, pid: u64, exit_code: i64) { - self.process_pid = None; - signal_exited(pid, exit_code); - self.set_listening(); + for cap in RE_BREAKPOINT_2.captures_iter(line) { + let file = cap[2].to_string(); + let line = cap[3].parse::().unwrap(); + log_msg( + LogLevel::INFO, + &format!("Breakpoint set at file {} and line number {}", file, line), + ); + return; + } + + for _ in RE_BREAKPOINT_PENDING.captures_iter(line) { + log_msg(LogLevel::INFO, &format!("Breakpoint pending")); + } } - fn found_breakpoint(&mut self, file: String, line: u64) { - let status = *self.lldb_status.lock().unwrap(); - match status { - LLDBStatus::Processing(msg) => { - match msg { - Message::Breakpoint(_) | Message::UnknownBreakpoint => { - log_msg( - LogLevel::INFO, - &format!("Breakpoint set at file {} and line number {}", file, line), - ); - } - _ => {} - }; + fn check_location(&mut self, line: &str) { + lazy_static! { + static ref RE_STOPPED_AT_POSITION: Regex = Regex::new(" *frame #\\d.*$").unwrap(); + static ref RE_JUMP_TO_POSITION: Regex = + Regex::new("^ *frame #\\d at (\\S+):(\\d+)$").unwrap(); + } + + for _ in RE_STOPPED_AT_POSITION.captures_iter(line) { + let mut found = false; + for cap in RE_JUMP_TO_POSITION.captures_iter(line) { + found = true; + let file = cap[1].to_string(); + let line = cap[2].parse::().unwrap(); + jump_to_position(&file, line); } - _ => {} - }; - //breakpoint_set(&file, line); - //let file_location = FileLocation::new(file, line); - //match self.listeners.remove(&Listener::Breakpoint) { - // Some(listener) => { - // listener - // .send(Event::BreakpointSet(file_location)) - // .wait() - // .unwrap(); - // } - // None => {} - //} - } - fn found_multiple_breakpoints(&mut self) { - //match self.listeners.remove(&Listener::Breakpoint) { - // Some(listener) => { - // listener.send(Event::BreakpointMultiple).wait().unwrap(); - // } - // None => {} - //} + if !found { + log_msg(LogLevel::WARN, "Stopped at unknown position"); + } + } } - fn found_pending_breakpoint(&mut self) { - //match self.listeners.remove(&Listener::Breakpoint) { - // Some(listener) => { - // listener.send(Event::BreakpointPending).wait().unwrap(); - // } - // None => {} - //} + fn check_process_running(&mut self, line: &str) { + lazy_static! { + static ref RE_PROCESS_STARTED: Regex = + Regex::new("^Process (\\d+) launched: '.*' \\((.*)\\)$").unwrap(); + } + + for cap in RE_PROCESS_STARTED.captures_iter(line) { + let pid = cap[1].parse::().unwrap(); + } } - fn jump_to_position(&mut self, file: String, line: u64) { - jump_to_position(&file, line); + fn check_process_exited(&mut self, line: &str) { + lazy_static! { + static ref RE_PROCESS_EXITED: Regex = + Regex::new("^Process (\\d+) exited with status = (\\d+) \\(0x[0-9a-f]*\\) *$") + .unwrap(); + } + + for cap in RE_PROCESS_EXITED.captures_iter(line) { + let pid = cap[1].parse::().unwrap(); + let exit_code = cap[2].parse::().unwrap(); + self.process_pid = None; + signal_exited(pid, exit_code); + } } - fn jump_to_unknown_position(&mut self) { - log_msg(LogLevel::WARN, "Stopped at unknown position"); + fn check_process_not_running(&mut self, line: &str) { + lazy_static! { + static ref RE_PROCESS_NOT_RUNNING: Regex = + Regex::new("error: invalid process$").unwrap(); + } + + for _ in RE_PROCESS_NOT_RUNNING.captures_iter(line) { + log_msg(LogLevel::WARN, "program not running"); + } } fn printed_variable(&mut self, variable: String, variable_type: String, data: &str) { @@ -503,37 +475,4 @@ impl Analyser { // None => {} // } } - - fn process_not_running(&self) { - log_msg(LogLevel::WARN, "program not running"); - } - - fn variable_not_found(&mut self, variable: String) { - //match self.listeners.remove(&Listener::PrintVariable) { - // Some(listener) => { - // let variable = Variable::new(variable); - // listener - // .send(Event::VariableNotFound(variable)) - // .wait() - // .unwrap(); - // } - // None => {} - //} - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn process_startup() { - // analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n"); - // assert_eq!( - // analyser.get_status(), - // PDBStatus::Processing(Message::Launching) - // ); - // analyser.analyse_stdout("(Pdb) "); - // assert_eq!(analyser.get_status(), PDBStatus::Listening); - } } diff --git a/padre/debuggers/python/src/debugger.rs b/padre/debuggers/python/src/debugger.rs index d232e34..4c1216d 100644 --- a/padre/debuggers/python/src/debugger.rs +++ b/padre/debuggers/python/src/debugger.rs @@ -103,7 +103,10 @@ impl PythonDebugger { rx.await.unwrap(); for pb in pbs { let (tx, rx) = oneshot::channel(); - process.lock().unwrap().send_msg(Message::Breakpoint(pb), Some(tx)); + process + .lock() + .unwrap() + .send_msg(Message::Breakpoint(pb), Some(tx)); rx.await.unwrap(); } }); diff --git a/padre/debuggers/python/src/process.rs b/padre/debuggers/python/src/process.rs index bff603e..1560bc7 100644 --- a/padre/debuggers/python/src/process.rs +++ b/padre/debuggers/python/src/process.rs @@ -154,7 +154,10 @@ impl Process { /// - Sets up a thread to read stdin and forward it onto Python interpreter; /// - Checks that Python and the program to be ran both exist, otherwise panics. pub fn run(&mut self, tx_done: Option>) { - self.analyser.lock().unwrap().analyse_message(Message::Launching, tx_done); + self.analyser + .lock() + .unwrap() + .analyse_message(Message::Launching, tx_done); let debugger_cmd = self.debugger_cmd.take().unwrap(); let run_cmd = self.run_cmd.take().unwrap(); @@ -278,16 +281,6 @@ impl Analyser { } pub fn analyse_stdout(&mut self, s: &str) { - lazy_static! { - static ref RE_RETURNING: Regex = - Regex::new("^> (.*)\\((\\d*)\\)[<>\\w]*\\(\\)->(.*)$").unwrap(); - static ref RE_PROCESS_EXITED: Regex = - Regex::new("^The program finished and will be restarted$").unwrap(); - static ref RE_PROCESS_EXITED_WITH_CODE: Regex = - Regex::new("^The program exited via sys.exit\\(\\)\\. Exit status: (-?\\d*)$") - .unwrap(); - } - match self.get_status() { PDBStatus::Processing(msg) => { match msg { @@ -348,34 +341,23 @@ impl Analyser { Message::Breakpoint(_) => { self.check_breakpoint(line); } - Message::Launching | Message::StepIn | Message::StepOver | Message::Continue => { + Message::Launching + | Message::StepIn + | Message::StepOver + | Message::Continue => { self.check_location(line); + self.check_returning(line); + self.check_exited(line); } Message::Custom => { self.check_breakpoint(line); self.check_location(line); + self.check_returning(line); + self.check_exited(line); } _ => {} }, }; - - for cap in RE_RETURNING.captures_iter(line) { - let file = cap[1].to_string(); - let line = cap[2].parse::().unwrap(); - let return_value = cap[3].to_string(); - jump_to_position(&file, line); - self.set_listening(); - log_msg(LogLevel::INFO, &format!("Returning value {}", return_value)); - } - - for _ in RE_PROCESS_EXITED.captures_iter(line) { - signal_exited(self.pid.unwrap(), 0); - } - - for cap in RE_PROCESS_EXITED_WITH_CODE.captures_iter(line) { - let exit_code = cap[1].parse::().unwrap(); - signal_exited(self.pid.unwrap(), exit_code); - } } } @@ -431,6 +413,40 @@ impl Analyser { jump_to_position(&file, line); } } + + fn check_returning(&self, line: &str) { + lazy_static! { + static ref RE_RETURNING: Regex = + Regex::new("^> (.*)\\((\\d*)\\)[<>\\w]*\\(\\)->(.*)$").unwrap(); + } + + for cap in RE_RETURNING.captures_iter(line) { + let file = cap[1].to_string(); + let line = cap[2].parse::().unwrap(); + let return_value = cap[3].to_string(); + jump_to_position(&file, line); + log_msg(LogLevel::INFO, &format!("Returning value {}", return_value)); + } + } + + fn check_exited(&self, line: &str) { + lazy_static! { + static ref RE_PROCESS_EXITED: Regex = + Regex::new("^The program finished and will be restarted$").unwrap(); + static ref RE_PROCESS_EXITED_WITH_CODE: Regex = + Regex::new("^The program exited via sys.exit\\(\\)\\. Exit status: (-?\\d*)$") + .unwrap(); + } + + for _ in RE_PROCESS_EXITED.captures_iter(line) { + signal_exited(self.pid.unwrap(), 0); + } + + for cap in RE_PROCESS_EXITED_WITH_CODE.captures_iter(line) { + let exit_code = cap[1].parse::().unwrap(); + signal_exited(self.pid.unwrap(), exit_code); + } + } } #[cfg(test)] @@ -504,7 +520,7 @@ mod tests { let mut analyser = Analyser::new(); analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n(Pdb) "); let msg = Message::Breakpoint(FileLocation::new("test.py".to_string(), 2)); - analyser.analyse_message(msg.clone()); + analyser.analyse_message(msg.clone(), None); assert_eq!(analyser.get_status(), PDBStatus::Processing(msg)); analyser.analyse_stdout("Breakpoint 1 at test.py:2\r\n(Pdb) "); assert_eq!(analyser.get_status(), PDBStatus::Listening); @@ -515,12 +531,12 @@ mod tests { let mut analyser = Analyser::new(); analyser.analyse_stdout("> /Users/me/test.py(1)()\r\n-> abc = 123\r\n(Pdb) "); let msg = Message::PrintVariable(Variable::new("abc".to_string())); - analyser.analyse_message(msg.clone()); + analyser.analyse_message(msg.clone(), None); analyser.analyse_stdout("print(abc)\r\n"); analyser.analyse_stdout("123\r\n"); assert_eq!(analyser.variable_value, "123\r\n"); analyser.analyse_stdout("(Pdb) "); - analyser.analyse_message(msg.clone()); + analyser.analyse_message(msg.clone(), None); analyser.analyse_stdout("print(abc)\r\n\"abcd1234\"\r\n"); assert_eq!(analyser.variable_value, "\"abcd1234\"\r\n"); analyser.analyse_stdout("(Pdb) "); diff --git a/padre/integration/features/lldb.feature b/padre/integration/features/lldb.feature index dfeccb6..cd7d0fe 100644 --- a/padre/integration/features/lldb.feature +++ b/padre/integration/features/lldb.feature @@ -6,23 +6,26 @@ Feature: LLDB And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' And that we have a test program 'test_prog' that runs with 'lldb' debugger When I debug the program with PADRE - And I give PADRE chance to start + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + When I give PADRE chance to start And I send a command 'b main' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#Log | [4, "Breakpoint set.*test_prog.c.*22"] | + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | When I send a command 'run' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 22] | + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | When I send a command 's' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 8] | + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",8] | When I send a command 'n' using the terminal Then I expect to be called with - | function | args | - | padre#debugger#JumpToPosition | [".*test_prog.c$", 9] | + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | When I send a command 'c' using the terminal Then I expect to be called with | function | args | @@ -36,20 +39,24 @@ Feature: LLDB And that we have a test program 'test_prog' that runs with 'lldb' debugger When I debug the program with PADRE And I give PADRE chance to start + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"test_prog.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4, ".*test_prog.c.*17"] | + | function | args | + | padre#debugger#Log | [4,".*test_prog.c.*17"] | + | padre#debugger#Log | [4,"Setting breakpoint.*test_prog.c.*17"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"not_exists.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with - | function | args | - | padre#debugger#Log | [4,".*not_exists.c.*17"] | + | function | args | + | padre#debugger#Log | [4,"Setting breakpoint.*not_exists.c.*17"] | + | padre#debugger#Log | [4,"Breakpoint pending"] | When I send a request to PADRE '{"cmd":"run"}' - Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - | function | args | - | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - | padre#debugger#Log | [4,"Launching process"] | + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Launching process"] | + | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | When I send a request to PADRE '{"cmd":"stepIn"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | @@ -91,36 +98,36 @@ Feature: LLDB # When I debug the program with PADRE # When I send a command 'b func3' using the terminal # Then I expect to be called with - # | function | args | - # | padre#debugger#BreakpointSet | [".*test_prog.c$", 17] | + # | function | args | + # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*17"] | # When I send a request to PADRE '{"cmd":"run"}' # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | + # | function | args | + # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | # When I send a command 's' using the terminal # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$", 8] | + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",8] | # When I send a request to PADRE '{"cmd":"stepOver"}' # Then I receive both a response '{"status":"OK"}' and I expect to be called with # | function | args | # | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | # When I send a command 'n' using the terminal # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$", 17] | + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",17] | # When I send a command 'n' using the terminal # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$", 18] | + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",18] | # When I send a request to PADRE '{"cmd":"print","variable":"a"}' # Then I receive a response '{"status":"OK","variable":"a","value":"1","type":"int"}' # When I send a command 'c' using the terminal # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$", 10] | + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",10] | # When I send a request to PADRE '{"cmd":"continue"}' # Then I receive both a response '{"status":"OK"}' and I expect to be called with # | function | args | @@ -159,10 +166,10 @@ Feature: LLDB # When I debug the program with PADRE # When I send a request to PADRE '{"cmd":"run"}' # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | + # | function | args | + # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | # When I send a request to PADRE '{"cmd":"print","variable":"a"}' # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with # | function | args | @@ -232,10 +239,10 @@ Feature: LLDB # Then I receive a response '{"status":"OK"}' # When I send a request to PADRE '{"cmd":"run"}' # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Launching process"] | - # | padre#debugger#BreakpointSet | ["test.c",25] | - # | padre#debugger#Log | [2,"Timed out spawning process"] | + # | function | args | + # | padre#debugger#Log | [4,"Launching process"] | + # | padre#debugger#Log | [4,"Breakpoint set.*test.c.*25"] | + # | padre#debugger#Log | [2,"Timed out spawning process"] | #Scenario: Test breakpoint timeout # Given that we have a file 'test_prog.c' @@ -259,10 +266,10 @@ Feature: LLDB # Then I receive a response '{"status":"OK"}' # When I send a request to PADRE '{"cmd":"run"}' # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#BreakpointSet | [".*test_prog.c$",22] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | + # | function | args | + # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | # When I send a request to PADRE '{"cmd":"print","variable":"a"}' # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with # | function | args | diff --git a/padre/integration/features/steps/shared.py b/padre/integration/features/steps/shared.py index 9f1a894..c6183c6 100644 --- a/padre/integration/features/steps/shared.py +++ b/padre/integration/features/steps/shared.py @@ -388,7 +388,7 @@ def sleep_at_startup(context): stdin. This gives PADRE a chance to fully startup before we start confusing it. """ - time.sleep(1) + time.sleep(2) @when("I open another connection to PADRE") diff --git a/padre/ptywrapper.py b/padre/ptywrapper.py index f3cf888..60c1cf4 100755 --- a/padre/ptywrapper.py +++ b/padre/ptywrapper.py @@ -1,6 +1,103 @@ #!/usr/bin/env python +from select import select +import os import pty +import signal import sys +import tty -pty.spawn(sys.argv[1:]) +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +CHILD = 0 +PID = -1 +TTY_MODE = None + + +def receiveSignal(signalNumber, frame): + fid = open("/tmp/ptyout_killing", "w") + fid.write("Signal {}".format(signalNumber)) + fid.write("PID {}".format(PID)) + fid.close() + + if PID != -1: + os.kill(PID, signalNumber) + + if TTY_MODE: + tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, TTY_MODE) + + sys.exit(0) + + +def _writen(fd, data): + """Write all the data to a descriptor.""" + while data: + n = os.write(fd, data) + data = data[n:] + + +def _read(fd): + """Default read function.""" + return os.read(fd, 1024) + + +def _copy(master_fd, master_read=_read, stdin_read=_read): + """Parent copy loop. + Copies + pty master -> standard output (master_read) + standard input -> pty master (stdin_read)""" + fds = [master_fd, STDIN_FILENO] + while True: + rfds, wfds, xfds = select(fds, [], []) + if master_fd in rfds: + data = master_read(master_fd) + if not data: # Reached EOF. + fds.remove(master_fd) + else: + os.write(STDOUT_FILENO, data) + if STDIN_FILENO in rfds: + data = stdin_read(STDIN_FILENO) + if not data: + fds.remove(STDIN_FILENO) + else: + _writen(master_fd, data) + + +def spawn(argv, master_read=_read, stdin_read=_read): + """Create a spawned process.""" + global PID, TTY_MODE + + PID, master_fd = pty.fork() + + if PID == CHILD: + os.execlp(argv[0], *argv) + + fid = open("/tmp/ptyout", "w") + fid.write("PID {}".format(PID)) + fid.close() + + signal.signal(signal.SIGINT, receiveSignal) + signal.signal(signal.SIGQUIT, receiveSignal) + signal.signal(signal.SIGTERM, receiveSignal) + try: + mode = tty.tcgetattr(STDIN_FILENO) + tty.setraw(STDIN_FILENO) + TTY_MODE = mode + except tty.error: # This is the same as termios.error + pass + + try: + _copy(master_fd, master_read, stdin_read) + except OSError: + pass + + if TTY_MODE: + tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, TTY_MODE) + + os.close(master_fd) + return os.waitpid(PID, 0)[1] + + +spawn(sys.argv[1:]) From d814b21e2662b3c2e43de83efcbd802b2568a767 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Tue, 3 Mar 2020 06:55:32 +0000 Subject: [PATCH 20/23] Printing and various improvements --- padre/debuggers/lldb/src/debugger.rs | 15 +- padre/debuggers/lldb/src/process.rs | 134 +++++---- padre/integration/features/lldb.feature | 379 +++++++++++++----------- 3 files changed, 279 insertions(+), 249 deletions(-) diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs index da35215..5f38ea9 100644 --- a/padre/debuggers/lldb/src/debugger.rs +++ b/padre/debuggers/lldb/src/debugger.rs @@ -113,7 +113,10 @@ impl LLDBDebugger { fn run(&mut self, _timeout: Instant) { log_msg(LogLevel::INFO, "Launching process"); - self.process.lock().unwrap().send_msg(Message::ProcessLaunching, None); + self.process + .lock() + .unwrap() + .send_msg(Message::ProcessLaunching, None); } fn breakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) { @@ -152,10 +155,7 @@ impl LLDBDebugger { //} fn step_in(&mut self, _timeout: Instant) { - self.process - .lock() - .unwrap() - .send_msg(Message::StepIn, None); + self.process.lock().unwrap().send_msg(Message::StepIn, None); } fn step_over(&mut self, _timeout: Instant) { @@ -219,6 +219,9 @@ impl LLDBDebugger { //let stmt = format!("frame variable {}\n", variable.name); - //self.process.lock().unwrap().write_stdin(Bytes::from(stmt)); + self.process + .lock() + .unwrap() + .send_msg(Message::PrintVariable(variable.clone()), None); } } diff --git a/padre/debuggers/lldb/src/process.rs b/padre/debuggers/lldb/src/process.rs index c2142ff..7aecfeb 100644 --- a/padre/debuggers/lldb/src/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -236,15 +236,15 @@ pub struct LLDBAnalyser { status: LLDBStatus, process_pid: Option, awakener: Option>, - // For keeping track of output over mulitple reads - stdout: String, + // For keeping track of the variable that we were told to print + variable_output: String, } impl LLDBAnalyser { pub fn new() -> Self { LLDBAnalyser { status: LLDBStatus::NotRunning, - stdout: "".to_string(), + variable_output: "".to_string(), awakener: None, process_pid: None, } @@ -255,22 +255,76 @@ impl LLDBAnalyser { } pub fn analyse_stdout(&mut self, s: &str) { - self.stdout.push_str(s); + // Check process running first + let mut process_running = true; - lazy_static! { - static ref RE_PRINTED_VARIABLE: Regex = - Regex::new("^\\((.*)\\) ([\\S+]*) = .*$").unwrap(); - static ref RE_VARIABLE_NOT_FOUND: Regex = - Regex::new("error: no variable named '([^']*)' found in this frame$").unwrap(); + for line in s.split("\r\n") { + if self.check_process_not_running(line) { + process_running = false; + } + + if !process_running && line == "(lldb) " { + self.set_listening(); + return; + } } - let s = self.stdout.clone(); + // Then check if we're printing a variable as we bail if not all output is available + // straight away + match self.get_status() { + LLDBStatus::Processing(msg) => match msg { + Message::PrintVariable(var) => { + let mut from = 0; + let mut to = s.len(); + + let print_cmd_size = 15 + var.name().len(); + if to >= print_cmd_size + 2 + && &s[0..print_cmd_size] == &format!("frame variable {}", var.name()) + { + // 2 extra for \r\n + from += print_cmd_size + 2; + } + + let lldb_prompt_length = "\r\n(lldb) ".len(); + if to >= lldb_prompt_length && &s[to - lldb_prompt_length..to] == "\r\n(lldb) " + { + to -= lldb_prompt_length; + } + + self.variable_output += &s[from..to]; + } + _ => {} + }, + _ => {} + } + // Then check everything else for line in s.split("\r\n") { - println!("Line: {:?}", line); if line == "(lldb) " { + match self.get_status() { + LLDBStatus::Processing(msg) => match msg { + Message::PrintVariable(var) => { + if self.variable_output + == format!( + "error: no variable named '{}' found in this frame", + var.name() + ) + { + log_msg( + LogLevel::WARN, + &format!("variable '{}' doesn't exist here", var.name()), + ); + } else { + log_msg(LogLevel::INFO, &self.variable_output); + } + self.variable_output = "".to_string(); + } + _ => {} + }, + _ => {} + } + self.set_listening(); - self.clear_analyser(); return; } @@ -279,7 +333,6 @@ impl LLDBAnalyser { _ => {} } - println!("Status: {:?}", self.get_status()); match self.get_status() { LLDBStatus::Processing(msg) => match msg { Message::LLDBSetup | Message::Breakpoint(_) => { @@ -292,32 +345,18 @@ impl LLDBAnalyser { self.check_location(line); self.check_process_running(line); self.check_process_exited(line); - self.check_process_not_running(line); } Message::Custom => { self.check_breakpoint(line); self.check_location(line); self.check_process_running(line); self.check_process_exited(line); - self.check_process_not_running(line); } _ => {} }, - _ => {}, + _ => {} }; - - for cap in RE_PRINTED_VARIABLE.captures_iter(line) { - let variable_type = cap[1].to_string(); - let variable = cap[2].to_string(); - self.printed_variable(variable, variable_type, &s); - } - - for cap in RE_VARIABLE_NOT_FOUND.captures_iter(line) { - let variable = cap[1].to_string(); - } } - - self.clear_analyser(); } fn set_listening(&mut self) { @@ -340,10 +379,6 @@ impl LLDBAnalyser { self.awakener = tx_done; } - fn clear_analyser(&mut self) { - self.stdout = "".to_string(); - } - pub fn is_process_running(&self) -> bool { match self.process_pid { Some(_) => true, @@ -437,42 +472,17 @@ impl LLDBAnalyser { } } - fn check_process_not_running(&mut self, line: &str) { + fn check_process_not_running(&mut self, line: &str) -> bool { lazy_static! { static ref RE_PROCESS_NOT_RUNNING: Regex = - Regex::new("error: invalid process$").unwrap(); + Regex::new("^error: invalid process$").unwrap(); } for _ in RE_PROCESS_NOT_RUNNING.captures_iter(line) { - log_msg(LogLevel::WARN, "program not running"); + log_msg(LogLevel::WARN, "No process running"); + return true; } - } - fn printed_variable(&mut self, variable: String, variable_type: String, data: &str) { - // let mut start = 1; - - // while &data[start..start + 1] != ")" { - // start += 1; - // } - // while &data[start..start + 1] != "=" { - // start += 1; - // } - // start += 2; - - // // TODO: Need a better way of doing this to strip of the last \n, - // // it's possible one day we'll screw the UTF-8 pooch here. - // let value = data[start..data.len() - 1].to_string(); - - // match self.listeners.remove(&Listener::PrintVariable) { - // Some(listener) => { - // let variable = Variable::new(variable); - // let value = VariableValue::new(variable_type, value); - // listener - // .send(Event::PrintVariable(variable, value)) - // .wait() - // .unwrap(); - // } - // None => {} - // } + false } } diff --git a/padre/integration/features/lldb.feature b/padre/integration/features/lldb.feature index cd7d0fe..cbd72cf 100644 --- a/padre/integration/features/lldb.feature +++ b/padre/integration/features/lldb.feature @@ -6,11 +6,11 @@ Feature: LLDB And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' And that we have a test program 'test_prog' that runs with 'lldb' debugger When I debug the program with PADRE + When I give PADRE chance to start Then I expect to be called with | function | args | | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | - When I give PADRE chance to start - And I send a command 'b main' using the terminal + When I send a command 'b main' using the terminal Then I expect to be called with | function | args | | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | @@ -45,7 +45,7 @@ Feature: LLDB When I send a request to PADRE '{"cmd":"breakpoint","file":"test_prog.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | - | padre#debugger#Log | [4,".*test_prog.c.*17"] | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*17"] | | padre#debugger#Log | [4,"Setting breakpoint.*test_prog.c.*17"] | When I send a request to PADRE '{"cmd":"breakpoint","file":"not_exists.c","line":17}' Then I receive both a response '{"status":"OK"}' and I expect to be called with @@ -78,7 +78,9 @@ Feature: LLDB | function | args | | padre#debugger#JumpToPosition | [".*test_prog.c$",18] | When I send a request to PADRE '{"cmd":"print","variable":"a"}' - Then I receive a response '{"status":"OK","variable":"a","value":"1","type":"int"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"^\\(int\\) a = 1$"] | When I send a request to PADRE '{"cmd":"continue"}' Then I receive both a response '{"status":"OK"}' and I expect to be called with | function | args | @@ -91,186 +93,201 @@ Feature: LLDB | gcc -g -O0 | | clang -g -O0 | - #Scenario: Debug a basic program with LLDB using the both the LLDB command line and the PADRE connection - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with 'lldb' debugger - # When I debug the program with PADRE - # When I send a command 'b func3' using the terminal - # Then I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*17"] | - # When I send a request to PADRE '{"cmd":"run"}' - # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | - # When I send a command 's' using the terminal - # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",8] | - # When I send a request to PADRE '{"cmd":"stepOver"}' - # Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | - # When I send a command 'n' using the terminal - # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",17] | - # When I send a command 'n' using the terminal - # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",18] | - # When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # Then I receive a response '{"status":"OK","variable":"a","value":"1","type":"int"}' - # When I send a command 'c' using the terminal - # Then I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",10] | - # When I send a request to PADRE '{"cmd":"continue"}' - # Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#ProcessExited | [0,"\\d+"] | - # When I terminate padre - # Then padre is not running + Scenario: Debug a basic program with LLDB using the both the LLDB command line and the PADRE connection + Given that we have a file 'test_prog.c' + And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + And that we have a test program 'test_prog' that runs with 'lldb' debugger + When I debug the program with PADRE + And I give PADRE chance to start + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + When I send a command 'b func3' using the terminal + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*17"] | + When I send a request to PADRE '{"cmd":"run"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + | padre#debugger#Log | [4,"Launching process"] | + When I send a command 's' using the terminal + Then I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",8] | + When I send a request to PADRE '{"cmd":"stepOver"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",9] | + When I send a command 'n' using the terminal + Then I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",17] | + When I send a command 'n' using the terminal + Then I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",18] | + When I send a request to PADRE '{"cmd":"print","variable":"a"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"^\\(int\\) a = 1$"] | + When I send a command 'c' using the terminal + Then I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",10] | + When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#ProcessExited | [0,"\\d+"] | + When I terminate padre + Then padre is not running - #Scenario: PADRE error reporting when program not running - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with 'lldb' debugger - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"stepIn"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"No process running"] | - # When I send a request to PADRE '{"cmd":"stepOver"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"No process running"] | - # When I send a request to PADRE '{"cmd":"continue"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"No process running"] | - # When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"No process running"] | - # When I terminate padre - # Then padre is not running + Scenario: PADRE error reporting when program not running + Given that we have a file 'test_prog.c' + And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + And that we have a test program 'test_prog' that runs with 'lldb' debugger + When I debug the program with PADRE + And I give PADRE chance to start + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + When I send a request to PADRE '{"cmd":"stepIn"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"No process running"] | + When I send a request to PADRE '{"cmd":"stepOver"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"No process running"] | + When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"No process running"] | + When I send a request to PADRE '{"cmd":"print","variable":"a"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"No process running"] | + When I terminate padre + Then padre is not running - #Scenario: General error handling over PADRE when program is running - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with 'lldb' debugger - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"run"}' - # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | - # When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"variable 'a' doesn't exist here"] | - # When I terminate padre - # Then padre is not running + Scenario: General error handling over PADRE when program is running + Given that we have a file 'test_prog.c' + And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + And that we have a test program 'test_prog' that runs with 'lldb' debugger + When I debug the program with PADRE + Then I expect to be called with + | function | args | + | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + When I send a request to PADRE '{"cmd":"run"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + | padre#debugger#Log | [4,"Launching process"] | + When I send a request to PADRE '{"cmd":"print","variable":"a"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"variable 'a' doesn't exist here"] | + When I terminate padre + Then padre is not running - #Scenario: Printing variables in rust - # Given that we have a file 'test_print_variables.rs' - # And I have compiled the test program 'test_print_variables.rs' with compiler 'rustc -g' to program 'test_print_variables' - # And that we have a test program 'test_print_variables' that runs with 'lldb' debugger - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"run"}' - # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [3,"Stopped at unknown position"] | - # | padre#debugger#Log | [4,"Launching process"] | - # When I send a request to PADRE '{"cmd":"continue"}' - # Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",16] | - # When I send a request to PADRE '{"cmd":"stepOver"}' - # Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",17] | - # When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # Then I receive a response '{"status":"OK","variable":"a","value":"42","type":"int"}' - # When I send a request to PADRE '{"cmd":"stepOver"}' - # Then I receive both a response '{"status":"OK"}' and I expect to be called with - # | function | args | - # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",18] | - # #When I send a request to PADRE '{"cmd":"print","variable":"b"}' - # #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"int","value":"42"},"type":"int \\*","value":"^&0x[0-9a-f]*$"}' - # #When I send a request to PADRE '{"cmd":"stepOver"}' - # #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # # | function | args | - # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",19] | - # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # #Then I receive a response '{"status":"OK","variable":"a","value":"^42.[0-9][0-9]*$","type":"float"}' - # #When I send a request to PADRE '{"cmd":"stepOver"}' - # #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # # | function | args | - # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",20] | - # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # #Then I receive a response '{"status":"OK","variable":"a","value":"true","type":"bool"}' - # #When I send a request to PADRE '{"cmd":"stepOver"}' - # #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # # | function | args | - # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",21] | - # #When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # #Then I receive a response '{"status":"OK","variable":"a","value":"TEST","type":"&str"}' - # #When I send a request to PADRE '{"cmd":"stepOver"}' - # #Then I receive both a response '{"status":"OK"}' and I expect to be called with - # # | function | args | - # # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",22] | - # #When I send a request to PADRE '{"cmd":"print","variable":"b"}' - # #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"&str","value":"TEST"},"type":"&str *","value":"^&0x[0-9a-f]*$"}' - # When I terminate padre - # Then padre is not running + Scenario: Printing variables in rust + Given that we have a file 'test_print_variables.rs' + And I have compiled the test program 'test_print_variables.rs' with compiler 'rustc -g' to program 'test_print_variables' + And that we have a test program 'test_print_variables' that runs with 'lldb' debugger + When I debug the program with PADRE + And I give PADRE chance to start + # Don't get breakpoint info in Rust as main is repeated there + When I send a request to PADRE '{"cmd":"run"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [3,"Stopped at unknown position"] | + | padre#debugger#Log | [4,"Launching process"] | + When I send a request to PADRE '{"cmd":"continue"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",16] | + When I send a request to PADRE '{"cmd":"stepOver"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",17] | + When I send a request to PADRE '{"cmd":"print","variable":"a"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#Log | [4,"^\\(int\\) a = 42$"] | + When I send a request to PADRE '{"cmd":"stepOver"}' + Then I receive both a response '{"status":"OK"}' and I expect to be called with + | function | args | + | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",18] | + #When I send a request to PADRE '{"cmd":"print","variable":"b"}' + #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"int","value":"42"},"type":"int \\*","value":"^&0x[0-9a-f]*$"}' + #When I send a request to PADRE '{"cmd":"stepOver"}' + #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",19] | + #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + #Then I receive a response '{"status":"OK","variable":"a","value":"^42.[0-9][0-9]*$","type":"float"}' + #When I send a request to PADRE '{"cmd":"stepOver"}' + #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",20] | + #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + #Then I receive a response '{"status":"OK","variable":"a","value":"true","type":"bool"}' + #When I send a request to PADRE '{"cmd":"stepOver"}' + #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",21] | + #When I send a request to PADRE '{"cmd":"print","variable":"a"}' + #Then I receive a response '{"status":"OK","variable":"a","value":"TEST","type":"&str"}' + #When I send a request to PADRE '{"cmd":"stepOver"}' + #Then I receive both a response '{"status":"OK"}' and I expect to be called with + # | function | args | + # | padre#debugger#JumpToPosition | [".*test_print_variables.rs$",22] | + #When I send a request to PADRE '{"cmd":"print","variable":"b"}' + #Then I receive a response '{"status":"OK","variable":"b","deref":{"variable":"\\*b","type":"&str","value":"TEST"},"type":"&str *","value":"^&0x[0-9a-f]*$"}' + When I terminate padre + Then padre is not running - #Scenario: Test spawning process timeout - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with './test_files/lldb_spawn_timeout.py' debugger of type 'lldb' - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"setConfig","key":"ProcessSpawnTimeout","value":1}' - # Then I receive a response '{"status":"OK"}' - # When I send a request to PADRE '{"cmd":"run"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Launching process"] | - # | padre#debugger#Log | [4,"Breakpoint set.*test.c.*25"] | - # | padre#debugger#Log | [2,"Timed out spawning process"] | + # Scenario: Test spawning process timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_spawn_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"ProcessSpawnTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [4,"Launching process"] | + # | padre#debugger#Log | [4,"Breakpoint set.*test.c.*25"] | + # | padre#debugger#Log | [2,"Timed out spawning process"] | - #Scenario: Test breakpoint timeout - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with './test_files/lldb_breakpoint_timeout.py' debugger of type 'lldb' - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"setConfig","key":"BreakpointTimeout","value":1}' - # Then I receive a response '{"status":"OK"}' - # When I send a request to PADRE '{"cmd":"breakpoint","file":"test.c","line":17}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Setting breakpoint in file test.c at line number 17"] | - # | padre#debugger#Log | [2,"Timed out setting breakpoint"] | + # Scenario: Test breakpoint timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_breakpoint_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"BreakpointTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"breakpoint","file":"test.c","line":17}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [4,"Setting breakpoint in file test.c at line number 17"] | + # | padre#debugger#Log | [2,"Timed out setting breakpoint"] | - #Scenario: Test print timeout - # Given that we have a file 'test_prog.c' - # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' - # And that we have a test program 'test_prog' that runs with './test_files/lldb_print_variable_timeout.py' debugger of type 'lldb' - # When I debug the program with PADRE - # When I send a request to PADRE '{"cmd":"setConfig","key":"PrintVariableTimeout","value":1}' - # Then I receive a response '{"status":"OK"}' - # When I send a request to PADRE '{"cmd":"run"}' - # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | - # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | - # | padre#debugger#Log | [4,"Launching process"] | - # When I send a request to PADRE '{"cmd":"print","variable":"a"}' - # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with - # | function | args | - # | padre#debugger#Log | [2,"Timed out printing variable"] | + # Scenario: Test print timeout + # Given that we have a file 'test_prog.c' + # And I have compiled the test program 'test_prog.c' with compiler 'gcc -g -O0' to program 'test_prog' + # And that we have a test program 'test_prog' that runs with './test_files/lldb_print_variable_timeout.py' debugger of type 'lldb' + # When I debug the program with PADRE + # When I send a request to PADRE '{"cmd":"setConfig","key":"PrintVariableTimeout","value":1}' + # Then I receive a response '{"status":"OK"}' + # When I send a request to PADRE '{"cmd":"run"}' + # Then I receive both a response '{"status":"OK","pid":"\\d+"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [4,"Breakpoint set.*test_prog.c.*22"] | + # | padre#debugger#JumpToPosition | [".*test_prog.c$",22] | + # | padre#debugger#Log | [4,"Launching process"] | + # When I send a request to PADRE '{"cmd":"print","variable":"a"}' + # Then I receive both a response '{"status":"ERROR"}' and I expect to be called with + # | function | args | + # | padre#debugger#Log | [2,"Timed out printing variable"] | From 52469e0c33e2a1baf2ea6671594a6473b0787cd8 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Tue, 3 Mar 2020 07:27:53 +0000 Subject: [PATCH 21/23] Tweaks --- padre/debuggers/lldb/src/debugger.rs | 70 +--------------------------- padre/debuggers/lldb/src/process.rs | 55 ++-------------------- 2 files changed, 5 insertions(+), 120 deletions(-) diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs index 5f38ea9..221148a 100644 --- a/padre/debuggers/lldb/src/debugger.rs +++ b/padre/debuggers/lldb/src/debugger.rs @@ -3,17 +3,14 @@ //! The main LLDB Debugger entry point. Handles listening for instructions and //! communicating through the `LLDBProcess`. -use std::io; use std::process::exit; use std::sync::{Arc, Mutex}; -use std::time::{Duration, Instant}; +use std::time::Instant; use super::process::{LLDBProcess, Message}; -use padre_core::config::Config; use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; use padre_core::notifier::{log_msg, LogLevel}; -use bytes::Bytes; use futures::prelude::*; use tokio::sync::{mpsc, oneshot}; @@ -135,24 +132,7 @@ impl LLDBDebugger { .send_msg(Message::Breakpoint(file_location.clone()), None); } - fn unbreakpoint(&mut self, file_location: &FileLocation, _timeout: Instant) {} - - //fn check_process( - // &mut self, - //) -> Option> { - // match self.process.lock().unwrap().is_process_running() { - // false => { - // log_msg(LogLevel::WARN, "No process running"); - // let f = future::lazy(move || { - // let resp = serde_json::json!({"status":"ERROR"}); - // Ok(resp) - // }); - - // Some(Box::new(f)) - // } - // true => None, - // } - //} + fn unbreakpoint(&mut self, _file_location: &FileLocation, _timeout: Instant) {} fn step_in(&mut self, _timeout: Instant) { self.process.lock().unwrap().send_msg(Message::StepIn, None); @@ -173,52 +153,6 @@ impl LLDBDebugger { } fn print(&mut self, variable: &Variable, _timeout: Instant) { - //match self.check_process() { - // Some(f) => return f, - // _ => {} - //} - - //let (tx, rx) = mpsc::channel(1); - - //self.process - // .lock() - // .unwrap() - // .add_listener(Listener::PrintVariable, tx); - - //let f = rx - // .take(1) - // .into_future() - // .timeout(Duration::new( - // config - // .lock() - // .unwrap() - // .get_config("PrintVariableTimeout") - // .unwrap() as u64, - // 0, - // )) - // .map(move |event| match event.0.unwrap() { - // Event::PrintVariable(variable, value) => serde_json::json!({ - // "status": "OK", - // "variable": variable.name, - // "value": value.value(), - // "type": value.type_() - // }), - // Event::VariableNotFound(variable) => { - // log_msg( - // LogLevel::WARN, - // &format!("variable '{}' doesn't exist here", variable.name), - // ); - // serde_json::json!({"status":"ERROR"}) - // } - // _ => unreachable!(), - // }) - // .map_err(|e| { - // eprintln!("Reading stdin error {:?}", e); - // io::Error::new(io::ErrorKind::Other, "Timed out printing variable") - // }); - - //let stmt = format!("frame variable {}\n", variable.name); - self.process .lock() .unwrap() diff --git a/padre/debuggers/lldb/src/process.rs b/padre/debuggers/lldb/src/process.rs index 7aecfeb..b5734c9 100644 --- a/padre/debuggers/lldb/src/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -26,7 +26,7 @@ pub enum Message { LLDBSetup, ProcessLaunching, Breakpoint(FileLocation), - Unbreakpoint(FileLocation), + // Unbreakpoint(FileLocation), StepIn, StepOver, Continue, @@ -42,27 +42,6 @@ pub enum LLDBStatus { Processing(Message), } -/// The value of a variable -#[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub struct VariableValue { - type_: String, - value: String, -} - -impl VariableValue { - pub fn new(type_: String, value: String) -> Self { - VariableValue { type_, value } - } - - pub fn type_(&self) -> &str { - &self.type_ - } - - pub fn value(&self) -> &str { - &self.value - } -} - /// Main handler for spawning the LLDB process #[derive(Debug)] pub struct LLDBProcess { @@ -117,12 +96,6 @@ impl LLDBProcess { self.lldb_process = None; } - /// Check the current status, either not running (None), running something - /// (Processing) or listening for a message on LLDB (Listening). - pub fn get_status(&self) -> LLDBStatus { - self.analyser.lock().unwrap().get_status() - } - /// Send a message to write to stdin pub fn send_msg(&mut self, message: Message, tx_done: Option>) { let mut lldb_stdin_tx = self.lldb_stdin_tx.clone(); @@ -185,10 +158,6 @@ impl LLDBProcess { }); } - // pub fn is_process_running(&self) -> bool { - // self.analyser.lock().unwrap().is_process_running() - // } - /// Perform setup of listening and forwarding of stdin and return a sender that will forward to the /// stdin of a process. fn setup_stdin(mut child_stdin: ChildStdin) -> mpsc::Sender { @@ -250,6 +219,8 @@ impl LLDBAnalyser { } } + /// Check the current status, either not running (None), running something + /// (Processing) or listening for a message on LLDB (Listening). pub fn get_status(&mut self) -> LLDBStatus { self.status.clone() } @@ -343,13 +314,11 @@ impl LLDBAnalyser { | Message::StepOver | Message::Continue => { self.check_location(line); - self.check_process_running(line); self.check_process_exited(line); } Message::Custom => { self.check_breakpoint(line); self.check_location(line); - self.check_process_running(line); self.check_process_exited(line); } _ => {} @@ -379,13 +348,6 @@ impl LLDBAnalyser { self.awakener = tx_done; } - pub fn is_process_running(&self) -> bool { - match self.process_pid { - Some(_) => true, - None => false, - } - } - fn check_breakpoint(&mut self, line: &str) { lazy_static! { static ref RE_BREAKPOINT: Regex = Regex::new( @@ -446,17 +408,6 @@ impl LLDBAnalyser { } } - fn check_process_running(&mut self, line: &str) { - lazy_static! { - static ref RE_PROCESS_STARTED: Regex = - Regex::new("^Process (\\d+) launched: '.*' \\((.*)\\)$").unwrap(); - } - - for cap in RE_PROCESS_STARTED.captures_iter(line) { - let pid = cap[1].parse::().unwrap(); - } - } - fn check_process_exited(&mut self, line: &str) { lazy_static! { static ref RE_PROCESS_EXITED: Regex = From 20a412434c1691b03f7026b449649afd8dd02e8a Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Wed, 4 Mar 2020 22:33:12 +0000 Subject: [PATCH 22/23] Added NodeJS --- padre/Cargo.lock | 301 ++++++++++++++ padre/cli/Cargo.toml | 6 +- padre/debuggers/lldb/Cargo.toml | 2 +- padre/debuggers/lldb/src/debugger.rs | 7 +- padre/debuggers/lldb/src/process.rs | 21 +- padre/debuggers/node/Cargo.toml | 4 +- padre/debuggers/node/src/analyser.rs | 179 +++++---- padre/debuggers/node/src/debugger.rs | 455 +++++++++++----------- padre/debuggers/node/src/lib.rs | 1 + padre/debuggers/node/src/process.rs | 88 ++--- padre/debuggers/node/src/utils.rs | 16 + padre/debuggers/node/src/ws.rs | 240 +++++------- padre/debuggers/python/src/lib.rs | 1 - padre/debuggers/python/src/process.rs | 7 +- padre/integration/features/basics.feature | 20 + padre/integration/features/nodejs.feature | 23 +- padre/integration/features/python.feature | 55 +-- padre/ptywrapper.py | 16 +- test/integration/test_debugger.vader | 12 +- 19 files changed, 873 insertions(+), 581 deletions(-) create mode 100644 padre/debuggers/node/src/utils.rs diff --git a/padre/Cargo.lock b/padre/Cargo.lock index 2a464bb..5586923 100644 --- a/padre/Cargo.lock +++ b/padre/Cargo.lock @@ -35,18 +35,66 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + [[package]] name = "bytes" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -68,6 +116,21 @@ dependencies = [ "vec_map", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fnv" version = "1.0.6" @@ -181,6 +244,26 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hermit-abi" version = "0.1.8" @@ -190,6 +273,43 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "input_buffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" +dependencies = [ + "bytes", +] + [[package]] name = "iovec" version = "0.1.4" @@ -236,6 +356,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "memchr" version = "2.3.3" @@ -317,6 +443,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "padre" version = "0.2.0" @@ -325,6 +457,7 @@ dependencies = [ "futures", "padre_core", "padre_lldb", + "padre_node", "padre_python", "serde", "serde_derive", @@ -361,6 +494,24 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "padre_node" +version = "0.2.0" +dependencies = [ + "bytes", + "futures", + "lazy_static", + "padre_core", + "regex", + "serde", + "serde_derive", + "serde_json", + "tokio", + "tokio-tungstenite", + "tokio-util", + "url", +] + [[package]] name = "padre_python" version = "0.2.0" @@ -373,6 +524,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pin-project" version = "0.4.8" @@ -405,6 +562,12 @@ version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + [[package]] name = "proc-macro-hack" version = "0.5.11" @@ -440,6 +603,47 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +dependencies = [ + "c2-chacha", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.1.56" @@ -498,6 +702,18 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "signal-hook-registry" version = "1.2.0" @@ -514,6 +730,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "smallvec" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" + [[package]] name = "socket2" version = "0.3.11" @@ -595,6 +817,19 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-tungstenite" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b8fe88007ebc363512449868d7da4389c9400072a3f666f212c7280082882a" +dependencies = [ + "futures", + "log", + "pin-project", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.2.0" @@ -609,6 +844,49 @@ dependencies = [ "tokio", ] +[[package]] +name = "tungstenite" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "input_buffer", + "log", + "rand", + "sha-1", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +dependencies = [ + "smallvec", +] + [[package]] name = "unicode-width" version = "0.1.7" @@ -621,12 +899,35 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "winapi" version = "0.2.8" diff --git a/padre/cli/Cargo.toml b/padre/cli/Cargo.toml index 3c8f64c..20bbae9 100644 --- a/padre/cli/Cargo.toml +++ b/padre/cli/Cargo.toml @@ -7,9 +7,9 @@ license = "APACHE" repository = "https://github.com/strottos/vim-padre" [features] -default = ["lldb", "python"] # ["node"] +default = ["lldb", "node", "python"] lldb = ["padre_lldb"] -# node = ["padre_node"] +node = ["padre_node"] python = ["padre_python"] [dependencies] @@ -33,5 +33,5 @@ tokio = { version = "0.2.12", features = [ # The debuggers, all optional padre_lldb = { path = "../debuggers/lldb", optional = true, version = "0.2.0" } -# padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } +padre_node = { path = "../debuggers/node", optional = true, version = "0.2.0" } padre_python = { path = "../debuggers/python", optional = true, version = "0.2.0" } diff --git a/padre/debuggers/lldb/Cargo.toml b/padre/debuggers/lldb/Cargo.toml index 8583e1d..968212d 100644 --- a/padre/debuggers/lldb/Cargo.toml +++ b/padre/debuggers/lldb/Cargo.toml @@ -13,7 +13,7 @@ path = "src/lib.rs" bytes = "0.5.0" futures = "0.3.1" lazy_static = "1.3.0" -regex = "1.1.2" padre_core = { path = "../../core", version = "0.2.0" } +regex = "1.1.2" tokio = { version = "0.2.12", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } diff --git a/padre/debuggers/lldb/src/debugger.rs b/padre/debuggers/lldb/src/debugger.rs index 221148a..b3cccfa 100644 --- a/padre/debuggers/lldb/src/debugger.rs +++ b/padre/debuggers/lldb/src/debugger.rs @@ -5,7 +5,8 @@ use std::process::exit; use std::sync::{Arc, Mutex}; -use std::time::Instant; +use std::thread; +use std::time::{Duration, Instant}; use super::process::{LLDBProcess, Message}; use padre_core::debugger::{Debugger, DebuggerCmd, DebuggerCmdBasic, FileLocation, Variable}; @@ -58,7 +59,7 @@ impl Debugger for ImplDebugger { DebuggerCmdBasic::Print(v) => debugger.print(&v, cmd.1), }, _ => { - log_msg(LogLevel::WARN, "Got a command that wasn't understood"); + log_msg(LogLevel::WARN, &format!("Got a command that wasn't understood {:?}", cmd)); } }; } @@ -90,6 +91,8 @@ impl LLDBDebugger { // Send a lot of startup messages to LLDB when ready tokio::spawn(async move { rx.await.unwrap(); + // Mini sleep to make sure VIM has connected + thread::sleep(Duration::from_millis(500)); process .clone() .lock() diff --git a/padre/debuggers/lldb/src/process.rs b/padre/debuggers/lldb/src/process.rs index b5734c9..126f220 100644 --- a/padre/debuggers/lldb/src/process.rs +++ b/padre/debuggers/lldb/src/process.rs @@ -93,7 +93,12 @@ impl LLDBProcess { } pub fn stop(&mut self) { - self.lldb_process = None; + match self.lldb_process.take() { + Some(mut p) => { + p.kill().unwrap(); + } + None => {} + }; } /// Send a message to write to stdin @@ -225,6 +230,8 @@ impl LLDBAnalyser { self.status.clone() } + // TODO: Find out why I need this? + #[allow(unused_mut)] pub fn analyse_stdout(&mut self, s: &str) { // Check process running first let mut process_running = true; @@ -256,13 +263,19 @@ impl LLDBAnalyser { from += print_cmd_size + 2; } + self.variable_output += &s[from..to]; + + let output = &self.variable_output[..]; + let mut to = output.len(); + let lldb_prompt_length = "\r\n(lldb) ".len(); - if to >= lldb_prompt_length && &s[to - lldb_prompt_length..to] == "\r\n(lldb) " + if to >= lldb_prompt_length + && &self.variable_output[to - lldb_prompt_length..to] == "\r\n(lldb) " { to -= lldb_prompt_length; } - self.variable_output += &s[from..to]; + self.variable_output = output[0..to].to_string(); } _ => {} }, @@ -411,7 +424,7 @@ impl LLDBAnalyser { fn check_process_exited(&mut self, line: &str) { lazy_static! { static ref RE_PROCESS_EXITED: Regex = - Regex::new("^Process (\\d+) exited with status = (\\d+) \\(0x[0-9a-f]*\\) *$") + Regex::new("Process (\\d+) exited with status = (\\d+) \\(0x[0-9a-f]*\\) *$") .unwrap(); } diff --git a/padre/debuggers/node/Cargo.toml b/padre/debuggers/node/Cargo.toml index 8837590..2a98eb0 100644 --- a/padre/debuggers/node/Cargo.toml +++ b/padre/debuggers/node/Cargo.toml @@ -20,5 +20,5 @@ serde_derive = "1.0" serde_json = "1.0" tokio = { version = "0.2.12", features = [] } tokio-util = { version = "0.2.0", features = ["codec"] } -tungstenite = "0.9.2" -url = "2.1.0" +tokio-tungstenite = "*" +url = "2.1.1" diff --git a/padre/debuggers/node/src/analyser.rs b/padre/debuggers/node/src/analyser.rs index e912828..eca6991 100644 --- a/padre/debuggers/node/src/analyser.rs +++ b/padre/debuggers/node/src/analyser.rs @@ -2,13 +2,12 @@ //! //! Analyses the messages that come from the WebSocket connection to Node Debugger -use std::sync::{Arc, Mutex}; - -use super::ws::WSHandler; +use super::utils::get_json; +use padre_core::debugger::FileLocation; use padre_core::notifier::{jump_to_position, log_msg, signal_exited, LogLevel}; -use padre_core::server::FileLocation; -use tokio::prelude::*; +use tokio::sync::{mpsc, oneshot}; +use tokio_tungstenite::tungstenite::protocol::Message; /// Node script, indicated by receiving a 'Debugger.scriptParsed' message from Node #[derive(Debug, Eq, PartialEq)] @@ -36,22 +35,24 @@ impl Script { pub struct Analyser { scripts: Vec