Initial commit: noxis JVM bytecode obfuscator
Workspace of 9 crates (noxis, noxis-core, noxis-classfile, noxis-analysis, noxis-passes, noxis-runtime, noxis-jar, noxis-verify, noxis-structure-check). AGPL-3.0-only license, Rust 2024 edition, unsafe_code denied.
This commit is contained in:
commit
a641e69455
140 changed files with 17197 additions and 0 deletions
93
crates/noxis-classfile/src/format/write/mod.rs
Normal file
93
crates/noxis-classfile/src/format/write/mod.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//! Наш IR → байты `.class` через backend `ristretto_classfile`.
|
||||
//!
|
||||
//! Пул собирается с нуля детерминированным обходом; backend сам пересчитывает
|
||||
//! номера инструкций в байтовые смещения и проверяет результат (`verify`).
|
||||
|
||||
mod attrs;
|
||||
pub(crate) mod code;
|
||||
pub(crate) mod pool;
|
||||
|
||||
use ristretto_classfile::{
|
||||
ClassAccessFlags, ClassFile as RtClass, Field as RtField, FieldAccessFlags, FieldType,
|
||||
Method as RtMethod, MethodAccessFlags, Version as RtVersion,
|
||||
};
|
||||
|
||||
use crate::error::ClassfileError;
|
||||
use crate::model::{ClassFile, Field, Method};
|
||||
|
||||
/// Класс нашего IR → байты `.class`.
|
||||
pub(crate) fn write_class(class: &ClassFile) -> Result<Vec<u8>, ClassfileError> {
|
||||
let mut pool = pool::Pool::new();
|
||||
let version = RtVersion::from(class.version.major, class.version.minor)
|
||||
.map_err(|e| ClassfileError::Write(e.to_string()))?;
|
||||
let this_class = pool.class(&class.this_class)?;
|
||||
let super_class = match &class.super_class {
|
||||
None => 0,
|
||||
Some(name) => pool.class(name)?,
|
||||
};
|
||||
let mut interfaces = Vec::with_capacity(class.interfaces.len());
|
||||
for interface in &class.interfaces {
|
||||
interfaces.push(pool.class(interface)?);
|
||||
}
|
||||
let mut fields = Vec::with_capacity(class.fields.len());
|
||||
for field in &class.fields {
|
||||
fields.push(convert_field(field, &mut pool)?);
|
||||
}
|
||||
let mut methods = Vec::with_capacity(class.methods.len());
|
||||
for method in &class.methods {
|
||||
methods.push(convert_method(method, &mut pool)?);
|
||||
}
|
||||
let mut attributes = Vec::with_capacity(class.attributes.len());
|
||||
for attr in &class.attributes {
|
||||
attributes.push(attrs::convert(attr, &mut pool)?);
|
||||
}
|
||||
let rt = RtClass {
|
||||
version,
|
||||
constant_pool: pool.finish(),
|
||||
access_flags: ClassAccessFlags::from_bits_truncate(class.access_flags),
|
||||
this_class,
|
||||
super_class,
|
||||
interfaces,
|
||||
fields,
|
||||
methods,
|
||||
attributes,
|
||||
code_source_url: None,
|
||||
};
|
||||
rt.verify()
|
||||
.map_err(|e| ClassfileError::Write(format!("собранный класс не верифицируется: {e}")))?;
|
||||
let mut bytes = Vec::new();
|
||||
rt.to_bytes(&mut bytes)
|
||||
.map_err(|e| ClassfileError::Write(e.to_string()))?;
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn convert_field(field: &Field, pool: &mut pool::Pool) -> Result<RtField, ClassfileError> {
|
||||
Ok(RtField {
|
||||
access_flags: FieldAccessFlags::from_bits_truncate(field.access_flags),
|
||||
name_index: pool.utf8(&field.name)?,
|
||||
descriptor_index: pool.utf8(&field.descriptor)?,
|
||||
field_type: FieldType::parse(&field.descriptor)
|
||||
.map_err(|e| ClassfileError::Write(format!("кривой дескриптор поля: {e}")))?,
|
||||
attributes: field
|
||||
.attributes
|
||||
.iter()
|
||||
.map(|attr| attrs::convert(attr, pool))
|
||||
.collect::<Result<_, _>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_method(method: &Method, pool: &mut pool::Pool) -> Result<RtMethod, ClassfileError> {
|
||||
let mut attributes = Vec::with_capacity(method.attributes.len() + 1);
|
||||
for attr in &method.attributes {
|
||||
attributes.push(attrs::convert(attr, pool)?);
|
||||
}
|
||||
if let Some(code) = &method.code {
|
||||
attributes.push(code::convert_code(code, pool)?);
|
||||
}
|
||||
Ok(RtMethod {
|
||||
access_flags: MethodAccessFlags::from_bits_truncate(method.access_flags),
|
||||
name_index: pool.utf8(&method.name)?,
|
||||
descriptor_index: pool.utf8(&method.descriptor)?,
|
||||
attributes,
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue