add a rought implem of code
This commit is contained in:
parent
026b9ddd41
commit
80968c9bcf
7 changed files with 198 additions and 13 deletions
|
|
@ -1,6 +1,6 @@
|
|||
//! Representation of an apk.
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use log::info;
|
||||
|
|
@ -280,7 +280,7 @@ impl Apk {
|
|||
))
|
||||
}
|
||||
|
||||
/// Return a [`Vec<DexAnnotationItem>`] for the offset of an [`AnnotationSet`].
|
||||
/// Return a [`Vec<DexAnnotationItem>`] for the offset of an [`AnnotationSetItem`].
|
||||
pub fn get_annotation_items_from_annotation_set_off(
|
||||
annotations_set_off: u32,
|
||||
dex: &DexFileReader,
|
||||
|
|
@ -577,7 +577,7 @@ impl Apk {
|
|||
pub fn get_method_from_idx(
|
||||
idx: usize,
|
||||
Uleb128(access_flags): Uleb128,
|
||||
Uleb128(_code_off): Uleb128,
|
||||
Uleb128(code_off): Uleb128,
|
||||
dex: &DexFileReader,
|
||||
) -> Result<Method> {
|
||||
let descriptor = Self::get_id_method_from_idx(idx, dex)?;
|
||||
|
|
@ -648,6 +648,13 @@ impl Apk {
|
|||
| ACC_DECLARED_SYNCHRONIZED)
|
||||
);
|
||||
}
|
||||
let code = if code_off == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Self::get_code_from_off(code_off, dex).with_context(|| {
|
||||
format!("Failed to parse code of method {}", descriptor.__str__())
|
||||
})?)
|
||||
};
|
||||
|
||||
Ok(Method {
|
||||
descriptor,
|
||||
|
|
@ -665,7 +672,56 @@ impl Apk {
|
|||
is_declared_syncrhonized,
|
||||
annotations: vec![],
|
||||
parameters_annotations: vec![],
|
||||
code: (),
|
||||
code,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return a [`Code`] from it's offset in the dex file.
|
||||
pub fn get_code_from_off(offset: u32, dex: &DexFileReader) -> Result<Code> {
|
||||
let code_item = dex.get_struct_at_offset::<CodeItem>(offset)?;
|
||||
let debug_info = if code_item.debug_info_off == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
dex.get_struct_at_offset::<DebugInfoItem>(code_item.debug_info_off)?
|
||||
.serialize_to_vec()? // no dealing with that right now
|
||||
};
|
||||
let mut tries = vec![];
|
||||
for TryItem {
|
||||
start_addr,
|
||||
insn_count,
|
||||
handler_off,
|
||||
} in code_item.tries
|
||||
{
|
||||
tries.push((start_addr, insn_count, handler_off));
|
||||
}
|
||||
let mut handlers_aux = vec![];
|
||||
if let Some(EncodedCatchHandlerList { list }) = code_item.handlers {
|
||||
for EncodedCatchHandler {
|
||||
handlers,
|
||||
catch_all_addr,
|
||||
} in list
|
||||
{
|
||||
let mut handlers_ = vec![];
|
||||
let catch_all_addr = catch_all_addr.map(|Uleb128(val)| val);
|
||||
for EncodedTypeAddrPair {
|
||||
type_idx: Uleb128(type_idx),
|
||||
addr: Uleb128(addr),
|
||||
} in handlers
|
||||
{
|
||||
handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, addr))
|
||||
}
|
||||
handlers_aux.push((handlers_, catch_all_addr));
|
||||
}
|
||||
}
|
||||
let handlers = handlers_aux;
|
||||
Ok(Code {
|
||||
registers_size: code_item.registers_size,
|
||||
ins_size: code_item.ins_size,
|
||||
outs_size: code_item.outs_size,
|
||||
debug_info,
|
||||
insns: code_item.insns,
|
||||
tries,
|
||||
handlers,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
63
androscalpel/src/code.rs
Normal file
63
androscalpel/src/code.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//! Representation of a method.
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::IdType;
|
||||
|
||||
// TODO: make this easy to edit/manipulate, maybe move to Method
|
||||
|
||||
type TmpHandlerType = (Vec<(IdType, u32)>, Option<u32>);
|
||||
|
||||
/// The code run by a method.
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Code {
|
||||
// TODO: remove and compute this value from code.
|
||||
/// The number of registers used by the code
|
||||
#[pyo3(get, set)]
|
||||
pub registers_size: u16,
|
||||
// TODO: what does it means? is it computable?
|
||||
/// The number of words of incoming arguments to the method
|
||||
#[pyo3(get, set)]
|
||||
pub ins_size: u16,
|
||||
// TODO: what does it means? is it computable?
|
||||
/// The number of words of outgoing argument space
|
||||
#[pyo3(get, set)]
|
||||
pub outs_size: u16,
|
||||
// TODO: implement
|
||||
/// The debug info
|
||||
#[pyo3(get, set)]
|
||||
pub debug_info: Vec<u8>,
|
||||
// TODO: implement OPcode
|
||||
/// The instructions.
|
||||
#[pyo3(get, set)]
|
||||
pub insns: Vec<u16>,
|
||||
// TODO: currently unusable, juste a mapping ty TryItem
|
||||
// TODO: maybe implement as custom OPcode to make me easy to modify?
|
||||
/// Try blocks
|
||||
#[pyo3(get, set)]
|
||||
pub tries: Vec<(u32, u16, u16)>,
|
||||
// TODO: currently unusable, juste a mapping ty TryItem
|
||||
// TODO: maybe implement as custom OPcode to make me easy to modify?
|
||||
/// The handlers associated to the tries blocks.
|
||||
#[pyo3(get, set)]
|
||||
pub handlers: Vec<TmpHandlerType>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Code {
|
||||
/*
|
||||
#[new]
|
||||
pub fn new() -> Self {
|
||||
todo!()
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn __str__(&self) -> String {
|
||||
self.__repr__()
|
||||
}
|
||||
|
||||
pub fn __repr__(&self) -> String {
|
||||
"Code()".into()
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ use pyo3::prelude::*;
|
|||
pub mod annotation;
|
||||
pub mod apk;
|
||||
pub mod class;
|
||||
pub mod code;
|
||||
pub mod dex_id;
|
||||
pub mod dex_string;
|
||||
pub mod field;
|
||||
|
|
@ -16,6 +17,7 @@ pub mod value;
|
|||
pub use annotation::*;
|
||||
pub use apk::*;
|
||||
pub use class::*;
|
||||
pub use code::*;
|
||||
pub use dex_id::*;
|
||||
pub use dex_string::*;
|
||||
pub use field::*;
|
||||
|
|
@ -63,6 +65,7 @@ fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> {
|
|||
m.add_class::<Method>()?;
|
||||
m.add_class::<Field>()?;
|
||||
m.add_class::<Class>()?;
|
||||
m.add_class::<Code>()?;
|
||||
m.add_class::<Apk>()?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{DexAnnotationItem, IdMethod};
|
||||
use crate::{Code, DexAnnotationItem, IdMethod};
|
||||
|
||||
/// Represent a method.
|
||||
#[pyclass]
|
||||
|
|
@ -57,7 +57,7 @@ pub struct Method {
|
|||
pub parameters_annotations: Vec<Vec<DexAnnotationItem>>,
|
||||
|
||||
/// The code of the method
|
||||
pub code: (),
|
||||
pub code: Option<Code>,
|
||||
}
|
||||
|
||||
/// Represent the visibility of a field
|
||||
|
|
@ -74,6 +74,7 @@ pub enum MethodVisibility {
|
|||
impl Method {
|
||||
#[new]
|
||||
pub fn new(descriptor: IdMethod) -> Self {
|
||||
// TODO: take code option as arg and set the default flags accordingly
|
||||
Self {
|
||||
descriptor,
|
||||
visibility: MethodVisibility::Public,
|
||||
|
|
@ -90,7 +91,7 @@ impl Method {
|
|||
is_declared_syncrhonized: false,
|
||||
annotations: vec![],
|
||||
parameters_annotations: vec![],
|
||||
code: (),
|
||||
code: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue