add flags and DexString cmp
This commit is contained in:
parent
9788d77b74
commit
625420c5f6
3 changed files with 108 additions and 4 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
//! Representation of an apk.
|
//! Representation of an apk.
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{Class, Error, Result};
|
use crate::{Class, DexString, Error, Result};
|
||||||
use androscalpel_serializer::{ClassDefItem, DexFileReader, TypeList, NO_INDEX};
|
use androscalpel_serializer::*;
|
||||||
|
|
||||||
/// Represent an apk.
|
/// Represent an apk.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
|
@ -37,7 +37,7 @@ impl Apk {
|
||||||
dex.get_type_ids().len()
|
dex.get_type_ids().len()
|
||||||
)))?
|
)))?
|
||||||
.descriptor_idx;
|
.descriptor_idx;
|
||||||
let name = dex.get_string(name_idx)?.into();
|
let name: DexString = dex.get_string(name_idx)?.into();
|
||||||
let superclass = if class_item.class_idx == NO_INDEX.0 {
|
let superclass = if class_item.class_idx == NO_INDEX.0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -75,11 +75,41 @@ impl Apk {
|
||||||
} else {
|
} else {
|
||||||
Some(dex.get_string(class_item.source_file_idx)?.into())
|
Some(dex.get_string(class_item.source_file_idx)?.into())
|
||||||
};
|
};
|
||||||
|
let is_public = (class_item.access_flags & ACC_PUBLIC) != 0;
|
||||||
|
let is_final = (class_item.access_flags & ACC_FINAL) != 0;
|
||||||
|
let is_interface = (class_item.access_flags & ACC_INTERFACE) != 0;
|
||||||
|
let is_abstract = (class_item.access_flags & ACC_ABSTRACT) != 0;
|
||||||
|
let is_synthetic = (class_item.access_flags & ACC_SYNTHETIC) != 0;
|
||||||
|
let is_annotation = (class_item.access_flags & ACC_ANNOTATION) != 0;
|
||||||
|
let is_enum = (class_item.access_flags & ACC_ENUM) != 0;
|
||||||
|
if (class_item.access_flags
|
||||||
|
& !(ACC_PUBLIC
|
||||||
|
| ACC_FINAL
|
||||||
|
| ACC_INTERFACE
|
||||||
|
| ACC_ABSTRACT
|
||||||
|
| ACC_SYNTHETIC
|
||||||
|
| ACC_ANNOTATION
|
||||||
|
| ACC_ENUM))
|
||||||
|
!= 0
|
||||||
|
{
|
||||||
|
println!(
|
||||||
|
"Unexpected flags found in class_def_item.access_flags for {}: 0x{:x}",
|
||||||
|
<&DexString as Into<String>>::into(&name),
|
||||||
|
class_item.access_flags
|
||||||
|
); // TODO: better logging
|
||||||
|
}
|
||||||
self.classes.push(Class {
|
self.classes.push(Class {
|
||||||
name,
|
name,
|
||||||
superclass,
|
superclass,
|
||||||
interfaces,
|
interfaces,
|
||||||
source_file,
|
source_file,
|
||||||
|
is_public,
|
||||||
|
is_final,
|
||||||
|
is_interface,
|
||||||
|
is_abstract,
|
||||||
|
is_synthetic,
|
||||||
|
is_annotation,
|
||||||
|
is_enum,
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,41 @@ use crate::DexString;
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
|
/// Type name, format described at
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub name: DexString,
|
pub name: DexString,
|
||||||
// pub access_flags: // TODO
|
/// If the class is visible everywhere
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_public: bool, // TODO: is it possible to not be public non a non inner class?
|
||||||
|
/// If the class is subclassable
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_final: bool,
|
||||||
|
/// If the class is a 'multipy-implementable abstract class' AKA an interface
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_interface: bool,
|
||||||
|
/// If the class is instanciable
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_abstract: bool,
|
||||||
|
/// If the class is not directly defined in the source code
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_synthetic: bool,
|
||||||
|
/// If the class is an annotation
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_annotation: bool,
|
||||||
|
/// If the class is an enum
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_enum: bool,
|
||||||
|
/// Name of the superclass, format described at
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub superclass: Option<DexString>,
|
pub superclass: Option<DexString>,
|
||||||
|
/// List of the interfaces that class implement, format of the interfaces
|
||||||
|
/// name is discribed at
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub interfaces: Vec<DexString>,
|
pub interfaces: Vec<DexString>,
|
||||||
|
/// Name of the source file where this class is defined.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub source_file: Option<DexString>,
|
pub source_file: Option<DexString>,
|
||||||
// pub annotations: Option<()> // TODO
|
// pub annotations: Option<()> // TODO
|
||||||
|
|
@ -32,6 +60,13 @@ impl Class {
|
||||||
superclass: None,
|
superclass: None,
|
||||||
interfaces: vec![],
|
interfaces: vec![],
|
||||||
source_file: None,
|
source_file: None,
|
||||||
|
is_public: true,
|
||||||
|
is_final: false,
|
||||||
|
is_interface: false,
|
||||||
|
is_abstract: false,
|
||||||
|
is_synthetic: false,
|
||||||
|
is_annotation: false,
|
||||||
|
is_enum: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use pyo3::class::basic::CompareOp;
|
||||||
use pyo3::exceptions::PyValueError;
|
use pyo3::exceptions::PyValueError;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
|
@ -93,11 +94,49 @@ impl From<DexString> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&str> for DexString {
|
||||||
|
fn from(string: &str) -> Self {
|
||||||
|
Self(string.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for DexString {
|
||||||
|
fn from(string: String) -> Self {
|
||||||
|
Self(string.as_str().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl DexString {
|
impl DexString {
|
||||||
|
#[new]
|
||||||
|
pub fn new(s: &str) -> Self {
|
||||||
|
s.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the binary mutf-8 encoded string (minus the trailling 0)
|
||||||
|
pub fn get_bytes(&self) -> &[u8] {
|
||||||
|
&self.0.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the 'utf-16' size of the string (number of unicode code point, ie its lenght in 'java-land')
|
||||||
|
pub fn get_utf16_size(&self) -> u32 {
|
||||||
|
self.0.utf16_size.0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
pub fn __str__(&self) -> String {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn __richcmp__(&self, other: &PyAny, op: CompareOp, py: Python<'_>) -> PyResult<PyObject> {
|
||||||
|
let other: Self = other
|
||||||
|
.extract()
|
||||||
|
.or(<String as FromPyObject>::extract(other).map(|string| string.into()))?;
|
||||||
|
match op {
|
||||||
|
CompareOp::Eq => Ok((self == &other).into_py(py)),
|
||||||
|
_ => Ok(py.NotImplemented()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue