Skip to content

Commit ad94a16

Browse files
committed
add get_seg class of functions to sdk_comp
1 parent be840a7 commit ad94a16

File tree

6 files changed

+180
-110
lines changed

6 files changed

+180
-110
lines changed

src/id0/db.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ impl<K: IDAKind> ID0Section<K> {
460460
.map(|x| x.map(|x| SegmentIdx(x.0)))
461461
}
462462

463+
/// Return an iterator of segments, ordered by address start
463464
pub fn segments(&self, idx: SegmentIdx<K>) -> SegmentIter<'_, K> {
464465
let segments = self.sup_range(idx.into(), ARRAY_SUP_TAG);
465466
SegmentIter {
@@ -502,17 +503,20 @@ impl<K: IDAKind> ID0Section<K> {
502503
// TODO there is also a "P" entry in patches, it seems to only contains
503504
// the value 0x01 for each equivalent "A" entry
504505

505-
pub fn segment_name(&self, idx: SegmentNameIdx<K>) -> Result<IDBStr<'_>> {
506+
pub fn segment_name(
507+
&self,
508+
idx: SegmentNameIdx<K>,
509+
) -> Result<Option<IDBStr<'_>>> {
506510
let seg_idx = self.segment_strings_idx()?;
507511
// TODO I think this is dependent on the version, and not on availability
508512
if let Some(seg_idx) = seg_idx {
509513
for seg in self.segment_strings(seg_idx) {
510514
let (seg_idx, seg_value) = seg?;
511515
if seg_idx.0 == idx.0 {
512-
return Ok(seg_value);
516+
return Ok(Some(seg_value));
513517
}
514518
}
515-
Err(anyhow!("Unable to find ID0 Segment Name"))
519+
Ok(None)
516520
} else {
517521
// if there is no names, AKA `$ segstrings`, search for the key directly
518522
self.name_by_index(idx)
@@ -522,16 +526,17 @@ impl<K: IDAKind> ID0Section<K> {
522526
pub(crate) fn name_by_index(
523527
&self,
524528
idx: SegmentNameIdx<K>,
525-
) -> Result<IDBStr<'_>> {
529+
) -> Result<Option<IDBStr<'_>>> {
526530
// if there is no names, AKA `$ segstrings`, search for the key directly
527-
let name_idx = self
528-
.netnode_tag_idx(
529-
NetnodeIdx(K::Usize::from(0xFFu8).swap_bytes() | idx.0),
530-
NAME_TAG,
531-
)
532-
.ok_or_else(|| anyhow!("Not found name for segment {}", idx.0))?;
531+
let Some(name_idx) = self.netnode_tag_idx(
532+
NetnodeIdx(K::Usize::from(0xFFu8).swap_bytes() | idx.0),
533+
NAME_TAG,
534+
) else {
535+
return Ok(None);
536+
};
533537
parse_maybe_cstr(&self.entries[name_idx].value)
534538
.map(IDBStr::new)
539+
.map(Option::Some)
535540
.ok_or_else(|| anyhow!("Invalid segment name {}", idx.0))
536541
}
537542

src/sdk_comp.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
pub mod bytes;
22
pub mod frame;
33
pub mod funcs;
4+
/// Functions that are exported on the lib but not part of the SDK
5+
pub mod inner;
46
pub mod lines;
57
pub mod nalt;
68
pub mod netnode;
@@ -16,3 +18,17 @@ pub enum DataFetch<T> {
1618
Qty(u16),
1719
Data(Vec<T>),
1820
}
21+
22+
pub mod prelude {
23+
pub use super::bytes::*;
24+
pub use super::frame::*;
25+
pub use super::funcs::*;
26+
pub use super::inner::*;
27+
pub use super::lines::*;
28+
pub use super::nalt::*;
29+
pub use super::netnode::*;
30+
pub use super::pro::*;
31+
pub use super::range::*;
32+
pub use super::segment::*;
33+
pub use super::typeinf::*;
34+
}

src/sdk_comp/inner.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use anyhow::Result;
2+
3+
use crate::id0::ID0Section;
4+
use crate::sdk_comp::segment::segment_t;
5+
use crate::{IDAKind, IDBStr};
6+
7+
// TODO implement based on the InnerRef
8+
pub fn get_segm_name<'a, K: IDAKind>(
9+
id0: &'a ID0Section<K>,
10+
s: &segment_t<K>,
11+
flags: i32,
12+
) -> Result<Option<IDBStr<'a>>> {
13+
if flags != 0 {
14+
todo!();
15+
}
16+
id0.segment_name(s.name)
17+
}
18+
19+
// TODO implement based on the InnerRef
20+
pub fn get_segm_class<'a, K: IDAKind>(
21+
id0: &'a ID0Section<K>,
22+
s: &segment_t<K>,
23+
) -> Result<Option<IDBStr<'a>>> {
24+
id0.segment_name(s.sclass)
25+
}

src/sdk_comp/lines.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ pub fn get_sourcefile<K: IDAKind>(
1616
id0: &ID0Section<K>,
1717
ea: ea_t<K>,
1818
) -> Result<Option<SourceFile<'_, K>>> {
19-
let seg = super::segment::getseg_inner(id0, ea)?;
19+
let seg =
20+
super::segment::getseg_inner(id0, |seg| seg.address.contains(&ea))?;
2021
if let Some(seg) = seg {
21-
let name = id0.segment_name(seg.name).unwrap_or(IDBStr::new(&[]));
22+
let name = id0.segment_name(seg.name)?.unwrap_or(IDBStr::new(&[]));
2223
Ok(Some(SourceFile {
2324
name,
2425
address: seg.address,

src/sdk_comp/segment.rs

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,61 @@ use anyhow::Result;
22

33
use std::ops::Range;
44

5-
use crate::id0::{ID0Section, Segment};
5+
use crate::id0::{
6+
ID0Section, Segment, SegmentBitness, SegmentNameIdx, SegmentType,
7+
};
68
use crate::IDAKind;
79

810
use super::pro::{bgcolor_t, ea_t, sel_t, uval_t};
911

1012
#[derive(Debug, Clone)]
1113
pub struct segment_t<K: IDAKind> {
12-
pub range: Range<ea_t<K>>,
13-
pub name: uval_t<K>,
14-
pub sclass: uval_t<K>,
14+
pub address: Range<ea_t<K>>,
15+
pub name: SegmentNameIdx<K>,
16+
pub sclass: SegmentNameIdx<K>,
1517
pub orgbase: uval_t<K>,
1618
pub align: u8,
1719
pub comb: u8,
1820
pub perm: u8,
19-
pub bitness: u8,
21+
pub bitness: SegmentBitness,
2022
pub flags: u16,
2123
pub sel: sel_t<K>,
2224
pub defsr: [sel_t<K>; 16usize],
23-
pub type_: u8,
25+
pub type_: SegmentType,
2426
pub color: bgcolor_t,
2527
}
2628

29+
impl<K: IDAKind> From<Segment<K>> for segment_t<K> {
30+
fn from(seg: Segment<K>) -> Self {
31+
Self {
32+
address: seg.address,
33+
name: seg.name,
34+
sclass: seg.class_id,
35+
orgbase: seg.orgbase,
36+
align: seg.align.into(),
37+
comb: seg.comb.into(),
38+
perm: seg.perm.map(|perm| perm.into_raw()).unwrap_or(0),
39+
bitness: seg.bitness.into(),
40+
flags: seg.flags.into_raw().into(),
41+
sel: seg.selector,
42+
defsr: seg.defsr,
43+
type_: seg.seg_type.into(),
44+
color: seg.color,
45+
}
46+
}
47+
}
48+
2749
// InnerRef v9.1 fa53bd30-ebf1-4641-80ef-4ddc73db66cd 0x5de220
2850
pub(crate) fn getseg_inner<K: IDAKind>(
2951
id0: &ID0Section<K>,
30-
ea: ea_t<K>,
52+
mut selector: impl FnMut(&Segment<K>) -> bool,
3153
) -> Result<Option<Segment<K>>> {
3254
let Some(seg_idx) = id0.segments_idx()? else {
3355
return Ok(None);
3456
};
3557
for seg in id0.segments(seg_idx) {
3658
let seg = seg?;
37-
if seg.address.contains(&ea) {
59+
if selector(&seg) {
3860
return Ok(Some(seg));
3961
}
4062
}
@@ -46,27 +68,53 @@ pub fn getseg<K: IDAKind>(
4668
id0: &ID0Section<K>,
4769
ea: ea_t<K>,
4870
) -> Result<Option<segment_t<K>>> {
49-
getseg_inner(id0, ea).map(|seg| {
50-
seg.map(|seg| segment_t {
51-
range: seg.address,
52-
name: seg.name.0,
53-
sclass: seg.class_id.0,
54-
orgbase: seg.orgbase,
55-
align: seg.align.into(),
56-
comb: seg.comb.into(),
57-
perm: seg.perm.map(|perm| perm.into_raw()).unwrap_or(0),
58-
bitness: seg.bitness.into(),
59-
flags: seg.flags.into_raw().into(),
60-
sel: seg.selector,
61-
defsr: seg.defsr,
62-
type_: seg.seg_type.into(),
63-
color: seg.color,
64-
})
65-
})
71+
getseg_inner(id0, |seg| seg.address.contains(&ea))
72+
.map(|seg| seg.map(|seg| seg.into()))
6673
}
6774

6875
// InnerRef v9.1 fa53bd30-ebf1-4641-80ef-4ddc73db66cd 0x5e41e0
6976
pub fn segtype<K: IDAKind>(id0: &ID0Section<K>, ea: ea_t<K>) -> Result<u8> {
70-
getseg_inner(id0, ea)
77+
getseg_inner(id0, |seg| seg.address.contains(&ea))
7178
.map(|seg| seg.map(|seg| seg.seg_type.into()).unwrap_or(8))
7279
}
80+
81+
pub fn get_segm_qty<K: IDAKind>(id0: &ID0Section<K>) -> Result<usize> {
82+
let Some(seg_idx) = id0.segments_idx()? else {
83+
return Ok(0);
84+
};
85+
Ok(id0.segments(seg_idx).count())
86+
}
87+
88+
pub fn get_next_seg<K: IDAKind>(
89+
id0: &ID0Section<K>,
90+
ea: ea_t<K>,
91+
) -> Result<Option<segment_t<K>>> {
92+
getseg_inner(id0, |seg| seg.address.start > ea)
93+
.map(|seg| seg.map(|seg| seg.into()))
94+
}
95+
96+
pub fn get_prev_seg<K: IDAKind>(
97+
id0: &ID0Section<K>,
98+
ea: ea_t<K>,
99+
) -> Result<Option<segment_t<K>>> {
100+
getseg_inner(id0, |seg| seg.address.end < ea)
101+
.map(|seg| seg.map(|seg| seg.into()))
102+
}
103+
104+
pub fn get_first_seg<K: IDAKind>(
105+
id0: &ID0Section<K>,
106+
) -> Result<Option<segment_t<K>>> {
107+
getseg_inner(id0, |_seg| true).map(|seg| seg.map(|seg| seg.into()))
108+
}
109+
110+
pub fn get_last_seg<K: IDAKind>(
111+
id0: &ID0Section<K>,
112+
) -> Result<Option<segment_t<K>>> {
113+
let Some(seg_idx) = id0.segments_idx()? else {
114+
return Ok(None);
115+
};
116+
id0.segments(seg_idx)
117+
.last()
118+
.map(|seg| seg.map(|seg| seg.into()))
119+
.transpose()
120+
}

0 commit comments

Comments
 (0)