diff --git a/Cargo.lock b/Cargo.lock index c8074902..012fda37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -502,9 +502,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags", "cfg-if", @@ -528,9 +528,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -873,9 +873,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -883,9 +883,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -898,9 +898,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -908,9 +908,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -921,9 +921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" diff --git a/docs/debugging.md b/docs/debugging.md index 9414e911..951e7f6f 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -107,31 +107,3 @@ alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes) # After this operation, 1 pointers are allocated, totalling 512 bytes. dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes) ``` - -A tool is provided to analyze such reports, in `tools/heapviz`. This tool -parses the console output, identifies the lines corresponding to (de)allocation -operations, and first computes some statistics: - -* Address range used by the heap over this run of the program, -* Peak heap usage (how many useful bytes are allocated), -* Peak heap consumption (how many bytes are used by the heap, including - unavailable bytes between allocated blocks, due to alignment constraints and - memory fragmentation), -* Fragmentation overhead (difference between heap consumption and usage). - -Then, the `heapviz` tool displays an animated "movie" of the allocated bytes in -heap memory. Each frame in this "movie" shows bytes that are currently -allocated, that were allocated but are now freed, and that have never been -allocated. A new frame is generated for each (de)allocation operation. This tool -uses the `ncurses` library, that you may have to install beforehand. - -You can control the tool with the following parameters: - -* `--logfile` (required) to provide the file which contains the console output - to parse, -* `--fps` (optional) to customize the number of frames per second in the movie - animation. - -```shell -cargo run --manifest-path tools/heapviz/Cargo.toml -- --logfile console.log --fps 50 -``` diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh index b8e3e7df..2c61eb4d 100755 --- a/run_desktop_tests.sh +++ b/run_desktop_tests.sh @@ -35,7 +35,6 @@ cargo check --release --target=thumbv7em-none-eabi --features "$MOST_FEATURES" cargo check --release --target=thumbv7em-none-eabi --examples cargo check --release --target=thumbv7em-none-eabi --examples --features with_nfc cargo check --release --target=thumbv7em-none-eabi --manifest-path bootloader/Cargo.toml -cargo check --release --manifest-path tools/heapviz/Cargo.toml echo "Checking Rust formatting..." cargo fmt -- --check @@ -46,7 +45,6 @@ cargo fmt --manifest-path libraries/cbor/fuzz/Cargo.toml -- --check cargo fmt --manifest-path libraries/persistent_store/Cargo.toml -- --check cargo fmt --manifest-path libraries/persistent_store/fuzz/Cargo.toml -- --check cargo fmt --manifest-path libraries/crypto/Cargo.toml -- --check -cargo fmt --manifest-path tools/heapviz/Cargo.toml -- --check cargo fmt --manifest-path bootloader/Cargo.toml -- --check echo "Checking Python formatting..." @@ -90,7 +88,6 @@ cargo test --manifest-path libraries/cbor/Cargo.toml cargo test --manifest-path libraries/persistent_store/Cargo.toml --features std # Running release mode to speed up. This library is legacy anyway. cargo test --manifest-path libraries/crypto/Cargo.toml --features std --release -cargo test --manifest-path tools/heapviz/Cargo.toml echo "Checking that boards build properly..." make -C third_party/tock/boards/nordic/nrf52840dk_opensk diff --git a/tools/heapviz/Cargo.lock b/tools/heapviz/Cargo.lock deleted file mode 100644 index cf94d5c5..00000000 --- a/tools/heapviz/Cargo.lock +++ /dev/null @@ -1,194 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "heapviz" -version = "0.1.0" -dependencies = [ - "clap", - "lazy_static", - "ncurses", - "regex", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[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.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "ncurses" -version = "5.101.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -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/tools/heapviz/Cargo.toml b/tools/heapviz/Cargo.toml deleted file mode 100644 index 4300f7e5..00000000 --- a/tools/heapviz/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "heapviz" -version = "0.1.0" -authors = [ - "Guillaume Endignoux ", -] -license = "Apache-2.0" -edition = "2018" - -[dependencies] -clap = "2.33.1" -lazy_static = "1.4.0" -ncurses = "5.99.0" -regex = "1" diff --git a/tools/heapviz/src/main.rs b/tools/heapviz/src/main.rs deleted file mode 100644 index 86dcb1e4..00000000 --- a/tools/heapviz/src/main.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use clap::{App, Arg}; -use lazy_static::lazy_static; -use regex::Regex; -use std::fs::File; -use std::io::{BufRead, BufReader, Read, Write}; -use std::thread::sleep; -use std::time::Duration; - -/// Configuration, built from CLI parameters. -struct Config { - /// Handle to the log file containing allocation operations. - logfile: File, - /// Number of allocation operations to show per second. - fps: u64, -} - -fn parse_cli() -> Config { - let matches = App::new("Heap visualizer") - .version("0.1") - .author("Guillaume Endignoux ") - .about("Tool to visualize heap usage of libtock-rs applications") - .arg(Arg::with_name("logfile") - .short("f") - .long("logfile") - .value_name("FILE") - .help("Log file containing allocation info (deploy OpenSK with --debug-allocations to obtain it)") - .takes_value(true) - .required(true)) - .arg(Arg::with_name("fps") - .long("fps") - .value_name("FPS") - .help("Number of allocation operations to show per second") - .takes_value(true) - .default_value("20")) - .get_matches(); - - let logpath = matches.value_of("logfile").unwrap(); - let fps = matches - .value_of("fps") - .unwrap() - .parse::() - .expect("The --fps parameter must be an integer"); - let logfile = File::open(logpath).expect("Couldn't open --logfile for reading"); - - Config { logfile, fps } -} - -/// An allocation or deallocation event. -#[cfg_attr(test, derive(Debug, PartialEq))] -struct Event { - /// Whether this even is an allocation (true) or a deallocation (false). - is_alloc: bool, - /// The start address of the (de)allocated block, in bytes. - start: usize, - /// The length of the (de)allocated block, in bytes. - len: usize, -} - -fn parse_event(line: &str) -> Option { - // The following regex matches lines looking like the following from OpenSK's output. Such lines - // are printed to the console when the `--debug-allocations` feature is enabled in the deploy - // script. - // - // ``` - // alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes) - // dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes) - // ``` - // - // The two integers between square brackets after the (de)alloc keywords represent the length - // and alignement of the allocated block, respectively. The integer serialized in hexadecimal - // after the equal sign represents the starting address of the allocated block. The two - // integers within parentheses represent statistics about the total number of allocated blocks - // and the total number of allocated bytes after the (de)allocation operation, respectively. - // - // This regex captures three elements, in this order. - // - The keyword to know whether this operation is an allocation or a deallocation. - // - The length of the allocated block. - // - The starting address of the allocated block. - lazy_static! { - static ref RE: Regex = - Regex::new(r"^(alloc|dealloc)\[(\d+), \d+\] = 0x([0-9a-f]+) \(\d+ ptrs, \d+ bytes\)$") - .unwrap(); - } - - RE.captures(line).map(|caps| { - let typ = caps.get(1).unwrap().as_str(); - let len = caps.get(2).unwrap().as_str().parse::().unwrap(); - let start = usize::from_str_radix(&caps.get(3).unwrap().as_str(), 16).unwrap(); - Event { - is_alloc: typ == "alloc", - start, - len, - } - }) -} - -fn main() { - let config = parse_cli(); - - let mut events = Vec::new(); - for line in BufReader::new(config.logfile).lines() { - if let Some(event) = parse_event(&line.unwrap()) { - events.push(event); - } - } - - let count_alloc = events.iter().filter(|e| e.is_alloc).count(); - let count_dealloc = events.len() - count_alloc; - let start = events.iter().map(|e| e.start).min().unwrap_or(0); - let end = events.iter().map(|e| e.start + e.len).max().unwrap_or(0); - let mut usage = 0; - let peak = events - .iter() - .map(|e| { - if e.is_alloc { - usage += e.len; - } else { - usage -= e.len; - } - usage - }) - .max() - .unwrap_or(0); - let len = end - start; - println!( - "Observed {} allocations and {} deallocations", - count_alloc, count_dealloc - ); - println!("Start address: {:08x}", start); - println!("End address: {:08x}", end); - println!("Peak usage: {0} = {0:08x} bytes", peak); - println!("Peak consumption: {0} = {0:08x} bytes", len); - println!("Fragmentation overhead: {0} = {0:08x} bytes", len - peak); - - print!("\nPress ENTER to start the visualization..."); - std::io::stdout().flush().unwrap(); - // Wait for ENTER, by reading a single byte and discarding it. - let _ = std::io::stdin().lock().read(&mut [0u8]).unwrap(); - - let window = ncurses::initscr(); - ncurses::cbreak(); - ncurses::noecho(); - ncurses::intrflush(window, false); - ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE); - - let width = ncurses::getmaxx(window) as usize; - - for e in events.iter() { - let position = e.start - start; - ncurses::wmove(window, (position / width) as i32, (position % width) as i32); - - let mut s = Vec::with_capacity(e.len); - if e.is_alloc { - s.resize(e.len, b'#'); - } else { - s.resize(e.len, b'.'); - } - ncurses::addstr(std::str::from_utf8(s.as_slice()).unwrap()); - ncurses::refresh(); - sleep(Duration::from_nanos(1_000_000_000 / config.fps)); - } - - ncurses::endwin(); -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_event_alloc() { - assert_eq!( - parse_event("alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes)"), - Some(Event { - is_alloc: true, - start: 0x2002401c, - len: 256, - }) - ); - } - - #[test] - fn test_parse_event_dealloc() { - assert_eq!( - parse_event("dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes)"), - Some(Event { - is_alloc: false, - start: 0x2002410c, - len: 64, - }) - ); - } - - #[test] - fn test_parse_event_none() { - assert_eq!( - parse_event( - "NRF52 HW INFO: Variant: AAD0, Part: N52840, Package: QI, Ram: K256, Flash: K1024" - ), - None - ); - } -}