1use crate::capture::types::ImplementationDifficulty;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct UnknownMemoryRegionAnalysis {
6 pub total_unknown_bytes: usize,
7 pub unknown_percentage: f64,
8 pub unknown_categories: Vec<UnknownMemoryCategory>,
9 pub potential_causes: Vec<UnknownMemoryCause>,
10 pub reduction_strategies: Vec<UnknownRegionReductionStrategy>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct UnknownMemoryCategory {
15 pub category_type: UnknownRegionType,
16 pub description: String,
17 pub estimated_size: usize,
18 pub confidence_level: f64,
19 pub examples: Vec<UnknownMemoryExample>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub enum UnknownRegionType {
24 MemoryMappedRegions,
25 ThreadLocalStorage,
26 DynamicLibraryRegions,
27 SystemReservedRegions,
28 JitCodeRegions,
29 ExternalLibraryAllocations,
30 GuardPages,
31 VdsoRegions,
32 AnonymousMappings,
33 SharedMemorySegments,
34 PreTrackingAllocations,
35 CorruptedMetadata,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct UnknownMemoryExample {
40 pub address_range: (usize, usize),
41 pub size: usize,
42 pub suspected_origin: String,
43 pub access_pattern: MemoryAccessPattern,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum UnknownMemoryCause {
48 ForeignFunctionInterface {
49 library_name: String,
50 function_name: Option<String>,
51 },
52 MemoryMapping {
53 mapping_type: MappingType,
54 file_path: Option<String>,
55 },
56 SystemAllocations {
57 allocation_type: SystemAllocationType,
58 },
59 ThreadingMemory {
60 thread_id: Option<u64>,
61 memory_type: ThreadMemoryType,
62 },
63 DynamicLoading {
64 library_path: String,
65 load_time: u64,
66 },
67 InstrumentationGaps {
68 gap_type: InstrumentationGapType,
69 description: String,
70 },
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub enum MappingType {
75 FileMapping,
76 AnonymousMapping,
77 SharedMapping,
78 DeviceMapping,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub enum SystemAllocationType {
83 KernelBuffers,
84 DriverMemory,
85 SystemCaches,
86 HardwareReserved,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub enum ThreadMemoryType {
91 ThreadStack,
92 ThreadLocalStorage,
93 ThreadControlBlock,
94 ThreadSynchronization,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub enum InstrumentationGapType {
99 EarlyBootstrap,
100 SignalHandlers,
101 InterruptHandlers,
102 AtomicOperations,
103 CompilerOptimizations,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct UnknownRegionReductionStrategy {
108 pub strategy_type: ReductionStrategyType,
109 pub description: String,
110 pub implementation_steps: Vec<String>,
111 pub expected_improvement: f64,
112 pub implementation_difficulty: ImplementationDifficulty,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub enum ReductionStrategyType {
117 EnhancedInstrumentation,
118 BetterSymbolResolution,
119 MemoryMappingTracking,
120 FfiCallInterception,
121 SystemCallMonitoring,
122 ThreadAwareTracking,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct SystemRegionInfo {
127 pub region_type: String,
128 pub description: String,
129 pub read_only: bool,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct LibraryMappingInfo {
134 pub start_address: usize,
135 pub end_address: usize,
136 pub permissions: String,
137 pub file_path: String,
138}
139
140impl LibraryMappingInfo {
141 pub fn contains_address(&self, addr: usize) -> bool {
142 addr >= self.start_address && addr < self.end_address
143 }
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub enum MemoryAccessPattern {
148 Sequential,
149 Random,
150 Sparse,
151 Unknown,
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
161 fn test_analysis_creation() {
162 let analysis = UnknownMemoryRegionAnalysis {
163 total_unknown_bytes: 1024,
164 unknown_percentage: 25.5,
165 unknown_categories: vec![],
166 potential_causes: vec![],
167 reduction_strategies: vec![],
168 };
169
170 assert_eq!(
171 analysis.total_unknown_bytes, 1024,
172 "Total bytes should match"
173 );
174 assert_eq!(analysis.unknown_percentage, 25.5, "Percentage should match");
175 }
176
177 #[test]
180 fn test_category_creation() {
181 let category = UnknownMemoryCategory {
182 category_type: UnknownRegionType::MemoryMappedRegions,
183 description: "Test category".to_string(),
184 estimated_size: 4096,
185 confidence_level: 0.85,
186 examples: vec![],
187 };
188
189 assert_eq!(category.estimated_size, 4096, "Size should match");
190 assert_eq!(category.confidence_level, 0.85, "Confidence should match");
191 }
192
193 #[test]
196 fn test_region_type_variants() {
197 let variants = [
198 UnknownRegionType::MemoryMappedRegions,
199 UnknownRegionType::ThreadLocalStorage,
200 UnknownRegionType::DynamicLibraryRegions,
201 UnknownRegionType::SystemReservedRegions,
202 UnknownRegionType::JitCodeRegions,
203 UnknownRegionType::ExternalLibraryAllocations,
204 UnknownRegionType::GuardPages,
205 UnknownRegionType::VdsoRegions,
206 UnknownRegionType::AnonymousMappings,
207 UnknownRegionType::SharedMemorySegments,
208 UnknownRegionType::PreTrackingAllocations,
209 UnknownRegionType::CorruptedMetadata,
210 ];
211
212 for variant in &variants {
213 let debug_str = format!("{variant:?}");
214 assert!(
215 !debug_str.is_empty(),
216 "Variant should have debug representation"
217 );
218 }
219 }
220
221 #[test]
224 fn test_example_creation() {
225 let example = UnknownMemoryExample {
226 address_range: (0x1000, 0x2000),
227 size: 4096,
228 suspected_origin: "mmap".to_string(),
229 access_pattern: MemoryAccessPattern::Sequential,
230 };
231
232 assert_eq!(
233 example.address_range.0, 0x1000,
234 "Start address should match"
235 );
236 assert_eq!(example.size, 4096, "Size should match");
237 }
238
239 #[test]
242 fn test_cause_variants() {
243 let ffi_cause = UnknownMemoryCause::ForeignFunctionInterface {
244 library_name: "libc".to_string(),
245 function_name: Some("malloc".to_string()),
246 };
247
248 let mmap_cause = UnknownMemoryCause::MemoryMapping {
249 mapping_type: MappingType::AnonymousMapping,
250 file_path: None,
251 };
252
253 let system_cause = UnknownMemoryCause::SystemAllocations {
254 allocation_type: SystemAllocationType::KernelBuffers,
255 };
256
257 let thread_cause = UnknownMemoryCause::ThreadingMemory {
258 thread_id: Some(1),
259 memory_type: ThreadMemoryType::ThreadStack,
260 };
261
262 let dynamic_cause = UnknownMemoryCause::DynamicLoading {
263 library_path: "/lib/test.so".to_string(),
264 load_time: 1000,
265 };
266
267 let gap_cause = UnknownMemoryCause::InstrumentationGaps {
268 gap_type: InstrumentationGapType::EarlyBootstrap,
269 description: "Early initialization".to_string(),
270 };
271
272 assert!(matches!(
273 ffi_cause,
274 UnknownMemoryCause::ForeignFunctionInterface { .. }
275 ));
276 assert!(matches!(
277 mmap_cause,
278 UnknownMemoryCause::MemoryMapping { .. }
279 ));
280 assert!(matches!(
281 system_cause,
282 UnknownMemoryCause::SystemAllocations { .. }
283 ));
284 assert!(matches!(
285 thread_cause,
286 UnknownMemoryCause::ThreadingMemory { .. }
287 ));
288 assert!(matches!(
289 dynamic_cause,
290 UnknownMemoryCause::DynamicLoading { .. }
291 ));
292 assert!(matches!(
293 gap_cause,
294 UnknownMemoryCause::InstrumentationGaps { .. }
295 ));
296 }
297
298 #[test]
301 fn test_mapping_type_variants() {
302 assert!(matches!(MappingType::FileMapping, MappingType::FileMapping));
303 assert!(matches!(
304 MappingType::AnonymousMapping,
305 MappingType::AnonymousMapping
306 ));
307 assert!(matches!(
308 MappingType::SharedMapping,
309 MappingType::SharedMapping
310 ));
311 assert!(matches!(
312 MappingType::DeviceMapping,
313 MappingType::DeviceMapping
314 ));
315 }
316
317 #[test]
320 fn test_system_allocation_type_variants() {
321 let variants = [
322 SystemAllocationType::KernelBuffers,
323 SystemAllocationType::DriverMemory,
324 SystemAllocationType::SystemCaches,
325 SystemAllocationType::HardwareReserved,
326 ];
327
328 for variant in &variants {
329 let debug_str = format!("{variant:?}");
330 assert!(
331 !debug_str.is_empty(),
332 "Variant should have debug representation"
333 );
334 }
335 }
336
337 #[test]
340 fn test_thread_memory_type_variants() {
341 let variants = [
342 ThreadMemoryType::ThreadStack,
343 ThreadMemoryType::ThreadLocalStorage,
344 ThreadMemoryType::ThreadControlBlock,
345 ThreadMemoryType::ThreadSynchronization,
346 ];
347
348 for variant in &variants {
349 let debug_str = format!("{variant:?}");
350 assert!(
351 !debug_str.is_empty(),
352 "Variant should have debug representation"
353 );
354 }
355 }
356
357 #[test]
360 fn test_instrumentation_gap_type_variants() {
361 let variants = [
362 InstrumentationGapType::EarlyBootstrap,
363 InstrumentationGapType::SignalHandlers,
364 InstrumentationGapType::InterruptHandlers,
365 InstrumentationGapType::AtomicOperations,
366 InstrumentationGapType::CompilerOptimizations,
367 ];
368
369 for variant in &variants {
370 let debug_str = format!("{variant:?}");
371 assert!(
372 !debug_str.is_empty(),
373 "Variant should have debug representation"
374 );
375 }
376 }
377
378 #[test]
381 fn test_reduction_strategy_creation() {
382 let strategy = UnknownRegionReductionStrategy {
383 strategy_type: ReductionStrategyType::EnhancedInstrumentation,
384 description: "Test strategy".to_string(),
385 implementation_steps: vec!["Step 1".to_string(), "Step 2".to_string()],
386 expected_improvement: 50.0,
387 implementation_difficulty: ImplementationDifficulty::Medium,
388 };
389
390 assert_eq!(
391 strategy.implementation_steps.len(),
392 2,
393 "Should have two steps"
394 );
395 assert_eq!(
396 strategy.expected_improvement, 50.0,
397 "Improvement should match"
398 );
399 }
400
401 #[test]
404 fn test_reduction_strategy_type_variants() {
405 let variants = [
406 ReductionStrategyType::EnhancedInstrumentation,
407 ReductionStrategyType::BetterSymbolResolution,
408 ReductionStrategyType::MemoryMappingTracking,
409 ReductionStrategyType::FfiCallInterception,
410 ReductionStrategyType::SystemCallMonitoring,
411 ReductionStrategyType::ThreadAwareTracking,
412 ];
413
414 for variant in &variants {
415 let debug_str = format!("{variant:?}");
416 assert!(
417 !debug_str.is_empty(),
418 "Variant should have debug representation"
419 );
420 }
421 }
422
423 #[test]
426 fn test_system_region_info_creation() {
427 let info = SystemRegionInfo {
428 region_type: "kernel".to_string(),
429 description: "Kernel region".to_string(),
430 read_only: true,
431 };
432
433 assert_eq!(info.region_type, "kernel", "Region type should match");
434 assert!(info.read_only, "Should be read-only");
435 }
436
437 #[test]
440 fn test_library_mapping_info() {
441 let info = LibraryMappingInfo {
442 start_address: 0x1000,
443 end_address: 0x2000,
444 permissions: "r-x".to_string(),
445 file_path: "/lib/test.so".to_string(),
446 };
447
448 assert!(info.contains_address(0x1000), "Start should be contained");
449 assert!(info.contains_address(0x1500), "Middle should be contained");
450 assert!(
451 !info.contains_address(0x2000),
452 "End should not be contained"
453 );
454 assert!(
455 !info.contains_address(0x500),
456 "Before should not be contained"
457 );
458 }
459
460 #[test]
463 fn test_memory_access_pattern_variants() {
464 assert!(matches!(
465 MemoryAccessPattern::Sequential,
466 MemoryAccessPattern::Sequential
467 ));
468 assert!(matches!(
469 MemoryAccessPattern::Random,
470 MemoryAccessPattern::Random
471 ));
472 assert!(matches!(
473 MemoryAccessPattern::Sparse,
474 MemoryAccessPattern::Sparse
475 ));
476 assert!(matches!(
477 MemoryAccessPattern::Unknown,
478 MemoryAccessPattern::Unknown
479 ));
480 }
481
482 #[test]
485 fn test_serialization() {
486 let analysis = UnknownMemoryRegionAnalysis {
487 total_unknown_bytes: 1024,
488 unknown_percentage: 25.5,
489 unknown_categories: vec![],
490 potential_causes: vec![],
491 reduction_strategies: vec![],
492 };
493
494 let json = serde_json::to_string(&analysis);
495 assert!(json.is_ok(), "Should serialize to JSON");
496
497 let deserialized: Result<UnknownMemoryRegionAnalysis, _> =
498 serde_json::from_str(&json.unwrap());
499 assert!(deserialized.is_ok(), "Should deserialize from JSON");
500 }
501
502 #[test]
505 fn test_zero_values() {
506 let analysis = UnknownMemoryRegionAnalysis {
507 total_unknown_bytes: 0,
508 unknown_percentage: 0.0,
509 unknown_categories: vec![],
510 potential_causes: vec![],
511 reduction_strategies: vec![],
512 };
513
514 assert_eq!(
515 analysis.total_unknown_bytes, 0,
516 "Zero bytes should be valid"
517 );
518 assert_eq!(
519 analysis.unknown_percentage, 0.0,
520 "Zero percentage should be valid"
521 );
522 }
523}