Skip to content

Commit

Permalink
fix til type field names association
Browse files Browse the repository at this point in the history
  • Loading branch information
rbran committed Dec 18, 2024
1 parent bb0bfbe commit 50ede22
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 128 deletions.
4 changes: 2 additions & 2 deletions src/id0/address_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ impl<'a> Iterator for AddressInfoIter<'a> {
let Some(fields) = crate::ida_reader::split_strings_from_array(value) else {
return Some(Err(anyhow!("Invalid Fields for TIL Type")));
};
(Some(fields), rest)
(fields, rest)
}
rest => (None, rest),
rest => (vec![], rest),
};

// condensate the data into a single buffer
Expand Down
2 changes: 1 addition & 1 deletion src/id0/btree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ impl ID0Section {
let key = parse_number(key, true, self.is_64).unwrap();
// TODO handle other values for the key
if key == key_find {
return til::Type::new_from_id0(&entry.value, None).map(Option::Some);
return til::Type::new_from_id0(&entry.value, vec![]).map(Option::Some);
}
}
Ok(None)
Expand Down
12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ mod test {
0x3d, 0x08, 0x48, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x3d, 0x06, 0x44, 0x57, 0x4f,
0x52, 0x44, 0x00,
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand All @@ -565,7 +565,7 @@ mod test {
0x82, 0x54, // ???? the 0x94 value?
0x00, // the final value always present
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand Down Expand Up @@ -605,7 +605,7 @@ mod test {
0x67, // "__jmp_buf_tag"
0x00, // end of type
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand Down Expand Up @@ -660,7 +660,7 @@ mod test {
0x27, // unsigned int
0x00,
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand Down Expand Up @@ -693,7 +693,7 @@ mod test {
0x05, 0x55, 0x49, 0x4e, 0x54, // typedef name
0x00, //end
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand Down Expand Up @@ -725,7 +725,7 @@ mod test {
0x01, // no params
0x00, // end
];
let _til = til::Type::new_from_id0(&function, None).unwrap();
let _til = til::Type::new_from_id0(&function, vec![]).unwrap();
}

#[test]
Expand Down
66 changes: 20 additions & 46 deletions src/til.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ impl TILTypeInfo {
}

fn read_inner(cursor: &mut &[u8], til: &TILSectionHeader) -> Result<Self> {
let og_cu = *cursor;
let flags: u32 = cursor.read_u32()?;
// TODO verify if flags equal to 0x7fff_fffe?
let name = cursor.read_c_string_raw()?;
Expand All @@ -71,21 +70,20 @@ impl TILTypeInfo {
(0..=0x11, _) | (_, false) => cursor.read_u32()?.into(),
(_, true) => cursor.read_u64()?,
};
let tinfo_raw = TypeRaw::read(&mut *cursor, til)
.context("parsing `TILTypeInfo::tiinfo`")
.inspect_err(|e| {
println!(
"Error: {}: {e:?}\n{og_cu:02x?}",
core::str::from_utf8(&name).unwrap()
);
})?;
let tinfo_raw =
TypeRaw::read(&mut *cursor, til).context("parsing `TILTypeInfo::tiinfo`")?;
let _info = cursor.read_c_string_raw()?;
let cmt = cursor.read_c_string_raw()?;
let fields = cursor.read_c_string_vec()?;
let fieldcmts = cursor.read_c_string_raw()?;
let sclass: u8 = cursor.read_u8()?;

let tinfo = Type::new(til, tinfo_raw, Some(fields))?;
let mut fields_iter = fields.into_iter();
let tinfo = Type::new(til, tinfo_raw, &mut fields_iter)?;
ensure!(
fields_iter.as_slice().is_empty(),
"Extra fields found for til"
);

Ok(Self {
_flags: flags,
Expand Down Expand Up @@ -122,27 +120,12 @@ impl Type {
pub(crate) fn new(
til: &TILSectionHeader,
tinfo_raw: TypeRaw,
fields: Option<Vec<Vec<u8>>>,
fields: &mut impl Iterator<Item = Vec<u8>>,
) -> Result<Self> {
let type_variant = match tinfo_raw.variant {
TypeVariantRaw::Basic(x) => {
if let Some(fields) = fields {
ensure!(fields.is_empty(), "Basic type with fields");
}
TypeVariant::Basic(x)
}
TypeVariantRaw::Bitfield(x) => {
if matches!(fields, Some(f) if !f.is_empty()) {
return Err(anyhow!("fields in a Bitfield"));
}
TypeVariant::Bitfield(x)
}
TypeVariantRaw::Typedef(x) => {
if matches!(fields, Some(f) if !f.is_empty()) {
return Err(anyhow!("fields in a Typedef"));
}
TypeVariant::Typedef(x)
}
TypeVariantRaw::Basic(x) => TypeVariant::Basic(x),
TypeVariantRaw::Bitfield(x) => TypeVariant::Bitfield(x),
TypeVariantRaw::Typedef(x) => TypeVariant::Typedef(x),
TypeVariantRaw::Pointer(x) => Pointer::new(til, x, fields).map(TypeVariant::Pointer)?,
TypeVariantRaw::Function(x) => {
Function::new(til, x, fields).map(TypeVariant::Function)?
Expand All @@ -159,7 +142,7 @@ impl Type {
})
}
// TODO find the best way to handle type parsing from id0
pub(crate) fn new_from_id0(data: &[u8], fields: Option<Vec<Vec<u8>>>) -> Result<Self> {
pub(crate) fn new_from_id0(data: &[u8], fields: Vec<Vec<u8>>) -> Result<Self> {
// TODO it's unclear what header information id0 types use to parse tils
// maybe it just use the til sector header, or more likelly it's from
// IDBParam in the `Root Node`
Expand Down Expand Up @@ -191,7 +174,13 @@ impl Type {
));
}
}
Self::new(&header, type_raw, fields)
let mut fields_iter = fields.into_iter();
let result = Self::new(&header, type_raw, &mut fields_iter)?;
ensure!(
fields_iter.as_slice().is_empty(),
"Extra fields found for id0 til"
);
Ok(result)
}

// TODO stub implementation
Expand Down Expand Up @@ -762,18 +751,3 @@ fn serialize_dt(value: u16) -> Result<Vec<u8>> {
result.push(hi as u8);
Ok(result)
}

fn associate_field_name_and_member<T>(
fields: Option<Vec<Vec<u8>>>,
members: Vec<T>,
) -> Result<impl Iterator<Item = (Option<Vec<u8>>, T)>> {
let fields_len: usize = fields.iter().filter(|t| !t.is_empty()).count();
ensure!(fields_len <= members.len(), "More fields then members");
// allow to have fewer fields then members, first fields will have names, others not
Ok(fields
.into_iter()
.flat_map(Vec::into_iter)
.map(Some)
.chain(std::iter::repeat(None))
.zip(members))
}
8 changes: 2 additions & 6 deletions src/til/array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::ida_reader::IdaGenericBufUnpack;
use crate::til::section::TILSectionHeader;
use crate::til::{Type, TypeRaw, TAH};
use anyhow::anyhow;

#[derive(Clone, Debug)]
pub struct Array {
Expand All @@ -14,16 +13,13 @@ impl Array {
pub(crate) fn new(
til: &TILSectionHeader,
value: ArrayRaw,
fields: Option<Vec<Vec<u8>>>,
fields: &mut impl Iterator<Item = Vec<u8>>,
) -> anyhow::Result<Self> {
if matches!(&fields, Some(f) if !f.is_empty()) {
return Err(anyhow!("fields in a Array"));
}
Ok(Self {
base: value.base,
nelem: value.nelem,
tah: value.tah,
elem_type: Type::new(til, *value.elem_type, None).map(Box::new)?,
elem_type: Type::new(til, *value.elem_type, fields).map(Box::new)?,
})
}
}
Expand Down
28 changes: 12 additions & 16 deletions src/til/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::num::NonZeroU8;

use crate::ida_reader::IdaGenericBufUnpack;
use crate::til::section::TILSectionHeader;
use crate::til::{associate_field_name_and_member, flag, Type, TypeAttribute, TypeRaw, SDACL, TAH};
use anyhow::{anyhow, ensure, Context};
use crate::til::{flag, Type, TypeAttribute, TypeRaw, SDACL, TAH};
use anyhow::{anyhow, ensure};

use super::r#struct::StructModifier;

Expand All @@ -25,35 +25,31 @@ impl Enum {
pub(crate) fn new(
til: &TILSectionHeader,
value: EnumRaw,
fields: Option<Vec<Vec<u8>>>,
fields: &mut impl Iterator<Item = Vec<u8>>,
) -> anyhow::Result<Self> {
match value {
EnumRaw::Ref {
ref_type,
taenum_bits,
} => {
if matches!(&fields, Some(f) if !f.is_empty()) {
return Err(anyhow!("fields in a Ref Enum"));
}
Ok(Enum::Ref {
ref_type: Type::new(til, *ref_type, None).map(Box::new)?,
taenum_bits,
})
}
} => Ok(Enum::Ref {
ref_type: Type::new(til, *ref_type, fields).map(Box::new)?,
taenum_bits,
}),
EnumRaw::NonRef {
output_format,
modifiers,
members,
groups,
storage_size,
} => {
let members = associate_field_name_and_member(fields, members)
.context("Enum")?
.collect();
let mut new_members = Vec::with_capacity(members.len());
for member in members {
new_members.push((fields.next(), member));
}
Ok(Enum::NonRef {
output_format,
modifiers,
members,
members: new_members,
groups,
storage_size,
})
Expand Down
19 changes: 11 additions & 8 deletions src/til/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::ida_reader::{IdaGenericBufUnpack, IdaGenericUnpack};
use crate::til::section::TILSectionHeader;
use crate::til::{associate_field_name_and_member, Basic, Type, TypeRaw, TAH};
use anyhow::{anyhow, Context};
use crate::til::{Basic, Type, TypeRaw, TAH};
use anyhow::anyhow;

use super::TypeVariantRaw;

Expand All @@ -16,15 +16,18 @@ impl Function {
pub(crate) fn new(
til: &TILSectionHeader,
value: FunctionRaw,
fields: Option<Vec<Vec<u8>>>,
fields: &mut impl Iterator<Item = Vec<u8>>,
) -> anyhow::Result<Self> {
let args = associate_field_name_and_member(fields, value.args)
.context("Function")?
.map(|(n, (t, a))| Type::new(til, t, None).map(|t| (n, t, a)))
.collect::<anyhow::Result<_, _>>()?;
let ret = Type::new(til, *value.ret, &mut *fields)?;
let mut args = Vec::with_capacity(value.args.len());
for (arg_type, arg_loc) in value.args {
let field_name = fields.next();
let new_member = Type::new(til, arg_type, &mut *fields)?;
args.push((field_name, new_member, arg_loc));
}
Ok(Self {
calling_convention: value.calling_convention,
ret: Type::new(til, *value.ret, None).map(Box::new)?,
ret: Box::new(ret),
args,
retloc: value.retloc,
})
Expand Down
11 changes: 9 additions & 2 deletions src/til/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ impl Pointer {
pub(crate) fn new(
til: &TILSectionHeader,
raw: PointerRaw,
fields: Option<Vec<Vec<u8>>>,
fields: &mut impl Iterator<Item = Vec<u8>>,
) -> anyhow::Result<Self> {
Ok(Self {
// TODO forward fields to closure?
closure: PointerType::new(til, raw.closure)?,
modifier: raw.modifier,
typ: Type::new(til, *raw.typ, fields).map(Box::new)?,
Expand All @@ -35,7 +36,13 @@ pub enum PointerType {
impl PointerType {
fn new(til: &TILSectionHeader, raw: PointerTypeRaw) -> anyhow::Result<Self> {
match raw {
PointerTypeRaw::Closure(c) => Type::new(til, *c, None).map(Box::new).map(Self::Closure),
PointerTypeRaw::Closure(c) => {
// TODO subtype get the fields?
let mut sub_fields = vec![].into_iter();
Type::new(til, *c, &mut sub_fields)
.map(Box::new)
.map(Self::Closure)
}
PointerTypeRaw::PointerBased(p) => Ok(Self::PointerBased(p)),
PointerTypeRaw::Default => Ok(Self::Default),
PointerTypeRaw::Far => Ok(Self::Far),
Expand Down
Loading

0 comments on commit 50ede22

Please sign in to comment.