memscope_rs/analysis/
mod.rs

1//! Memory analysis functionality
2//!
3//! This module provides advanced analysis capabilities:
4//! - Enhanced memory analysis
5//! - Circular reference detection
6//! - Unsafe FFI tracking
7//! - Unknown memory region analysis
8
9pub mod circular_reference;
10pub mod enhanced_memory_analysis;
11pub mod unknown_memory_regions;
12pub mod unsafe_ffi_tracker;
13pub mod variable_relationships;
14
15// New analysis modules for ComplexTypeForRust.md features
16pub mod async_analysis;
17pub mod borrow_analysis;
18pub mod closure_analysis;
19pub mod enhanced_ffi_function_resolver;
20pub mod ffi_function_resolver;
21pub mod generic_analysis;
22pub mod lifecycle_analysis;
23pub mod memory_passport_tracker;
24pub mod safety_analyzer;
25pub mod security_violation_analyzer;
26
27// Re-export key analysis functions
28pub use circular_reference::{CircularReference, CircularReferenceAnalysis, CircularReferenceNode};
29pub use enhanced_memory_analysis::{analyze_memory_with_enhanced_features, EnhancedMemoryAnalyzer};
30pub use unsafe_ffi_tracker::UnsafeFFITracker;
31pub use variable_relationships::{
32    build_variable_relationship_graph, GraphStatistics, RelationshipType as VarRelationshipType,
33    SmartPointerInfo as VarSmartPointerInfo, VariableCategory, VariableCluster, VariableNode,
34    VariableRelationship, VariableRelationshipGraph,
35};
36
37// Re-export new analysis modules
38pub use async_analysis::{
39    get_global_async_analyzer, AsyncAnalyzer, AsyncPatternAnalysis, AsyncStatistics,
40};
41pub use borrow_analysis::{get_global_borrow_analyzer, BorrowAnalyzer, BorrowPatternAnalysis};
42pub use closure_analysis::{get_global_closure_analyzer, ClosureAnalysisReport, ClosureAnalyzer};
43pub use ffi_function_resolver::{
44    get_global_ffi_resolver, initialize_global_ffi_resolver, FfiFunctionCategory,
45    FfiFunctionResolver, FfiRiskLevel, ResolutionStats, ResolvedFfiFunction, ResolverConfig,
46};
47pub use generic_analysis::{get_global_generic_analyzer, GenericAnalyzer, GenericStatistics};
48pub use lifecycle_analysis::{
49    get_global_lifecycle_analyzer, LifecycleAnalysisReport, LifecycleAnalyzer,
50};
51pub use memory_passport_tracker::{
52    get_global_passport_tracker, initialize_global_passport_tracker, LeakDetail,
53    LeakDetectionResult, MemoryPassport, MemoryPassportTracker, PassportEvent, PassportEventType,
54    PassportStatus, PassportTrackerConfig, PassportTrackerStats,
55};
56pub use safety_analyzer::{
57    DynamicViolation, RiskAssessment, RiskFactor, RiskFactorType, SafetyAnalysisConfig,
58    SafetyAnalysisStats, SafetyAnalyzer, UnsafeReport, UnsafeSource,
59};
60pub use unsafe_ffi_tracker::ComprehensiveSafetyReport;
61
62use crate::core::types::*;
63use std::sync::Arc;
64
65/// Main analysis interface - consolidates all analysis functionality
66pub struct AnalysisManager {
67    // This will contain the consolidated analysis functionality
68}
69
70impl AnalysisManager {
71    /// Create a new analysis manager instance
72    pub fn new() -> Self {
73        Self {}
74    }
75
76    /// Analyze memory fragmentation
77    pub fn analyze_fragmentation(&self, _allocations: &[AllocationInfo]) -> FragmentationAnalysis {
78        // Simple implementation for now
79        FragmentationAnalysis::default()
80    }
81
82    /// Analyze system library usage
83    pub fn analyze_system_libraries(&self, _allocations: &[AllocationInfo]) -> SystemLibraryStats {
84        // Simple implementation for now
85        SystemLibraryStats::default()
86    }
87
88    /// Analyze concurrency safety
89    pub fn analyze_concurrency_safety(
90        &self,
91        _allocations: &[AllocationInfo],
92    ) -> ConcurrencyAnalysis {
93        // Simple implementation for now
94        ConcurrencyAnalysis::default()
95    }
96
97    /// Get unsafe/FFI tracker instance
98    pub fn get_unsafe_ffi_tracker(&self) -> Arc<crate::unsafe_ffi_tracker::UnsafeFFITracker> {
99        // Delegate to existing global tracker
100        crate::unsafe_ffi_tracker::get_global_unsafe_ffi_tracker()
101    }
102
103    /// Get unsafe/FFI statistics
104    pub fn get_unsafe_ffi_stats(&self) -> crate::unsafe_ffi_tracker::UnsafeFFIStats {
105        // Get stats from the global tracker
106        self.get_unsafe_ffi_tracker().get_stats()
107    }
108
109    /// Analyze circular references in smart pointers
110    pub fn analyze_circular_references(
111        &self,
112        allocations: &[AllocationInfo],
113    ) -> crate::circular_reference::CircularReferenceAnalysis {
114        crate::circular_reference::detect_circular_references(allocations)
115    }
116
117    /// Analyze advanced types (Cell, RefCell, Mutex, etc.)
118    pub fn analyze_advanced_types(
119        &self,
120        allocations: &[AllocationInfo],
121    ) -> crate::advanced_types::AdvancedTypeAnalysisReport {
122        crate::advanced_types::analyze_advanced_types(allocations)
123    }
124
125    /// Analyze borrow checker integration and lifetime tracking
126    pub fn analyze_borrow_patterns(
127        &self,
128        _allocations: &[AllocationInfo],
129    ) -> BorrowPatternAnalysis {
130        let analyzer = get_global_borrow_analyzer();
131        analyzer.analyze_borrow_patterns()
132    }
133
134    /// Analyze generic type usage and constraints
135    pub fn analyze_generic_types(&self, _allocations: &[AllocationInfo]) -> GenericStatistics {
136        // Create a new analyzer instance to avoid global state pollution in tests
137        let analyzer = GenericAnalyzer::new();
138        analyzer.get_generic_statistics()
139    }
140
141    /// Analyze async types and Future state machines
142    pub fn analyze_async_patterns(&self, _allocations: &[AllocationInfo]) -> AsyncPatternAnalysis {
143        let analyzer = get_global_async_analyzer();
144        analyzer.analyze_async_patterns()
145    }
146
147    /// Analyze closure captures and lifetime relationships
148    pub fn analyze_closure_patterns(
149        &self,
150        allocations: &[AllocationInfo],
151    ) -> ClosureAnalysisReport {
152        let analyzer = get_global_closure_analyzer();
153        analyzer.analyze_closure_patterns(allocations)
154    }
155
156    /// Analyze lifecycle patterns including Drop trait and RAII
157    pub fn analyze_lifecycle_patterns(
158        &self,
159        _allocations: &[AllocationInfo],
160    ) -> LifecycleAnalysisReport {
161        let analyzer = get_global_lifecycle_analyzer();
162        analyzer.get_lifecycle_report()
163    }
164
165    /// Perform comprehensive analysis
166    pub fn perform_comprehensive_analysis(
167        &self,
168        allocations: &[AllocationInfo],
169        stats: &MemoryStats,
170    ) -> ComprehensiveAnalysisReport {
171        let fragmentation = self.analyze_fragmentation(allocations);
172        let system_libs = self.analyze_system_libraries(allocations);
173        let concurrency = self.analyze_concurrency_safety(allocations);
174        let unsafe_stats = self.get_unsafe_ffi_stats();
175        let circular_refs = self.analyze_circular_references(allocations);
176        let advanced_types = self.analyze_advanced_types(allocations);
177
178        // New comprehensive analysis features
179        let borrow_analysis = self.analyze_borrow_patterns(allocations);
180        let generic_analysis = self.analyze_generic_types(allocations);
181        let async_analysis = self.analyze_async_patterns(allocations);
182        let closure_analysis = self.analyze_closure_patterns(allocations);
183        let lifecycle_analysis = self.analyze_lifecycle_patterns(allocations);
184
185        ComprehensiveAnalysisReport {
186            fragmentation_analysis: fragmentation,
187            system_library_stats: system_libs,
188            concurrency_analysis: concurrency,
189            unsafe_ffi_stats: unsafe_stats,
190            circular_reference_analysis: circular_refs,
191            advanced_type_analysis: advanced_types,
192            borrow_analysis,
193            generic_analysis,
194            async_analysis,
195            closure_analysis,
196            lifecycle_analysis,
197            memory_stats: stats.clone(),
198            analysis_timestamp: std::time::SystemTime::now()
199                .duration_since(std::time::UNIX_EPOCH)
200                .unwrap_or_default()
201                .as_secs(),
202        }
203    }
204}
205
206impl Default for AnalysisManager {
207    fn default() -> Self {
208        Self::new()
209    }
210}
211
212/// Comprehensive analysis report
213#[derive(Debug, Clone)]
214pub struct ComprehensiveAnalysisReport {
215    /// Memory fragmentation analysis results
216    pub fragmentation_analysis: FragmentationAnalysis,
217    /// System library usage statistics
218    pub system_library_stats: SystemLibraryStats,
219    /// Concurrency safety analysis
220    pub concurrency_analysis: ConcurrencyAnalysis,
221    /// Unsafe and FFI operation statistics
222    pub unsafe_ffi_stats: crate::unsafe_ffi_tracker::UnsafeFFIStats,
223    /// Circular reference analysis for smart pointers
224    pub circular_reference_analysis: crate::circular_reference::CircularReferenceAnalysis,
225    /// Advanced type analysis (Cell, RefCell, Mutex, etc.)
226    pub advanced_type_analysis: crate::advanced_types::AdvancedTypeAnalysisReport,
227    /// Borrow checker integration and lifetime tracking
228    pub borrow_analysis: BorrowPatternAnalysis,
229    /// Generic type usage and constraint analysis
230    pub generic_analysis: GenericStatistics,
231    /// Async type and Future state machine analysis
232    pub async_analysis: AsyncPatternAnalysis,
233    /// Closure capture and lifetime analysis
234    pub closure_analysis: ClosureAnalysisReport,
235    /// Lifecycle patterns including Drop trait and RAII
236    pub lifecycle_analysis: LifecycleAnalysisReport,
237    /// Overall memory statistics
238    pub memory_stats: MemoryStats,
239    /// Timestamp when analysis was performed
240    pub analysis_timestamp: u64,
241}
242
243// Re-export all the existing analysis functions for backward compatibility
244// This ensures that existing code continues to work without changes
245
246/// Analyze memory fragmentation - backward compatibility function
247pub fn analyze_fragmentation(allocations: &[AllocationInfo]) -> FragmentationAnalysis {
248    let manager = AnalysisManager::new();
249    manager.analyze_fragmentation(allocations)
250}
251
252/// Analyze system library usage - backward compatibility function
253pub fn analyze_system_libraries(allocations: &[AllocationInfo]) -> SystemLibraryStats {
254    let manager = AnalysisManager::new();
255    manager.analyze_system_libraries(allocations)
256}
257
258/// Analyze concurrency safety - backward compatibility function
259pub fn analyze_concurrency_safety(allocations: &[AllocationInfo]) -> ConcurrencyAnalysis {
260    let manager = AnalysisManager::new();
261    manager.analyze_concurrency_safety(allocations)
262}
263
264/// Get global unsafe/FFI tracker - backward compatibility function
265pub fn get_global_unsafe_ffi_tracker() -> Arc<crate::unsafe_ffi_tracker::UnsafeFFITracker> {
266    crate::unsafe_ffi_tracker::get_global_unsafe_ffi_tracker()
267}
268
269/// Get unsafe/FFI statistics - convenience function
270pub fn get_unsafe_ffi_stats() -> crate::unsafe_ffi_tracker::UnsafeFFIStats {
271    let manager = AnalysisManager::new();
272    manager.get_unsafe_ffi_stats()
273}
274
275/// Perform comprehensive analysis - convenience function
276pub fn perform_comprehensive_analysis(
277    allocations: &[AllocationInfo],
278    stats: &MemoryStats,
279) -> ComprehensiveAnalysisReport {
280    let manager = AnalysisManager::new();
281    manager.perform_comprehensive_analysis(allocations, stats)
282}
283
284// Analysis module - consolidating implementations for better organization
285// For now, we're just creating the interface and delegating to the existing implementations
286
287#[cfg(test)]
288mod tests {
289    use super::*;
290    use crate::core::types::AllocationInfo;
291
292    #[test]
293    fn test_analyze_fragmentation() {
294        let manager = AnalysisManager::new();
295        let allocations = vec![
296            AllocationInfo::new(0x1000, 1024),
297            AllocationInfo::new(0x2000, 512),
298        ];
299
300        let result = manager.analyze_fragmentation(&allocations);
301
302        // Test that fragmentation analysis returns valid default values
303        assert_eq!(result.fragmentation_ratio, 0.0);
304        assert_eq!(result.largest_free_block, 0);
305        assert_eq!(result.free_block_count, 0);
306        assert_eq!(result.total_free_memory, 0);
307        assert_eq!(result.external_fragmentation, 0.0);
308        assert_eq!(result.internal_fragmentation, 0.0);
309    }
310
311    #[test]
312    fn test_analyze_system_libraries() {
313        let manager = AnalysisManager::new();
314        let allocations = vec![AllocationInfo::new(0x1000, 256)];
315
316        let result = manager.analyze_system_libraries(&allocations);
317
318        // Test that system library analysis returns valid default values
319        assert_eq!(result.std_collections.allocation_count, 0);
320        assert_eq!(result.async_runtime.total_bytes, 0);
321        assert_eq!(result.network_io.peak_bytes, 0);
322        assert_eq!(result.file_system.average_size, 0.0);
323        assert!(result.serialization.categories.is_empty());
324        assert!(result.regex_engine.hotspot_functions.is_empty());
325    }
326
327    #[test]
328    fn test_analyze_concurrency_safety() {
329        let manager = AnalysisManager::new();
330        let allocations = vec![AllocationInfo::new(0x3000, 2048)];
331
332        let result = manager.analyze_concurrency_safety(&allocations);
333
334        // Test that concurrency analysis returns valid default values
335        assert_eq!(result.thread_safety_allocations, 0);
336        assert_eq!(result.shared_memory_bytes, 0);
337        assert_eq!(result.mutex_protected, 0);
338        assert_eq!(result.arc_shared, 0);
339        assert_eq!(result.rc_shared, 0);
340        assert_eq!(result.channel_buffers, 0);
341        assert_eq!(result.thread_local_storage, 0);
342        assert_eq!(result.atomic_operations, 0);
343        assert_eq!(result.lock_contention_risk, "");
344    }
345
346    #[test]
347    fn test_get_unsafe_ffi_tracker() {
348        let manager = AnalysisManager::new();
349
350        let _tracker = manager.get_unsafe_ffi_tracker();
351
352        // Test that tracker is returned successfully
353    }
354
355    #[test]
356    fn test_get_unsafe_ffi_stats() {
357        let manager = AnalysisManager::new();
358
359        let stats = manager.get_unsafe_ffi_stats();
360
361        // Test that stats are returned with valid default values
362        assert_eq!(stats.total_operations, 0);
363        assert_eq!(stats.ffi_calls, 0);
364        assert_eq!(stats.raw_pointer_operations, 0);
365        assert_eq!(stats.memory_violations, 0);
366        assert!(stats.operations.is_empty());
367    }
368
369    #[test]
370    fn test_analyze_circular_references() {
371        let manager = AnalysisManager::new();
372        let allocations = vec![
373            AllocationInfo::new(0x4000, 128),
374            AllocationInfo::new(0x5000, 256),
375        ];
376
377        let result = manager.analyze_circular_references(&allocations);
378
379        // Test that circular reference analysis returns valid results
380        assert_eq!(result.total_smart_pointers, 0);
381        assert_eq!(result.circular_references.len(), 0);
382        assert_eq!(result.pointers_in_cycles, 0);
383        assert_eq!(result.total_leaked_memory, 0);
384    }
385
386    #[test]
387    fn test_analyze_advanced_types() {
388        let manager = AnalysisManager::new();
389        let allocations = vec![AllocationInfo::new(0x6000, 512)];
390
391        let result = manager.analyze_advanced_types(&allocations);
392
393        // Test that advanced type analysis returns valid results
394        assert!(result.by_category.is_empty());
395        assert!(result.all_issues.is_empty());
396        // Performance summary may have default values, so just check it's not negative
397        assert!(result.performance_summary.total_overhead_factor >= 0.0);
398        assert_eq!(result.statistics.total_advanced_types, 0);
399    }
400
401    #[test]
402    fn test_analyze_borrow_patterns() {
403        let manager = AnalysisManager::new();
404        let allocations = vec![AllocationInfo::new(0x7000, 1024)];
405
406        let result = manager.analyze_borrow_patterns(&allocations);
407
408        // Test that borrow pattern analysis returns valid results
409        assert!(result.patterns.is_empty());
410        assert_eq!(result.total_events, 0);
411        assert!(result.analysis_timestamp > 0);
412    }
413
414    #[test]
415    fn test_analyze_generic_types() {
416        let manager = AnalysisManager::new();
417        let allocations = vec![AllocationInfo::new(0x8000, 256)];
418
419        let result = manager.analyze_generic_types(&allocations);
420
421        // Test that generic type analysis returns valid results
422        assert_eq!(result.total_instances, 0);
423        assert_eq!(result.unique_base_types, 0);
424        assert_eq!(result.total_instantiations, 0);
425        assert_eq!(result.constraint_violations, 0);
426        assert!(result.most_used_types.is_empty());
427    }
428
429    #[test]
430    fn test_analyze_async_patterns() {
431        let manager = AnalysisManager::new();
432        let allocations = vec![AllocationInfo::new(0x9000, 2048)];
433
434        let result = manager.analyze_async_patterns(&allocations);
435
436        // Test that async pattern analysis returns valid results
437        assert!(result.patterns.is_empty());
438        assert_eq!(result.total_futures_analyzed, 0);
439        assert!(result.analysis_timestamp > 0);
440    }
441
442    #[test]
443    fn test_analyze_closure_patterns() {
444        let manager = AnalysisManager::new();
445        let allocations = vec![AllocationInfo::new(0xa000, 128)];
446
447        let result = manager.analyze_closure_patterns(&allocations);
448
449        // Test that closure pattern analysis returns valid results
450        assert!(result.detected_closures.is_empty());
451        assert_eq!(result.capture_statistics.total_closures, 0);
452        assert!(result.optimization_suggestions.is_empty());
453        assert!(result.lifetime_analysis.lifetime_patterns.is_empty());
454        assert!(result.analysis_timestamp > 0);
455    }
456
457    #[test]
458    fn test_analyze_lifecycle_patterns() {
459        let manager = AnalysisManager::new();
460        let allocations = vec![AllocationInfo::new(0xb000, 512)];
461
462        let result = manager.analyze_lifecycle_patterns(&allocations);
463
464        // Test that lifecycle pattern analysis returns valid results
465        assert!(result.drop_events.is_empty());
466        assert!(result.raii_patterns.is_empty());
467        assert!(result.borrow_analysis.borrow_patterns.is_empty());
468        assert!(result.closure_captures.is_empty());
469        assert!(result.analysis_timestamp > 0);
470    }
471
472    #[test]
473    fn test_perform_comprehensive_analysis() {
474        let manager = AnalysisManager::new();
475        let allocations = vec![
476            AllocationInfo::new(0x1000, 1024),
477            AllocationInfo::new(0x2000, 512),
478            AllocationInfo::new(0x3000, 256),
479        ];
480        let stats = MemoryStats::new();
481
482        let result = manager.perform_comprehensive_analysis(&allocations, &stats);
483
484        // Test that comprehensive analysis includes all components
485        assert_eq!(result.fragmentation_analysis.fragmentation_ratio, 0.0);
486        assert_eq!(
487            result.system_library_stats.std_collections.allocation_count,
488            0
489        );
490        assert_eq!(result.concurrency_analysis.thread_safety_allocations, 0);
491        assert_eq!(result.unsafe_ffi_stats.total_operations, 0);
492        assert_eq!(result.circular_reference_analysis.total_smart_pointers, 0);
493        assert!(result.advanced_type_analysis.by_category.is_empty());
494        assert!(result.borrow_analysis.patterns.is_empty());
495        assert_eq!(result.generic_analysis.total_instances, 0);
496        assert!(result.async_analysis.patterns.is_empty());
497        assert!(result.closure_analysis.detected_closures.is_empty());
498        assert!(result.lifecycle_analysis.drop_events.is_empty());
499        assert_eq!(result.memory_stats.total_allocations, 0);
500        assert!(result.analysis_timestamp > 0);
501    }
502
503    #[test]
504    fn test_backward_compatibility_functions() {
505        let allocations = vec![AllocationInfo::new(0x1000, 1024)];
506
507        // Test backward compatibility functions
508        let frag_result = analyze_fragmentation(&allocations);
509        assert_eq!(frag_result.fragmentation_ratio, 0.0);
510
511        let lib_result = analyze_system_libraries(&allocations);
512        assert_eq!(lib_result.std_collections.allocation_count, 0);
513
514        let conc_result = analyze_concurrency_safety(&allocations);
515        assert_eq!(conc_result.thread_safety_allocations, 0);
516
517        let _tracker = get_global_unsafe_ffi_tracker();
518
519        let stats = get_unsafe_ffi_stats();
520        assert_eq!(stats.total_operations, 0);
521
522        let memory_stats = MemoryStats::new();
523        let comp_result = perform_comprehensive_analysis(&allocations, &memory_stats);
524        assert!(comp_result.analysis_timestamp > 0);
525    }
526
527    #[test]
528    fn test_empty_allocations_analysis() {
529        let manager = AnalysisManager::new();
530        let empty_allocations: Vec<AllocationInfo> = vec![];
531
532        // Test that analysis works with empty allocation list
533        let frag_result = manager.analyze_fragmentation(&empty_allocations);
534        assert_eq!(frag_result.fragmentation_ratio, 0.0);
535
536        let lib_result = manager.analyze_system_libraries(&empty_allocations);
537        assert_eq!(lib_result.std_collections.allocation_count, 0);
538
539        let conc_result = manager.analyze_concurrency_safety(&empty_allocations);
540        assert_eq!(conc_result.thread_safety_allocations, 0);
541
542        let circ_result = manager.analyze_circular_references(&empty_allocations);
543        assert_eq!(circ_result.total_smart_pointers, 0);
544
545        let adv_result = manager.analyze_advanced_types(&empty_allocations);
546        assert!(adv_result.by_category.is_empty());
547    }
548
549    #[test]
550    fn test_large_allocation_list_analysis() {
551        let manager = AnalysisManager::new();
552        let mut allocations = Vec::new();
553
554        // Create a larger list of allocations to test performance
555        for i in 0..100 {
556            allocations.push(AllocationInfo::new(0x1000 + i * 0x1000, 1024 + i));
557        }
558
559        let stats = MemoryStats::new();
560        let result = manager.perform_comprehensive_analysis(&allocations, &stats);
561
562        // Test that analysis completes successfully with larger datasets
563        assert!(result.analysis_timestamp > 0);
564        assert_eq!(result.memory_stats.total_allocations, 0); // Default stats
565    }
566}