From 9086221bac10e56ad7387ef9892a3f71a2c73f44 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 26 Nov 2023 11:56:25 +0100 Subject: [PATCH] Improve binary support (#552) * Remove 0X notation * Fix method name * Add binary * Replace {:#x} with {:#X} * Replace {:#016x} with {:#016X} * Rewrite print_hex * Use offset in elf command * Replace remaining ':#x' format --- src/sys/acpi.rs | 6 ++--- src/sys/allocator.rs | 2 +- src/sys/fs/block.rs | 4 +-- src/sys/idt.rs | 2 +- src/sys/process.rs | 10 +++---- src/sys/syscall/service.rs | 4 +-- src/usr/elf.rs | 6 ++--- src/usr/hex.rs | 54 ++++++++++++++++++++------------------ src/usr/lisp/mod.rs | 7 +++-- src/usr/lisp/number.rs | 20 +++++++++----- src/usr/lisp/parse.rs | 16 +++++++++-- 11 files changed, 79 insertions(+), 52 deletions(-) diff --git a/src/sys/acpi.rs b/src/sys/acpi.rs index a65abd7d5..3e0331bc4 100644 --- a/src/sys/acpi.rs +++ b/src/sys/acpi.rs @@ -26,12 +26,12 @@ pub fn shutdown() { if let Ok(fadt) = acpi.find_table::() { if let Ok(block) = fadt.pm1a_control_block() { pm1a_control_block = block.address as u32; - //debug!("ACPI Found PM1a Control Block: {:#x}", pm1a_control_block); + //debug!("ACPI Found PM1a Control Block: {:#X}", pm1a_control_block); } } if let Ok(dsdt) = &acpi.dsdt() { let address = sys::mem::phys_to_virt(PhysAddr::new(dsdt.address as u64)); - //debug!("ACPI Found DSDT at {:#x} {:#x}", dsdt.address, address); + //debug!("ACPI Found DSDT at {:#X} {:#X}", dsdt.address, address); let table = unsafe { core::slice::from_raw_parts(address.as_ptr(), dsdt.length as usize) }; if aml.parse_table(table).is_ok() { let name = AmlName::from_str("\\_S5").unwrap(); @@ -69,7 +69,7 @@ pub struct MorosAcpiHandler; impl AcpiHandler for MorosAcpiHandler { unsafe fn map_physical_region(&self, physical_address: usize, size: usize) -> PhysicalMapping { let virtual_address = sys::mem::phys_to_virt(PhysAddr::new(physical_address as u64)); - //debug!("ACPI mapping phys {:#x} -> virt {:#x}", physical_address, virtual_address); + //debug!("ACPI mapping phys {:#X} -> virt {:#X}", physical_address, virtual_address); PhysicalMapping::new(physical_address, NonNull::new(virtual_address.as_mut_ptr()).unwrap(), size, size, Self) } diff --git a/src/sys/allocator.rs b/src/sys/allocator.rs index 7c006a610..018c8cc82 100644 --- a/src/sys/allocator.rs +++ b/src/sys/allocator.rs @@ -55,7 +55,7 @@ pub fn init_heap() -> Result<(), MapToError> { } pub fn alloc_pages(mapper: &mut OffsetPageTable, addr: u64, size: usize) -> Result<(), ()> { - //debug!("Alloc pages (addr={:#x}, size={})", addr, size); + //debug!("Alloc pages (addr={:#X}, size={})", addr, size); let mut frame_allocator = sys::mem::frame_allocator(); let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER_ACCESSIBLE; let pages = { diff --git a/src/sys/fs/block.rs b/src/sys/fs/block.rs index 8ec04e0e3..ab4f5890f 100644 --- a/src/sys/fs/block.rs +++ b/src/sys/fs/block.rs @@ -44,7 +44,7 @@ impl Block { let mut buf = [0; super::BLOCK_SIZE]; if let Some(ref mut block_device) = *super::block_device::BLOCK_DEVICE.lock() { if block_device.read(addr, &mut buf).is_err() { - debug!("MFS: could not read block {:#x}", addr); + debug!("MFS: could not read block {:#X}", addr); } } Self { addr, buf } @@ -53,7 +53,7 @@ impl Block { pub fn write(&self) { if let Some(ref mut block_device) = *super::block_device::BLOCK_DEVICE.lock() { if block_device.write(self.addr, &self.buf).is_err() { - debug!("MFS: could not write block {:#x}", self.addr); + debug!("MFS: could not write block {:#X}", self.addr); } } } diff --git a/src/sys/idt.rs b/src/sys/idt.rs index ab0eb50fd..0342cdb38 100644 --- a/src/sys/idt.rs +++ b/src/sys/idt.rs @@ -120,7 +120,7 @@ extern "x86-interrupt" fn page_fault_handler(_stack_frame: InterruptStackFrame, if sys::allocator::alloc_pages(&mut mapper, addr, 1).is_err() { let csi_color = api::console::Style::color("LightRed"); let csi_reset = api::console::Style::reset(); - printk!("{}Error:{} Could not allocate address {:#x}\n", csi_color, csi_reset, addr); + printk!("{}Error:{} Could not allocate address {:#X}\n", csi_color, csi_reset, addr); if error_code.contains(PageFaultErrorCode::USER_MODE) { api::syscall::exit(ExitCode::PageFaultError); } else { diff --git a/src/sys/process.rs b/src/sys/process.rs index ba279d73b..a347ad2a0 100644 --- a/src/sys/process.rs +++ b/src/sys/process.rs @@ -341,8 +341,8 @@ impl Process { let proc_size = MAX_PROC_SIZE as u64; let code_addr = CODE_ADDR.fetch_add(proc_size, Ordering::SeqCst); let stack_addr = code_addr + proc_size - 4096; - //debug!("code_addr: {:#x}", code_addr); - //debug!("stack_addr: {:#x}", stack_addr); + //debug!("code_addr: {:#X}", code_addr); + //debug!("stack_addr: {:#X}", stack_addr); let mut entry_point_addr = 0; let code_ptr = code_addr as *mut u8; @@ -356,7 +356,7 @@ impl Process { let addr = segment.address() as usize; if let Ok(data) = segment.data() { for (i, b) in data.iter().enumerate() { - //debug!("code: {:#x}", unsafe { code_ptr.add(addr + i) as usize }); + //debug!("code: {:#X}", unsafe { code_ptr.add(addr + i) as usize }); unsafe { core::ptr::write(code_ptr.add(addr + i), *b) }; } } @@ -401,7 +401,7 @@ impl Process { let mut mapper = unsafe { OffsetPageTable::new(page_table, VirtAddr::new(phys_mem_offset)) }; let heap_addr = self.code_addr + (self.stack_addr - self.code_addr) / 2; - //debug!("user-args: {:#016x}", heap_addr); + //debug!("user-args: {:#016X}", heap_addr); sys::allocator::alloc_pages(&mut mapper, heap_addr, 1).expect("proc heap alloc"); let args_ptr = ptr_from_addr(args_ptr as u64) as usize; @@ -429,7 +429,7 @@ impl Process { let heap_addr = addr; let heap_size = (self.stack_addr - heap_addr) / 2; - //debug!("user-heap: {:#016x}..{:#016x}", heap_addr, heap_addr + heap_size); + //debug!("user-heap: {:#016X}..{:#016X}", heap_addr, heap_addr + heap_size); unsafe { self.allocator.lock().init(heap_addr as *mut u8, heap_size as usize) }; set_id(self.id); // Change PID diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index f28bb1a3a..6264c26b7 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -90,7 +90,7 @@ pub fn close(handle: usize) { } pub fn spawn(path: &str, args_ptr: usize, args_len: usize) -> ExitCode { - //debug!("syscall::spawn(path={}, args_ptr={:#x}, args_len={})", path, args_ptr, args_len); + //debug!("syscall::spawn(path={}, args_ptr={:#X}, args_len={})", path, args_ptr, args_len); let path = match sys::fs::canonicalize(path) { Ok(path) => path, Err(_) => return ExitCode::OpenError, @@ -127,7 +127,7 @@ pub fn stop(code: usize) -> usize { sys::acpi::shutdown(); } _ => { - debug!("STOP SYSCALL: Invalid code '{:#x}' received", code); + debug!("STOP SYSCALL: Invalid code '{:#X}' received", code); } } 0 diff --git a/src/usr/elf.rs b/src/usr/elf.rs index b0bbf302a..8f3c0f268 100644 --- a/src/usr/elf.rs +++ b/src/usr/elf.rs @@ -21,7 +21,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { if let Ok(buf) = fs::read_to_bytes(pathname) { let bin = buf.as_slice(); if let Ok(obj) = object::File::parse(bin) { - println!("ELF entry address: {:#x}", obj.entry()); + println!("ELF entry address: {:#X}", obj.entry()); for section in obj.sections() { if let Ok(name) = section.name() { if name.is_empty() { @@ -31,9 +31,9 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { let size = section.size(); let align = section.align(); println!(); - println!("{}{}{} (addr: {:#x}, size: {}, align: {})", color, name, reset, addr, size, align); + println!("{}{}{} (addr: {:#X}, size: {}, align: {})", color, name, reset, addr, size, align); if let Ok(data) = section.data() { - usr::hex::print_hex(data); + usr::hex::print_hex_at(data, addr); } } } diff --git a/src/usr/hex.rs b/src/usr/hex.rs index 686c5fac5..553096e93 100644 --- a/src/usr/hex.rs +++ b/src/usr/hex.rs @@ -2,6 +2,10 @@ use crate::api::fs; use crate::api::console::Style; use crate::api::process::ExitCode; +use alloc::format; +use alloc::string::String; +use alloc::vec::Vec; + // TODO: add `--skip` and `--length` params pub fn main(args: &[&str]) -> Result<(), ExitCode> { if args.len() != 2 { @@ -24,32 +28,32 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { // TODO: move this to api::hex::print_hex pub fn print_hex(buf: &[u8]) { - let n = buf.len() / 2; - for i in 0..n { - print!("{}", Style::color("LightCyan")); - if i % 8 == 0 { - print!("{:08X}: ", i * 2); - } - print!("{}", Style::color("Pink")); - print!("{:02X}{:02X} ", buf[i * 2], buf[i * 2 + 1]); - print!("{}", Style::reset()); - if i % 8 == 7 || i == n - 1 { - for _ in 0..(7 - (i % 8)) { - print!(" "); - } - let m = ((i % 8) + 1) * 2; - for j in 0..m { - let c = buf[(i * 2 + 1) - (m - 1) + j] as char; - if c.is_ascii_graphic() { - print!("{}", c); - } else if c.is_ascii_whitespace() { - print!(" "); - } else { - print!("."); - } + print_hex_at(buf, 0) +} + +pub fn print_hex_at(buf: &[u8], offset: usize) { + let cyan = Style::color("LightCyan"); + let pink = Style::color("Pink"); + let reset = Style::reset(); + + for (index, chunk) in buf.chunks(16).enumerate() { + let addr = offset + index * 16; + + let hex = chunk.chunks(2).map(|pair| + pair.iter().map(|byte| + format!("{:02X}", byte) + ).collect::>().join("") + ).collect::>().join(" "); + + let ascii: String = chunk.iter().map(|byte| + if *byte >= 32 && *byte <= 126 { + *byte as char + } else { + '.' } - println!(); - } + ).collect(); + + println!("{}{:08X}: {}{:40}{}{}", cyan, addr, pink, hex, reset, ascii); } } diff --git a/src/usr/lisp/mod.rs b/src/usr/lisp/mod.rs index 3302ee235..facc1fd83 100644 --- a/src/usr/lisp/mod.rs +++ b/src/usr/lisp/mod.rs @@ -347,7 +347,10 @@ fn test_lisp() { assert_eq!(eval!("0x10"), "16"); assert_eq!(eval!("1.5"), "1.5"); assert_eq!(eval!("0xff"), "255"); - assert_eq!(eval!("0XFF"), "255"); + assert_eq!(eval!("0b0"), "0"); + assert_eq!(eval!("0b1"), "1"); + assert_eq!(eval!("0b10"), "2"); + assert_eq!(eval!("0b11"), "3"); assert_eq!(eval!("-6"), "-6"); assert_eq!(eval!("-16"), "-16"); @@ -356,7 +359,7 @@ fn test_lisp() { assert_eq!(eval!("-0x10"), "-16"); assert_eq!(eval!("-1.5"), "-1.5"); assert_eq!(eval!("-0xff"), "-255"); - assert_eq!(eval!("-0XFF"), "-255"); + assert_eq!(eval!("-0b11"), "-3"); // quote assert_eq!(eval!("(quote (1 2 3))"), "(1 2 3)"); diff --git a/src/usr/lisp/number.rs b/src/usr/lisp/number.rs index 7a06481ec..b2b3d6357 100644 --- a/src/usr/lisp/number.rs +++ b/src/usr/lisp/number.rs @@ -200,20 +200,28 @@ operator!(Shl, shl); operator!(Shr, shr); fn parse_int(s: &str) -> Result { - if s.starts_with("0x") || s.starts_with("0X") { + if s.starts_with("0x") { i64::from_str_radix(&s[2..], 16) - } else if s.starts_with("-0x") || s.starts_with("-0X") { + } else if s.starts_with("-0x") { i64::from_str_radix(&s[3..], 16).map(|n| -n) + } else if s.starts_with("0b") { + i64::from_str_radix(&s[2..], 2) + } else if s.starts_with("-0b") { + i64::from_str_radix(&s[3..], 2).map(|n| -n) } else { i64::from_str_radix(s, 10) } } -fn parse_float(s: &str) -> Result { - if s.starts_with("0x") || s.starts_with("0X") { +fn parse_bigint(s: &str) -> Result { + if s.starts_with("0x") { BigInt::from_str_radix(&s[2..], 16) - } else if s.starts_with("-0x") || s.starts_with("-0X") { + } else if s.starts_with("-0x") { BigInt::from_str_radix(&s[3..], 16).map(|n| -n) + } else if s.starts_with("0b") { + BigInt::from_str_radix(&s[2..], 2) + } else if s.starts_with("-0b") { + BigInt::from_str_radix(&s[3..], 2).map(|n| -n) } else { BigInt::from_str_radix(s, 10) } @@ -234,7 +242,7 @@ impl FromStr for Number { } } else if let Ok(n) = parse_int(s) { Ok(Number::Int(n)) - } else if let Ok(n) = parse_float(s) { + } else if let Ok(n) = parse_bigint(s) { Ok(Number::BigInt(n)) } else { err diff --git a/src/usr/lisp/parse.rs b/src/usr/lisp/parse.rs index fda0bd966..6b15034a5 100644 --- a/src/usr/lisp/parse.rs +++ b/src/usr/lisp/parse.rs @@ -29,7 +29,7 @@ use nom::sequence::terminated; // https://docs.rs/nom/latest/nom/recipes/index.html#hexadecimal fn hexadecimal(input: &str) -> IResult<&str, &str> { preceded( - alt((tag("0x"), tag("0X"))), + tag("0x"), recognize( many1( terminated(one_of("0123456789abcdefABCDEF"), many0(char('_'))) @@ -47,6 +47,18 @@ fn decimal(input: &str) -> IResult<&str, &str> { )(input) } +// https://docs.rs/nom/latest/nom/recipes/index.html#binary +fn binary(input: &str) -> IResult<&str, &str> { + preceded( + tag("0b"), + recognize( + many1( + terminated(one_of("01"), many0(char('_'))) + ) + ) + )(input) +} + // https://docs.rs/nom/latest/nom/recipes/index.html#floating-point-numbers fn float(input: &str) -> IResult<&str, &str> { alt(( @@ -108,7 +120,7 @@ fn parse_sym(input: &str) -> IResult<&str, Exp> { fn parse_num(input: &str) -> IResult<&str, Exp> { let (input, num) = recognize(tuple(( opt(alt((char('+'), char('-')))), - alt((float, hexadecimal, decimal)) + alt((float, hexadecimal, binary, decimal)) )))(input)?; Ok((input, Exp::Num(Number::from(num)))) }