From 2e4fb672aba25d2386acfc32b1809030c196f4e2 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 10 May 2021 14:12:19 +0800 Subject: [PATCH] arguments: document and add pnam tag The `PNam` tag stores information in the kernel about process names. This can be used at runtime to discover what process maps to what program name. Signed-off-by: Sean Cross --- docs/arguments.md | 12 +++++++ tools/src/bin/create-image.rs | 17 ++++++++++ tools/src/tags/mod.rs | 1 + tools/src/tags/pnam.rs | 63 +++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 tools/src/tags/pnam.rs diff --git a/docs/arguments.md b/docs/arguments.md index 8fbc6120c..0d2ca66be 100644 --- a/docs/arguments.md +++ b/docs/arguments.md @@ -125,3 +125,15 @@ offsets must be in the range `0xffc0_0000` - `0xfff0_0000`. * ENTRYPOINT -- Virtual address of the `_start()` function The kernel will run in Supervisor mode, and have its own private stack. + +### PNam + +`PNam` maps process IDs to process names. If multiple `PNam` tags exist +within a block, the first one that is encountered should take precedence. +This tag is a series of entries that take the following format: + +| Size (bytes) | Name | Description +| --------- | ---- | ----- +| 4 | PID | ID of the process that this name describes +| 4 | Length | The length of the data that follows +| varies | Data | The UTF-8 name string diff --git a/tools/src/bin/create-image.rs b/tools/src/bin/create-image.rs index c4079b44c..a25024672 100644 --- a/tools/src/bin/create-image.rs +++ b/tools/src/bin/create-image.rs @@ -10,6 +10,7 @@ use tools::elf::{read_minielf, read_program}; use tools::tags::bflg::Bflg; use tools::tags::inie::IniE; use tools::tags::memory::{MemoryRegion, MemoryRegions}; +use tools::tags::pnam::ProcessNames; use tools::tags::xkrn::XousKernel; use tools::utils::{parse_csr_csv, parse_u32}; use tools::xous_arguments::XousArguments; @@ -138,6 +139,8 @@ fn main() { memory_required: 0, }; + let mut process_names = ProcessNames::new(); + if let Some(val) = matches.value_of("ram") { let ram_parts: Vec<&str> = val.split(':').collect(); if ram_parts.len() != 2 { @@ -224,8 +227,20 @@ fn main() { ) .expect("unable to read kernel"); + process_names.set(1, "kernel"); if let Some(init_paths) = matches.values_of("init") { + let mut pid = 2; for init_path in init_paths { + let program_name = std::path::Path::new(init_path); + process_names.set( + pid, + program_name + .file_stem() + .expect("program had no name") + .to_str() + .expect("program name is not valid utf-8"), + ); + pid += 1; let init = read_minielf(init_path).expect("couldn't parse init file"); args.add(IniE::new(init.entry_point, init.sections, init.program)); } @@ -242,6 +257,8 @@ fn main() { ); args.add(xkrn); + args.add(process_names); + // Add tags for init and kernel. These point to the actual data, which should // immediately follow the tags. Therefore, we must know the length of the tags // before we create them. diff --git a/tools/src/tags/mod.rs b/tools/src/tags/mod.rs index 4275ccec8..34b0fcb19 100644 --- a/tools/src/tags/mod.rs +++ b/tools/src/tags/mod.rs @@ -1,4 +1,5 @@ pub mod bflg; pub mod inie; pub mod memory; +pub mod pnam; pub mod xkrn; diff --git a/tools/src/tags/pnam.rs b/tools/src/tags/pnam.rs new file mode 100644 index 000000000..bc062152f --- /dev/null +++ b/tools/src/tags/pnam.rs @@ -0,0 +1,63 @@ +use crate::xous_arguments::{XousArgument, XousArgumentCode, XousSize}; +use std::fmt; +use std::io; +use std::collections::BTreeMap; + +#[derive(Debug)] +pub struct ProcessNames { + /// A vec of all known process names + names: BTreeMap, +} + +impl fmt::Display for ProcessNames { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, " process names:")?; + for (pid, name) in self.names.iter() { + writeln!(f, " PID {}: {}", pid, name)?; + } + Ok(()) + } +} + +impl ProcessNames { + pub fn new() -> ProcessNames { + ProcessNames { names: BTreeMap::new() } + } + + pub fn set(&mut self, pid: u32, name: &str) { + self.names.insert(pid, name.to_owned()); + } +} + +impl XousArgument for ProcessNames { + fn code(&self) -> XousArgumentCode { + u32::from_le_bytes(*b"PNam") + } + + fn length(&self) -> XousSize { + let mut size = 0; + for val in self.names.values() { + size += 4; + size += 4; + size += val.len(); + // Pad it to 4-bytes + size += (4-(val.len() & 3))&3; + } + size as XousSize + } + + fn serialize(&self, output: &mut dyn io::Write) -> io::Result { + let mut written = 0; + for (pid, name) in self.names.iter() { + written += output.write(&(*pid as u32).to_le_bytes())?; + written += output.write(&(name.len() as u32).to_le_bytes())?; + written += output.write(name.as_bytes())?; + + // Pad it to 4-bytes + for _ in 0..(4-(name.len() & 3))&3 { + written += output.write(&[0])?; + } + } + Ok(written) + } +}