diff --git a/crates/noxis-analysis/src/keep.rs b/crates/noxis-analysis/src/keep.rs index 2addd9f..bdb9ad2 100644 --- a/crates/noxis-analysis/src/keep.rs +++ b/crates/noxis-analysis/src/keep.rs @@ -1,7 +1,7 @@ //! Keep-правила: что нельзя переименовывать (glob-паттерны + entrypoint'ы). -use regex::Regex; use noxis_classfile::{Attribute, Const, Program}; +use regex::Regex; use crate::entrypoints::Entrypoints; use noxis_core::Config; diff --git a/crates/noxis-classfile/tests/roundtrip.rs b/crates/noxis-classfile/tests/roundtrip.rs index a3eef33..f24d27b 100644 --- a/crates/noxis-classfile/tests/roundtrip.rs +++ b/crates/noxis-classfile/tests/roundtrip.rs @@ -6,6 +6,7 @@ #![allow(clippy::expect_used, clippy::unwrap_used)] +use noxis_classfile::{ClassFile, format}; use ristretto_classfile::attributes::{ Attribute as RtAttr, BootstrapMethod as RtBsm, ExceptionTableEntry as RtEntry, Instruction as Rt, LineNumber as RtLine, StackFrame as RtFrame, @@ -14,7 +15,6 @@ use ristretto_classfile::{ ClassAccessFlags, ClassFile as RtClass, ConstantPool, Field as RtField, FieldAccessFlags, FieldType, JAVA_21, Method as RtMethod, MethodAccessFlags, ReferenceKind, }; -use noxis_classfile::{ClassFile, format}; /// Минимальный класс: версия, флаги, поле с `ConstantValue`, `SourceFile`. #[test] diff --git a/crates/noxis-core/src/pipeline/mod.rs b/crates/noxis-core/src/pipeline/mod.rs index 920745b..b8be11e 100644 --- a/crates/noxis-core/src/pipeline/mod.rs +++ b/crates/noxis-core/src/pipeline/mod.rs @@ -3,8 +3,8 @@ pub mod context; pub mod report; -use serde::Serialize; use noxis_classfile::Program; +use serde::Serialize; use self::context::Context; use self::report::Report; diff --git a/crates/noxis-verify/src/metrics.rs b/crates/noxis-verify/src/metrics.rs index 85a019d..958c6a3 100644 --- a/crates/noxis-verify/src/metrics.rs +++ b/crates/noxis-verify/src/metrics.rs @@ -1,8 +1,8 @@ //! Метрики программы: счётчики, раздувание, стабильность маппингов. -use serde::Serialize; use noxis_classfile::{Const, Insn, Program}; use noxis_core::Mapping; +use serde::Serialize; /// Счётчики программы (для отчёта и бюджетов). #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)] diff --git a/crates/noxis/examples/dbg.rs b/crates/noxis/examples/dbg.rs index dc9aa4e..8c930ba 100644 --- a/crates/noxis/examples/dbg.rs +++ b/crates/noxis/examples/dbg.rs @@ -1,11 +1,38 @@ -fn rd_u16(b: &[u8], p: &mut usize) -> u16 { let v = u16::from_be_bytes([b[*p], b[*p+1]]); *p += 2; v } -fn rd_u32(b: &[u8], p: &mut usize) -> u32 { let v = u32::from_be_bytes([b[*p], b[*p+1], b[*p+2], b[*p+3]]); *p += 4; v } -fn hex(b: &[u8]) -> String { b.iter().map(|x| format!("{x:02x}")).collect::>().join(" ") } +//! Одноразовый отладочный обход байткода (scratch): ручной парсинг пула и +//! Code-атрибутов, вывод заголовков вложенных атрибутов. +#![allow(clippy::unwrap_used, clippy::expect_used)] + +fn rd_u16(b: &[u8], p: &mut usize) -> u16 { + let v = u16::from_be_bytes([b[*p], b[*p + 1]]); + *p += 2; + v +} +fn rd_u32(b: &[u8], p: &mut usize) -> u32 { + let v = u32::from_be_bytes([b[*p], b[*p + 1], b[*p + 2], b[*p + 3]]); + *p += 4; + v +} +fn hex(b: &[u8]) -> String { + b.iter() + .map(|x| format!("{x:02x}")) + .collect::>() + .join(" ") +} fn main() { - let entries = noxis_jar::read_file(std::path::Path::new("/storage/project/jvm/LoReport/build/libs/lorep-1.1.0.jar")).unwrap(); + let entries = noxis_jar::read_file(std::path::Path::new( + "/storage/project/jvm/LoReport/build/libs/lorep-1.1.0.jar", + )) + .unwrap(); let program = noxis_jar::load(entries).unwrap(); - let class = program.classes.iter().find(|c| c.this_class.ends_with("ReportStatsCommand")).unwrap(); - let prog = noxis_classfile::Program { classes: vec![class.clone()], resources: vec![] }; + let class = program + .classes + .iter() + .find(|c| c.this_class.ends_with("ReportStatsCommand")) + .unwrap(); + let prog = noxis_classfile::Program { + classes: vec![class.clone()], + resources: vec![], + }; let out = noxis_jar::save(&prog).unwrap(); let entry = out.iter().find(|e| e.name.ends_with(".class")).unwrap(); let bytes = &entry.data; @@ -17,26 +44,45 @@ fn main() { let mut utf8s: std::collections::BTreeMap = Default::default(); let mut idx = 1u16; while idx < pool_count { - let tag = bytes[pos]; pos += 1; + let tag = bytes[pos]; + pos += 1; match tag { - 1 => { let len = rd_u16(bytes, &mut pos) as usize; utf8s.insert(idx, String::from_utf8_lossy(&bytes[pos..pos+len]).into_owned()); pos += len; } + 1 => { + let len = rd_u16(bytes, &mut pos) as usize; + utf8s.insert( + idx, + String::from_utf8_lossy(&bytes[pos..pos + len]).into_owned(), + ); + pos += len; + } 3 | 4 => pos += 4, - 5 | 6 => { pos += 8; idx += 1; } + 5 | 6 => { + pos += 8; + idx += 1; + } 7 | 8 | 16 | 19 | 20 => pos += 2, 9 | 10 | 11 | 12 | 17 | 18 => pos += 4, 15 => pos += 3, - _ => { eprintln!("pool tag {tag}"); return; } + _ => { + eprintln!("pool tag {tag}"); + return; + } } idx += 1; } let name_of = |i: u16| utf8s.get(&i).cloned().unwrap_or(format!("#{i}")); pos += 6; - let ifaces = rd_u16(bytes, &mut pos); pos += 2 * ifaces as usize; + let ifaces = rd_u16(bytes, &mut pos); + pos += 2 * ifaces as usize; let fields = rd_u16(bytes, &mut pos); for _ in 0..fields { pos += 6; let n = rd_u16(bytes, &mut pos); - for _ in 0..n { pos += 2; let l = rd_u32(bytes, &mut pos); pos += l as usize; } + for _ in 0..n { + pos += 2; + let l = rd_u32(bytes, &mut pos); + pos += l as usize; + } } let methods = rd_u16(bytes, &mut pos); for _ in 0..methods { @@ -60,7 +106,11 @@ fn main() { for _ in 0..subn { let sname = rd_u16(bytes, &mut pos); let slen = rd_u32(bytes, &mut pos) as usize; - eprintln!("{mname}: sub={} len={slen} head=[{}]", name_of(sname), hex(&bytes[pos..pos+slen.min(24)])); + eprintln!( + "{mname}: sub={} len={slen} head=[{}]", + name_of(sname), + hex(&bytes[pos..pos + slen.min(24)]) + ); pos += slen; } assert_eq!(pos, start + alen, "Code length mismatch in {mname}");