factorize value parsing
This commit is contained in:
parent
cdf68c506a
commit
77be653786
4 changed files with 123 additions and 67 deletions
|
|
@ -133,6 +133,72 @@ impl Apk {
|
|||
})
|
||||
}
|
||||
|
||||
/// Return a [`IdType`] from its idx.
|
||||
pub fn get_id_type_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdType> {
|
||||
Ok(IdType(
|
||||
dex.get_string(dex.get_type_id(idx)?.descriptor_idx)?.into(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Return a [`IdMethodType`] from its idx.
|
||||
pub fn get_id_method_type_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdMethodType> {
|
||||
let proto = dex.get_proto_id(idx)?;
|
||||
let shorty: DexString = dex.get_string(proto.shorty_idx)?.into();
|
||||
let return_type: IdType = Self::get_id_type_from_idx(proto.return_type_idx as usize, dex)?;
|
||||
let parameters: Vec<IdType> = if proto.parameters_off == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
dex.get_struct_at_offset::<TypeList>(proto.parameters_off)?
|
||||
.list
|
||||
.iter()
|
||||
.map(|ty| Self::get_id_type_from_idx(ty.type_idx as usize, dex).clone())
|
||||
.collect::<Result<_>>()?
|
||||
};
|
||||
Ok(IdMethodType {
|
||||
shorty,
|
||||
return_type,
|
||||
parameters,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return a [`IdField`] from its idx.
|
||||
pub fn get_id_field_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdField> {
|
||||
let field = dex.get_field_id(idx)?;
|
||||
let name = dex.get_string(field.name_idx)?.into();
|
||||
let type_ = IdType(
|
||||
dex.get_string(dex.get_type_id(field.type_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
);
|
||||
let class_ = IdType(
|
||||
dex.get_string(dex.get_type_id(field.class_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
);
|
||||
Ok(IdField {
|
||||
name,
|
||||
type_,
|
||||
class_,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return a [`IdMethod`] from its idx.
|
||||
pub fn get_id_method_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdMethod> {
|
||||
let method_id = dex.get_method_id(idx)?;
|
||||
let class_ = IdType(
|
||||
dex.get_string(
|
||||
dex.get_type_id(method_id.class_idx as usize)?
|
||||
.descriptor_idx,
|
||||
)?
|
||||
.into(),
|
||||
);
|
||||
let proto = Self::get_id_method_type_from_idx(method_id.proto_idx as usize, dex)?;
|
||||
let name = dex.get_string(method_id.name_idx)?.into();
|
||||
Ok(IdMethod {
|
||||
class_,
|
||||
proto,
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encoded_value_to_dex_value(
|
||||
encoded_value: &EncodedValue,
|
||||
dex: &DexFileReader,
|
||||
|
|
@ -145,60 +211,24 @@ impl Apk {
|
|||
EncodedValue::Long(val) => Ok(DexValue::Long(DexLong(*val))),
|
||||
EncodedValue::Float(val) => Ok(DexValue::Float(DexFloat(*val))),
|
||||
EncodedValue::Double(val) => Ok(DexValue::Double(DexDouble(*val))),
|
||||
EncodedValue::MethodType(val) => {
|
||||
let proto = dex.get_proto_id(*val as usize)?;
|
||||
let shorty: DexString = dex.get_string(proto.shorty_idx)?.into();
|
||||
let return_type: IdType = IdType(
|
||||
dex.get_string(
|
||||
dex.get_type_id(proto.return_type_idx as usize)?
|
||||
.descriptor_idx,
|
||||
)?
|
||||
.into(),
|
||||
);
|
||||
let parameters = if proto.parameters_off == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
let type_list = dex.get_struct_at_offset::<TypeList>(proto.parameters_off)?;
|
||||
let mut parameters: Vec<IdType> = vec![];
|
||||
for ty in type_list.list {
|
||||
parameters.push(IdType(
|
||||
dex.get_string(dex.get_type_id(ty.type_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
parameters
|
||||
};
|
||||
Ok(DexValue::MethodType(IdMethodType {
|
||||
shorty,
|
||||
return_type,
|
||||
parameters,
|
||||
}))
|
||||
}
|
||||
EncodedValue::MethodType(val) => Ok(DexValue::MethodType(
|
||||
Self::get_id_method_type_from_idx(*val as usize, dex)?,
|
||||
)),
|
||||
// TODO: need method to be implemented first
|
||||
EncodedValue::MethodHandle(_val) => todo!(), //Ok(DexValue::MethodHandle(DexMethodHandle(*val))),
|
||||
EncodedValue::String(val) => Ok(DexValue::String(dex.get_string(*val)?.into())),
|
||||
EncodedValue::Type(val) => Ok(DexValue::Type(IdType(
|
||||
dex.get_string(dex.get_type_id(*val as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
))),
|
||||
EncodedValue::Field(val) => {
|
||||
let field = dex.get_field_id(*val as usize)?;
|
||||
let name = dex.get_string(field.name_idx)?.into();
|
||||
let type_ = IdType(
|
||||
dex.get_string(dex.get_type_id(field.type_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
);
|
||||
let class_ = IdType(
|
||||
dex.get_string(dex.get_type_id(field.class_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
);
|
||||
Ok(DexValue::Field(IdField {
|
||||
name,
|
||||
type_,
|
||||
class_,
|
||||
}))
|
||||
}
|
||||
EncodedValue::Method(val) => Ok(DexValue::Method(IdMethod(*val))),
|
||||
EncodedValue::Type(val) => Ok(DexValue::Type(Self::get_id_type_from_idx(
|
||||
*val as usize,
|
||||
dex,
|
||||
)?)),
|
||||
EncodedValue::Field(val) => Ok(DexValue::Field(Self::get_id_field_from_idx(
|
||||
*val as usize,
|
||||
dex,
|
||||
)?)),
|
||||
EncodedValue::Method(val) => Ok(DexValue::Method(Self::get_id_method_from_idx(
|
||||
*val as usize,
|
||||
dex,
|
||||
)?)),
|
||||
EncodedValue::Enum(val) => Ok(DexValue::Enum(IdEnum(*val))),
|
||||
EncodedValue::Array(_val) => todo!(), //Ok(DexValue::Array(DexArray(*val))),
|
||||
EncodedValue::Annotation(_val) => todo!(), //Ok(DexValue::Annotation(DexAnnotation(*val))),
|
||||
|
|
|
|||
|
|
@ -369,25 +369,41 @@ impl IdField {
|
|||
}
|
||||
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct IdMethod(pub u32);
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IdMethod {
|
||||
pub class_: IdType,
|
||||
pub proto: IdMethodType,
|
||||
pub name: DexString,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl IdMethod {
|
||||
#[new]
|
||||
pub fn new(val: u32) -> Self {
|
||||
Self(val)
|
||||
pub fn new(class_: IdType, proto: IdMethodType, name: DexString) -> Self {
|
||||
Self {
|
||||
class_,
|
||||
proto,
|
||||
name,
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn __str__(&self) -> String {
|
||||
self.__repr__()
|
||||
format!(
|
||||
"{}.{}({}){}",
|
||||
self.class_.__str__(),
|
||||
self.name.__str__(),
|
||||
self.proto
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|param| param.__str__())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
self.proto.return_type.__str__()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn __repr__(&self) -> String {
|
||||
format!("DexMethod({})", self.0)
|
||||
format!("DexMethod({})", self.__str__())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub use field::*;
|
|||
pub use scalar::*;
|
||||
pub use value::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
InputTooSmall(String),
|
||||
SerializationError(String),
|
||||
|
|
|
|||
|
|
@ -154,6 +154,16 @@ impl<'a> DexFileReader<'a> {
|
|||
)))
|
||||
}
|
||||
|
||||
/// Return a [`ProtoIdItem`] reference from its idx.
|
||||
pub fn get_proto_id(&self, idx: usize) -> Result<&ProtoIdItem> {
|
||||
self.proto_ids
|
||||
.get(idx)
|
||||
.ok_or(Error::InconsistantStruct(format!(
|
||||
"prototype idx {idx} is out of bound (|proto_ids|={})",
|
||||
self.proto_ids.len()
|
||||
)))
|
||||
}
|
||||
|
||||
/// Return a [`FieldIdItem`] reference from its idx.
|
||||
pub fn get_field_id(&self, idx: usize) -> Result<&FieldIdItem> {
|
||||
self.field_ids
|
||||
|
|
@ -164,13 +174,13 @@ impl<'a> DexFileReader<'a> {
|
|||
)))
|
||||
}
|
||||
|
||||
/// Return a [`ProtoIdItem`] reference from its idx.
|
||||
pub fn get_proto_id(&self, idx: usize) -> Result<&ProtoIdItem> {
|
||||
self.proto_ids
|
||||
/// Return a [`MethodIdItem`] reference from its idx.
|
||||
pub fn get_method_id(&self, idx: usize) -> Result<&MethodIdItem> {
|
||||
self.method_ids
|
||||
.get(idx)
|
||||
.ok_or(Error::InconsistantStruct(format!(
|
||||
"prototype idx {idx} is out of bound (|proto_ids|={})",
|
||||
self.proto_ids.len()
|
||||
"method idx {idx} is out of bound (|method_ids|={})",
|
||||
self.method_ids.len()
|
||||
)))
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue