@@ -97,6 +97,19 @@ impl Drop for BoxedCallback {
9797 }
9898}
9999
100+ /// Info of a binary's section that can be used to populate an `Image`
101+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
102+ pub struct SectionInfo {
103+ /// Path of the binary
104+ pub filename : String ,
105+ /// Offset of the section in the file
106+ pub offset : u64 ,
107+ /// Size of the section
108+ pub size : u64 ,
109+ /// Start virtual address of the section once loaded in memory
110+ pub virtual_address : u64 ,
111+ }
112+
100113/// An Image defines the memory image that was traced as a collection
101114/// of file sections and the virtual addresses at which those sections were loaded.
102115#[ derive( Debug ) ]
@@ -109,7 +122,7 @@ pub struct Image {
109122 callback : Option < BoxedCallback > ,
110123 caches : Vec < Rc < SectionCache > > ,
111124 // `HashSet` might grow and move the content around, we cannot use `Asid` directly since we
112- // share a pointer with libipt and it must be valid for the entire Image (section) filetime .
125+ // share a pointer with libipt, and it must be valid for the entire Image (section) lifetime .
113126 asids : HashSet < Rc < Asid > > ,
114127}
115128
@@ -321,6 +334,31 @@ impl Image {
321334 } ) ?;
322335 Ok ( ( ) )
323336 }
337+
338+ /// Add multiple file sections to the traced memory image, backed by a cache.
339+ ///
340+ /// This is the same as creating a `SectionCache` and subsequently calling `add_cached()` for
341+ /// each section.
342+ pub fn add_files_cached (
343+ & mut self ,
344+ sections_info : & [ SectionInfo ] ,
345+ asid : Option < & Asid > ,
346+ ) -> Result < ( ) , PtError > {
347+ let mut image_cache = SectionCache :: new ( None ) ?;
348+
349+ let mut isids = Vec :: with_capacity ( sections_info. len ( ) ) ;
350+ for s in sections_info {
351+ let isid = image_cache. add_file ( & s. filename , s. offset , s. size , s. virtual_address ) ?;
352+ isids. push ( isid) ;
353+ }
354+
355+ let rc_cache = Rc :: new ( image_cache) ;
356+ for isid in isids {
357+ self . add_cached ( rc_cache. clone ( ) , isid, asid) ?;
358+ }
359+
360+ Ok ( ( ) )
361+ }
324362}
325363
326364impl Drop for Image {
@@ -511,4 +549,22 @@ mod test {
511549 assert_eq ! ( img. remove_by_asid( & Asid :: new( Some ( i) , Some ( i) ) ) . unwrap( ) , 1 ) ;
512550 }
513551 }
552+
553+ #[ test]
554+ fn img_add_files_cached ( ) {
555+ let file: PathBuf = [ env ! ( "CARGO_MANIFEST_DIR" ) , "testfiles" , "garbage.txt" ]
556+ . iter ( )
557+ . collect ( ) ;
558+
559+ let section = SectionInfo {
560+ filename : file. to_string_lossy ( ) . to_string ( ) ,
561+ offset : 5 ,
562+ size : 15 ,
563+ virtual_address : 0x1337 ,
564+ } ;
565+ let mut i = img_with_file ( ) ;
566+ let asid = Asid :: new ( Some ( 3 ) , Some ( 4 ) ) ;
567+ i. add_files_cached ( & [ section] , Some ( & asid) ) . unwrap ( ) ;
568+ assert_eq ! ( i. remove_by_asid( & asid) . unwrap( ) , 1 ) ;
569+ }
514570}
0 commit comments