idakit_sys/
function_flags.rs1use bitflags::bitflags;
4
5bitflags! {
6 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11 #[doc(alias(
12 "FUNC_NORET", "FUNC_FAR", "FUNC_LIB", "FUNC_STATICDEF", "FUNC_FRAME", "FUNC_USERFAR",
13 "FUNC_HIDDEN", "FUNC_THUNK", "FUNC_BOTTOMBP", "FUNC_NORET_PENDING", "FUNC_SP_READY",
14 "FUNC_FUZZY_SP", "FUNC_PROLOG_OK", "FUNC_PURGED_OK", "FUNC_TAIL", "FUNC_LUMINA",
15 "FUNC_OUTLINE", "FUNC_REANALYZE", "FUNC_UNWIND", "FUNC_CATCH", "FUNC_RESERVED"
16 ))]
17 pub struct FuncFlags: u64 {
18 #[doc(alias("FUNC_NORET"))]
20 const NORET = 0x0000_0001;
21 #[doc(alias("FUNC_FAR"))]
23 const FAR = 0x0000_0002;
24 #[doc(alias("FUNC_LIB"))]
26 const LIB = 0x0000_0004;
27 #[doc(alias("FUNC_STATICDEF"))]
29 const STATICDEF = 0x0000_0008;
30 #[doc(alias("FUNC_FRAME"))]
32 const FRAME = 0x0000_0010;
33 #[doc(alias("FUNC_USERFAR"))]
35 const USERFAR = 0x0000_0020;
36 #[doc(alias("FUNC_HIDDEN"))]
38 const HIDDEN = 0x0000_0040;
39 #[doc(alias("FUNC_THUNK"))]
41 const THUNK = 0x0000_0080;
42 #[doc(alias("FUNC_BOTTOMBP"))]
44 const BOTTOMBP = 0x0000_0100;
45 #[doc(alias("FUNC_NORET_PENDING"))]
47 const NORET_PENDING = 0x0000_0200;
48 #[doc(alias("FUNC_SP_READY"))]
50 const SP_READY = 0x0000_0400;
51 #[doc(alias("FUNC_FUZZY_SP"))]
53 const FUZZY_SP = 0x0000_0800;
54 #[doc(alias("FUNC_PROLOG_OK"))]
56 const PROLOG_OK = 0x0000_1000;
57 #[doc(alias("FUNC_PURGED_OK"))]
59 const PURGED_OK = 0x0000_4000;
60 #[doc(alias("FUNC_TAIL"))]
62 const TAIL = 0x0000_8000;
63 #[doc(alias("FUNC_LUMINA"))]
65 const LUMINA = 0x0001_0000;
66 #[doc(alias("FUNC_OUTLINE"))]
68 const OUTLINE = 0x0002_0000;
69 #[doc(alias("FUNC_REANALYZE"))]
71 const REANALYZE = 0x0004_0000;
72 #[doc(alias("FUNC_UNWIND"))]
74 const UNWIND = 0x0008_0000;
75 #[doc(alias("FUNC_CATCH"))]
77 const CATCH = 0x0010_0000;
78 #[doc(alias("FUNC_RESERVED"))]
80 const RESERVED = 0x8000_0000_0000_0000;
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use assert2::assert;
87 use proptest::prelude::*;
88 use rstest::rstest;
89
90 use super::*;
91
92 #[rstest]
93 #[case::noret(FuncFlags::NORET, 0x0000_0001)]
94 #[case::far(FuncFlags::FAR, 0x0000_0002)]
95 #[case::lib(FuncFlags::LIB, 0x0000_0004)]
96 #[case::staticdef(FuncFlags::STATICDEF, 0x0000_0008)]
97 #[case::frame(FuncFlags::FRAME, 0x0000_0010)]
98 #[case::userfar(FuncFlags::USERFAR, 0x0000_0020)]
99 #[case::hidden(FuncFlags::HIDDEN, 0x0000_0040)]
100 #[case::thunk(FuncFlags::THUNK, 0x0000_0080)]
101 #[case::bottombp(FuncFlags::BOTTOMBP, 0x0000_0100)]
102 #[case::noret_pending(FuncFlags::NORET_PENDING, 0x0000_0200)]
103 #[case::sp_ready(FuncFlags::SP_READY, 0x0000_0400)]
104 #[case::fuzzy_sp(FuncFlags::FUZZY_SP, 0x0000_0800)]
105 #[case::prolog_ok(FuncFlags::PROLOG_OK, 0x0000_1000)]
106 #[case::purged_ok(FuncFlags::PURGED_OK, 0x0000_4000)]
107 #[case::tail(FuncFlags::TAIL, 0x0000_8000)]
108 #[case::lumina(FuncFlags::LUMINA, 0x0001_0000)]
109 #[case::outline(FuncFlags::OUTLINE, 0x0002_0000)]
110 #[case::reanalyze(FuncFlags::REANALYZE, 0x0004_0000)]
111 #[case::unwind(FuncFlags::UNWIND, 0x0008_0000)]
112 #[case::catch(FuncFlags::CATCH, 0x0010_0000)]
113 #[case::reserved(FuncFlags::RESERVED, 0x8000_0000_0000_0000)]
114 fn flags_pin_the_raw_sdk_values(#[case] flag: FuncFlags, #[case] raw: u64) {
115 assert!(flag.bits() == raw);
116 }
117
118 proptest! {
119 #[test]
120 fn from_bits_retain_round_trips_every_bit_pattern(raw: u64) {
121 prop_assert_eq!(FuncFlags::from_bits_retain(raw).bits(), raw);
122 }
123
124 #[test]
125 fn union_and_intersection_are_raw_bitwise_ops(a: u64, b: u64) {
126 let (fa, fb) = (FuncFlags::from_bits_retain(a), FuncFlags::from_bits_retain(b));
127 prop_assert_eq!((fa | fb).bits(), a | b);
128 prop_assert_eq!((fa & fb).bits(), a & b);
129 }
130
131 #[test]
132 fn complement_truncates_to_the_known_flag_mask(a: u64) {
133 let fa = FuncFlags::from_bits_retain(a);
134 prop_assert_eq!((!fa).bits(), !a & FuncFlags::all().bits());
135 }
136 }
137}