Skip to content

Commit 14ca426

Browse files
committed
replace function and comments with sdk api aligned alt
1 parent c252ac3 commit 14ca426

File tree

8 files changed

+185
-189
lines changed

8 files changed

+185
-189
lines changed

src/id0/btree.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,27 @@ impl ID0Header {
5555
// NOTE before version V15, the string was at 0xd(13), after that
5656
// at 0x13(19). I think this is was a mistake on the developers part,
5757
// mixing the offset 13 with 0x13.
58-
let version = if magic == IDBMagic::IDA0 {
59-
let version = ID0Version::read(&mut &buf[0xd..0x27])
60-
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
61-
if version != ID0Version::V15 {
62-
return Err(anyhow!(
63-
"Unexpected ID0 B-Tree Version header location"
64-
));
58+
let version = match magic {
59+
IDBMagic::IDA0 => {
60+
let version = ID0Version::read(&mut &buf[0xd..0x27])
61+
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
62+
if version != ID0Version::V15 {
63+
return Err(anyhow!(
64+
"Unexpected ID0 B-Tree Version header location"
65+
));
66+
}
67+
version
6568
}
66-
version
67-
} else {
68-
let version = ID0Version::read(&mut &buf[0x13..0x2d])
69-
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
70-
if version == ID0Version::V15 {
71-
return Err(anyhow!(
72-
"Unexpected ID0 B-Tree Version header location"
73-
));
69+
IDBMagic::IDA1 | IDBMagic::IDA2 => {
70+
let version = ID0Version::read(&mut &buf[0x13..0x2d])
71+
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
72+
if version == ID0Version::V15 {
73+
return Err(anyhow!(
74+
"Unexpected ID0 B-Tree Version header location"
75+
));
76+
}
77+
version
7478
}
75-
version
7679
};
7780

7881
let mut buf_current = &buf[..];

src/id0/db.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::addr_info::SubtypeId;
99
use crate::id0::entry_iter::EntryTagContinuousFlat;
1010
use crate::id0::flag::nsup::NSUP_LLABEL;
1111
use crate::ida_reader::{IdbBufRead, IdbReadKind};
12-
use crate::SectionReader;
1312
use crate::{til, Address, IDBStr};
13+
use crate::{IDBString, SectionReader};
1414

1515
use super::entry_iter::{
1616
EntryTagContinuousSubkeys, NetnodeRangeIter, NetnodeSupRangeIter,
@@ -1000,33 +1000,67 @@ impl<K: IDAKind> ID0Section<K> {
10001000
funcs_idx(self)
10011001
}
10021002

1003-
/// read the `$ funcs` entries of the database
1004-
pub fn functions_and_comments(
1005-
&self,
1006-
idx: FuncIdx<K>,
1007-
) -> impl Iterator<Item = Result<FunctionsAndComments<'_, K>>> {
1008-
functions_and_comments(self, idx)
1009-
}
1010-
10111003
pub fn fchunks(
10121004
&self,
10131005
idx: FuncIdx<K>,
10141006
) -> impl Iterator<Item = Result<IDBFunction<K>>> + use<'_, K> {
10151007
fchunks(self, idx)
10161008
}
10171009

1018-
pub fn function_containing_address(
1010+
fn cmt_inner(
10191011
&self,
10201012
idx: FuncIdx<K>,
1021-
ea: Address<K>,
1022-
) -> Result<Option<IDBFunction<K>>> {
1023-
for fun in fchunks(self, idx) {
1024-
let fun = fun?;
1025-
if fun.address.contains(&ea) {
1026-
return Ok(Some(fun));
1027-
}
1013+
netdelta: Netdelta<K>,
1014+
addr: Address<K>,
1015+
tag: u8,
1016+
) -> Result<Option<IDBString>> {
1017+
let Some(cmt) = self.sup_value(idx.into(), addr.into_raw(), tag) else {
1018+
return Ok(None);
1019+
};
1020+
// NOTE this is a u32
1021+
if !cmt.starts_with(&0x01020304u32.to_le_bytes()) {
1022+
return Ok(Some(IDBString(cmt.to_vec())));
10281023
}
1029-
Ok(None)
1024+
1025+
let netnode = netdelta.ea2node(addr);
1026+
let Some(cmt) = self.sup_value(idx.into(), netnode.into_raw(), tag)
1027+
else {
1028+
return Ok(None);
1029+
};
1030+
// TODO is this u64 or usize?
1031+
// NOTE this is a u64
1032+
ensure!(
1033+
cmt.starts_with(&0x01020304u64.to_le_bytes()),
1034+
"Invalid cmt type 4321"
1035+
);
1036+
let Some(num) = cmt.get(8..16).and_then(K::usize_try_from_le_bytes)
1037+
else {
1038+
return Err(anyhow!("Invalid cmt type 4321 value"));
1039+
};
1040+
1041+
// TODO ignore if it is repeatable not not?
1042+
Ok(Some(IDBString(
1043+
self.blob(NetnodeIdx::from_raw(num), 0u8.into(), b'S')
1044+
.collect(),
1045+
)))
1046+
}
1047+
1048+
pub fn func_cmt(
1049+
&self,
1050+
idx: FuncIdx<K>,
1051+
netdelta: Netdelta<K>,
1052+
addr: Address<K>,
1053+
) -> Result<Option<IDBString>> {
1054+
self.cmt_inner(idx, netdelta, addr, b'C')
1055+
}
1056+
1057+
pub fn func_repeatable_cmt(
1058+
&self,
1059+
idx: FuncIdx<K>,
1060+
netdelta: Netdelta<K>,
1061+
addr: Address<K>,
1062+
) -> Result<Option<IDBString>> {
1063+
self.cmt_inner(idx, netdelta, addr, b'R')
10301064
}
10311065

10321066
// TODO implement $ fixups

src/id0/function.rs

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,6 @@ pub(crate) fn funcs_idx<K: IDAKind>(
5555
Ok(id0.netnode_idx_by_name("$ funcs")?.map(|x| FuncIdx(x.0)))
5656
}
5757

58-
pub(crate) fn functions_and_comments<K: IDAKind>(
59-
id0: &ID0Section<K>,
60-
idx: FuncIdx<K>,
61-
) -> impl Iterator<Item = Result<FunctionsAndComments<'_, K>>> {
62-
id0.netnode_range(idx.into())
63-
.map(move |(key, value)| FunctionsAndComments::read(key, value))
64-
}
65-
6658
pub(crate) fn fchunks<K: IDAKind>(
6759
id0: &ID0Section<K>,
6860
idx: FuncIdx<K>,
@@ -112,68 +104,6 @@ pub struct IDBFunctionNonTail<K: IDAKind> {
112104
pub fpd: K::Usize,
113105
}
114106

115-
#[derive(Clone, Debug, Serialize)]
116-
pub enum FunctionsAndComments<'a, K: IDAKind> {
117-
// It's just the name "$ funcs"
118-
Name,
119-
Function(IDBFunction<K>),
120-
Comment {
121-
address: K::Usize,
122-
comment: Comments<'a>,
123-
},
124-
Unknown {
125-
key: &'a [u8],
126-
value: &'a [u8],
127-
},
128-
}
129-
130-
impl<'a, K: IDAKind> FunctionsAndComments<'a, K> {
131-
pub(crate) fn read(key: &'a [u8], value: &'a [u8]) -> Result<Self> {
132-
let [key_type, sub_key @ ..] = key else {
133-
return Err(anyhow!("invalid Funcs subkey"));
134-
};
135-
match *key_type {
136-
flag::netnode::nn_res::NAME_TAG => {
137-
ensure!(parse_maybe_cstr(value) == Some(&b"$ funcs"[..]));
138-
Ok(Self::Name)
139-
}
140-
flag::netnode::nn_res::ARRAY_SUP_TAG => {
141-
IDBFunction::read(value).map(Self::Function)
142-
}
143-
// some kind of style setting, maybe setting font and background color
144-
b'R' | b'C' if value.starts_with(&[4, 3, 2, 1]) => {
145-
Ok(Self::Unknown { key, value })
146-
}
147-
b'C' => {
148-
let address = K::usize_try_from_be_bytes(sub_key)
149-
.ok_or_else(|| anyhow!("Invalid Comment address"))?;
150-
parse_maybe_cstr(value)
151-
.map(|value| Self::Comment {
152-
address,
153-
comment: Comments::Comment(IDBStr::new(value)),
154-
})
155-
.ok_or_else(|| anyhow!("Invalid Comment string"))
156-
}
157-
b'R' => {
158-
let address =
159-
K::usize_try_from_be_bytes(sub_key).ok_or_else(|| {
160-
anyhow!("Invalid Repetable Comment address")
161-
})?;
162-
parse_maybe_cstr(value)
163-
.map(|value| Self::Comment {
164-
address,
165-
comment: Comments::RepeatableComment(IDBStr::new(
166-
value,
167-
)),
168-
})
169-
.ok_or_else(|| anyhow!("Invalid Repetable Comment string"))
170-
}
171-
// TODO find the meaning of "$ funcs" b'V' entries
172-
_ => Ok(Self::Unknown { key, value }),
173-
}
174-
}
175-
}
176-
177107
impl<K: IDAKind> IDBFunction<K> {
178108
// InnerRef 66961e377716596c17e2330a28c01eb3600be518 0x37dd30
179109
// InnerRef 5c1b89aa-5277-4c98-98f6-cec08e1946ec 0x28f810

src/sdk_comp/funcs.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ use std::ops::Range;
33
use crate::id0::function::{
44
IDBFunctionNonTail, IDBFunctionTail, IDBFunctionType,
55
};
6-
use crate::Address;
6+
use crate::id0::Netdelta;
77
use crate::{id0::ID0Section, IDAKind};
8+
use crate::{Address, IDBString};
89

910
use super::frame::{regvar_t, stkpnt_t};
1011
use super::nalt::type_t;
1112
use super::pro::{asize_t, bgcolor_t, ea_t, uval_t};
1213
use super::DataFetch;
1314

14-
use anyhow::Result;
15+
use anyhow::{anyhow, Result};
1516

1617
pub struct func_t<'a, K: IDAKind> {
17-
pub range: Range<K::Usize>,
18+
pub range: Range<Address<K>>,
1819
pub flags: u64,
1920
pub func_t_type: func_t_type<'a, K>,
2021
}
@@ -66,8 +67,7 @@ pub fn get_fchunk<'a, K: IDAKind>(
6667
let chunk = chunk?;
6768
if chunk.address.contains(&Address::from_raw(ea.0)) {
6869
return Ok(Some(func_t {
69-
range: chunk.address.start.into_raw()
70-
..chunk.address.end.into_raw(),
70+
range: chunk.address,
7171
flags: chunk.flags.into_raw(),
7272
func_t_type: match chunk.extra {
7373
IDBFunctionType::Tail(IDBFunctionTail {
@@ -129,3 +129,57 @@ pub fn get_func<'a, K: IDAKind>(
129129
Ok(Some(func))
130130
}
131131
}
132+
133+
pub fn getn_func<'a, K: IDAKind>(
134+
id0: &'a ID0Section<K>,
135+
n: usize,
136+
) -> Result<Option<func_t<'a, K>>> {
137+
// TODO how the old versions work?
138+
let ords = id0
139+
.funcords_idx()?
140+
.ok_or_else(|| anyhow!("Missing funcords entry"))?;
141+
let Some(addr) = id0.funcords(ords)?.skip(n).next() else {
142+
return Ok(None);
143+
};
144+
get_func(id0, addr?)
145+
}
146+
147+
pub fn get_func_num<'a, K: IDAKind>(
148+
id0: &'a ID0Section<K>,
149+
ea: ea_t<K>,
150+
) -> Result<Option<usize>> {
151+
// TODO how the old versions work?
152+
let ords = id0
153+
.funcords_idx()?
154+
.ok_or_else(|| anyhow!("Missing funcords entry"))?;
155+
for (i, fun_addr) in id0.funcords(ords)?.enumerate() {
156+
if fun_addr? == ea {
157+
return Ok(Some(i));
158+
}
159+
}
160+
Ok(None)
161+
}
162+
163+
pub fn get_func_qty<'a, K: IDAKind>(id0: &'a ID0Section<K>) -> Result<usize> {
164+
// TODO how the old versions work?
165+
let ords = id0
166+
.funcords_idx()?
167+
.ok_or_else(|| anyhow!("Missing funcords entry"))?;
168+
Ok(id0.funcords(ords)?.count())
169+
}
170+
171+
pub fn get_func_cmt<'a, K: IDAKind>(
172+
id0: &'a ID0Section<K>,
173+
netdelta: Netdelta<K>,
174+
addr: Address<K>,
175+
repeatable: bool,
176+
) -> Result<Option<IDBString>> {
177+
let func_idx = id0
178+
.funcs_idx()?
179+
.ok_or_else(|| anyhow!("Missing funcs entry"))?;
180+
if repeatable {
181+
id0.func_repeatable_cmt(func_idx, netdelta, addr)
182+
} else {
183+
id0.func_cmt(func_idx, netdelta, addr)
184+
}
185+
}

src/tools/dump_dirtree_funcs.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,15 @@ pub fn print_function<K: IDAKind>(
4444
let root_info_idx = id0.root_node()?;
4545
let root_info = id0.ida_info(root_info_idx)?;
4646
let image_base = root_info.netdelta();
47-
let info = AddressInfo::new(id0, id1, id2, image_base, address).unwrap();
48-
let name = info.label()?;
49-
let ty = info.tinfo()?;
47+
let info = AddressInfo::new(id0, id1, id2, image_base, address);
48+
let name = info
49+
.as_ref()
50+
.and_then(|info| info.label().transpose())
51+
.transpose()?;
52+
let ty = info
53+
.as_ref()
54+
.and_then(|info| info.tinfo().transpose())
55+
.transpose()?;
5056

5157
print!("{:#x}:", address.into_raw());
5258
match (name, ty) {

0 commit comments

Comments
 (0)